Skip to content

EX-262: Create widgets#81

Open
hptrk wants to merge 6 commits intodevelopfrom
feature/EX-262-statistics-backend
Open

EX-262: Create widgets#81
hptrk wants to merge 6 commits intodevelopfrom
feature/EX-262-statistics-backend

Conversation

@hptrk
Copy link
Owner

@hptrk hptrk commented Mar 1, 2026

No description provided.

@hptrk hptrk added this to the v1.1.0 milestone Mar 1, 2026
@hptrk hptrk requested review from Copilot and ntamasa March 1, 2026 17:07
@hptrk hptrk self-assigned this Mar 1, 2026
@hptrk hptrk added the backend label Mar 1, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a configurable “widgets” system for the statistics dashboard, including persistence for widget layout/configuration, a materialized-view-backed statistics aggregation layer, and a set of widget data providers exposed via new REST endpoints.

Changes:

  • Adds widget persistence (Liquibase changelog + JPA entity/repository/service/controller) and layout validation.
  • Adds mv_daily_category_stat materialized view + refresh function/triggers to pre-aggregate daily stats.
  • Implements multiple widget data providers and supporting DTO/projection payload types.

Reviewed changes

Copilot reviewed 99 out of 99 changed files in this pull request and generated 21 comments.

Show a summary per file
File Description
backend/exence/src/main/resources/db/changelog/v1.1.0/sql/create-trigger-on-transaction.sql Trigger to refresh MV on transaction changes
backend/exence/src/main/resources/db/changelog/v1.1.0/sql/create-trigger-on-category.sql Trigger to refresh MV on category updates
backend/exence/src/main/resources/db/changelog/v1.1.0/sql/create-refresh-function.sql PL/pgSQL refresh function for MV
backend/exence/src/main/resources/db/changelog/v1.1.0/sql/create-mv-daily-category-stat.sql Defines the daily category stats MV
backend/exence/src/main/resources/db/changelog/v1.1.0/create-widget-table.yaml Liquibase widget table + sequence + FK/index
backend/exence/src/main/resources/db/changelog/v1.1.0/create-mv-refresh-trigger.yaml Liquibase to install MV refresh function + triggers
backend/exence/src/main/resources/db/changelog/v1.1.0/create-mv-daily-category-stat.yaml Liquibase to create MV + required indexes
backend/exence/src/main/resources/db/changelog/v1.1.0/changelog-v1.1.0.yaml Includes new widget + MV changelogs
backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/TransactionRepository.java Adds scatter + boxplot chart queries
backend/exence/src/main/java/com/exence/finance/modules/statistics/validators/WidgetLayoutValidator.java Validates widget layout fields by widget type
backend/exence/src/main/java/com/exence/finance/modules/statistics/validators/AtLeastOneNotEmptyValidator.java Validates update-layout request has content
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/YearlySlopeProvider.java Provider for yearly slope widget payload
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/WidgetDataProvider.java Sealed provider SPI for widget data
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/WealthGrowthComboProvider.java Provider for wealth growth combo series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/TransactionScatterProvider.java Provider for transaction scatter series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/TransactionCountExpenseComboProvider.java Provider for expense+count combo series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/StatCardProvider.java (Placeholder) provider for stat card widgets
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/SpendingRadarProvider.java Provider for spending radar distribution
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/SpendingHeatmapProvider.java Provider for spending heatmap series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/SavingsGaugeProvider.java Provider for savings-rate gauge payload
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/SankeyProvider.java Provider for category sankey payload
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ProviderHelper.java Shared helpers for provider computations/mapping
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/MonthlyPeakPolarProvider.java Provider for monthly peak polar distribution
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/MonthlyCategoryRadarProvider.java Provider for monthly category radar series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/MonthlyBoxplotProvider.java Provider for monthly expense boxplot
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/MonthlyBalanceColumnProvider.java Provider for monthly balance column series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/IncomeTrendProvider.java Provider for income daily trend series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/IncomePieProvider.java Provider for income pie distribution
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/IncomeExpenseColumnProvider.java Provider for income vs expense columns
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/IncomeCategoryTrendProvider.java Provider for income category trend series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ExpenseTrendProvider.java Provider for expense daily trend series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ExpenseSavingsComboProvider.java Provider for expense + savings rate combo
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ExpensePieProvider.java Provider for expense pie distribution
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ExpenseCategoryTrendProvider.java Provider for expense category trend series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ExpenseCategoryColumnProvider.java Provider for expense category column series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/CategoryTreemapProvider.java Provider for income/expense treemap
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/CategoryBubbleProvider.java Provider for category bubble payload
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/CategoryBoxplotProvider.java Provider for category boxplot payload
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/CategoryAvgPolarProvider.java Provider for category average polar distribution
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/BalanceYearComparisonProvider.java Provider for balance year comparison series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/BalanceTrendProvider.java Provider for cumulative balance trend series
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/impl/WidgetServiceImpl.java Widget layout CRUD + data dispatch to providers
backend/exence/src/main/java/com/exence/finance/modules/statistics/service/WidgetService.java Widget service interface
backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/WidgetRepository.java Widget repository queries
backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/StatisticsRepository.java MV-backed statistics queries + projections
backend/exence/src/main/java/com/exence/finance/modules/statistics/mapper/WidgetMapper.java MapStruct mapping between entity/DTOs
backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/Widget.java Widget JPA entity with JSON settings
backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStatId.java Composite id for MV entity
backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStat.java Read-only MV entity mapping
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/response/WidgetLayoutResponse.java API response for widget layout
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/response/WidgetDataResponse.java API response for widget data
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/response/StatCardWidgetDTO.java API DTO for stat card widget layout
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/response/ChartWidgetDTO.java API DTO for chart widget layout
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/base/MonthlyProjection.java Base projection for month bucketing
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/base/CategoryProjection.java Base projection for category name/color
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/YearlyCategoryProjection.java Projection for yearly totals by category
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/TypeAmountProjection.java Projection for sums by transaction type
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/ScatterProjection.java Projection for scatter chart points
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/MonthlyTrendProjection.java Projection for monthly type trends
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/MonthlyIncomeExpenseProjection.java Projection for monthly income/expense(+count)
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/MonthlyCategoryProjection.java Projection for monthly category totals
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/MonthlyBalanceProjection.java Projection for monthly balance totals
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/HeatmapProjection.java Projection for heatmap day/week totals
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/DailyTrendProjection.java Projection for daily totals
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/CategoryStatsProjection.java Projection for amount/count/avg by category
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/CategoryFlowProjection.java Projection for totals by type+category
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/CategoryAverageProjection.java Projection for avg by category
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/projection/CategoryAmountProjection.java Projection for totals by category
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/WidgetDataPayload.java Sealed payload supertype
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/Trend.java Trend enum for stat card payload
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/StatCardPayload.java Stat card payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/SlopePayload.java Slope chart payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/SlopeItem.java Slope chart item structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/SeriesPayload.java Series payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/SeriesItem.java Series item structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/SankeyPayload.java Sankey payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/SankeyLink.java Sankey link structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/GaugePayload.java Gauge payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/DistributionPayload.java Distribution payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/DistributionItem.java Distribution item structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/DataPoint.java Generic chart datapoint structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/BubbleSeries.java Bubble series structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/BubblePoint.java Bubble point structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/BubblePayload.java Bubble payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/BoxplotPoint.java Boxplot point structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/payload/BoxplotPayload.java Boxplot payload structure
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/WidgetType.java Enumerates widget types and grouping helpers
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/WidgetSetting.java JSON-mapped widget settings keys
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/WidgetRequest.java Provider request inputs (dates/settings)
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/WidgetDTO.java Widget create DTO + layout validation hook
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/UpdateLayoutRequest.java Layout update request DTO
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/Timeframe.java Timeframe handling for widget queries
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/StatCardLayoutItem.java Layout item DTO for stat cards
backend/exence/src/main/java/com/exence/finance/modules/statistics/dto/ChartLayoutItem.java Layout item DTO for charts
backend/exence/src/main/java/com/exence/finance/modules/statistics/controller/impl/WidgetControllerImpl.java REST endpoints for widgets
backend/exence/src/main/java/com/exence/finance/modules/statistics/controller/WidgetController.java Widget controller interface
backend/exence/src/main/java/com/exence/finance/modules/statistics/annotations/ValidWidgetLayout.java Bean validation annotation for widget DTO
backend/exence/src/main/java/com/exence/finance/modules/statistics/annotations/AtLeastOneNotEmpty.java Bean validation annotation for update layout
backend/exence/src/main/java/com/exence/finance/common/util/DateUtils.java Date helpers for chart bucketing/labels

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +51 to +55

return new SeriesPayload(List.of(
new SeriesItem("Income", "column", "todo: zold kene ide", incomePoints),
new SeriesItem("Expense", "column", "todo: piros kene ide", expensePoints)));
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This provider returns placeholder strings ("todo: ...") in the color field for series items. If the API contract expects a valid color, this will break clients; return null or a valid color before merging.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +18
public class DailyCategoryStatId implements Serializable {
private Long userId;
private Instant statDate;
private Long categoryId;
private TransactionType type;
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IdClass requires the id-class to expose key fields as public/protected fields or JavaBean properties. This class currently has only private fields and no accessors, which can break JPA provider mapping. Consider making fields public/protected, adding getters/setters (e.g., Lombok @DaTa), or switching to @Embeddable + @EmbeddedId.

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +93
for (ChartLayoutItem item : request.charts()) {
Widget widget = existingWidgets.get(item.id());
if (widget == null) {
throw new EntityNotFoundException("Widget not found: " + item.id());
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, the charts loop updates x/y without verifying the widget is actually a graph widget. Validate widget.getType().isGraph() before applying x/y to prevent invalid persisted layouts.

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +42
@PathVariable Long widgetId, @RequestParam(required = false) Timeframe timeframe) {
return ResponseFactory.ok(widgetService.getWidgetData(widgetId, timeframe));
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeframe request param is bound directly to the Timeframe enum, so Spring will only accept values like ONE_WEEK, not the short codes (1W, YTD, etc.). If the API is meant to accept the codes, accept a String here and parse via Timeframe.fromCode(...), or register a Converter<String, Timeframe>.

Suggested change
@PathVariable Long widgetId, @RequestParam(required = false) Timeframe timeframe) {
return ResponseFactory.ok(widgetService.getWidgetData(widgetId, timeframe));
@PathVariable Long widgetId, @RequestParam(required = false) String timeframe) {
Timeframe parsedTimeframe = timeframe != null ? Timeframe.fromCode(timeframe) : null;
return ResponseFactory.ok(widgetService.getWidgetData(widgetId, parsedTimeframe));

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +57

return new SeriesPayload(List.of(
new SeriesItem("Expense", "column", "todo: piros szin", expensePoints),
new SeriesItem("Savings Rate", "line", null, savingsRatePoints)));
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This provider returns a placeholder string ("todo: ...") in the color field for a series item. If clients expect a real color value, this will break rendering; return null or a valid color.

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +21
@Override
public StatCardPayload getData(WidgetRequest request) {
return null;
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StatCardProvider#getData currently returns null, which will produce a null payload in the API response (or NPEs in callers/serializers) for EXAMPLE_STATCARD. Either implement a minimal payload or fail fast with an explicit exception until the stat card provider is implemented.

Copilot uses AI. Check for mistakes.
@hptrk hptrk force-pushed the feature/EX-262-statistics-backend branch from 2979a27 to fef8e64 Compare March 1, 2026 17:57
@hptrk hptrk force-pushed the feature/EX-262-statistics-backend branch from dcb648f to 7e261b3 Compare March 5, 2026 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants