v1.22.0: POS completions and dockd reads
"POS completions and dockd reads" release. Two threads.
The POS sale path is rounded out -- shipping charges and ship method persist on the order, split (part cash + part card) tender is accepted, and a full refund now cancels the original sale instead of leaving it SHIPPED. And the dockd warehouse-floor integration gains a barcode item-lookup endpoint plus the ordered quantity on its order payload.
Mobile. Zero mobile/ diffs on this release. The current mobile build (version 1.19.0, versionCode 9) remains current; no new APK for v1.22.0.
Added
- POS shipping charge, ship method, and totals (#399): the payment summary gains
shipping_cents(default 0, preserving the counter-sale contract) and checkout gains an optionalship_method. On a phone order the shipping charge persists tosales_orders.customer_shipping_paid, the operator-selected method toship_method, and the order total toorder_total, so the picking ticket and downstream consumers see real freight figures. A full refund credits the shipping back with the order: the credit-memo SO stores negativeorder_totalandcustomer_shipping_paidto mirror its negative credit lines. - POS split tender (#400):
splitis accepted as aPaymentSummary.methodfor a part-cash + part-card sale; the tenders list carries the per-method breakdown and the refund path matches it symmetrically (split sale -> split refund). Additive under the DRAFT-v1 POS contract. - dockd item lookup + ordered quantity (#401):
GET /api/v1/dockd/items/<barcode>resolves an item by barcode (UPC) and returns its canonical detail plus per-location stock, scoped to the token's warehouses; gated as a dockd inbound resource like the other dockd reads. The dockd GET order payload also returnsqty_orderedalongside the fulfilledqtyon each line. The OpenAPI spec anddocs/api/dockd-openapi.yamlare regenerated to match (parity test enforced).
Fixed
- POS refund cancels the original SO (#402): a v1 refund is full-order only, so a refunded sale is now a cancelled sale -- the original SO moves to
status=CANCELLED(keeping therefunded_at+refund_so_idlink) so admin and picker views stop showing it as SHIPPED. The "must be SHIPPED" state gate moves below the already-refunded check, so a repeat refund attempt surfaces422 already_refundedinstead of 404-ing on the now-CANCELLED status.