import { pgTable, uuid, varchar, text, timestamp, boolean, integer, numeric, pgEnum, jsonb, } from 'drizzle-orm/pg-core' import { locations } from './stores.js' import { accounts } from './accounts.js' import { products, inventoryUnits } from './inventory.js' import { users } from './users.js' import { repairTickets, repairBatches } from './repairs.js' // --- Enums --- export const transactionTypeEnum = pgEnum('transaction_type', [ 'sale', 'repair_payment', 'rental_deposit', 'account_payment', 'refund', ]) export const transactionStatusEnum = pgEnum('transaction_status', [ 'pending', 'completed', 'voided', 'refunded', ]) export const paymentMethodEnum = pgEnum('payment_method', [ 'cash', 'card_present', 'card_keyed', 'check', 'account_charge', ]) export const discountTypeEnum = pgEnum('discount_type', ['percent', 'fixed']) export const discountAppliesToEnum = pgEnum('discount_applies_to', [ 'order', 'line_item', 'category', ]) export const drawerStatusEnum = pgEnum('drawer_status', ['open', 'closed']) // --- Tables --- export const discounts = pgTable('discount', { id: uuid('id').primaryKey().defaultRandom(), locationId: uuid('location_id').references(() => locations.id), name: varchar('name', { length: 255 }).notNull(), discountType: discountTypeEnum('discount_type').notNull(), discountValue: numeric('discount_value', { precision: 10, scale: 2 }).notNull(), appliesTo: discountAppliesToEnum('applies_to').notNull().default('line_item'), requiresApprovalAbove: numeric('requires_approval_above', { precision: 10, scale: 2 }), isActive: boolean('is_active').notNull().default(true), validFrom: timestamp('valid_from', { withTimezone: true }), validUntil: timestamp('valid_until', { withTimezone: true }), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }) export const adjustmentTypeEnum = pgEnum('adjustment_type', ['cash_in', 'cash_out']) export const registers = pgTable('register', { id: uuid('id').primaryKey().defaultRandom(), locationId: uuid('location_id') .notNull() .references(() => locations.id), name: varchar('name', { length: 100 }).notNull(), isActive: boolean('is_active').notNull().default(true), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }) export const drawerSessions = pgTable('drawer_session', { id: uuid('id').primaryKey().defaultRandom(), locationId: uuid('location_id').references(() => locations.id), registerId: uuid('register_id').references(() => registers.id), openedBy: uuid('opened_by') .notNull() .references(() => users.id), closedBy: uuid('closed_by').references(() => users.id), openingBalance: numeric('opening_balance', { precision: 10, scale: 2 }).notNull(), closingBalance: numeric('closing_balance', { precision: 10, scale: 2 }), expectedBalance: numeric('expected_balance', { precision: 10, scale: 2 }), overShort: numeric('over_short', { precision: 10, scale: 2 }), denominations: jsonb('denominations').$type>(), status: drawerStatusEnum('status').notNull().default('open'), notes: text('notes'), openedAt: timestamp('opened_at', { withTimezone: true }).notNull().defaultNow(), closedAt: timestamp('closed_at', { withTimezone: true }), }) export const drawerAdjustments = pgTable('drawer_adjustment', { id: uuid('id').primaryKey().defaultRandom(), drawerSessionId: uuid('drawer_session_id') .notNull() .references(() => drawerSessions.id), type: adjustmentTypeEnum('type').notNull(), amount: numeric('amount', { precision: 10, scale: 2 }).notNull(), reason: text('reason').notNull(), createdBy: uuid('created_by') .notNull() .references(() => users.id), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }) export const transactions = pgTable('transaction', { id: uuid('id').primaryKey().defaultRandom(), locationId: uuid('location_id').references(() => locations.id), transactionNumber: varchar('transaction_number', { length: 50 }).notNull().unique(), accountId: uuid('account_id').references(() => accounts.id), repairTicketId: uuid('repair_ticket_id').references(() => repairTickets.id), repairBatchId: uuid('repair_batch_id').references(() => repairBatches.id), transactionType: transactionTypeEnum('transaction_type').notNull(), status: transactionStatusEnum('status').notNull().default('pending'), subtotal: numeric('subtotal', { precision: 10, scale: 2 }).notNull().default('0'), discountTotal: numeric('discount_total', { precision: 10, scale: 2 }).notNull().default('0'), taxTotal: numeric('tax_total', { precision: 10, scale: 2 }).notNull().default('0'), total: numeric('total', { precision: 10, scale: 2 }).notNull().default('0'), paymentMethod: paymentMethodEnum('payment_method'), amountTendered: numeric('amount_tendered', { precision: 10, scale: 2 }), changeGiven: numeric('change_given', { precision: 10, scale: 2 }), checkNumber: varchar('check_number', { length: 50 }), stripePaymentIntentId: varchar('stripe_payment_intent_id', { length: 255 }), roundingAdjustment: numeric('rounding_adjustment', { precision: 10, scale: 2 }).notNull().default('0'), taxExempt: boolean('tax_exempt').notNull().default(false), taxExemptReason: text('tax_exempt_reason'), processedBy: uuid('processed_by') .notNull() .references(() => users.id), drawerSessionId: uuid('drawer_session_id').references(() => drawerSessions.id), notes: text('notes'), completedAt: timestamp('completed_at', { withTimezone: true }), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }) export const transactionLineItems = pgTable('transaction_line_item', { id: uuid('id').primaryKey().defaultRandom(), transactionId: uuid('transaction_id') .notNull() .references(() => transactions.id), productId: uuid('product_id').references(() => products.id), inventoryUnitId: uuid('inventory_unit_id').references(() => inventoryUnits.id), description: varchar('description', { length: 255 }).notNull(), qty: integer('qty').notNull().default(1), unitPrice: numeric('unit_price', { precision: 10, scale: 2 }).notNull(), discountAmount: numeric('discount_amount', { precision: 10, scale: 2 }).notNull().default('0'), discountReason: text('discount_reason'), taxRate: numeric('tax_rate', { precision: 5, scale: 4 }).notNull().default('0'), taxAmount: numeric('tax_amount', { precision: 10, scale: 2 }).notNull().default('0'), lineTotal: numeric('line_total', { precision: 10, scale: 2 }).notNull().default('0'), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }) export const discountAudits = pgTable('discount_audit', { id: uuid('id').primaryKey().defaultRandom(), transactionId: uuid('transaction_id') .notNull() .references(() => transactions.id), transactionLineItemId: uuid('transaction_line_item_id').references(() => transactionLineItems.id), discountId: uuid('discount_id').references(() => discounts.id), appliedBy: uuid('applied_by') .notNull() .references(() => users.id), approvedBy: uuid('approved_by').references(() => users.id), originalAmount: numeric('original_amount', { precision: 10, scale: 2 }).notNull(), discountedAmount: numeric('discounted_amount', { precision: 10, scale: 2 }).notNull(), reason: text('reason').notNull(), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }) // --- Type exports --- export type Discount = typeof discounts.$inferSelect export type DiscountInsert = typeof discounts.$inferInsert export type Transaction = typeof transactions.$inferSelect export type TransactionInsert = typeof transactions.$inferInsert export type TransactionLineItem = typeof transactionLineItems.$inferSelect export type TransactionLineItemInsert = typeof transactionLineItems.$inferInsert export type DiscountAudit = typeof discountAudits.$inferSelect export type DiscountAuditInsert = typeof discountAudits.$inferInsert export type DrawerSession = typeof drawerSessions.$inferSelect export type DrawerSessionInsert = typeof drawerSessions.$inferInsert