What happens
Since #7081 a generates: create-from runs header + lines + sourceStatus flip inside one UnitOfWork. The generated document now comes out with every total 0.00 although its lines exist and are correct, and nothing ever recomputes it.
Reproduced on dirigiblelabs/dirigible:14.48.0 with base-timesheets invoice-from-timesheet (items EmployeeTimesheet -> SalesInvoiceItem, quantity: totalHours, price: rate) against a base-sales-invoices target regenerated on 14.48.0 (so the target's repositories are the current templates):
POST .../InvoiceFromTimesheetGenerate/run {"id": 3} -> 200, SalesInvoice 5
GET .../SalesInvoiceItemController (SalesInvoice == 5) -> [("QA Employee One", Quantity 176, Price 60, Net 10560.00)]
GET .../SalesInvoiceController/5 at t+0s / +5s / +15s / +3min -> Net 0.0, Vat 0.0, Total 0.0, Payable 0.0, Balance 0.0
Control, same instance, outside a unit of work: POST .../SalesInvoiceItemController {"SalesInvoice": 2, "Quantity": 1, "Price": 10, ...} -> the header of invoice 2 is recomputed at once (Net 8810 = the generated 8800 line, which had also been ignored, + 10). So the recompute machinery is fine; it is the run inside the unit that loses its result.
The recompute is the synchronous one every line write performs (SalesInvoiceItemRepository.save -> new SalesInvoiceRepository().recalculate(saved.SalesInvoice)), which findByIds the header, findAlls the lines by FK and persists the sums through the targeted updateProperties (a createMutationQuery("update ... where id = :id")). Inside the unit both reads and writes join UNIT_OF_WORK.get().session (JavaEntityStore.read/write), while the inserts are session.persist(entityName, map). Two candidate mechanisms, both consistent with the observation and both fixable in the store rather than in the templates:
- the bulk HQL update runs against the database before the still-pending
persist of the header is flushed, so it updates 0 rows, and the header is then inserted at commit with the zeros it was built with;
- the lines query inside the same session does not see the pending line inserts (no auto-flush for the dynamic-map entity), so the sum is 0 and 0 is what gets written.
Either way the fix belongs where the unit is bound: flush the session before a query / mutation query issued inside a unit (or make the mutation path go through the managed entity), so that "reads inside the block see the block's own writes" (#7081's own statement) also holds for the write-then-aggregate pattern every document repository uses.
Why it matters
A generated invoice with lines and Total 0.00 is the empty-document class QG-2/QG-3 exist for, produced by the platform's own generator on every create-from with items: (timesheet -> invoice, proforma -> invoice, quotation -> order, order -> invoice). On 14.46.0 (each save its own transaction) the totals were right; this is a 14.48.0 regression introduced by the fix for #7069, and it would ship to sta with the 14.48.0 train.
Expected
The header's totals after a create-from equal the sum of its lines, exactly as after a line POSTed through REST. JavaUnitOfWorkIT gets the write-then-query-then-targeted-update case; IntentEngineIT's create-from with items: asserts the header total.
Found 2026-09-07 adapting base-timesheets for the 14.48.0 train (BusinessIntents/base-timesheets#19, PR pending). Related: #7069 / #7081 (the unit of work), #7068 / #7080.
What happens
Since #7081 a
generates:create-from runs header + lines + sourceStatus flip inside oneUnitOfWork. The generated document now comes out with every total 0.00 although its lines exist and are correct, and nothing ever recomputes it.Reproduced on
dirigiblelabs/dirigible:14.48.0with base-timesheetsinvoice-from-timesheet(itemsEmployeeTimesheet -> SalesInvoiceItem,quantity: totalHours,price: rate) against a base-sales-invoices target regenerated on 14.48.0 (so the target's repositories are the current templates):Control, same instance, outside a unit of work:
POST .../SalesInvoiceItemController {"SalesInvoice": 2, "Quantity": 1, "Price": 10, ...}-> the header of invoice 2 is recomputed at once (Net 8810 = the generated 8800 line, which had also been ignored, + 10). So the recompute machinery is fine; it is the run inside the unit that loses its result.The recompute is the synchronous one every line write performs (
SalesInvoiceItemRepository.save->new SalesInvoiceRepository().recalculate(saved.SalesInvoice)), whichfindByIds the header,findAlls the lines by FK and persists the sums through the targetedupdateProperties(acreateMutationQuery("update ... where id = :id")). Inside the unit both reads and writes joinUNIT_OF_WORK.get().session(JavaEntityStore.read/write), while the inserts aresession.persist(entityName, map). Two candidate mechanisms, both consistent with the observation and both fixable in the store rather than in the templates:persistof the header is flushed, so it updates 0 rows, and the header is then inserted at commit with the zeros it was built with;Either way the fix belongs where the unit is bound: flush the session before a query / mutation query issued inside a unit (or make the mutation path go through the managed entity), so that "reads inside the block see the block's own writes" (#7081's own statement) also holds for the write-then-aggregate pattern every document repository uses.
Why it matters
A generated invoice with lines and Total 0.00 is the empty-document class QG-2/QG-3 exist for, produced by the platform's own generator on every create-from with
items:(timesheet -> invoice, proforma -> invoice, quotation -> order, order -> invoice). On 14.46.0 (each save its own transaction) the totals were right; this is a 14.48.0 regression introduced by the fix for #7069, and it would ship to sta with the 14.48.0 train.Expected
The header's totals after a create-from equal the sum of its lines, exactly as after a line POSTed through REST.
JavaUnitOfWorkITgets the write-then-query-then-targeted-update case;IntentEngineIT's create-from withitems:asserts the header total.Found 2026-09-07 adapting base-timesheets for the 14.48.0 train (BusinessIntents/base-timesheets#19, PR pending). Related: #7069 / #7081 (the unit of work), #7068 / #7080.