feat(aftersale): per-line refund/return flow with ledger-backed completion (add-aftersale-refunds)
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
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);
|
||||
Reference in New Issue
Block a user