Document Lifecycle: Open, Released, Posted
Every document in Business Central — sales order, purchase invoice, warehouse shipment — lives inside a status state machine: while it is Open you may edit it, once it is Released the warehouse can act on it, and after posting it is history that nothing may touch. The guards that keep each action legal only in the right status are what make an ERP trustworthy. This task is that state machine in miniature.
The starter ships two finished data objects. Do not rename them or their fields — the grading tests bind to every name below character for character.
The objects you get
- Table
"Lifecycle Document"— primary key"No."(Code[20]); fieldsDescription(Text[50]),Amount(Decimal),Status(enum"Lifecycle Document Status", defaults toOpen),"Posted On"(Date). - Enum
"Lifecycle Document Status"— valuesOpen,Released,Posted.
Requirements
Implement the three actions in the codeunit "Document Lifecycle", keeping exactly these signatures:
procedure Release(var LifecycleDocument: Record "Lifecycle Document")
procedure Reopen(var LifecycleDocument: Record "Lifecycle Document")
procedure Post(var LifecycleDocument: Record "Lifecycle Document")The transition rules — this is the whole matrix, there are no hidden cases:
Releaseis legal only whenStatusisOpen: it moves the document toReleased. A document whoseAmountis zero must not release — fail with the standard field-guard error: the message namesAmountand containsmust have a value(exactly whatTestFieldproduces).Reopenis legal only whenStatusisReleased: it moves the document back toOpen.Postis legal only whenStatusisReleased: it moves the document toPostedand stamps"Posted On"with the session's work date (WorkDate) — never with today's calendar date.- Every illegal transition fails with the standard field-guard error (exactly what
TestFieldproduces): the message namesStatusand the one status the action requires:Releaseon a document that is notOpen— error text containsStatus must be equal to 'Open'.ReopenorPoston a document that is notReleased— error text containsStatus must be equal to 'Released'.- Posted is final: no action ever leaves it — the same guards reject all three actions there.
- A successful action updates both the
varrecord you were handed and the database — a caller must see the new status on its own variable without re-reading, and the change must survive a freshGet. - A failed action changes nothing: the document keeps its status in the database, and a failed
Postleaves"Posted On"empty. - The open/released cycle is repeatable: a document can be released, reopened and released again any number of times, and still post.
What the tests check
One test per cell of the 3×3 action-by-status matrix — the three legal transitions (asserted on the var parameter and on a fresh read from the database) and all six illegal ones (error fragment plus untouched status) — plus the zero-Amount release guard, the WorkDate stamp on "Posted On", and a release–reopen–release–post round trip. Error matching is case-insensitive; the quoted fragments must appear in the message, quotes included. The illegal-transition tests all use documents with a non-zero Amount, so the order in which you check the status and the amount never decides a test.
Learn More
Status and reject the wrong states — only then may it change anything.must be equal to message is a one-liner. TestField(Amount) likewise produces exactly the must have a value error the release guard needs.TestField(Status, ...) with the action's one legal source status, then assign the new status (and "Posted On" := WorkDate() in Post) and call Modify(). Mutate the var parameter itself — the tests read the caller's variable AND re-Get the record from the database.