Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 39s
refund.sx — refund as a second flow-on-sx flow (request -> approve -> settle) with two suspension points (approval = human/policy decision, settle = provider). refund-begin! records :refund-requested and suspends at approval; refund-approve! advances to settle; refund-settle! records :refunded (idempotent) and completes; refund-reject! records :refund-rejected and cancels. Only :refunded moves the books. Reuses order.sx flow helpers. Completes the Phase 5 backlog. Total 278/278 across 17 suites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
2.7 KiB
Plaintext
79 lines
2.7 KiB
Plaintext
;; lib/commerce/tests/refund.sx — refund lifecycle as a flow-on-sx flow.
|
|
;; Uses (commerce-test name got expected) provided by conformance.sh.
|
|
;; Builds the (expensive) flow env once; all assertions share it.
|
|
|
|
(define env (refund-make-env))
|
|
(define b (persist/mem-backend))
|
|
(define q1 {:codes (list) :subtotal 1000 :discount 0 :total 1200 :tax 200})
|
|
|
|
;; a paid, fulfilled order to refund (set up directly via the ledger)
|
|
(define _c (order-create b "O1" 1 q1))
|
|
(define _p (order-pay b "O1" "pay-1" 2 1200))
|
|
(commerce-test "setup-recon-ok" (order-recon b "O1") :ok)
|
|
|
|
;; --- happy path: request -> approve -> settle ---
|
|
|
|
(define rid (refund-begin! env b "O1" "rf-1" 10 500))
|
|
|
|
(commerce-test "begin-waiting-approve" (order-flow-waiting env rid) "approve")
|
|
(commerce-test
|
|
"begin-not-yet-refunded"
|
|
(order-refunded-amount-of (order-events b "O1"))
|
|
0)
|
|
(commerce-test "begin-recon-unchanged" (order-recon b "O1") :ok)
|
|
|
|
(define a1 (refund-approve! env rid))
|
|
(commerce-test "approve-result" a1 :approved)
|
|
(commerce-test "approve-waiting-settle" (order-flow-waiting env rid) "settle")
|
|
|
|
(define s1 (refund-settle! env b rid "O1" "rf-1" 11 500))
|
|
(commerce-test "settle-result" s1 :settled)
|
|
(commerce-test "settle-flow-done" (order-flow-status env rid) "done")
|
|
(commerce-test
|
|
"settle-refunded-amount"
|
|
(order-refunded-amount-of (order-events b "O1"))
|
|
500)
|
|
;; net 1200 - 500 = 700 < total 1200 -> underpaid (partial refund)
|
|
(commerce-test "settle-recon-underpaid" (order-recon b "O1") :underpaid)
|
|
|
|
;; --- idempotent settle: replayed provider callback is a no-op ---
|
|
|
|
(define s1b (refund-settle! env b rid "O1" "rf-1" 11 500))
|
|
(commerce-test "replay-already-settled" s1b :already-settled)
|
|
(commerce-test
|
|
"replay-refunded-once"
|
|
(order-refunded-amount-of (order-events b "O1"))
|
|
500)
|
|
|
|
;; --- reject path: approval denied, books untouched ---
|
|
|
|
(define _c2 (order-create b "O2" 1 q1))
|
|
(define _p2 (order-pay b "O2" "pay-2" 2 1200))
|
|
|
|
(define rid2 (refund-begin! env b "O2" "rf-2" 20 1200))
|
|
(commerce-test
|
|
"reject-waiting-approve"
|
|
(order-flow-waiting env rid2)
|
|
"approve")
|
|
|
|
(define j2 (refund-reject! env b "O2" rid2 21 "policy"))
|
|
(commerce-test "reject-result" j2 :rejected)
|
|
(commerce-test "reject-flow-not-waiting" (order-flow-waiting env rid2) nil)
|
|
(commerce-test
|
|
"reject-no-refund"
|
|
(order-refunded-amount-of (order-events b "O2"))
|
|
0)
|
|
(commerce-test "reject-recon-ok" (order-recon b "O2") :ok)
|
|
|
|
;; settling a rejected/cancelled refund does nothing
|
|
(define s2 (refund-settle! env b rid2 "O2" "rf-2" 22 1200))
|
|
(commerce-test "reject-then-settle-noop" s2 :already-settled)
|
|
(commerce-test
|
|
"reject-still-no-refund"
|
|
(order-refunded-amount-of (order-events b "O2"))
|
|
0)
|
|
|
|
;; --- distinct flow ids ---
|
|
|
|
(commerce-test "distinct-refund-ids" (not (= rid rid2)) true)
|