feat(db): 新增 exchange_rates 汇率表,支持联合主键与基础交叉汇率数据

This commit is contained in:
2026-04-27 23:36:14 +08:00
parent 8f17573fa4
commit 84b8dc3226
4 changed files with 120 additions and 1 deletions
+68
View File
@@ -0,0 +1,68 @@
'use server';
import { db } from '@/db';
import { exchangeRates } from '@/db/schema';
import { eq } from 'drizzle-orm';
import { z } from 'zod';
const updateExchangeRateSchema = z.object({
from: z.string().min(1).max(10),
to: z.string().min(1).max(10),
rate: z.string().min(1),
});
export async function updateExchangeRate(
from: string,
to: string,
rate: string,
) {
const validation = updateExchangeRateSchema.safeParse({ from, to, rate });
if (!validation.success) {
return { success: false, error: 'Invalid input' };
}
try {
await db
.insert(exchangeRates)
.values({
fromCurrency: validation.data.from.toUpperCase(),
toCurrency: validation.data.to.toUpperCase(),
rate: validation.data.rate,
})
.onConflictDoUpdate({
target: [exchangeRates.fromCurrency, exchangeRates.toCurrency],
set: {
rate: validation.data.rate,
updatedAt: new Date(),
},
});
return { success: true };
} catch (error: unknown) {
if (
error &&
typeof error === 'object' &&
'code' in error &&
(error as { code: string }).code === '23505'
) {
return { success: false, error: 'Failed to update exchange rate' };
}
throw error;
}
}
export async function getExchangeRate(from: string, to: string) {
const result = await db
.select()
.from(exchangeRates)
.where(
eq(exchangeRates.fromCurrency, from.toUpperCase()),
)
.execute();
return result[0] || null;
}
export async function getAllExchangeRates() {
return db.select().from(exchangeRates).execute();
}
+12 -1
View File
@@ -1,4 +1,4 @@
import { pgTable, uuid, varchar, timestamp, pgEnum, numeric } from "drizzle-orm/pg-core";
import { pgTable, uuid, varchar, timestamp, pgEnum, numeric, uniqueIndex } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
@@ -51,3 +51,14 @@ export const transactions = pgTable("transactions", {
createdAt: timestamp("created_at", { withTimezone: true, mode: "date" })
.defaultNow(),
});
export const exchangeRates = pgTable("exchange_rates", {
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
fromCurrency: varchar("from_currency", { length: 10 }).notNull(),
toCurrency: varchar("to_currency", { length: 10 }).notNull(),
rate: numeric("rate", { precision: 20, scale: 8 }).notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true, mode: "date" })
.defaultNow(),
}, (table) => [
uniqueIndex("currency_pair_idx").on(table.fromCurrency, table.toCurrency),
]);