v1.15.0: admin picking ops
"Admin picking ops" release. Admins gain two outbound tools: a virtual-pick path that marks an OPEN sales order picked from the admin UI when the digital pick never landed, and a printable Picking Tickets queue with per-SO and Print All packing-slip views. The packing slip's branding is Settings-driven with neutral defaults, so a fresh install prints a clean, unbranded slip. Migration 064 adds printed_at so the queue can hide already-printed orders without dropping them.
Mobile. Zero mobile/ diffs on this release. The v1.14.0 mobile build (versionCode 8) remains current; no new APK for v1.15.0.
Added
- Admin virtual pick (#369):
POST /admin/sales-orders/<id>/admin-pickapplies a batched, all-or-nothing pick from the SO edit view -- per-line{bin, quantity}entries (split-bin allowed) bump the line counters, decrement inventory at the chosen bin, write anACTION_PICKaudit row withdetails.source='admin_virtual', and emitpick.confirmedwhen the SO flips to PICKED. The end state is indistinguishable from a handheld pick, and the syntheticpick_tasksfeed the existing Release Picked Quantities flow for undo. AGET .../lines/<line>/available-binsendpoint powers the per-line bin dropdown. Gated to ADMIN or the so-full-edit override. - Picking Tickets queue + print views (#370): Outbound > Picking Tickets lists OPEN sales orders with a status switcher, a Hide-Printed toggle, and a sortable Bin column in warehouse-walk order (lowest-
pick_sequencepreferred bin). A per-SO packing slip renders with a Code 128 barcode, and a standalone Print All tab renders the on-screen queue page-broken for printing, capped at 200 tickets per tab. Gated by a newpicking-ticketspage permission. - printed_at tracking (#370, migration 064):
POST /admin/sales-orders/mark-printedstampsprinted_atonce the client confirms a render, never as a side effect of the GET, so the queue hides already-printed orders without dropping them; the print pages mark-printed with one retry and surface persistent failures via a toast. - Configurable packing-slip branding (#370): the picking-ticket response carries a
brandingobject read fromapp_settings(picking_ticket_company_name/_company_address/_logo_url/_returns_text), all defaulting to empty so a fresh install prints an unbranded slip; the slip renders the logo, company block, and returns text only when set, and Settings > Picking Ticket configures them.
Migrations
- 064 (#370) --
sales_orders.printed_at TIMESTAMPTZplus a partial index(status, ship_by_date) WHERE printed_at IS NULLfor the unprinted-queue predicate.
See CHANGELOG.md for the full notes.