WFDASH-WEBAPP/docs/handover-driver-invoice-photos.md
Dave 16743f87ed docs: driver invoice photo handover - widen the filter, use confirm_collected
Tested the handover against live PB on 2026-10-27. The read path works as
written; four defects fixed:

- The filter only caught item_status = 'assigned'. The collection_pool
  tab group is [collection_pool, assigned, ready_delivery] and
  order_items.confirm_collected accepts collection_pool or assigned, so
  a line stuck in either was invisible to the sweep.
- Stock POs were not covered at all. Stock lines live in
  stock_purchase_items and their photos on the parent
  stock_purchases.additional_attachments.
- The write path hand-rolled order_items.update + update_status, which
  skips the eligibility check, the over-collect guard, drv_collected_at
  and the actor-stamped audit note. Now uses
  order_items.confirm_collected / stock_purchase_items.mark_collected.
- No de-duplication: the NSS M24 line is still 'assigned' with a photo,
  so every run would re-report it. Added a 'Waiting on a person' list.

Also noted that no cron runs this yet, that order_items_attachements is
multi-file (read every filename), and added a supplier check.
2026-10-27 07:07:40 +02:00

130 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Handover: driver invoice photos that were never collected
Run every 30 minutes during the working day (06:00–17:00 SAST).
> **Not scheduled yet.** No cron task runs this — the 5 live crons are the
> MCODe basket, three PocketBase backups and the n8n watchdog. Until one is
> created, someone has to run this by hand.
## The problem
Drivers photograph the supplier invoice on a PO in the driver app, but
sometimes never tap **Collect**. The line then stays waiting, so it
never reaches **Collection Confirm** and never gets invoiced. A new app
version (auto invoice match + "Collect these items?" prompt) should stop
this, but until it is proven, check by hand.
Sometimes the photo is also on the **wrong PO** (e.g. the Metabo invoice
was uploaded on the Mega Lube PO), or is not an invoice at all.
Two sides to check — they are different collections with different
attachment fields:
| Side | Line lives in | Waiting statuses | Photo lives in |
|---|---|---|---|
| Customer PO | `order_items` | `collection_pool`, `assigned`, `ready_delivery` | `order_items.order_item_attachements` |
| Stock PO | `stock_purchase_items` | `collection_pool`, `assigned_to_driver` | `stock_purchases.additional_attachments` (**on the parent PO**) |
All three customer waiting statuses count. The "collection pool" tab group
is `["collection_pool", "assigned", "ready_delivery"]` and
`order_items_confirm_collected` accepts `collection_pool` **or**
`assigned` — a line stuck in any of them never reaches Collection Confirm.
## The check
### 1. Find the lines
Customer lines — `order_items_list` with filter:
```
(item_status = "collection_pool" || item_status = "assigned" || item_status = "ready_delivery") && order_item_attachements:length > 0
```
expand `purchase_order,supplier` — the PO number is
`expand.purchase_order.po_number`, it is not a field on the line itself.
Stock lines — `stock_purchase_items_list` with filter:
```
status = "collection_pool" || status = "assigned_to_driver"
```
expand `purchase` — the PO number is `expand.purchase.purchase_number`
(looks like `PO26100606STK`, not `PO...MAS`), and the photos are in
`expand.purchase.additional_attachments`.
### 2. Read every photo
`order_item_attachements` is a **multi-file** field (up to 10), and stock
POs can have several pages (`..._p1_`, `..._p2_`). Open **each** filename:
- customer line → `files_fetch`, collection `order_items`, the line id, the filename
- stock line → `files_fetch`, collection `stock_purchases`, the **parent PO** id, the filename
If a photo cannot be read as an invoice, treat the whole line as
unreadable (below).
### 3. Compare the invoice with the line
- the PO number printed on the invoice (reference / customer order no.)
= the line's PO number
- the supplier on the invoice = the line's supplier
- the item matches the line's description
- the quantity on the invoice = the line's `quantity`
- the invoice is dated today or recently
## What to do
- **Everything matches** → mark it collected. Do **not** hand-roll this
with `order_items_update` + `order_items_update_status`; use the tool
that exists for it, because it validates eligibility, refuses to
over-collect, stamps the audit note and refuses rows that are already
past the pool:
- customer line → `order_items_confirm_collected` with
`{ item_ids: [...], actor: { id, name }, quantity_collected: { <line id>: <invoice qty> } }`
- stock line → `stock_purchase_items_mark_collected` with
`{ id: <line id>, quantity_collected: <invoice qty> }`
- `quantity_collected` is the qty to **add**, not the new total. Omit it
to collect the full remaining quantity.
- `actor.id` is a free-form string — use `mavis` / `Mavis` so the
`notes` feed shows who did it.
- Do every line on that PO that is on the invoice.
- **Invoice shows less than ordered** → do NOT mark it. Report it
(the driver must collect the short quantity on the item card).
- **Photo is for a different PO** → do NOT mark it. Report both PO
numbers so a person can move the photo to the right PO.
- **Photo is not an invoice** → do NOT mark it. Report it.
- **Can't read the photo / not sure** → do NOT mark it. Report it.
Never cancel, delete, confirm, or change prices. Only ever mark a line
collected, and nothing else.
## Report
A short list: what you marked collected (supplier, PO, item, qty,
invoice number) and what needs a person (and why). If nothing was
found, say "nothing new".
**Do not re-report what is already on the "Waiting on a person" list
below** — those lines stay in the waiting status until somebody moves
them, so every run would otherwise find them again and repeat the same
report 22 times a day. Add anything new to that list.
## Waiting on a person
- **NSS M24 × 160 hex bolt ×60, PO202610018MAS** (line
`890919xtp0i8zfp`, driver Joachim): the photo on it is NSS invoice
5031768 for **PO202610080MAS** (M12 cap screws, already collected and
confirmed on 27 Oct). Wrong photo, so nothing proves the M24 bolts
were collected. Ask Joachim.
- **Mega Lube oil aerosol ×3, PO202610073MAS** (line `ganf24h10lyrzdl`,
driver Joachim): no Mega Lube invoice anywhere — the line has no
attachment at all, so the filter will not find it. Moved to 27 Oct.
Ask Joachim.
- **UPL UNBRAKO 1 1/2 × 7 allen caps ×34, PO202609005CEM** (line
`47it7cxyu27dmd5`): photo is on the line, but an operator bounced it
back to "NOT READY" on 26 Oct, so it is not a forgotten Collect.
Do not mark it.
- **NSS M6 × 30 CSK ×100, PO26100606STK** (stock line
`o9jtrr0wasxxq2g`): the photo on the PO is a picture of a laptop
keyboard, not an invoice. Needs a person to re-shoot it.