import pg from 'pg' const { Pool } = pg export const pool = new Pool({ connectionString: process.env.DATABASE_URL }) export async function initDb() { await pool.query(` CREATE TABLE IF NOT EXISTS cash_ups ( id SERIAL PRIMARY KEY, session_date DATE NOT NULL UNIQUE, created_by TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), status TEXT NOT NULL DEFAULT 'draft', total_float_counted NUMERIC(10,2) NOT NULL DEFAULT 0, total_cash_counted NUMERIC(10,2) NOT NULL DEFAULT 0, notes TEXT, submitted_at TIMESTAMPTZ, submitted_by TEXT ); CREATE TABLE IF NOT EXISTS denominations ( id SERIAL PRIMARY KEY, cash_up_id INTEGER NOT NULL REFERENCES cash_ups(id) ON DELETE CASCADE, count_type TEXT NOT NULL DEFAULT 'takings', denomination_type TEXT NOT NULL, denomination_value NUMERIC(10,2) NOT NULL, quantity INTEGER, value_entered NUMERIC(10,2), total_amount NUMERIC(10,2) NOT NULL ); CREATE TABLE IF NOT EXISTS card_machines ( id SERIAL PRIMARY KEY, cash_up_id INTEGER NOT NULL REFERENCES cash_ups(id) ON DELETE CASCADE, machine_name TEXT NOT NULL, total_amount NUMERIC(10,2) NOT NULL DEFAULT 0, amex_amount NUMERIC(10,2) NOT NULL DEFAULT 0, visa_mc_amount NUMERIC(10,2) NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS payment_records ( id SERIAL PRIMARY KEY, cash_up_id INTEGER REFERENCES cash_ups(id) ON DELETE SET NULL, newbook_payment_id TEXT, booking_id TEXT, guest_name TEXT, payment_date TIMESTAMPTZ NOT NULL, payment_type TEXT, payment_method TEXT, transaction_method TEXT, card_type TEXT, amount NUMERIC(10,2) NOT NULL, tendered NUMERIC(10,2), processed_by TEXT, synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS reconciliation ( id SERIAL PRIMARY KEY, cash_up_id INTEGER NOT NULL REFERENCES cash_ups(id) ON DELETE CASCADE, category TEXT NOT NULL, banked_amount NUMERIC(10,2) NOT NULL, reported_amount NUMERIC(10,2) NOT NULL, variance NUMERIC(10,2) NOT NULL ); CREATE TABLE IF NOT EXISTS daily_stats ( id SERIAL PRIMARY KEY, business_date DATE NOT NULL UNIQUE, gross_sales NUMERIC(10,2) NOT NULL DEFAULT 0, debtors_creditors_balance NUMERIC(10,2) NOT NULL DEFAULT 0, rooms_sold INTEGER NOT NULL DEFAULT 0, total_people INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), source TEXT NOT NULL DEFAULT 'manual' ); CREATE TABLE IF NOT EXISTS sales_breakdown ( id SERIAL PRIMARY KEY, business_date DATE NOT NULL, category TEXT NOT NULL, net_amount NUMERIC(10,2) NOT NULL ); CREATE TABLE IF NOT EXISTS float_counts ( id SERIAL PRIMARY KEY, count_type TEXT NOT NULL, count_date TIMESTAMPTZ NOT NULL, created_by TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), total_counted NUMERIC(10,2) NOT NULL DEFAULT 0, total_receipts NUMERIC(10,2) NOT NULL DEFAULT 0, target_amount NUMERIC(10,2) NOT NULL DEFAULT 0, variance NUMERIC(10,2) NOT NULL DEFAULT 0, notes TEXT ); CREATE TABLE IF NOT EXISTS float_denominations ( id SERIAL PRIMARY KEY, float_count_id INTEGER NOT NULL REFERENCES float_counts(id) ON DELETE CASCADE, denomination_value NUMERIC(10,2) NOT NULL, quantity INTEGER NOT NULL DEFAULT 0, total_amount NUMERIC(10,2) NOT NULL ); CREATE TABLE IF NOT EXISTS float_receipts ( id SERIAL PRIMARY KEY, float_count_id INTEGER NOT NULL REFERENCES float_counts(id) ON DELETE CASCADE, receipt_value NUMERIC(10,2) NOT NULL, receipt_description TEXT ); CREATE TABLE IF NOT EXISTS cash_count_attachments ( id SERIAL PRIMARY KEY, cash_up_id INTEGER NOT NULL REFERENCES cash_ups(id) ON DELETE CASCADE, file_name TEXT NOT NULL, file_path TEXT NOT NULL, file_size BIGINT NOT NULL, mime_type TEXT NOT NULL, uploaded_by TEXT NOT NULL, uploaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); `) // Seed default settings if not present (Newbook credentials live in the settings service) await pool.query(` INSERT INTO settings (key, value) VALUES ('default_report_days', '7'), ('petty_cash_float', '200.00'), ('sales_breakdown_columns', '[]'), ('change_tin_breakdown', '{"50.00":0,"20.00":0,"10.00":0,"5.00":0,"2.00":20,"1.00":20,"0.50":10,"0.20":10,"0.10":5,"0.05":5}') ON CONFLICT (key) DO NOTHING `) }