;; lib/commerce/tests/recon.sx — reconciliation as relational ledger queries. ;; Uses (commerce-test name got expected) provided by conformance.sh. (define q1 {:codes (list) :subtotal 1000 :discount 0 :total 1200 :tax 200}) (define b (persist/mem-backend)) ;; OK1 — clean payment (define _ok (order-create b "OK1" 1 q1)) (define _okp (order-pay b "OK1" "ok-ref" 2 1200)) ;; OVER1 — double charge under two different refs (define _ov (order-create b "OVER1" 1 q1)) (define _ova (order-pay b "OVER1" "ov-a" 2 1200)) (define _ovb (order-pay b "OVER1" "ov-b" 3 1200)) ;; UNDER1 — short payment (define _un (order-create b "UNDER1" 1 q1)) (define _unp (order-pay b "UNDER1" "un-ref" 2 900)) ;; PART1 — paid in full, then partially refunded (define _pa (order-create b "PART1" 1 q1)) (define _pap (order-pay b "PART1" "pa-ref" 2 1200)) (define _par (order-refund b "PART1" "pa-rf" 3 200)) ;; REPLAY1 — webhook fires twice with the same ref (idempotent) (define _rp (order-create b "REPLAY1" 1 q1)) (define _rpa (order-pay b "REPLAY1" "rp-ref" 2 1200)) (define _rpb (order-pay b "REPLAY1" "rp-ref" 2 1200)) ;; PEND1 — created, not yet paid (define _pe (order-create b "PEND1" 1 q1)) ;; --- summaries --- (commerce-test "summary-count" (len (ledger-summaries b)) 6) (commerce-test "summary-ok1" (order-summary b "order/OK1") (list "order/OK1" 1200 1200 0 1200 :ok)) (commerce-test "summary-part1" (order-summary b "order/PART1") (list "order/PART1" 1200 1200 200 1000 :underpaid)) ;; --- forward status query --- (commerce-test "status-forward-ok" (run* st (recon-statuso (ledger-summaries b) "order/OK1" st)) (list :ok)) ;; --- backward status queries (the showcase) --- (commerce-test "settled" (sort (settled-orders b)) (sort (list "order/OK1" "order/REPLAY1"))) (commerce-test "overpaid" (overpaid-orders b) (list "order/OVER1")) (commerce-test "underpaid" (sort (underpaid-orders b)) (sort (list "order/UNDER1" "order/PART1"))) (commerce-test "unpaid" (unpaid-orders b) (list "order/PEND1")) (commerce-test "mismatched" (sort (mismatched-orders b)) (sort (list "order/OVER1" "order/UNDER1" "order/PART1"))) ;; --- backward net-amount query --- (commerce-test "net-1200" (sort (orders-with-net b 1200)) (sort (list "order/OK1" "order/REPLAY1"))) (commerce-test "net-2400" (orders-with-net b 2400) (list "order/OVER1")) (commerce-test "net-900" (orders-with-net b 900) (list "order/UNDER1")) ;; --- discrepancy: +1200 (over) - 300 (under) - 200 (refund) = 700 --- (commerce-test "discrepancy" (ledger-discrepancy b) 700) ;; --- double-charge guard --- (commerce-test "double-charge-detected" (order-recon b "OVER1") :overpaid) (commerce-test "double-charge-amount" (order-paid b "OVER1") 2400) ;; --- partial refund --- (commerce-test "partial-refund-net" (order-recon b "PART1") :underpaid) (commerce-test "partial-refund-amount" (order-refunded-amount-of (order-events b "PART1")) 200) ;; --- webhook replay: same ref twice records once --- (commerce-test "replay-single-event" (len (order-events b "REPLAY1")) 2) (commerce-test "replay-paid-once" (order-paid b "REPLAY1") 1200) (commerce-test "replay-settled" (order-recon b "REPLAY1") :ok)