Storefront Picking / Delivery Sheet
Storefront Picking is the workflow for invoices whose goods are prepared and handed out at a branch/storefront. It is different from route delivery and different from cashier POS. The work unit shown to the user is now a sales order (orderNo), while API acceptance, Lot/Batch persistence, delivery creation, and B1 stock movement still run one invoice at a time.
App Entry Points
| App | Target |
|---|---|
| Mobile | StorefrontListScreen -> StorefrontDetailScreen |
| POS Terminal | shippingStorefront -> StorefrontDetailForm in HomeScreen |
What This Menu Shows
The list is built from invoices with shippingType = 2. Rows with invoiceStatus = CANCELED are removed completely before grouping. The remaining rows are deduplicated and grouped by orderNo; an invoice-specific fallback key is used only when an order number is missing.
Each card displays the customer, sales order number, every included invoice number on its own row, sales employee, and warehouse employee. The NEW tab is evaluated from the grouped card: a group remains NEW until every included invoice is CONFIRMED.
Group card background colors
Color conditions are evaluated after canceled invoices have been removed and in this order:
| Group condition | Background |
|---|---|
Every invoice is CONFIRMED | Green #76ffa3 |
Any invoice is NEW and has hasDelivery != null | Purple #d382ff |
Any invoice has a pending cancel request (canceledNote != null and rejectCanceledAt == null) | Light purple #e7bce7 |
| All other mixed/unconfirmed groups | Yellow-green #cffd67 |
Opening a card passes all grouped invoice IDs plus orderNo into the detail flow. Detail data for every ID is loaded with includeLot=true and combined into one screen. Product rows retain sourceInvoiceId, sourceInvoiceNo, sourceInvoiceStatus, and the source acceptance owner so that validation and API work remain invoice-specific.
Main Workflow
Accept Job Rules
| Condition | Behavior |
|---|---|
| Main branch | Users in accept departments are prompted to accept the job when acceptedBy is empty. |
| Non-main branch | Accept flow is enabled, but Lot/Batch editing uses the same permission as the main branch and does not depend on isMain. |
| Every invoice already accepted | The prompt is skipped. |
| Mixed acceptance state | One modal is shown; confirmation calls the accept API sequentially only for invoices whose acceptedBy is empty. Already accepted invoices are not sent again. |
| Accepted by current user | That user can continue editing and saving. |
| Override user | User code 999997 is treated as an accepted/action user. |
Accept permission is controlled by departments 8, 12, 22, 28.
Item Checking And Lot/Batch Rules
Important item rules:
| Rule | Behavior |
|---|---|
| Editable status | Product checks are editable only when their source invoice is NEW. Rows from a CONFIRMED invoice remain visible but cannot open the Lot/Batch editor. |
| Invoice prefilled lots | A non-empty, valid items[].lots[] response from GET /invoices/{id}?includeLot=true is displayed as the initial value. Users can edit quantity, delete it, or select a replacement lot while the invoice is NEW and they have edit permission. |
| Lot selection | Tapping an item with existing lots opens the editor with the current rows so they can be edited/deleted and replaced. Items without lots load current stock; if exactly one available lot covers the pending quantity, the app auto-fills it. |
isMain | It does not lock or restrict Lot/Batch selection. Lot editing uses the same rule for main and non-main branches. |
| Available stock | Lot options and their validation use available (after booking), not the raw lot quantity; lots with no available balance are excluded. |
| Empty lot options | The editor shows a red no-data message and a reload action; it shows a loading indicator while that request is running. |
| Required product context | itemCode, whsCode, and company are required before lot options can be loaded. |
| Duplicate lot | The same Lot/Batch cannot be selected twice for one item. |
| Lot balance | Entered quantity cannot exceed the selected lot balance. |
| Invoice line quantity | Entered quantity cannot exceed the pending quantity of that invoice line. |
| Completion | Every line must have checked quantity greater than or equal to invoice quantity before save. |
Save To Delivery / B1 Rules
The submit button is shown when at least one grouped invoice is not CONFIRMED/CANCELED and the current user has action permission for that invoice. A CONFIRMED source invoice is display-only and is excluded from submit processing.
Before saving, the app blocks:
| Guard | Error Case |
|---|---|
| Permission | User cannot save storefront data. |
| SAP reference | refKey is missing, which means the invoice has not reached SAP/B1 context. |
| Cancellation request | canceledAt exists and rejectCanceledAt is still empty. |
| Incomplete checks | Not all items have been checked to the required quantity. |
Validation is performed per pending invoice against only its own product rows. When every pending invoice passes, Mobile and POS Terminal iterate through those invoices sequentially:
- Skip invoices already in
CONFIRMEDstate. - Add the current invoice to delivery
0when itsdeliveryIdis missing. - Build
invoices[].items[].lots[]from only that invoice's selected product rows. - Save delivery lots for the current invoice.
- Create delivery/send stock movement for the current invoice.
- Continue with the next invoice, then reload grouped detail and list state.
Grouped Detail Metadata
| Field | Display |
|---|---|
| Customer | Shared customer name from the grouped order |
| Sales order | orderNo |
| Picking invoice | Every invoiceNo, joined with , in detail metadata |
| Products | Product rows from every grouped invoice |
| Confirmed products | Visible as completed/read-only rows; Lot/Batch selection is disabled |
Cancel Rules
Cancellation is a request with a required reason. It does not hard-delete invoice history. In grouped detail, cancellation validation is checked across the group and the request is sent sequentially to non-confirmed invoices only. Printing an invoice from grouped detail prints every included invoice sequentially.
Permissions And Guards
| Topic | Behavior |
|---|---|
| Terminal menu key | shippingStorefront |
| Menu deptCode set | -2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 12, 20, 22, 23, 27, 28 |
| Accept departments | 8, 12, 22, 28 |
| Save/action departments | 2, 8, 22, or the user who accepted the job, or override user 999997 |
| Editable invoice status | Source invoice NEW only |
| Hidden submit states | CONFIRMED, CANCELED, or no action permission |
Mobile vs POS Terminal
| Topic | Mobile | POS Terminal |
|---|---|---|
| Navigation | Full-screen storefront stack | HomeScreen split-pane detail |
| Accept flow | Prompted in detail screen | Prompted in detail form |
| Lot selection | Bottom sheets and modals | Split-pane modals and pickers |
| Save behavior | Delivery lots + create delivery | Same service behavior |
| Cancel | Reason modal | Reason modal |
Developer Handoff Map
| Area | Code |
|---|---|
| Mobile list/detail | apps/mobile/src/screens/storefrontStack/storefrontListScreen, storefrontDetailScreen |
| Mobile storefront helpers | apps/mobile/src/screens/storefrontStack/storefrontDetailScreen/helpers.ts |
| Terminal split data | apps/pos-terminal/src/services/splitMenuData.ts -> shippingStorefront |
| Terminal detail | apps/pos-terminal/src/screens/HomeScreen/StorefrontDetailForm.tsx |
| Terminal rules | apps/pos-terminal/src/screens/HomeScreen/StorefrontDetailHelpers.ts |
| Storefront service | apps/*/src/services/storefront.ts |
| Delivery/lot service | apps/*/src/services/shipping.ts |