feat(intent): balance report kind - opening/period/closing totals with runtime date parameters#6225
Merged
Merged
Conversation
…h runtime date parameters
kind: balance on a report generates the accounting balance shape: six
SUM(CASE WHEN ...) totals (Opening/period/Closing Debit and Credit)
per dimension around a runtime :fromDate/:toDate window, with the
window declared as .report parameters ({name, type, initial} - the
report editor's existing shape) that the generated repository already
binds and the controller already passes through. The Harmonia report
page renders every declared parameter as a first-class input (date
pickers for the balance window) sent with every search/count/export,
plus a totals footer for balance reports. Report filters normalize the
intent-guard-style '==' to SQL '=' (PostgreSQL rejects '=='), and the
balance sums COALESCE the amounts so one-sided ledger lines (the
exactlyOne debit/credit shape) do not yield NULL totals.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
kind: balanceon an intent report generates the accounting balance shape — the report type behind a trial balance, a general ledger summary, or receivables per counterparty:Instead of
measures, the generated.reportquery computes six windowed totals per dimension row — Opening Debit/Credit (strictly before:fromDate), Debit/Credit (the inclusive period), Closing Debit/Credit (up to and including:toDate) — asSUM(CASE WHEN ... COALESCE(amount, 0) ELSE 0 END)columns, so opening + period = closing on every row.Runtime user parameters (the general half)
The window bounds are declared
.reportparametersin the report editor's existing{name, type, initial}shape, with all-time defaults (1900-01-01/9999-12-31). The generated Java repository (baseParameters) and controller (GET query params / POST body pass-through) already supported declared parameters — this is the first generator that emits them, no new backend plumbing.The Harmonia report page now renders every declared parameter as a first-class input above the column filters (date → picker), sent by name with every
/search,/count,/exportand print; an empty value falls back to the server-side default. Balance reports additionally get a totals footer, shown only when the whole (filtered) result fits on one page so a page-local sum is never presented as the report total. (AngularJS report UI ignores the parameters — Harmonia-only pickers, likewhere:.)Robustness fixes surfaced by live verification
==→=normalization in report filters: intent authors writeStatus == 2out of guard-syntax habit; H2 tolerates==but PostgreSQL rejects it.COALESCEin the balance sums: a one-sided ledger line (theexactlyOnedebit/credit shape) holds NULL on the other side, andSUMover all-NULL returnednullinstead of0.00.Validation
Parser (
validateBalanceReport):datemust resolve to adate-typed field (atimestampis rejected — the window bounds are dates, and a midnighttoDatewould silently drop that day's intra-day entries);debit/creditmust be numeric fields of the source; at least one dimension;measuresforbidden;date/debit/creditwithoutkind: balancerejected; unknown kinds rejected.Verified live
On a ledger fixture (JournalEntry/JournalEntryItem with EntityStatus workflow + posted entries): all-time balance (411 D/702 C, balanced), opening boundary (
fromDatepast the entry moves it to opening), window-before (all zeros), covering window, DRAFT entries excluded by the status filter, export honoring the window, generated page carrying the pickers + footer (generated JSnode --checked).Tests
ReportIntentGeneratorTest: full balance.reportshape (windowed SQL, joins, GROUP BY, parameters, column metadata,==normalization) + validation rejections; newTestContextstest factory for the package-private generation context.IntentEngineIT: anOrderBalancebalance report in the showcase intent, asserting the windowed SQL, the declared parameters and their defaults on the generated.report.IntentEngineITruns wedge on the known macOSPollingWatchServicedeadlock (environment flake) — the Linux smoke gate covers it.Docs:
intent-assistant-guide.md(reports section) + engine-intentCLAUDE.md.🤖 Generated with Claude Code