Files
aura-crm/production/backend/migrations/013_loyalty.sql
T

31 lines
1.8 KiB
SQL

-- +goose Up
-- Append-only ledger, same doctrine as cash_transactions (006_cash.sql):
-- balance is never a stored column, always SUM(points) on read — a
-- mis-entered correction gets a compensating row of the same type, not an
-- edit/delete. Unlike cash, points really does have one meaningful
-- "at most once" fact: an order/batch is only ever accrued once, enforced
-- below as a real constraint (dedupe_key in internal/clientnotify is an
-- app-computed analog of the same idea; here the natural key already is
-- just "this order").
CREATE TABLE loyalty_transactions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
client_id UUID NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
type TEXT NOT NULL CHECK (type IN ('accrual', 'redemption', 'adjustment')),
points INT NOT NULL CHECK (points <> 0),
order_id UUID REFERENCES orders(id) ON DELETE SET NULL,
cartridge_batch_id UUID REFERENCES cartridge_batches(id) ON DELETE SET NULL,
note TEXT,
created_by_staff_id UUID NOT NULL,
created_by_staff_name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX loyalty_transactions_client_id_idx ON loyalty_transactions (client_id, created_at DESC);
CREATE UNIQUE INDEX loyalty_transactions_order_accrual_idx
ON loyalty_transactions (order_id) WHERE type = 'accrual' AND order_id IS NOT NULL;
CREATE UNIQUE INDEX loyalty_transactions_batch_accrual_idx
ON loyalty_transactions (cartridge_batch_id) WHERE type = 'accrual' AND cartridge_batch_id IS NOT NULL;
ALTER TABLE settings ADD COLUMN loyalty_enabled BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE settings ADD COLUMN loyalty_accrual_percent NUMERIC(5, 2) NOT NULL DEFAULT 0;