2.0 KiB
2.0 KiB
F-189 — Implementer evidence
Delivered
- Migration
056_pos_return_lines.js:- Adds
orders_items.returned_quantity integer NOT NULL DEFAULT 0with CHECK. - Extends
inventory_movements.operationCHECK to allow'return'. - Creates
pos_returnsledger with UNIQUE(order_id, idempotency_key)for replay.
- Adds
- New
ApplyPosReturnUseCase:- Locks order and stock rows.
- Validates per-line return bounds; rejects over-return with
POS_RETURN_EXCEEDS_AVAILABLE. - Requires full return for free items with
POS_RETURN_FREE_ITEM_PARTIAL. - Restores inventory, decrements cash session expected cash proportionally.
- Emits
reporting_payment_linesrow withstatus='refund'/'partial_refund'. - Inserts
orders_order_history,pos_returns, audit events. - Idempotent via
pos_returns.idempotency_key.
- New
buildPosReturnReceiptreturning anR-<original>numbered receipt with negative totals andoriginalReceiptNumber. - New
POST /pos/sales/:id/returnsendpoint (POS roles +x-terminal-idbinding). - New
GET /pos/sales/:id/itemsendpoint returning order items withreturnedQuantity. - Removed legacy
POST /pos/sales/:id/refund. - POS cashier UI: new
ReturnModalexposed via aDevolver artículosbutton on the receipt modal; shows per-line steppers, reason and refund total; on success replaces the active receipt with the return receipt. - Type updates so both POS, admin and backend see
originalReceiptNumber/isReturnflags.
Validation
- Backend, POS, admin typecheck: PASS.
- Real PostgreSQL sequential suite: 365/365 PASS (5 new in
pos-returns.itest.ts). - Migration cycle (
fresh up / second no-op / full down / re-up): 4/4 PASS. - Targeted ESLint + Prettier on every changed file: PASS.
./scripts/verify.sh: PASS.
Baselines
- Backend global lint remains unchanged; no new errors.
- Boundary check stays at one pre-existing security import violation; F-189 introduces none.
- Untracked upload JPGs excluded from the feature commit.