Skip to content

intent: a create-from's items where:/refuse: refusal fires AFTER the header save - every refused click burns a document number and a history row #7224

Description

@delchev

Summary

#7164 (#7091) added items: where: + refuse: to a create-from. Both refusals - "an unqualified row exists" and "no row qualifies, the target would have no lines" - are evaluated AFTER the target header has been saved. The header save is inside the UnitOfWork, so the row itself is rolled back - but two things the generated repository does inside save() are, by the #7069 design, deliberately OUTSIDE the unit: the document-number allocation and the History create entry. Every hit of the rule the author declared therefore burns a number of a "continuous, never auto-reset" series and leaves a history row for a document that never existed. Pressing "Invoice this month" on a month with one rejected timesheet, three times, consumes three invoice numbers.

Evidence (origin/master)

components/template/template-application-events-java/src/main/resources/META-INF/dirigible/template-application-events-java/events/Generate.java.template:

  • line 150: UnitOfWork.call(() -> {
  • line 223: ... ${toEntity}Repository().save(target); (the header)
  • lines 225-235: the where:-narrowed item query (.eq("${srcFkProperty}", sourceId)${itemWhere})
  • lines 236-257: the refuse: scan and throw new ValidationException("${itemRefuse} (${fromItemEntity} " + unqualified + ")")
  • lines 260-265: throw new ValidationException("no ${fromItemEntity} row of the ${fromEntity} qualifies ... would have no lines")

components/template/template-application-dao-java/.../data/Repository.java.template, inside save(...) (line 331): line 390/392 DocumentNumbers.next(...), line 405 History.recordCreate(...). Per .claude/docs/client-java.md ("The History trail and document numbering deliberately stay outside" the unit) neither is undone by the rollback.

Fix

Both refusal queries depend only on sourceId and the source rows. Run them BEFORE the header is built and saved (before line 223, or before entering the unit at 150), so a refused click writes nothing at all - which is also what the template's own comment at line 98 promises for the prompt: refusal ("refused BEFORE anything is written"). The IntentGeneratesItemsWhereIT (or whatever the behavioural test is) should assert the series counter and the history table are unchanged after a refused run.

Found reviewing #7164.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions