Files
NianAIGC/backend/internal/migrations/sql/0008_wechat_refunds.sql
T
2026-10-12 13:57:23 +08:00

35 lines
2.3 KiB
SQL

-- Reserve each requested refund against its original, successful payment.
-- A successful external refund can exceed the current wallet balance.
alter table public.billing_wallets drop constraint if exists billing_wallets_balance_fen_check;
alter table public.billing_ledger drop constraint if exists billing_ledger_balance_after_fen_check;
alter table public.billing_ledger drop constraint if exists billing_ledger_kind_check;
alter table public.billing_ledger add constraint billing_ledger_kind_check
check (kind in ('recharge', 'charge', 'refund', 'adjustment', 'recharge_refund'));
create table public.payment_refunds (
id text primary key check (length(id) between 1 and 32 and id ~ '^[A-Za-z0-9_-]+$'),
order_id text not null references public.payment_orders(id) on delete restrict,
organization_id text not null references public.platform_organizations(id) on delete restrict,
operator_id text not null references public.platform_users(id) on delete restrict,
request_key text not null check (length(request_key) between 1 and 64 and request_key ~ '^[A-Za-z0-9_-]+$'),
mch_id text not null check (length(mch_id) between 1 and 64),
transaction_id text not null check (length(transaction_id) > 0),
provider_id text,
amount_fen bigint not null check (amount_fen > 0),
total_fen bigint not null check (total_fen > 0 and total_fen >= amount_fen),
currency text not null check (currency = 'CNY'),
reason text not null,
status text not null default 'pending' check (status in ('pending', 'processing', 'success', 'closed', 'abnormal', 'rejected')),
failure_reason text not null default '',
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
succeeded_at timestamptz,
constraint payment_refunds_request_unique unique (order_id, request_key),
constraint payment_refunds_success_check check ((status = 'success') = (succeeded_at is not null))
);
create unique index payment_refunds_provider_unique on public.payment_refunds(mch_id, provider_id)
where provider_id is not null;
create index payment_refunds_order_idx on public.payment_refunds(order_id, created_at desc, id desc);
create index payment_refunds_pending_idx on public.payment_refunds(updated_at, created_at, id)
where status in ('pending', 'processing', 'abnormal');