;; lib/commerce/tests/integration.sx — end-to-end composition proof. ;; Uses (commerce-test name got expected) provided by conformance.sh. ;; ;; One narrative across every module: catalog → stock check → quote ;; (promo+stack+tax) → order flow → payment envelope → settle → recon → refund. ;; Proves the seams tie together with consistent numbers (the project's thesis: ;; minikanren pricing + flow lifecycle + persist ledger compose). ;; Builds one flow env with BOTH the order and refund flows. (define env (order-make-env)) (define _rf (refund-flow-load! env)) (define b (persist/mem-backend)) (define cat (make-catalog (list (list "widget" 1000 :standard) (list "book" 800 :zero-rated)) (list (list "widget" :small -200)) (list (list "widget" :small 10) (list "book" :none 5)))) (define rules (list (list :uk :standard :guest 2000) (list :uk :zero-rated :guest 0))) (define ctx (make-pricing-context cat rules :uk :guest)) (define ruleset (list (list :percent "TEN" :standard 1000) (list :fixed "FIVE" 0 50))) ;; widget :small x2 → unit 800, extended 1600 (standard); book x1 → 800 (zero-rated) (define cart (list (list "widget" :small 2) (list "book" :none 1))) ;; 1. stock gating passes (widget:small 10 >= 2) (commerce-test "int-can-reserve" (can-reserve? cat cart) true) ;; 2. quote ties the whole pricing pipeline together ;; subtotal 2400; discount TEN 160 + FIVE 50 = 210; tax 1600@20% = 320; ;; total 2400 - 210 + 320 = 2510 (define q (cart-quote ctx cart ruleset (list))) (commerce-test "int-quote-subtotal" (quote-subtotal q) 2400) (commerce-test "int-quote-discount" (quote-discount q) 210) (commerce-test "int-quote-tax" (quote-tax q) 320) (commerce-test "int-quote-total" (quote-total q) 2510) ;; 3. attribution explains where the discount landed (commerce-test "int-attribution" (codes-for-line ctx cart ruleset (list "widget" :small 2)) (list "TEN")) (commerce-test "int-order-level" (order-level-codes ctx cart ruleset) (list "FIVE")) ;; 4. order carries the quote total into the ledger; suspends at payment (define oid "INT-1") (define id (order-begin! env b oid 1000 q)) (commerce-test "int-order-total-from-quote" (order-total b oid) 2510) (commerce-test "int-waiting-payment" (order-flow-waiting env id) "payment") ;; 5. the payment envelope reflects the quoted total (commerce-test "int-payment-envelope" (payment-request b oid :GBP "https://shop/return") {:order "INT-1" :amount 2510 :return-url "https://shop/return" :currency :GBP}) ;; 6. settle the quoted amount → reconciles exactly (commerce-test "int-settled" (order-settle! env b id oid "pay-int" 1002 2510) :settled) (commerce-test "int-status-fulfilled" (order-status b oid) :fulfilled) (commerce-test "int-recon-ok" (order-recon b oid) :ok) ;; 7. partial refund via its own flow → recon moves to underpaid (define rid (refund-begin! env b oid "rf-int" 2000 510)) (commerce-test "int-refund-approve" (refund-approve! env rid) :approved) (commerce-test "int-refund-settle" (refund-settle! env b rid oid "rf-int" 2001 510) :settled) (commerce-test "int-refunded-amount" (order-refunded-amount-of (order-events b oid)) 510) (commerce-test "int-recon-after-refund" (order-recon b oid) :underpaid) ;; 8. ledger reconciliation flags the now-mismatched order (commerce-test "int-mismatch" (mismatched-orders b) (list (order-stream "INT-1"))) ;; 9. distinct flow ids for the order and the refund (commerce-test "int-distinct-flow-ids" (not (= id rid)) true)