Create a document
Updated
A document is a state machine. The subtype is the current state
(Draft → Ordered → Received …). A transition is the business event: the
engine replaces movements (Mix), it does not add them. It drops every
movement the document already has and runs the posting chain of the target
subtype only.
Note
Do not add
statuses. State is the subtype. Posted-ness ispostOnSave: true— a saved document is posted in its current subtype. After Save, the subtype select on the card is frozen. The user changes state with a command.
How to#
1. Table part type — TableParts/<Document>Lines.json, plus an event
handler on the line. The owner of a line is Owner<Document>(context) from
memory of the form. Optional scalars on a line are nullable (decimal?).
The same optional scalar on the header is not. Empty on a line is null;
empty on a header date is the sentinel 1901-01-01 (Year < 1902).
2. The document — Documents/<Name>/<Name>.object.json: header fields,
subtypes (displayOrder is the workflow order; the first subtype is the
initial state, usually a draft with no scripts), table parts. Do not declare
ID, number, or date. displayFormat is the closed-field text of a document
picker. lookupProperties is a CSV of header field names for the dropdown
columns (the Lookup properties tab in the designer); empty means Code plus
the display-format fields. Another model overlays extras and hides on its
extension (lookupPropertiesAdd / lookupPropertiesHide). The journal lists
every header field; the user hides extras in the column picker.
3. Posting scripts — as many as the subtype needs, one per accounting
goal (stock, cost, GL). Each is a file pair under
Documents/<Name>/Transactions/. Bind them with subtypeTransactionScripts
on the document. A script in the pool that is not bound to the subtype does
not run. See Write postings.
4. Event handler — Events/<Name>EventHandler.*. Fill fields and refuse
values here. Spawn related documents in OnAfterPostAsync, and make that
idempotent. Do not write register movements here.
5. A command per user transition. Scripts on a subtype without a command the user can press will never post from the UI.
6. Menu item in the model's Documents subgroup, and bump modelVersion.
Tip
Do not read a second table in a create event (
OnAfterSavewhenisNew,OnAfterInsert). That opens a new connection inside the insert transaction and on Linux fails with "This platform does not support distributed transactions". Put "look something up at create" on a command.
What's not there yet#
A subtype with posting scripts and no command is not a user-facing document.
Programmatic SetSubtypeAsync / document.Subtype = … is for services,
events, and tests — not instead of the button.