ZuloOne
English
Sign in
Menu

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 is postOnSave: 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 (OnAfterSave when isNew, 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.

Where next#

Was this page helpful?