All checks were successful
Test and deploy staging / staging (push) Successful in 2m30s
159 lines
4.7 KiB
TypeScript
159 lines
4.7 KiB
TypeScript
import { date, index, integer, numeric, pgTable, text, unique } from 'drizzle-orm/pg-core';
|
|
import { id, timestamps } from './helpers';
|
|
import { user } from './auth';
|
|
|
|
export const moneyAccounts = pgTable(
|
|
'money_accounts',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
name: text('name').notNull(),
|
|
openingBalanceCents: integer('opening_balance_cents').notNull().default(0),
|
|
kind: text('kind').notNull().default('spendable'),
|
|
color: text('color'),
|
|
...timestamps
|
|
},
|
|
(table) => [unique().on(table.userId, table.name), index().on(table.userId)]
|
|
);
|
|
|
|
export const moneyTransactions = pgTable(
|
|
'money_transactions',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
accountId: integer('account_id')
|
|
.notNull()
|
|
.references(() => moneyAccounts.id),
|
|
date: date('date', { mode: 'string' }).notNull(),
|
|
description: text('description').notNull(),
|
|
amountCents: integer('amount_cents').notNull(),
|
|
...timestamps
|
|
},
|
|
(table) => [index().on(table.userId, table.date, table.id), index().on(table.accountId)]
|
|
);
|
|
|
|
export const moneyRecurring = pgTable(
|
|
'money_recurring',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
name: text('name').notNull(),
|
|
amountCents: integer('amount_cents').notNull(),
|
|
cadence: text('cadence').notNull(),
|
|
startsOn: date('starts_on', { mode: 'string' }),
|
|
endsOn: date('ends_on', { mode: 'string' }),
|
|
accountId: integer('account_id').references(() => moneyAccounts.id, { onDelete: 'set null' }),
|
|
...timestamps
|
|
},
|
|
(table) => [index().on(table.userId)]
|
|
);
|
|
|
|
export const moneyForecasts = pgTable(
|
|
'money_forecasts',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
date: date('date', { mode: 'string' }).notNull(),
|
|
description: text('description').notNull(),
|
|
amountCents: integer('amount_cents').notNull(),
|
|
accountId: integer('account_id').references(() => moneyAccounts.id, { onDelete: 'set null' }),
|
|
...timestamps
|
|
},
|
|
(table) => [index().on(table.userId, table.date)]
|
|
);
|
|
|
|
export const moneyUtilitySettings = pgTable(
|
|
'money_utility_settings',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
kind: text('kind').notNull(),
|
|
ratePerUnit: numeric('rate_per_unit', { precision: 12, scale: 4 }).notNull().default('0'),
|
|
monthlyAdvanceCents: integer('monthly_advance_cents').notNull().default(0),
|
|
billingStart: date('billing_start', { mode: 'string' }),
|
|
...timestamps
|
|
},
|
|
(table) => [unique().on(table.userId, table.kind)]
|
|
);
|
|
|
|
export const moneyUtilityReadings = pgTable(
|
|
'money_utility_readings',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
kind: text('kind').notNull(),
|
|
date: date('date', { mode: 'string' }).notNull(),
|
|
reading: numeric('reading', { precision: 12, scale: 3 }).notNull(),
|
|
...timestamps
|
|
},
|
|
(table) => [index().on(table.userId, table.kind, table.date)]
|
|
);
|
|
|
|
export const moneyWishlist = pgTable(
|
|
'money_wishlist',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
name: text('name').notNull(),
|
|
estimatedCents: integer('estimated_cents'),
|
|
priority: integer('priority').notNull().default(3),
|
|
notes: text('notes'),
|
|
...timestamps
|
|
},
|
|
(table) => [index().on(table.userId)]
|
|
);
|
|
|
|
export const moneyProjectionSettings = pgTable(
|
|
'money_projection_settings',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
investmentAccountId: integer('investment_account_id').references(() => moneyAccounts.id, {
|
|
onDelete: 'set null'
|
|
}),
|
|
reserveCents: integer('reserve_cents').notNull().default(100000),
|
|
annualReturnPercent: numeric('annual_return_percent', { precision: 5, scale: 2 })
|
|
.notNull()
|
|
.default('5.00'),
|
|
contributionMode: text('contribution_mode').notNull().default('excess'),
|
|
includeRecurring: integer('include_recurring').notNull().default(1),
|
|
fixedMonthlyCents: integer('fixed_monthly_cents').notNull().default(0),
|
|
endDate: date('end_date', { mode: 'string' }),
|
|
...timestamps
|
|
},
|
|
(table) => [unique().on(table.userId)]
|
|
);
|
|
|
|
export const moneyInsurances = pgTable(
|
|
'money_insurances',
|
|
{
|
|
id: id(),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: 'cascade' }),
|
|
name: text('name').notNull(),
|
|
provider: text('provider'),
|
|
coverage: text('coverage'),
|
|
premiumCents: integer('premium_cents'),
|
|
cadence: text('cadence').notNull().default('monthly'),
|
|
...timestamps
|
|
},
|
|
(table) => [index().on(table.userId)]
|
|
);
|