CREATE TYPE order_status AS ENUM ( 'pending_payment', 'paid', 'fulfilling', 'shipped', 'completed', 'cancelled' ); CREATE TYPE shipment_status AS ENUM ('pending', 'shipped', 'delivered'); CREATE TYPE invoice_status AS ENUM ('requested', 'issued', 'cancelled'); CREATE TYPE invoice_kind AS ENUM ('personal', 'company'); CREATE SEQUENCE order_no_seq; CREATE SEQUENCE shipment_no_seq; CREATE SEQUENCE invoice_no_seq; CREATE TABLE orders ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), order_no TEXT NOT NULL UNIQUE, shop_id UUID NOT NULL REFERENCES shops (id), user_id UUID NOT NULL REFERENCES users (id), status order_status NOT NULL DEFAULT 'pending_payment', currency CHAR(3) NOT NULL REFERENCES currencies (code), total_minor BIGINT NOT NULL CHECK (total_minor >= 0), shipping_address JSONB NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_orders_user ON orders (user_id); CREATE INDEX idx_orders_shop ON orders (shop_id); CREATE TABLE order_items ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), order_id UUID NOT NULL REFERENCES orders (id) ON DELETE CASCADE, sku_id UUID NOT NULL REFERENCES skus (id), product_name JSONB NOT NULL, sku_code TEXT NOT NULL, image TEXT, unit_price_minor BIGINT NOT NULL CHECK (unit_price_minor >= 0), qty INT NOT NULL CHECK (qty > 0) ); CREATE INDEX idx_order_items_order ON order_items (order_id); CREATE TABLE shipments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), shipment_no TEXT NOT NULL UNIQUE, order_id UUID NOT NULL REFERENCES orders (id), carrier TEXT NOT NULL, tracking_no TEXT NOT NULL, status shipment_status NOT NULL DEFAULT 'pending', shipped_at TIMESTAMPTZ, delivered_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_shipments_order ON shipments (order_id); CREATE TABLE shipment_items ( shipment_id UUID NOT NULL REFERENCES shipments (id) ON DELETE CASCADE, order_item_id UUID NOT NULL REFERENCES order_items (id), qty INT NOT NULL CHECK (qty > 0), PRIMARY KEY (shipment_id, order_item_id) ); CREATE TABLE invoices ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), invoice_no TEXT UNIQUE, order_id UUID NOT NULL REFERENCES orders (id), user_id UUID NOT NULL REFERENCES users (id), title TEXT NOT NULL, tax_no TEXT, kind invoice_kind NOT NULL, amount_minor BIGINT NOT NULL CHECK (amount_minor >= 0), currency CHAR(3) NOT NULL, status invoice_status NOT NULL DEFAULT 'requested', issued_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- at most one open (requested/issued) invoice per order CREATE UNIQUE INDEX one_open_invoice_per_order ON invoices (order_id) WHERE status IN ('requested', 'issued'); CREATE INDEX idx_invoices_user ON invoices (user_id);