iVendNextDevelopers Request a sandbox

S16 — Assign pick route (pp_pck): a Desk action

Assign pick route, end to end in Desk

A stock user presses Warehouse → Assign pick route on a Sales Order, picks a colleague and a priority, and the partner's service opens a pick task listed under the order.

A button in iVendNext Desk that hands a record to your own service, which does real work and answers. This sample is for a developer who wants a press in Desk to create something in their system: here, a pick task for a Sales Order.

When to use it: you want a button on a Desk record that sends the record to your service and shows the answer.

What happens

  1. A stock user opens a submitted Sales Order and presses Assign pick route (menu Warehouse).
  2. The shop's own dialog asks for a picker and a priority. The user fills them in and confirms.
  3. The shop sends the order's lines to your service, signed.
  4. Your service creates a pick task (PP PCK Pick Task, this app's own record type) over the record API, with its own key, then answers.
  5. The task opens. It is also listed under the order (Connections, Picking).

The Sales Order itself does not change. From the order list, the same button runs on several orders at once (one task each, one message).

What it looks like

The names in the pictures are a demo shop's: a stock user, a customer's order, and a colleague picked as the picker.

Step Screenshot
1. A submitted Sales Order: the Warehouse menu holds Assign pick route
2. The shop's own dialog: Picker and Priority, filled in
3. The partner's answer: Route assigned — 2 lines across 2 warehouses
4. The pick task the service made, opened: the order, the picker, the priority, the lines in walking order
5. The order's Connections: the task is listed under Picking

The files

File What
manifest.json the pick task and its lines, the Connections link, the service (extension_subscriptions, extension point desk_action) and the button (desk_actions), installed switched off
route.py the pure core: the signature check, the press's shape, the task for one order (lines in walking order; quantities arrive in thousandths), the answer
service/app.py the HTTP service (standard library): POST /press/route, GET /health; the record API as the integration user
tests/test_service.py laptop tests: the real service, a stand-in record API, presses signed as the shop signs them
tests/test_contract.py every answer, and every press our test shop recorded, against the published contract (desk_action.v1.schema.json)

The recipe is recipes/desk_action.md.

How to run it

Start the service on your server, under your own process manager: python3 service/app.py service/.env.local. Install the manifest in the shop. It installs switched off: the shop's System Manager reads what is sent, ticks the consent, and switches the service and then the button on (the recipe has the steps).

Before you copy it

Technical notes

What was walked, and where

The GIF: frame: Desk, a 1440-wide window. Walked on our test bench on 2026-10-07, iVendNext POS app at 8dc36aab8. Built from the same screens as the stills, uncropped.

The stills: walked in a real browser on our test bench, 2026-10-07, iVendNext POS app at 8dc36aab8. Frame: Desk, a 1440-wide window. The names are the bench's demo shop: a stock user (Nomsa Zulu), a customer's order, and a colleague picked as the picker (Sipho Dlamini's login, sipho.assoc@…).

On our test bench the real button was pressed through ivendnext_mpos.api.desk_action.run, as a Stock User, on every case in the recipe. tests/test_contract.py checks every press the bench recorded.

Why it is built this way

Option Cost Verdict
Do nothing (a partner reads the spec) 0 the reference apps (quick-commerce hub, 3PL) have nothing to copy
One file that answers without writing (a message only) ~40 lines shows no real work: the point of a Desk action is that the partner's service does something
A pure core + a standard-library service that writes one record over the API ~250 lines picked: the smallest thing that shows the whole loop, signature to record, in code any Python developer reads unaided

Idempotency without a database. The press's idempotency_key is stored on the task (press_key). A retry from the same dialog finds the task it already made and answers about that task (its picker, even if the user changed the dialog), even after a restart. One process serialises presses with a lock, so a retry racing its first try cannot make two.

Bounds, stated

This page in the kit