Skip to main content

Voucher Lifecycle States

The system has two separate state machines. They must stay separate in API, CLI, UI, and agent output.

Staged Operation State

staged_operations.status describes a proposed or reviewed action:

StatusMeaning
stagedWaiting for approval or operator review.
approvedApproved and ready to execute/apply.
executedThe operation has run. Check execution_reference_* for what it affected.
rejectedOperator rejected it.
failedExecution failed.
cancelledOperation was cancelled.

staged_operations.max_effect describes the strongest accounting effect the operation is allowed to have:

ValueMeaning
draftApplying can only create or update draft/review state. It must not post a voucher.
postApplying is allowed to post if the operation logic says it will post.

max_effect=post is a cap, not a promise. Use lifecycle.will_post from the staged-operation response to show whether this specific operation intends to post.

Ledger Entry State

ledger_entries.status describes an actual voucher/ledger entry:

StatusMeaning
draftA ledger-entry draft exists and can be reviewed or posted.
postedThe voucher is posted.
partially_clearedPosted voucher is partly cleared against bank/payment state.
clearedPosted voucher is fully cleared.
reversedVoucher has been reversed.
cancelledVoucher was cancelled.
archivedVoucher is archived from the active workflow.

Derived API Lifecycle

Staged-operation responses include lifecycle to connect the two state machines without merging them:

FieldMeaning
stageDerived stage such as staged_create_proposal, staged_operation, ledger_entry_linked, or terminal_without_ledger_entry.
ledger_entry_idActual ledger entry id when one is known.
ledger_entry_ref_sourceentity_id or execution_reference, showing where the ledger entry id came from.
voucher_materializedTrue only when a ledger-entry row is known.
will_create_entryTrue when the preview says applying will create a ledger entry.
will_postTrue when the preview says applying will post.
needs_apply_to_create_draftTrue for the proposal state: there is no draft yet, and apply is needed before the draft appears in ledger/bookkeeping views.

The receipt-create proposal shape is:

{
"status": "staged",
"entity_type": "ledger_entry",
"entity_id": null,
"max_effect": "post",
"preview": {
"accounting_effect": {
"will_create_entry": true,
"will_post": false
}
},
"lifecycle": {
"stage": "staged_create_proposal",
"voucher_materialized": false,
"needs_apply_to_create_draft": true
}
}

That is not a ledger-entry draft. The UI and CLI must label it as a proposal that still needs apply before a review draft exists.

UI Display Rule

Materialized ledger rows must display only ledger_entries.status as the current voucher state. A row may say Posted only when the materialized ledger entry status is posted.

Preview rows are different: operation_preview_entities.row_payload.status describes the proposed after-state of a staged operation. For example, a staged accounting_entries.post operation can have preview status posted while the actual ledger entry is still draft. The UI must label that preview as Will post, not Posted.