Repository navigation
feat(plugin-report): a summary report with two or more row levels draws per-group subtotals - #28376
Conversation
… per-group subtotals A summary report asks the server for every proper prefix of its rows through totals.groupings, and draws each outer group as a header row, its inner rows without the repeated outer value, and the server's subtotal row. A one-level summary, tabular and matrix keep their face; an answer without the prefix groupings renders the plain table. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwTmv3iyLca6doQ7h7
…, drill and export Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwTmv3iyLca6doQ7h7
…am type-checks Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwTmv3iyLca6doQ7h7
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwTmv3iyLca6doQ7h7
|
domain:ui#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract-review-claim: |
|
domain:ui#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract reviewServed-tier: Inputs: card #27975 (body; the seat's retriage request 6539388814; triage 6539817671 ruling the default with no new key; the seat's claim 6540287709; the dev report 6540832419), PR #28376 (body with the live showcase measure, the file list of 14 files, the diff of 909 lines against ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Verdict reasoning. The retriage ruling is implemented in the shape the spec already describes for totals, every other report face is unchanged and pinned, the subtotals are the server's, drill and export follow the drawn table, the declarations and the patch level are right, and every check is green or skipped. Implemented-by: VERDICT: PASS |
|
domain:ui#1 · os-tesla · session_01L9qibzC6RxMfB59EsgAoNN 席位核对ACCEPT · seat 席位意见:多层(两层及以上)的汇总报表现在按外层分组显示:每组先有一行组头,外层值只写一次,然后是组内明细,最后一行「小计」。小计由服务器按分组计算,浏览器不做加总,所以平均值、去重计数等也是正确的。点击小计行会打开该组的全部记录,导出的表格和屏幕上看到的一致。单层汇总、明细表和交叉表都不变;如果服务器没有返回分组小计,就退回原来的平铺表。这是维护者裁定的默认行为,没有新增配置项。
|
Requested by Tesla · project thread
Fixes #27975
Clause-②: no
Metadata-protocol: none
维护者速读
summary报表的rows有两层及以上时,按外层分组画:每组一行组头(外层值只写一次)、组内明细行(外层列留空)、一行「小计」;三层时逐层嵌套。小计取服务端按前缀分组算出的值,浏览器不做加总。summary报表下次渲染即出现小计行(已在 changeset 写明);单层 summary、tabular、matrix不变;服务端不回前缀分组时退回原平铺表。回滚即 revert 本 PR。ui/packages/plugin-report/src/DatasetReportRenderer.tsx的DatasetReportTable(totals 请求与lines渲染)和nestSummaryLines/spanDrillRanges;新测试DatasetReportRenderer.summarySubtotals-27975.test.tsx。pnpm --dir ui exec vitest run packages/plugin-report/src/__tests__/DatasetReportRenderer.summarySubtotals-27975.test.tsx,预期 16 个用例全绿。What changes
Renderer (
ui/packages/plugin-report/src/DatasetReportRenderer.tsx,DatasetReportTable).summarytable with two or morerowslevels asks the dataset for every proper prefix ofrowsplus the grand total throughtotals.groupings:[[a], []]for[a, b],[[a], [a, b], []]for[a, b, c](summarySubtotalPrefixes). The server already re-runs the selection per grouping, which is what thematrixpath relies on.nestSummaryLines): per outer group a header row naming the value once, its inner lines (the outer columns left blank), and aSubtotalrow carrying the server's pre-aggregated row for that prefix. The subtotal lookup relabels the totals rows the same way the display rows are relabeled and matches by bucket id, the matrix's rule. Nothing is summed client-side.orderboth hold; rows of one group that anorderby a measure returns apart are drawn together under it.groupKeyand the raw-value filter take the prefix dimensions, and its ranges are the span of its group's ranges (spanDrillRanges): a prefix range passes through, an inner time bucket widens to the group's buckets (already narrowed to any report period by the server), and a key some row lacks (the empty bucket) is dropped.summary(still[[]], grand-total footer only),tabular(no totals), amatrixwithcolumns, and amatrixwithoutcolumns(it still degrades to this table with the grand total only;withSubtotalsis passed forsummaryalone, top level and joined blocks). An answer missing any prefix grouping (an older server) draws the plain table with the outer value repeated.i18n.
report.subtotaladded to all ten packs, reusing each pack's existingmasterDetail.subtotalwording.Changeset.
.changeset/27975-summary-report-subtotals.md, patch for@object-ui/plugin-reportand@object-ui/i18n, with both declaration lines and the visible default change named.Tests
ui/packages/plugin-report/src/__tests__/DatasetReportRenderer.summarySubtotals-27975.test.tsx, 16 cases: the totals request for two and three levels; the grouped body for two levels; the server subtotal placed where the rows would sum differently (anavg); three-level nesting; grouping under an interleaving authoredorder; a joined summary block; drill on a subtotal (prefix only), on an inner row (every dimension), over a time-bucketed inner dimension (span), and over a group holding the empty bucket (range dropped). Controls: older server without the prefix grouping, no totals at all, one-level summary, two-leveltabular,matrixwithoutcolumns.DatasetReportRenderer.export-25873.test.tsx: one new case, the CSV of a two-level summary equals the drawn table cell for cell.node scripts/ablation-replace.mjsreplacedwithTotals && withSubtotals ? summarySubtotalPrefixes(rows) : []with an empty list (anchor 1 → 0, blobdc35dc45→4b92969b). Predicted: every grouped-face case red, the controls green. Measured over the two files: 11 failed, 18 passed. Restore verified by the tool: blob back todc35dc45,git diff HEADempty.Acceptance notes
ddbba1e8). The showcase ships no two-level summary, so one was saved into the throwaway--freshdatabase throughPUT /api/v1/meta/report/showcase_hours_by_status_priority(rows: [status, priority],values: [est_hours]); noexamples/**edit. The Console dev server rendered it from this branch's source.origin/mainrenderer swapped in, then restored byte-identical): requesttotals.groupings: [[]]; 8 rows, each repeating its status (Backlog · Low · 12.0,Backlog · Medium · 18.0, …), footerTotal 244.0.totals.groupings: [["status"], []]; the server answeredtotals[0].dimensions: ["status"]with 5 rows (Backlog 30, Done 24, In Progress 100, In Review 54, To Do 36) andtotals[1]the grand total 244. Drawn:Backlogheader,Low 12.0,Medium 18.0,Subtotal 30.0, …Doneheader,Medium 24.0,Subtotal 24.0,Total 244.0, in the status field's declared order.Backlogwith both Backlog tasks (Low and Medium).orderby a measure are ordered by their first row, not by their subtotal. Ordering groups by subtotal would need the server to order the prefix grouping, which it drops for totals by design. Noted, not filed.Subtotal(report.subtotal), placed in the column of the level it closes; it does not repeat the group's value. Noted.git merge-treeof this branch against feat(plugin-report): a report chart draws its seriesBy split #28305's head39eb423bis clean. feat(plugin-report): a report chart draws its seriesBy split #28305 is still open; this branch mergesorigin/mainagain after it lands.Verification
All readings on head
91ccb5a5(after mergingorigin/main) unless named.Affected package tests and type-checks
pnpm --dir ui exec vitest run packages/plugin-report/ packages/i18n/underos-verify-lock: Test Files 124 passed (124), Tests 1728 passed, 20 skipped. VERDICT command-exit 0.pnpm --filter @object-ui/plugin-report --filter @object-ui/i18n run type-check(after building the plugin-report dependency closure with declarations): VERDICT command-exit 0.pnpm check:new-line-citations(ui): 0 new citations.Derived gates (dispatch-gates --commands, reconciled with --ran)
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ranon headddbba1e8: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN; every recorded exit code 0.node scripts/check-sdui-manifest.mjsand its--self-test: exit 0.pnpm --dir ui exec vitest run scripts/: Test Files 169 passed, 2 skipped; Tests 4901 passed, 2 skipped.origin/mainmerge the derivation on91ccb5a5names the same 34 families. Re-run there: 32 of them, all exit 0. Not re-run on91ccb5a5:pnpm check:type-check-debtandpnpm --dir ui exec vitest run scripts/(both green onddbba1e8; the merge brought no change toui/scripts/or to a type-check ledger).Generated by Claude Code