-- QBO OAuth2 tokens (single row for Wulf Consulting's QBO) CREATE TABLE IF NOT EXISTS qbo_tokens ( id SERIAL PRIMARY KEY, realm_id TEXT NOT NULL UNIQUE, access_token TEXT NOT NULL, refresh_token TEXT NOT NULL, access_token_expires_at TIMESTAMPTZ NOT NULL, refresh_token_expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Invoices CREATE TABLE IF NOT EXISTS qbo_invoices ( id TEXT PRIMARY KEY, -- QBO Id realm_id TEXT NOT NULL, doc_number TEXT, txn_date DATE, due_date DATE, customer_ref_id TEXT, customer_ref_name TEXT, email_address TEXT, total_amt NUMERIC(12,2), balance NUMERIC(12,2), status TEXT, -- Open, Paid, Voided, etc. currency_code TEXT DEFAULT 'USD', line_items JSONB, linked_txns JSONB, sync_token TEXT, qbo_created_at TIMESTAMPTZ, qbo_updated_at TIMESTAMPTZ, synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_qbo_invoices_txn_date ON qbo_invoices(txn_date); CREATE INDEX IF NOT EXISTS idx_qbo_invoices_customer ON qbo_invoices(customer_ref_id); CREATE INDEX IF NOT EXISTS idx_qbo_invoices_status ON qbo_invoices(status); -- Payments CREATE TABLE IF NOT EXISTS qbo_payments ( id TEXT PRIMARY KEY, -- QBO Id realm_id TEXT NOT NULL, txn_date DATE, customer_ref_id TEXT, customer_ref_name TEXT, total_amt NUMERIC(12,2), unapplied_amt NUMERIC(12,2), currency_code TEXT DEFAULT 'USD', payment_method_ref TEXT, deposit_account_ref TEXT, linked_txns JSONB, sync_token TEXT, qbo_created_at TIMESTAMPTZ, qbo_updated_at TIMESTAMPTZ, synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_qbo_payments_txn_date ON qbo_payments(txn_date); CREATE INDEX IF NOT EXISTS idx_qbo_payments_customer ON qbo_payments(customer_ref_id); -- Deposits CREATE TABLE IF NOT EXISTS qbo_deposits ( id TEXT PRIMARY KEY, -- QBO Id realm_id TEXT NOT NULL, txn_date DATE, deposit_to_account_ref_id TEXT, deposit_to_account_ref_name TEXT, total_amt NUMERIC(12,2), line_items JSONB, sync_token TEXT, qbo_created_at TIMESTAMPTZ, qbo_updated_at TIMESTAMPTZ, synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_qbo_deposits_txn_date ON qbo_deposits(txn_date); -- General ledger transactions (purchases, expenses, journal entries, etc.) CREATE TABLE IF NOT EXISTS qbo_transactions ( id TEXT NOT NULL, txn_type TEXT NOT NULL, -- Purchase, Expense, JournalEntry, Transfer, etc. realm_id TEXT NOT NULL, txn_date DATE, doc_number TEXT, entity_ref_id TEXT, -- Vendor/Customer ref entity_ref_name TEXT, entity_type TEXT, -- Vendor, Customer account_ref_id TEXT, account_ref_name TEXT, total_amt NUMERIC(12,2), currency_code TEXT DEFAULT 'USD', private_note TEXT, line_items JSONB, sync_token TEXT, qbo_created_at TIMESTAMPTZ, qbo_updated_at TIMESTAMPTZ, synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (id, txn_type) ); CREATE INDEX IF NOT EXISTS idx_qbo_transactions_txn_date ON qbo_transactions(txn_date); CREATE INDEX IF NOT EXISTS idx_qbo_transactions_type ON qbo_transactions(txn_type); CREATE INDEX IF NOT EXISTS idx_qbo_transactions_entity ON qbo_transactions(entity_ref_id); -- Financial reports: P&L and Balance Sheet stored as JSONB per period CREATE TABLE IF NOT EXISTS qbo_reports ( id SERIAL PRIMARY KEY, realm_id TEXT NOT NULL, report_type TEXT NOT NULL, -- ProfitAndLoss, BalanceSheet period_start DATE NOT NULL, period_end DATE NOT NULL, summarize_by TEXT DEFAULT 'Month', report_data JSONB NOT NULL, -- Full report response synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (realm_id, report_type, period_start, period_end) ); CREATE INDEX IF NOT EXISTS idx_qbo_reports_type_period ON qbo_reports(report_type, period_start); COMMENT ON TABLE qbo_tokens IS 'QuickBooks Online OAuth2 tokens for Wulf Consulting'; COMMENT ON TABLE qbo_invoices IS 'QBO invoices synced from QuickBooks Online'; COMMENT ON TABLE qbo_payments IS 'QBO customer payments synced from QuickBooks Online'; COMMENT ON TABLE qbo_deposits IS 'QBO bank deposits synced from QuickBooks Online'; COMMENT ON TABLE qbo_transactions IS 'QBO general transactions (purchases, expenses, journals) synced from QuickBooks Online'; COMMENT ON TABLE qbo_reports IS 'QBO financial reports (P&L, Balance Sheet) stored per period';