107 lines
4.2 KiB
TypeScript
107 lines
4.2 KiB
TypeScript
import { pgTable, uuid, varchar, timestamp, pgEnum, numeric, uniqueIndex, date } from "drizzle-orm/pg-core";
|
|
|
|
export const users = pgTable("users", {
|
|
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
username: varchar("username", { length: 50 }).notNull().unique(),
|
|
passwordHash: varchar("password_hash", { length: 255 }).notNull(),
|
|
createdAt: timestamp("created_at", { withTimezone: true, mode: "date" })
|
|
.defaultNow()
|
|
.notNull(),
|
|
});
|
|
|
|
export const assetTypeEnum = pgEnum("asset_type_enum", [
|
|
"STOCK",
|
|
"CRYPTO",
|
|
"CASH",
|
|
]);
|
|
|
|
export const assets = pgTable("assets", {
|
|
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
symbol: varchar("symbol", { length: 20 }).notNull().unique(),
|
|
name: varchar("name", { length: 100 }),
|
|
type: assetTypeEnum("type").notNull(),
|
|
exchange: varchar("exchange", { length: 10 }).default('US'),
|
|
baseCurrency: varchar("base_currency", { length: 10 }).notNull(),
|
|
latestPrice: numeric("latest_price", { precision: 36, scale: 18 }).default('0').notNull(),
|
|
createdAt: timestamp("created_at", { withTimezone: true, mode: "date" })
|
|
.defaultNow(),
|
|
});
|
|
|
|
export const transactionTypeEnum = pgEnum("transaction_type_enum", [
|
|
"BUY",
|
|
"SELL",
|
|
"DIVIDEND",
|
|
"AIRDROP",
|
|
"FEE",
|
|
]);
|
|
|
|
export const transactions = pgTable("transactions", {
|
|
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
assetId: uuid("asset_id")
|
|
.notNull()
|
|
.references(() => assets.id),
|
|
txType: transactionTypeEnum("tx_type").notNull(),
|
|
quantity: numeric("quantity", { precision: 36, scale: 18 }).notNull(),
|
|
price: numeric("price", { precision: 36, scale: 18 }).notNull(),
|
|
fee: numeric("fee", { precision: 36, scale: 18 })
|
|
.notNull()
|
|
.default("0"),
|
|
txCurrency: varchar("tx_currency", { length: 10 }).notNull(),
|
|
exchangeRate: numeric("exchange_rate", { precision: 20, scale: 8 })
|
|
.notNull()
|
|
.default("1"),
|
|
executedAt: timestamp("executed_at", { withTimezone: true }).notNull(),
|
|
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),
|
|
]);
|
|
|
|
export const portfolioSnapshots = pgTable("portfolio_snapshots", {
|
|
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
date: date("date", { mode: "string" }).notNull().unique(),
|
|
totalValueCny: numeric("total_value_cny", { precision: 36, scale: 18 }).notNull(),
|
|
totalCostCny: numeric("total_cost_cny", { precision: 36, scale: 18 }).notNull(),
|
|
createdAt: timestamp("created_at", { withTimezone: true, mode: "date" })
|
|
.defaultNow()
|
|
.notNull(),
|
|
updatedAt: timestamp("updated_at", { withTimezone: true, mode: "date" })
|
|
.defaultNow()
|
|
.notNull(),
|
|
});
|
|
|
|
export const assetPricesHistory = pgTable("asset_prices_history", {
|
|
id: uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
assetId: uuid("asset_id")
|
|
.notNull()
|
|
.references(() => assets.id),
|
|
price: numeric("price", { precision: 36, scale: 18 }).notNull(),
|
|
date: date("date", { mode: "string" }).notNull(),
|
|
createdAt: timestamp("created_at", { withTimezone: true, mode: "date" })
|
|
.defaultNow()
|
|
.notNull(),
|
|
}, (table) => [
|
|
uniqueIndex("asset_price_date_idx").on(table.assetId, table.date),
|
|
]);
|
|
|
|
export const exchangeRatesHistory = pgTable("exchange_rates_history", {
|
|
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(),
|
|
fetchTime: timestamp("fetch_time", { withTimezone: true, mode: "date" })
|
|
.notNull(),
|
|
createdAt: timestamp("created_at", { withTimezone: true, mode: "date" })
|
|
.defaultNow()
|
|
.notNull(),
|
|
});
|