Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/docs/intent-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ A single `app.intent` YAML file at a project root is the source of truth one alt

**A create-from is not offered twice (`fromStatus:`, [#7068](https://github.com/eclipse-dirigible/dirigible/issues/7068)):** a `generates:` with a `sourceStatus:` completion hook flipped its source once the target existed and then went on offering the same button on the flipped record - and answering the same endpoint 200 - so a second click minted a **second document**: a proforma already INVOICED produced a second invoice, in the customer's hands. The hook declared what "already done" looks like; nothing consulted it. A create-from now carries a from-status guard resolved ONCE and fed to both halves of the action: the generated `run()` refuses with **409** before anything is created, and the contributed action descriptor carries the same guard so the shared `customActions` store stops OFFERING the click on a record it would refuse (`getActions(view, type, record)` takes the record the view already has). Two shapes: `fromStatus: [...]` is the explicit allow-list - the `from:` of a `transitions:` entry, spelled differently only because `from:` on a create-from already names the source ENTITY - and absent it a declared `sourceStatus` IMPLIES the deny-list of exactly that status, so a model that already carries the defect is fixed with no authoring change. The guard is on the CLICK: an event-driven create-from keeps its own at-most-once back-reference guard and qualifies its moment with `event.when`, so `fromStatus` on an event-only rule is refused at parse rather than silently ignored - as are a `page` scope, a source with no `function: EntityStatus` relation, and an allow-list containing the `sourceStatus` the action itself writes.

**An amended source rewrites its posting ([#7071](https://github.com/eclipse-dirigible/dirigible/issues/7071)):** the amend path (Confirm → Reject → edit the lines → Issue again) raises a `postings:` trigger a SECOND time, and the old idempotency test - an existing post whose item count reached the derived one - read that as "already posted", so the journal entry silently kept the amounts of the previous issue while the invoice it references had moved on. No second entry (right), a ledger short by the difference (wrong), and nothing anywhere said so. The generated handler now derives the WHOLE content first and compares it with what the post carries: identical is a redelivery (no-op), different is either a half-post to complete or an amendment to REWRITE the post from - header assignments re-applied, items replaced, never a second document. The rewrite stops where the created document's own lifecycle says someone has taken it over: it is rewritable only while its `function: EntityStatus` relation still holds the `init:` the posting's own create wrote (with no status lifecycle there is nothing to act on, so it is always rewritable), and past that the divergence is logged naming both documents and left to a correcting entry - `reverses:` - rather than overwritten behind the accountant's back. The comparison is order-insensitive over every cell the item rows assign, and numbers compare by value so a rescaled amount is not a change.
**An amended source rewrites its posting ([#7071](https://github.com/eclipse-dirigible/dirigible/issues/7071)):** the amend path (Confirm → Reject → edit the lines → Issue again) raises a `postings:` trigger a SECOND time, and the old idempotency test - an existing post whose item count reached the derived one - read that as "already posted", so the journal entry silently kept the amounts of the previous issue while the invoice it references had moved on. No second entry (right), a ledger short by the difference (wrong), and nothing anywhere said so. The generated handler now derives the WHOLE content first and compares it with what the post carries: identical is a redelivery (no-op), different is either a half-post to complete or an amendment to REWRITE the post from - header assignments re-applied, items replaced, never a second document. The rewrite stops where the created document's own lifecycle says someone has taken it over: it is rewritable only while its `function: EntityStatus` relation still holds the `init:` the posting's own create wrote (with no status lifecycle there is nothing to act on, so it is always rewritable), and past that the divergence is logged naming both documents and left to a correcting entry - `reverses:` - rather than overwritten behind the accountant's back. The comparison is order-insensitive over every cell the item rows assign, and numbers compare by value so a rescaled amount is not a change. The rewrite is ONE transaction ([#7132](https://github.com/eclipse-dirigible/dirigible/issues/7132)) - the stale rows it replaces, the header and every derived line share a `UnitOfWork`, because a line a validation refuses halfway would leave a header with a partial line set, and unlike the half-post case no second event ever comes to repair it: worse than the stale but balanced post the rewrite set out to fix.

**Event-driven create-from (`generates` + `event:`, [#6711](https://github.com/eclipse-dirigible/dirigible/issues/6711)):** a `generates` entry may declare `event: { onTransition: <from>, when: "<Status> == <status>" }` (guard mandatory) or `{ onCreate: <from> }` and mint the follow-up **document — header AND items** by itself when the source reaches a state, instead of waiting for the button (`posts` is event-driven but emits flat rows and cannot reference the new header). The `map` entry copying the source's key IS the back-reference and therefore the **at-most-once** guard, derived rather than declared twice; the button is dropped unless `button: true`, and both triggers share ONE generated create-from (a new `GenerateOnEvent.java.template` listener calls `<X>Generate.create(id)` and carries no mapping of its own). Details in the engine-intent guide's `event:` bullet.

Expand Down
Loading
Loading