Skip to content

Merge GroupsBuilder into ReportBuilder with GroupBy support#110

Merged
SimonBarrettACT merged 16 commits intomainfrom
feature/issue-109-merge-groupby-into-report-builder
Mar 8, 2026
Merged

Merge GroupsBuilder into ReportBuilder with GroupBy support#110
SimonBarrettACT merged 16 commits intomainfrom
feature/issue-109-merge-groupby-into-report-builder

Conversation

@SimonBarrettACT
Copy link
Member

Summary

  • Add optional groupBy/aggregation support to ReportBuilder via $enableGroupBy flag
  • WithReportBuilder gains $groupBy, $aggregateColumn, $aggregateFunction properties with UI controls in report-editor.blade.php
  • ReportBuilder overrides rowsQuery() to apply GROUP BY and aggregate SELECT when active
  • Deprecate GroupsBuilder (now extends ReportBuilder with enableGroupBy = true) and WithGroupBuilder
  • Simplify group-table.blade.php to delegate to report-table.blade.php
  • Improve README with comprehensive documentation for all component types and the new GroupBy feature

Test plan

  • Existing ReportBuilder subclasses work unchanged (no groupBy UI shown)
  • Setting $enableGroupBy = true shows Group By controls in the report editor
  • Selecting a group by column, function, and aggregate column produces correct grouped results
  • Aggregate functions are validated against the whitelist before use in raw SQL
  • Existing GroupsBuilder subclasses continue working via the deprecated shim
  • Reset clears groupBy state along with criteria and selected columns

Closes #109

🤖 Generated with Claude Code

SimonBarrettACT and others added 16 commits March 8, 2026 19:14
Add groupBy/aggregation properties ($groupBy, $aggregateColumn,
$aggregateFunction) to WithReportBuilder trait, controlled by
$enableGroupBy flag. ReportBuilder overrides rowsQuery() to apply
GROUP BY and aggregate SELECT when active. Report editor view gains
conditional groupBy UI controls. GroupsBuilder now extends ReportBuilder
with enableGroupBy=true and is marked deprecated.

Closes #109

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add documentation for all three builder types (QueryBuilder,
TableBuilder, ReportBuilder), the new GroupBy feature, column types,
conditions, filters, and relationship support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dot-notation column keys (e.g. contract.department.name) are Eloquent
relationship paths, not SQL columns. The groupBy/aggregate selectRaw
was using them directly, causing "column not found" errors.

- Add resolveColumnWithJoins() to walk the relationship chain and add
  proper joins for BelongsTo/HasOne/HasMany relationships
- Replace normal columns with group_value + aggregate columns when
  grouping is active
- Update displayColumns on groupBy/aggregate property changes

Closes #109

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MySQL's ONLY_FULL_GROUP_BY mode rejects ORDER BY clauses that reference
non-aggregated columns not in the GROUP BY. Use reorder() to clear
inherited ordering and default to ordering by the group column.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Global scopes are applied at query execution time, after reorder().
The Employee model's global 'order' scope re-adds last_name/first_name
ordering which conflicts with GROUP BY under ONLY_FULL_GROUP_BY mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flux listbox select with placeholder requires null (not empty string)
to show the placeholder text. Empty string causes the first option
to be selected by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows consuming apps to define a separate set of groupable columns
instead of defaulting to all available columns. Falls back to
availableColumns() when not overridden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
COUNT always operates on id so the aggregate column picker is
unnecessary. Reset to id when switching back to COUNT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
COUNT always uses the base table's id column directly. The ID option
is removed from the aggregatable columns list since it's only relevant
to COUNT which no longer needs a column picker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flux clearable select sets value to empty string, not null. Using
filled() handles both cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a groupBy column has a view component defined (e.g. enum, company),
use it for rendering the grouped column values instead of plain text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The view component definition lives in the group_by config, not the
main columns config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a group_by config entry includes an options array, use reformatUsing
to map raw database values to human-readable labels (e.g. enum values).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When using SUM/AVG/MIN/MAX, look up the aggregate column's config and
apply its view component (e.g. currency, integer-to-float) so values
display formatted rather than raw.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename functions to Count/Sum/Average/Minimum/Maximum. Change
'Aggregate Column' label to 'Value Column'. Use human-readable
column header like 'Sum of Salary' instead of 'SUM(payroll.salary)'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check query's existing joins instead of a local array, preventing
duplicate table joins when resolveColumnWithJoins is called multiple
times (e.g. for both groupBy and aggregate columns).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@SimonBarrettACT SimonBarrettACT merged commit 0cc1d6d into main Mar 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Merge GroupsBuilder into ReportBuilder with GroupBy support

1 participant