Files
vmall/apps/api/migrations/0016_aftersales.sql
T

56 lines
2.1 KiB
SQL

CREATE TYPE aftersale_kind AS ENUM ('refund_only', 'return_refund');
CREATE TYPE aftersale_status AS ENUM (
'pending',
'approved',
'rejected',
'buyer_shipping',
'merchant_confirmed',
'refunded',
'cancelled'
);
-- Authoritative per-order refund total; every increment is a guarded UPDATE.
ALTER TABLE orders
ADD COLUMN refund_total_minor BIGINT NOT NULL DEFAULT 0
CHECK (refund_total_minor >= 0);
CREATE TABLE aftersales (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_id UUID NOT NULL REFERENCES orders (id),
order_item_id UUID NOT NULL REFERENCES order_items (id),
shop_id UUID NOT NULL REFERENCES shops (id),
user_id UUID NOT NULL REFERENCES users (id),
kind aftersale_kind NOT NULL,
status aftersale_status NOT NULL DEFAULT 'pending',
reason JSONB NOT NULL,
amount_minor BIGINT NOT NULL CHECK (amount_minor > 0),
evidence JSONB NOT NULL DEFAULT '[]',
reopened BOOLEAN NOT NULL DEFAULT false,
return_carrier TEXT,
return_tracking_no TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- At most one active (non-terminal) aftersale per order item.
CREATE UNIQUE INDEX aftersales_one_active_per_item
ON aftersales (order_item_id)
WHERE status NOT IN ('refunded', 'rejected', 'cancelled');
CREATE INDEX idx_aftersales_user ON aftersales (user_id);
CREATE INDEX idx_aftersales_shop ON aftersales (shop_id);
CREATE INDEX idx_aftersales_order ON aftersales (order_id);
-- Append-only bilateral message log; no UPDATE/DELETE paths exist.
CREATE TABLE aftersale_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
aftersale_id UUID NOT NULL REFERENCES aftersales (id) ON DELETE CASCADE,
author_role TEXT NOT NULL CHECK (author_role IN ('buyer', 'merchant', 'platform')),
author_id UUID NOT NULL REFERENCES users (id),
content JSONB NOT NULL,
evidence JSONB NOT NULL DEFAULT '[]',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_aftersale_messages_aftersale ON aftersale_messages (aftersale_id);