Lifecycle
A transfer has one status at a time. Every transition is guarded β a call that does not match the current status is refused rather than silently ignored.
Statusesβ
| Status | Wire value | Meaning |
|---|---|---|
| Created | CREATED | a draft. Only the store that raised it can see it; lines can still be added, changed and removed |
| Requested | REQUESTED | sent to the other store. The stock is now reserved at the sending store and on order at the receiving one |
| In progress | IN-PROGRESS | the sending store has started picking |
| Completed | COMPLETED | picked and sent. Stock has moved and a Goods Received delivery exists |
| Deleted | DELETED | abandoned before it was sent. The row is kept, not removed |
π IN-PROGRESS is spelled with a hyphen on the wire, unlike every other value. If you are
matching statuses as strings, match IN-PROGRESS β an IN_PROGRESS comparison will silently never
be true.
Transitionsβ
ββββββββββββββββ
β CREATED β draft β created by either store
ββββββββ¬ββββββββ
:send-requestβ ββββββββββββββββΊ DELETED
βΌ (only from CREATED)
ββββββββββββββββ
β REQUESTED β reserved at the sending store
ββββββββ¬ββββββββ
picking started β βββββββββββββββββββββββββββββ
βΌ β β
βββββββββββββββββ β
β IN-PROGRESS ββ β
ββββββββ¬βββββββββ β
β β β
βΌ βΌ β
ββββββββββββββββββββββββββββββββββββββββββ β
β COMPLETED ββββ
ββββββββββββββββββββββββββββββββββββββββββ
from REQUESTED or IN-PROGRESS
| Transition | Trigger | Guard |
|---|---|---|
CREATED β REQUESTED | :send-request | must be CREATED, have at least one line, and be called by the receiving store |
CREATED β DELETED | DELETE the transfer | must be CREATED, and be called by the receiving store |
REQUESTED β IN-PROGRESS | the sending store starts picking | must be REQUESTED |
REQUESTED or IN-PROGRESS β COMPLETED | :submit, or picking finishing | must be REQUESTED or IN-PROGRESS, and the caller must be the sending store |
What each store may doβ
Both stores can reach the transfer, but they cannot do the same things to it. The business unit in
the URL is what decides, and a call from the wrong one is refused β usually as a 404, because the
guard is written into the lookup rather than applied afterwards.
Receiving store (toBusinessUnitId) | Sending store (fromBusinessUnitId) | |
|---|---|---|
| Create the transfer | β | β |
| Change the transfer's comment | β | β |
| Add or change a line | β
β sets quantityRequested | β
β sets quantityApproved β½β±βΎ |
| Add or change batch / serial detail | β β½β±βΎ | β β½β±βΎ |
| Remove a line | β | β |
| Send the request | β | β |
| Delete the draft | β | β |
| Pick the goods | β β it does not hold them | β in Click and Collect |
| Complete the transfer | β refused | β β½β±βΎ, or automatically when the pick finishes |
β½β±βΎ Integration-only. Supported over REST, but nothing in the supplied flow calls it β a store's staff never do these things. See the API.
Two asymmetries are worth remembering, and they point in opposite directions:
π Sending the request belongs to the receiving store alone. Either store may create a
transfer, but only the store named in toBusinessUnitId can call :send-request. A store that
raises a transfer to push stock away from itself therefore cannot send it β the receiving store
has to. If you are building a push flow, create the transfer with the receiving store as the URL
business unit.
Completion belongs to the sending store alone. A :submit whose URL business unit is not the
transfer's fromBusinessUnitId is rejected, because the store that does not hold the goods cannot
assert they were sent.
β The same line endpoint writes a different field depending on who calls it. PUT β¦/lines takes
a single quantity; called by the receiving store it becomes quantityRequested, called by the
sending store it becomes quantityApproved, and calling as the wrong one silently writes the wrong
field. See the API.
Once completed, it is finalβ
There is no transition out of COMPLETED. A transfer that shipped the wrong goods is not reopened β
the correction happens on the receiving side, in Goods Received, where the delivery can be received
short or over. See Stock and Goods Received.
Likewise DELETED is only reachable from CREATED. Once the other store has been told to expect
goods, the transfer cannot be made to disappear.