import { pgTable, text, numeric, integer, timestamp, date, index, uniqueIndex, primaryKey, } from 'drizzle-orm/pg-core'; import { ports } from './ports'; import { files } from './documents'; export const expenses = pgTable( 'expenses', { id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()), portId: text('port_id') .notNull() .references(() => ports.id), establishmentName: text('establishment_name'), amount: numeric('amount').notNull(), currency: text('currency').notNull().default('USD'), amountUsd: numeric('amount_usd'), exchangeRate: numeric('exchange_rate'), paymentMethod: text('payment_method'), category: text('category'), payer: text('payer'), expenseDate: timestamp('expense_date', { withTimezone: true }).notNull(), description: text('description'), receiptFileIds: text('receipt_file_ids').array(), // references to files table paymentStatus: text('payment_status').default('unpaid'), // unpaid, paid, partial paymentDate: date('payment_date'), paymentReference: text('payment_reference'), paymentNotes: text('payment_notes'), createdBy: text('created_by').notNull(), archivedAt: timestamp('archived_at', { withTimezone: true }), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }, (table) => [ index('idx_expenses_port').on(table.portId), index('idx_expenses_date').on(table.portId, table.expenseDate), index('idx_expenses_category').on(table.portId, table.category), ], ); export const invoices = pgTable( 'invoices', { id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()), portId: text('port_id') .notNull() .references(() => ports.id), invoiceNumber: text('invoice_number').notNull(), // INV-YYYYMM-### auto-generated clientName: text('client_name').notNull(), billingEmail: text('billing_email'), billingAddress: text('billing_address'), dueDate: date('due_date').notNull(), paymentTerms: text('payment_terms').notNull().default('net30'), // immediate, net10, net15, net30, net45, net60 currency: text('currency').notNull().default('USD'), subtotal: numeric('subtotal').notNull(), discountPct: numeric('discount_pct').default('0'), discountAmount: numeric('discount_amount').default('0'), feePct: numeric('fee_pct').default('0'), feeAmount: numeric('fee_amount').default('0'), total: numeric('total').notNull(), status: text('status').notNull().default('draft'), // draft, sent, paid, overdue, cancelled paymentStatus: text('payment_status').default('unpaid'), paymentDate: date('payment_date'), paymentMethod: text('payment_method'), paymentReference: text('payment_reference'), pdfFileId: text('pdf_file_id').references(() => files.id), notes: text('notes'), createdBy: text('created_by').notNull(), archivedAt: timestamp('archived_at', { withTimezone: true }), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }, (table) => [ uniqueIndex('idx_invoices_number').on(table.portId, table.invoiceNumber), index('idx_invoices_port').on(table.portId), index('idx_invoices_status').on(table.portId, table.status), ], ); export const invoiceLineItems = pgTable( 'invoice_line_items', { id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()), invoiceId: text('invoice_id') .notNull() .references(() => invoices.id, { onDelete: 'cascade' }), description: text('description').notNull(), quantity: numeric('quantity').notNull().default('1'), unitPrice: numeric('unit_price').notNull(), total: numeric('total').notNull(), sortOrder: integer('sort_order').notNull().default(0), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }, (table) => [index('idx_ili_invoice').on(table.invoiceId)], ); export const invoiceExpenses = pgTable( 'invoice_expenses', { invoiceId: text('invoice_id') .notNull() .references(() => invoices.id, { onDelete: 'cascade' }), expenseId: text('expense_id') .notNull() .references(() => expenses.id, { onDelete: 'cascade' }), }, (table) => [primaryKey({ columns: [table.invoiceId, table.expenseId] })], ); export type Expense = typeof expenses.$inferSelect; export type NewExpense = typeof expenses.$inferInsert; export type Invoice = typeof invoices.$inferSelect; export type NewInvoice = typeof invoices.$inferInsert; export type InvoiceLineItem = typeof invoiceLineItems.$inferSelect; export type NewInvoiceLineItem = typeof invoiceLineItems.$inferInsert; export type InvoiceExpense = typeof invoiceExpenses.$inferSelect; export type NewInvoiceExpense = typeof invoiceExpenses.$inferInsert;