93 lines
3.2 KiB
Markdown
93 lines
3.2 KiB
Markdown
|
|
# Phase 7 Backend Contract — Refunds + Reconciliation
|
|||
|
|
|
|||
|
|
Companion to [PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md](../PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md) Phase 7 (Sprints 7.1–7.3). Extends [Phase 1](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) §6 (payment state machine).
|
|||
|
|
|
|||
|
|
**Status: ready to build.** `requestRefund(id)` exists today only as a mock gateway method; `reconcil*` and `settlement*` return zero hits anywhere in the codebase.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Refunds
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
interface Refund {
|
|||
|
|
id: string;
|
|||
|
|
orderId: string;
|
|||
|
|
orderLineIds: string[]; // which lines this refund covers - partial refunds must specify
|
|||
|
|
amount: Money;
|
|||
|
|
reason: string;
|
|||
|
|
actor: string; // user id who initiated it, never anonymous
|
|||
|
|
status: 'requested' | 'approved' | 'processing' | 'completed' | 'failed';
|
|||
|
|
requestedAt: string;
|
|||
|
|
completedAt?: string;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /api/admin/v2/orders/{orderId}/refunds { orderLineIds, amount, reason }
|
|||
|
|
GET /api/admin/v2/orders/{orderId}/refunds
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
A `Refund` updates `Payment.status` to `refunded` or `partially_refunded` (Phase 1 §6.1) and emits `refund.requested`/`refund.completed` on the Phase 2 event bus.
|
|||
|
|
|
|||
|
|
## 2. Reconciliation
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
interface ReconciliationRecord {
|
|||
|
|
id: string;
|
|||
|
|
orderId: string;
|
|||
|
|
providerPaymentId?: string;
|
|||
|
|
internalAmount: Money;
|
|||
|
|
providerAmount?: Money;
|
|||
|
|
matchStrategy: 'provider_payment_id' | 'merchant_reference' | 'amount_currency_fallback';
|
|||
|
|
result: 'matched' | 'unmatched' | 'duplicate' | 'amount_mismatch' | 'status_mismatch';
|
|||
|
|
resolvedBy?: string;
|
|||
|
|
resolvedAt?: string;
|
|||
|
|
resolutionNote?: string;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Process (per plan §7.3):
|
|||
|
|
```
|
|||
|
|
1. Collect internal paid orders for a period.
|
|||
|
|
2. Fetch provider transactions/events for the same period.
|
|||
|
|
3. Match by providerPaymentId, falling back to merchant reference, falling back to amount+currency.
|
|||
|
|
4. Classify: matched / unmatched / duplicate / amount_mismatch / status_mismatch.
|
|||
|
|
5. Surface the non-matched set in backoffice with controlled, audited resolution.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /api/admin/v2/reconciliation/queue?marketplaceId=&result=
|
|||
|
|
POST /api/admin/v2/reconciliation/{id}/resolve { note }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. Settlements
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
interface Settlement {
|
|||
|
|
id: string;
|
|||
|
|
sellerId: string;
|
|||
|
|
periodStart: string;
|
|||
|
|
periodEnd: string;
|
|||
|
|
grossAmount: Money;
|
|||
|
|
commission: Money;
|
|||
|
|
refunds: Money;
|
|||
|
|
netPayout: Money;
|
|||
|
|
status: 'pending' | 'paid';
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /api/seller/v1/finance/settlements
|
|||
|
|
GET /api/admin/v2/finance/settlements?sellerId=&period=
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. Provider breadth (open business question)
|
|||
|
|
|
|||
|
|
Current flow supports QR and card only, via one custom provider integration. Adding wallets/BNPL is an explicit open business decision (not answered in Sprint 0.1) — this contract's `PaymentIntent`/`Payment` shapes from Phase 1 §6 are provider-agnostic already, so a new provider is a new adapter behind the same state machine, not a schema change. No action needed here until that business decision is made.
|
|||
|
|
|
|||
|
|
## 5. What the frontend will start doing once this ships
|
|||
|
|
|
|||
|
|
- Wire the mock `requestRefund(id)` to a real endpoint.
|
|||
|
|
- Build the backoffice **Payments & Finance** section (missing from admin nav today): payments, refunds, reconciliation queue, unmatched events, settlements.
|
|||
|
|
- Reconciliation-queue resolution UI with full audit trail.
|