forked from wangziqi/gongxue-base
feat: add commerce reconciliation ledger
This commit is contained in:
100
supabase/migrations/202606290022_commerce_reconciliation.sql
Normal file
100
supabase/migrations/202606290022_commerce_reconciliation.sql
Normal file
@@ -0,0 +1,100 @@
|
||||
create table if not exists public.commerce_reconciliation_batches (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
tenant_id uuid not null references public.tenants(id) on delete cascade,
|
||||
provider text not null,
|
||||
bill_date date not null,
|
||||
bill_type text not null default 'combined'
|
||||
check (bill_type in ('payment', 'refund', 'combined')),
|
||||
source text not null default 'manual_upload'
|
||||
check (source in ('manual_upload', 'provider_download', 'api', 'worker')),
|
||||
source_name text,
|
||||
source_hash text not null,
|
||||
status text not null default 'completed'
|
||||
check (status in ('preview', 'pending', 'processing', 'completed', 'completed_with_issues', 'failed')),
|
||||
total_count integer not null default 0 check (total_count >= 0),
|
||||
matched_count integer not null default 0 check (matched_count >= 0),
|
||||
mismatch_count integer not null default 0 check (mismatch_count >= 0),
|
||||
missing_local_count integer not null default 0 check (missing_local_count >= 0),
|
||||
missing_provider_count integer not null default 0 check (missing_provider_count >= 0),
|
||||
duplicate_count integer not null default 0 check (duplicate_count >= 0),
|
||||
ignored_count integer not null default 0 check (ignored_count >= 0),
|
||||
amount_cents integer not null default 0 check (amount_cents >= 0),
|
||||
refund_amount_cents integer not null default 0 check (refund_amount_cents >= 0),
|
||||
fee_cents integer not null default 0,
|
||||
created_by uuid references public.platform_users(id) on delete set null,
|
||||
completed_at timestamptz,
|
||||
error text,
|
||||
metadata jsonb not null default '{}'::jsonb,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
create table if not exists public.commerce_reconciliation_items (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
tenant_id uuid not null references public.tenants(id) on delete cascade,
|
||||
batch_id uuid not null references public.commerce_reconciliation_batches(id) on delete cascade,
|
||||
row_no integer not null check (row_no > 0),
|
||||
provider text not null,
|
||||
transaction_type text not null
|
||||
check (transaction_type in ('payment', 'refund')),
|
||||
provider_trade_no text,
|
||||
provider_refund_no text,
|
||||
order_no text,
|
||||
refund_no text,
|
||||
amount_cents integer not null default 0 check (amount_cents >= 0),
|
||||
refund_amount_cents integer not null default 0 check (refund_amount_cents >= 0),
|
||||
fee_cents integer not null default 0,
|
||||
paid_at timestamptz,
|
||||
refunded_at timestamptz,
|
||||
provider_status text,
|
||||
local_status text,
|
||||
order_id uuid references public.orders(id) on delete set null,
|
||||
payment_id uuid references public.payments(id) on delete set null,
|
||||
refund_request_id uuid references public.commerce_refund_requests(id) on delete set null,
|
||||
match_status text not null
|
||||
check (match_status in ('matched', 'amount_mismatch', 'status_mismatch', 'missing_local', 'missing_provider', 'duplicate', 'ignored')),
|
||||
severity text not null default 'info'
|
||||
check (severity in ('info', 'warning', 'error', 'critical')),
|
||||
issue_code text,
|
||||
details jsonb not null default '{}'::jsonb,
|
||||
created_at timestamptz not null default now(),
|
||||
unique (batch_id, row_no)
|
||||
);
|
||||
|
||||
create index if not exists idx_commerce_recon_batches_tenant_date
|
||||
on public.commerce_reconciliation_batches(tenant_id, provider, bill_date desc, created_at desc);
|
||||
|
||||
create index if not exists idx_commerce_recon_batches_status
|
||||
on public.commerce_reconciliation_batches(tenant_id, status, created_at desc);
|
||||
|
||||
create index if not exists idx_commerce_recon_items_batch_status
|
||||
on public.commerce_reconciliation_items(tenant_id, batch_id, match_status, row_no);
|
||||
|
||||
create index if not exists idx_commerce_recon_items_order
|
||||
on public.commerce_reconciliation_items(tenant_id, order_no, created_at desc);
|
||||
|
||||
create index if not exists idx_commerce_recon_items_refund
|
||||
on public.commerce_reconciliation_items(tenant_id, refund_no, provider_refund_no, created_at desc);
|
||||
|
||||
create index if not exists idx_commerce_recon_items_trade
|
||||
on public.commerce_reconciliation_items(tenant_id, provider, provider_trade_no, created_at desc);
|
||||
|
||||
alter table public.commerce_reconciliation_batches enable row level security;
|
||||
alter table public.commerce_reconciliation_items enable row level security;
|
||||
|
||||
drop policy if exists tenant_isolation on public.commerce_reconciliation_batches;
|
||||
create policy tenant_isolation on public.commerce_reconciliation_batches
|
||||
for all
|
||||
using (tenant_id = app.current_tenant_id() or app.is_platform_admin())
|
||||
with check (tenant_id = app.current_tenant_id() or app.is_platform_admin());
|
||||
|
||||
drop policy if exists tenant_isolation on public.commerce_reconciliation_items;
|
||||
create policy tenant_isolation on public.commerce_reconciliation_items
|
||||
for all
|
||||
using (tenant_id = app.current_tenant_id() or app.is_platform_admin())
|
||||
with check (tenant_id = app.current_tenant_id() or app.is_platform_admin());
|
||||
|
||||
drop trigger if exists set_updated_at on public.commerce_reconciliation_batches;
|
||||
create trigger set_updated_at
|
||||
before update on public.commerce_reconciliation_batches
|
||||
for each row execute function app.touch_updated_at();
|
||||
Reference in New Issue
Block a user