Rev 37693 |
Last modification |
Compare with Previous |
View Log
| RSS feed
Last modification
- Rev 37704 2026-09-18 04:18:12
- Author: amit
- Log message:
- Reopen a movement PO whose stock arrived late, and stop stranding GRN price corrections
Internal movements auto-close after four days, which fits 99.6% of them - 5,491 of 5,515 receipts
land inside the window. The remainder leave the PO closed with the stock still in transit and
nowhere to receive it: 998 internal POs closed during 2026 still holding 21,996 unreceived units.
A closed movement PO can now be reopened from the purchase order list. Reopening stamps
reopenedAt, and auto-close measures from WarehousePurchaseOrder.getOpenSince() - reopenedAt when
set, the PO date otherwise - so a reopened PO gets the same fresh window a new one gets instead of
being closed straight back on the next sweep. Only movements between our own warehouses: an
external vendor PO that has closed is settled with that vendor, not reopened unilaterally.
Separately, a GRN price correction now checks that the PO it just raised is one the invoice can
actually be received against. Matching reads POs that are open and approved for the same supplier
and warehouse dated on or before the invoice; it never looks at the PO being corrected, so what
matters is that the new PO is receivable. 54 were not - backdated into INIT by the old approval
gate, hence outside the match - and each stranded silently: original line discarded, GRN completed
without it, the correction left holding a reservation for stock that had already arrived.
isOpen() names the open set - INIT, READY, PARTIALLY_FULFILLED - that the movement and commitment
queries already read.
Migration sql/add_po_reopened_at_20260918.sql adds reopenedAt, nullable and additive. It must run
before this ships: the entity maps the column.