438 lines
19 KiB
SQL
438 lines
19 KiB
SQL
|
|
-- BOC Schema Extension: Quotes, Orders, Suppliers, Inventory
|
||
|
|
-- Created: 2026-07-12
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- SALES: Quotes (Offert)
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_quotes (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
customer_id UUID REFERENCES boc_customers(id) ON DELETE CASCADE,
|
||
|
|
contact_id UUID REFERENCES boc_contacts(id),
|
||
|
|
quote_number TEXT NOT NULL,
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
status TEXT NOT NULL DEFAULT 'draft', -- draft, sent, accepted, rejected, expired
|
||
|
|
amount DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_amount DECIMAL(15,2) DEFAULT 0,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
valid_until DATE,
|
||
|
|
accepted_at TIMESTAMPTZ,
|
||
|
|
converted_to_order_id UUID,
|
||
|
|
notes TEXT,
|
||
|
|
terms TEXT,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_by UUID REFERENCES boc_users(id),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_quote_items (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
quote_id UUID REFERENCES boc_quotes(id) ON DELETE CASCADE,
|
||
|
|
product_id UUID REFERENCES boc_products(id),
|
||
|
|
description TEXT NOT NULL,
|
||
|
|
quantity DECIMAL(10,2) NOT NULL DEFAULT 1,
|
||
|
|
unit_price DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_rate DECIMAL(5,2) DEFAULT 0,
|
||
|
|
discount DECIMAL(5,2) DEFAULT 0,
|
||
|
|
total DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
sort_order INTEGER DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- SALES: Orders
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_orders (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
customer_id UUID REFERENCES boc_customers(id) ON DELETE CASCADE,
|
||
|
|
quote_id UUID REFERENCES boc_quotes(id),
|
||
|
|
order_number TEXT NOT NULL,
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
status TEXT NOT NULL DEFAULT 'draft', -- draft, confirmed, processing, shipped, delivered, cancelled
|
||
|
|
amount DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_amount DECIMAL(15,2) DEFAULT 0,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
delivery_date DATE,
|
||
|
|
shipped_at TIMESTAMPTZ,
|
||
|
|
delivered_at TIMESTAMPTZ,
|
||
|
|
tracking_number TEXT,
|
||
|
|
notes TEXT,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_by UUID REFERENCES boc_users(id),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_order_items (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
order_id UUID REFERENCES boc_orders(id) ON DELETE CASCADE,
|
||
|
|
product_id UUID REFERENCES boc_products(id),
|
||
|
|
description TEXT NOT NULL,
|
||
|
|
quantity DECIMAL(10,2) NOT NULL DEFAULT 1,
|
||
|
|
unit_price DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_rate DECIMAL(5,2) DEFAULT 0,
|
||
|
|
discount DECIMAL(5,2) DEFAULT 0,
|
||
|
|
total DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
delivered_qty DECIMAL(10,2) DEFAULT 0,
|
||
|
|
sort_order INTEGER DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- PURCHASE: Suppliers
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_suppliers (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
email TEXT,
|
||
|
|
phone TEXT,
|
||
|
|
org_number TEXT,
|
||
|
|
address JSONB,
|
||
|
|
payment_terms TEXT DEFAULT '30 days',
|
||
|
|
bank_account TEXT,
|
||
|
|
bankgiro TEXT,
|
||
|
|
postgiro TEXT,
|
||
|
|
currency TEXT DEFAULT 'USD',
|
||
|
|
status TEXT NOT NULL DEFAULT 'active',
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- PURCHASE: Purchase Orders
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_purchase_orders (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
supplier_id UUID REFERENCES boc_suppliers(id) ON DELETE CASCADE,
|
||
|
|
po_number TEXT NOT NULL,
|
||
|
|
status TEXT NOT NULL DEFAULT 'draft', -- draft, sent, confirmed, received, invoiced, paid
|
||
|
|
amount DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_amount DECIMAL(15,2) DEFAULT 0,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
expected_delivery DATE,
|
||
|
|
received_at TIMESTAMPTZ,
|
||
|
|
notes TEXT,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_by UUID REFERENCES boc_users(id),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_purchase_order_items (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
po_id UUID REFERENCES boc_purchase_orders(id) ON DELETE CASCADE,
|
||
|
|
product_id UUID REFERENCES boc_products(id),
|
||
|
|
description TEXT NOT NULL,
|
||
|
|
quantity DECIMAL(10,2) NOT NULL DEFAULT 1,
|
||
|
|
unit_price DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_rate DECIMAL(5,2) DEFAULT 0,
|
||
|
|
total DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
received_qty DECIMAL(10,2) DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- PURCHASE: Supplier Invoices (Leverantörsfakturor)
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_supplier_invoices (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
supplier_id UUID REFERENCES boc_suppliers(id),
|
||
|
|
po_id UUID REFERENCES boc_purchase_orders(id),
|
||
|
|
invoice_number TEXT NOT NULL,
|
||
|
|
amount DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_amount DECIMAL(15,2) DEFAULT 0,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
status TEXT NOT NULL DEFAULT 'draft', -- draft, received, approved, paid, disputed
|
||
|
|
due_date DATE,
|
||
|
|
paid_at TIMESTAMPTZ,
|
||
|
|
paid_amount DECIMAL(15,2) DEFAULT 0,
|
||
|
|
ocr_number TEXT,
|
||
|
|
notes TEXT,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_by UUID REFERENCES boc_users(id),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- INVENTORY: Stock / Warehouse
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_warehouses (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
location TEXT,
|
||
|
|
address JSONB,
|
||
|
|
is_default BOOLEAN DEFAULT FALSE,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_inventory (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
product_id UUID REFERENCES boc_products(id) ON DELETE CASCADE,
|
||
|
|
warehouse_id UUID REFERENCES boc_warehouses(id),
|
||
|
|
quantity DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||
|
|
reserved_qty DECIMAL(10,2) DEFAULT 0,
|
||
|
|
reorder_point DECIMAL(10,2) DEFAULT 0,
|
||
|
|
reorder_qty DECIMAL(10,2) DEFAULT 0,
|
||
|
|
unit_cost DECIMAL(15,2) DEFAULT 0,
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
UNIQUE(tenant_id, product_id, warehouse_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_inventory_movements (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
product_id UUID REFERENCES boc_products(id),
|
||
|
|
warehouse_id UUID REFERENCES boc_warehouses(id),
|
||
|
|
type TEXT NOT NULL, -- in, out, adjustment, transfer
|
||
|
|
quantity DECIMAL(10,2) NOT NULL,
|
||
|
|
reference_type TEXT, -- order, po, adjustment
|
||
|
|
reference_id TEXT,
|
||
|
|
notes TEXT,
|
||
|
|
created_by UUID REFERENCES boc_users(id),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- RECURRING: Subscriptions & Recurring Invoices
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_subscription_plans (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
product_id UUID REFERENCES boc_products(id),
|
||
|
|
interval TEXT NOT NULL DEFAULT 'monthly', -- weekly, monthly, quarterly, yearly
|
||
|
|
interval_count INTEGER DEFAULT 1,
|
||
|
|
price DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
trial_days INTEGER DEFAULT 0,
|
||
|
|
setup_fee DECIMAL(15,2) DEFAULT 0,
|
||
|
|
status TEXT NOT NULL DEFAULT 'active',
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_subscriptions (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
customer_id UUID REFERENCES boc_customers(id) ON DELETE CASCADE,
|
||
|
|
plan_id UUID REFERENCES boc_subscription_plans(id),
|
||
|
|
status TEXT NOT NULL DEFAULT 'active', -- active, paused, cancelled, expired
|
||
|
|
start_date DATE NOT NULL,
|
||
|
|
end_date DATE,
|
||
|
|
trial_end DATE,
|
||
|
|
current_period_start DATE,
|
||
|
|
current_period_end DATE,
|
||
|
|
price DECIMAL(15,2) NOT NULL,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_recurring_invoices (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
customer_id UUID REFERENCES boc_customers(id),
|
||
|
|
subscription_id UUID REFERENCES boc_subscriptions(id),
|
||
|
|
plan_id UUID REFERENCES boc_subscription_plans(id),
|
||
|
|
invoice_number TEXT,
|
||
|
|
amount DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
currency TEXT NOT NULL DEFAULT 'USD',
|
||
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending, generated, sent, paid, failed
|
||
|
|
scheduled_date DATE NOT NULL,
|
||
|
|
generated_at TIMESTAMPTZ,
|
||
|
|
sent_at TIMESTAMPTZ,
|
||
|
|
error TEXT,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- EXPENSES: Receipts & OCR
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_receipts (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
employee_id UUID REFERENCES boc_employees(id),
|
||
|
|
expense_id UUID REFERENCES boc_expenses(id),
|
||
|
|
image_url TEXT NOT NULL,
|
||
|
|
ocr_text TEXT,
|
||
|
|
ocr_data JSONB DEFAULT '{}', -- extracted: amount, date, vendor, category
|
||
|
|
ocr_confidence DECIMAL(5,2) DEFAULT 0,
|
||
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending, processed, failed
|
||
|
|
processed_at TIMESTAMPTZ,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- PAYROLL: Basic structure
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_payroll_runs (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
period_start DATE NOT NULL,
|
||
|
|
period_end DATE NOT NULL,
|
||
|
|
pay_date DATE NOT NULL,
|
||
|
|
status TEXT NOT NULL DEFAULT 'draft', -- draft, processing, approved, paid
|
||
|
|
total_gross DECIMAL(15,2) DEFAULT 0,
|
||
|
|
total_tax DECIMAL(15,2) DEFAULT 0,
|
||
|
|
total_net DECIMAL(15,2) DEFAULT 0,
|
||
|
|
total_employer_tax DECIMAL(15,2) DEFAULT 0,
|
||
|
|
currency TEXT DEFAULT 'USD',
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_by UUID REFERENCES boc_users(id),
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_payroll_lines (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
payroll_run_id UUID REFERENCES boc_payroll_runs(id) ON DELETE CASCADE,
|
||
|
|
employee_id UUID REFERENCES boc_employees(id),
|
||
|
|
gross_salary DECIMAL(15,2) NOT NULL DEFAULT 0,
|
||
|
|
tax_deduction DECIMAL(15,2) DEFAULT 0,
|
||
|
|
social_fees DECIMAL(15,2) DEFAULT 0,
|
||
|
|
pension DECIMAL(15,2) DEFAULT 0,
|
||
|
|
other_deductions DECIMAL(15,2) DEFAULT 0,
|
||
|
|
net_salary DECIMAL(15,2) DEFAULT 0,
|
||
|
|
hours_worked DECIMAL(5,2) DEFAULT 0,
|
||
|
|
vacation_days_used DECIMAL(4,1) DEFAULT 0,
|
||
|
|
sick_days DECIMAL(4,1) DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- BANK: Accounts & Transactions
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_bank_accounts (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
bank_name TEXT NOT NULL,
|
||
|
|
account_number TEXT NOT NULL,
|
||
|
|
iban TEXT,
|
||
|
|
bic TEXT,
|
||
|
|
currency TEXT DEFAULT 'USD',
|
||
|
|
balance DECIMAL(15,2) DEFAULT 0,
|
||
|
|
is_default BOOLEAN DEFAULT FALSE,
|
||
|
|
status TEXT NOT NULL DEFAULT 'active',
|
||
|
|
last_sync TIMESTAMPTZ,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_bank_transactions (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
account_id UUID REFERENCES boc_bank_accounts(id) ON DELETE CASCADE,
|
||
|
|
transaction_date DATE NOT NULL,
|
||
|
|
amount DECIMAL(15,2) NOT NULL,
|
||
|
|
currency TEXT DEFAULT 'USD',
|
||
|
|
description TEXT,
|
||
|
|
counterparty TEXT,
|
||
|
|
reference TEXT,
|
||
|
|
external_id TEXT,
|
||
|
|
status TEXT NOT NULL DEFAULT 'unmatched', -- unmatched, matched, reconciled
|
||
|
|
matched_to_type TEXT, -- invoice, expense, payroll
|
||
|
|
matched_to_id UUID,
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================
|
||
|
|
-- PROJECTS
|
||
|
|
-- ============================================
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_projects (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
customer_id UUID REFERENCES boc_customers(id),
|
||
|
|
status TEXT NOT NULL DEFAULT 'active', -- active, completed, on_hold, cancelled
|
||
|
|
budget DECIMAL(15,2) DEFAULT 0,
|
||
|
|
spent DECIMAL(15,2) DEFAULT 0,
|
||
|
|
currency TEXT DEFAULT 'USD',
|
||
|
|
start_date DATE,
|
||
|
|
end_date DATE,
|
||
|
|
manager_id UUID REFERENCES boc_employees(id),
|
||
|
|
metadata JSONB DEFAULT '{}',
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_project_times (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
project_id UUID REFERENCES boc_projects(id) ON DELETE CASCADE,
|
||
|
|
employee_id UUID REFERENCES boc_employees(id),
|
||
|
|
date DATE NOT NULL,
|
||
|
|
hours DECIMAL(4,2) NOT NULL DEFAULT 0,
|
||
|
|
description TEXT,
|
||
|
|
billable BOOLEAN DEFAULT TRUE,
|
||
|
|
hourly_rate DECIMAL(15,2) DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS boc_project_expenses (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
tenant_id UUID REFERENCES boc_tenants(id) ON DELETE CASCADE,
|
||
|
|
project_id UUID REFERENCES boc_projects(id) ON DELETE CASCADE,
|
||
|
|
expense_id UUID REFERENCES boc_expenses(id),
|
||
|
|
amount DECIMAL(15,2) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Indexes
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_quotes_tenant ON boc_quotes(tenant_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_quotes_customer ON boc_quotes(customer_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_orders_tenant ON boc_orders(tenant_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_orders_customer ON boc_orders(customer_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_suppliers_tenant ON boc_suppliers(tenant_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_po_tenant ON boc_purchase_orders(tenant_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supplier_invoices_tenant ON boc_supplier_invoices(tenant_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_inventory_product ON boc_inventory(product_id, warehouse_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_inventory_movements ON boc_inventory_movements(product_id, created_at DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_subscriptions_customer ON boc_subscriptions(customer_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_recurring_invoices ON boc_recurring_invoices(scheduled_date, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_receipts_status ON boc_receipts(status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_payroll_runs ON boc_payroll_runs(period_start, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bank_transactions ON boc_bank_transactions(account_id, transaction_date DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_projects_tenant ON boc_projects(tenant_id, status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_project_times ON boc_project_times(project_id, date);
|
||
|
|
|
||
|
|
-- Triggers for updated_at
|
||
|
|
DO $$
|
||
|
|
BEGIN
|
||
|
|
CREATE TRIGGER update_boc_quotes_updated_at BEFORE UPDATE ON boc_quotes FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_orders_updated_at BEFORE UPDATE ON boc_orders FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_suppliers_updated_at BEFORE UPDATE ON boc_suppliers FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_purchase_orders_updated_at BEFORE UPDATE ON boc_purchase_orders FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_supplier_invoices_updated_at BEFORE UPDATE ON boc_supplier_invoices FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_inventory_updated_at BEFORE UPDATE ON boc_inventory FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_subscription_plans_updated_at BEFORE UPDATE ON boc_subscription_plans FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_subscriptions_updated_at BEFORE UPDATE ON boc_subscriptions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_payroll_runs_updated_at BEFORE UPDATE ON boc_payroll_runs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_bank_accounts_updated_at BEFORE UPDATE ON boc_bank_accounts FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
CREATE TRIGGER update_boc_projects_updated_at BEFORE UPDATE ON boc_projects FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||
|
|
EXCEPTION WHEN duplicate_object THEN
|
||
|
|
-- Triggers already exist, ignore
|
||
|
|
END;
|
||
|
|
$$;
|