Order-to-cash medium gaps (audit-M-o2c / audit-M-sales)#204
Conversation
…les) Cluster of order-to-cash medium findings (47fa + chc2, duplicate clusters): 1. Refund tolerance: the cumulative-refunded check used a 0.1% RELATIVE slack (so a large order had pounds of headroom, and partial refunds could creep over). New pure refundWouldExceedOrderTotal() applies a fixed rounding epsilon (0.011) to the cumulative total instead. 2. Deleting the last payment cleared paidAt but never reverted status. deletePayment now detects when the order became not-fully-paid while in an advanced status (SHIPPED/COMPLETED/DELIVERED/PARTIALLY_REFUNDED) and emits a payment_status_mismatch WARNING; the SO detail shows an amber '<status> but not paid' chip. 3. applySalesOrderStatusTransition now rejects status edits on ARCHIVED orders (manual + sessionless-cron callers); the WooCommerce force-sync bypass token keeps its escape-hatch semantics. 4. queueSalesInvoiceForOrder idempotency key — VERIFIED already payload-based (accountingPayloadKey(..., payload)); no change needed. 5. confirmSalesOrderShipments double-shipment — VERIFIED already guarded (it nets committed non-PENDING shipment lines out of the allocation before recreating); no change needed. 6. Documented COMPLETED vs DELIVERED semantics + the archived/payment-mismatch behaviour in docs/workflows.md. Shared pure o2c-guards.ts (refundWouldExceedOrderTotal, isPaymentStatusMismatch, PAID_EXPECTED_SALES_STATUSES) reused by both call sites. Tests: 5 guard cases (refund within/at/over total incl. the relative-vs-fixed contrast; mismatch true/false); 105/105 sales suite; type-check + lint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…p (adversarial review) Codex adversarial pass on PR #204: HIGH — the archived guard blocked the sessionless delivery cron, so an archived-but-SHIPPED order could never auto-reach DELIVERED. The guard now also lets skipPermissionCheck (the cron) through alongside the WC force-sync token; only genuinely-manual edits are rejected. HIGH — payment_status_mismatch fired even when the order was NEVER fully paid (e.g. shipped on credit, a held partial payment deleted) because becameUnpaid only checked 'not fully paid now'. Now requires a genuine paid→unpaid transition (so.paidAt was set before the delete). MEDIUM — the read-time amber chip keyed on !so.paidAt false-positived on credit-term and WC-imported-partial-refund orders and contradicted the existing Part. Paid indicator. Dropped it: a read-time chip can't distinguish 'never paid' from 'was paid then unpaid' without a persisted marker, so the accurate signal is the (now transition-gated) WARNING activity log plus the existing Paid/Part. Paid chips. Docs updated to match. LOW — added a single-shot full-refund test. Verified sound: refund epsilon currency basis (all base); WC bypass intact; refund-payment deletions don't flag; invoice idempotency key + confirmShipments netting confirmed. 7/7 guard tests; type-check + lint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex adversarial review — findings + fixes (commit c0c051f)Codex was at its usage cap; the adversarial pass ran by hand with equal rigour. Verified sound: refund epsilon currency basis (all three operands in base currency); the WC force-sync bypass still transitions archived orders; refund-payment (credit-note) deletions don't flag a mismatch; verified-only claims confirmed — the invoice queue idempotency key genuinely hashes the payload, and Fixed:
Validation7/7 guard tests; type-check + lint clean. |
Wave 4 of the workflow-audit remediation (epic onetwo3d-ims-r3xh). Closes the two duplicate order-to-cash medium clusters (47fa + chc2).
Fixes
refundWouldExceedOrderTotal()applies a fixed rounding epsilon (0.011) to the cumulative total.deletePaymentnow detects when an order became not-fully-paid while in an advanced status (SHIPPED/COMPLETED/DELIVERED/PARTIALLY_REFUNDED) and emits apayment_status_mismatchWARNING; the SO detail shows an amber "<status> but not paid" chip.applySalesOrderStatusTransitionrejects status edits on archived orders (manual + sessionless-cron callers); the WooCommerce force-sync bypass token keeps its escape-hatch semantics.accountingPayloadKey(..., payload)); no change needed.confirmSalesOrderShipmentsalready nets committed (non-PENDING) shipment lines out of the allocation before recreating; no change needed.COMPLETEDvsDELIVEREDsemantics + the archived / payment-mismatch behaviour indocs/workflows.md.Shared pure
o2c-guards.tsreused by both call sites.Tests
5 guard cases (refund within/at/over total incl. the relative-vs-fixed contrast; mismatch true/false); 105/105 sales suite; type-check + lint clean.
Closes onetwo3d-ims-47fa, onetwo3d-ims-chc2.