feat(110): statistics summary

Phase 110 complete:
- add Statistics -> Podsumowanie page
- add monthly order count and value charts per integration plus total
- use Chart.js with table fallback and 04-2026 default history start
- update PAUL and DOCS technical documentation
This commit is contained in:
2026-04-28 22:47:14 +02:00
parent 1156ce046c
commit 0b4ffb7146
21 changed files with 2454 additions and 26 deletions

View File

@@ -0,0 +1,266 @@
---
phase: 110-statistics-summary
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/Modules/Statistics/OrdersStatisticsController.php
- src/Modules/Statistics/OrdersStatisticsRepository.php
- routes/web.php
- resources/views/layouts/app.php
- resources/views/statistics/summary.php
- resources/lang/pl.php
- public/assets/js/modules/statistics-summary-charts.js
- resources/scss/app.scss
- public/assets/css/app.css
- DOCS/ARCHITECTURE.md
- DOCS/DB_SCHEMA.md
- DOCS/TECH_CHANGELOG.md
- .paul/codebase/architecture.md
- .paul/codebase/db_schema.md
- .paul/codebase/tech_changelog.md
autonomous: false
delegation: off
---
<objective>
## Goal
Add a new first submenu item `Statystyki -> Podsumowanie` with two monthly line charts:
- monthly order count per integration plus a total line,
- monthly order value per integration plus a total line.
## Purpose
The operator needs a quick trend view before opening detailed daily order statistics. The summary should show how each sales integration contributes month by month and how the total business volume changes over time.
## Output
- New authenticated endpoint `/statistics/summary`.
- Sidebar order: `Podsumowanie` first, existing `Zamowienia` second.
- New summary view with compact filters and two charts.
- Backend monthly aggregation using existing orders data, grouped by integration/channel.
- Technical documentation updates. No database migration is expected.
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@AGENTS.md
@.paul/codebase/architecture.md
@.paul/codebase/db_schema.md
## Prior Work
@.paul/phases/105-orders-statistics/105-01-SUMMARY.md
@.paul/phases/109-checkbox-multiselect-filters/109-01-SUMMARY.md
## Source Files
@src/Modules/Statistics/OrdersStatisticsController.php
@src/Modules/Statistics/OrdersStatisticsRepository.php
@resources/views/statistics/orders.php
@resources/views/layouts/app.php
@routes/web.php
@resources/lang/pl.php
@resources/scss/app.scss
@package.json
## Notes
- `DOCS/DB_SCHEMA.md` and `DOCS/ARCHITECTURE.md` are required by `AGENTS.md`, but they are currently missing in the repo. APPLY should create them or reconcile them from `.paul/codebase/*` before documenting this feature.
- Existing statistics code already has filter parsing patterns, channel labels, status group defaults, collation handling, and amount fallback logic. Reuse those rather than creating a separate query style.
- `SPECIAL-FLOWS.md` requires `sonar-scanner` after APPLY and before UNIFY; frontend-design is optional for this UI work.
</context>
<skills>
## Required Skills (from SPECIAL-FLOWS.md)
| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| sonar-scanner | required | After APPLY, before UNIFY | o |
| /frontend-design | optional | During chart UI implementation/review | o |
**BLOCKING:** `sonar-scanner` must be run before UNIFY unless the environment blocks it.
</skills>
<acceptance_criteria>
## AC-1: Sidebar Navigation
```gherkin
Given the user is authenticated
When the sidebar statistics section is visible
Then the first item under "Statystyki" is "Podsumowanie"
And the second item remains "Zamowienia"
And clicking "Podsumowanie" opens `/statistics/summary`
And the active state highlights "Podsumowanie" on that page
```
## AC-2: Monthly Order Count Chart
```gherkin
Given orders exist across multiple months and integrations
When the user opens `/statistics/summary`
Then the page shows an order count chart grouped by month
And each integration has its own line
And an additional "Razem" line sums all selected integrations per month
```
## AC-3: Monthly Order Value Chart
```gherkin
Given orders exist across multiple months and integrations
When the user opens `/statistics/summary`
Then the page shows an order value chart grouped by month
And each integration has its own line
And an additional "Razem" line sums all selected integrations per month
And values are displayed as money with two decimal places
```
## AC-4: Existing Statistics Semantics Reused
```gherkin
Given the user changes the date range, channel selection, or status group selection
When the summary page reloads
Then both charts use the same selected filters
And channel labels match existing statistics labels
And default status groups still exclude the cancelled group
```
## AC-5: Empty and Degraded States
```gherkin
Given the selected filters return no orders
When the user opens `/statistics/summary`
Then the page shows a clear empty state instead of broken charts
Given JavaScript fails to load
When the user opens `/statistics/summary`
Then the monthly data remains visible in an HTML table fallback
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Add monthly statistics backend and route</name>
<files>src/Modules/Statistics/OrdersStatisticsController.php, src/Modules/Statistics/OrdersStatisticsRepository.php, routes/web.php</files>
<action>
Extend the existing Statistics module with a new summary action:
- Add `summary(Request $request): Response` to `OrdersStatisticsController`.
- Reuse or extract existing filter helpers for date range, channel options, selected channels, status groups, selected status groups, and status-code resolution.
- Use a useful monthly default range: first day of January of the current year through the current date, unless GET filters are supplied.
- Add repository method `aggregateByMonth(string $dateFrom, string $dateTo, array $channels, array $statusCodes): array`.
- The query must reuse the existing effective date, channel, gross amount, and status SQL semantics from `aggregateByDay()`.
- Group rows by `DATE_FORMAT(effective_date, "%Y-%m")` and channel key.
- Build a controller view-model with ordered month labels, per-channel count series, per-channel value series, and total series for both charts.
- Add route `GET /statistics/summary` behind `AuthMiddleware` using the existing controller instance.
Avoid: no schema changes, no raw user input in SQL strings, no duplicate channel/status logic that can drift from `/statistics/orders`.
</action>
<verify>
- `php -l src/Modules/Statistics/OrdersStatisticsController.php`
- `php -l src/Modules/Statistics/OrdersStatisticsRepository.php`
- `php -l routes/web.php`
- Manual check that `/statistics/summary` returns HTTP 200 for an authenticated session.
</verify>
<done>AC-2, AC-3, and AC-4 satisfied at backend/view-model level.</done>
</task>
<task type="auto">
<name>Task 2: Add summary UI, charts, menu item, and translations</name>
<files>resources/views/layouts/app.php, resources/views/statistics/summary.php, resources/lang/pl.php, public/assets/js/modules/statistics-summary-charts.js, resources/scss/app.scss, public/assets/css/app.css</files>
<action>
Create the visible statistics summary experience:
- Add `Podsumowanie` translation keys under navigation and `statistics.summary.*`.
- In the sidebar statistics group, place `Podsumowanie` before `Zamowienia`, link it to `/statistics/summary`, and use `activeStatistics='summary'`.
- Create `resources/views/statistics/summary.php` with compact filters matching `/statistics/orders`: date from/to, channels multiselect, status groups multiselect, submit/reset actions.
- Render two chart panels: order count and order value. Each panel must include a `<canvas>` or SVG/chart container plus a table fallback with monthly rows and per-series columns.
- Add `public/assets/js/modules/statistics-summary-charts.js` to render the two charts from JSON embedded in the page after escaping through `json_encode(..., JSON_HEX_*)`.
- Keep chart rendering small and local. Do not add a package dependency unless implementation discovers existing project-approved chart tooling.
- Include the module in `resources/views/layouts/app.php` with `filemtime()` cache busting.
- Add compact SCSS in `resources/scss/app.scss`, then build `public/assets/css/app.css` with `npm run build:css`.
Avoid: no inline CSS in PHP views, no native `alert()`/`confirm()`, no decorative oversized dashboard layout. The page should stay dense and operational.
</action>
<verify>
- `php -l resources/views/layouts/app.php`
- `php -l resources/views/statistics/summary.php`
- `php -l resources/lang/pl.php`
- `npm run build:css`
- Browser/manual check confirms two non-empty charts render when data exists and fallback tables are present in the DOM.
</verify>
<done>AC-1, AC-2, AC-3, and AC-5 satisfied at UI level.</done>
</task>
<task type="auto">
<name>Task 3: Update technical documentation</name>
<files>DOCS/ARCHITECTURE.md, DOCS/DB_SCHEMA.md, DOCS/TECH_CHANGELOG.md, .paul/codebase/architecture.md, .paul/codebase/db_schema.md, .paul/codebase/tech_changelog.md</files>
<action>
Update documentation required by `AGENTS.md` and PAUL:
- If root `DOCS/` files are still missing, create `DOCS/ARCHITECTURE.md`, `DOCS/DB_SCHEMA.md`, and `DOCS/TECH_CHANGELOG.md` using the current `.paul/codebase/*` documents as the baseline where appropriate.
- Document the new `/statistics/summary` route, controller action, repository monthly aggregation method, chart frontend module, and sidebar change in architecture docs.
- Document that the feature uses existing `orders`, `integrations`, `order_status_groups`, and `order_statuses` tables without migration changes.
- Add a dated technical changelog entry explaining the new summary charts and why no DB schema change was needed.
- Keep `.paul/codebase/*` in sync with the same architecture/schema/changelog facts.
</action>
<verify>
- `git diff -- DOCS .paul/codebase` shows architecture/changelog updates and no false DB migration claim.
- Documentation mentions `/statistics/summary`, `aggregateByMonth()`, and `statistics-summary-charts.js`.
</verify>
<done>Documentation requirements from `AGENTS.md` and PAUL are satisfied.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>`Statystyki -> Podsumowanie` with two monthly charts</what-built>
<how-to-verify>
1. Open `/statistics/summary`.
2. Confirm the sidebar shows `Podsumowanie` as the first item under `Statystyki`.
3. Confirm chart 1 shows monthly order counts with one line per integration plus `Razem`.
4. Confirm chart 2 shows monthly order values with one line per integration plus `Razem`.
5. Change filters and confirm both charts update consistently.
</how-to-verify>
<resume-signal>Type "approved" to continue to UNIFY, or describe visual/data issues to fix.</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- Import/synchronization modules for Allegro/shopPRO.
- Existing `/statistics/orders` route contract and GET parameter names.
- Database migrations unless a blocker proves the existing schema cannot support the charts.
- Runtime DB env behavior: do not wire `DB_HOST_REMOTE` into application runtime.
## SCOPE LIMITS
- This plan adds only summary charts for orders. It does not add exports, product charts, inventory charts, or accounting reports.
- Values chart uses the existing gross amount semantics from current order statistics unless the user explicitly asks for net values.
- Chart interactivity is limited to readable lines/legend/tooltips if implemented locally; advanced drill-down is out of scope.
- No new native alerts or confirms.
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `php -l src/Modules/Statistics/OrdersStatisticsController.php`
- [ ] `php -l src/Modules/Statistics/OrdersStatisticsRepository.php`
- [ ] `php -l routes/web.php`
- [ ] `php -l resources/views/layouts/app.php`
- [ ] `php -l resources/views/statistics/summary.php`
- [ ] `php -l resources/lang/pl.php`
- [ ] `npm run build:css`
- [ ] Manual/browser check: `/statistics/summary` renders two charts and table fallbacks.
- [ ] Manual/browser check: sidebar order and active states are correct.
- [ ] Manual data check: monthly total equals sum of integration values for at least one month.
- [ ] Documentation updated in `DOCS/` and `.paul/codebase/`.
- [ ] `sonar-scanner` run before UNIFY, or blocker recorded if unavailable.
- [ ] All acceptance criteria met.
</verification>
<success_criteria>
- `Statystyki -> Podsumowanie` is the first statistics submenu item.
- `/statistics/summary` displays two monthly charts: order count and order value.
- Each chart includes separate integration series and a `Razem` series.
- Filters are consistent with existing order statistics behavior.
- No database schema change is introduced.
- Technical documentation is updated.
</success_criteria>
<output>
After completion, create `.paul/phases/110-statistics-summary/110-01-SUMMARY.md`.
</output>

View File

@@ -0,0 +1,197 @@
---
phase: 110-statistics-summary
plan: 01
subsystem: statistics
tags: [statistics, charts, chartjs, monthly-summary, ui, reporting]
requires:
- phase: 105-orders-statistics
provides: daily statistics filters, channel semantics, status group filtering
- phase: 109-checkbox-multiselect-filters
provides: reusable checkbox multiselect filter enhancement
provides:
- /statistics/summary monthly summary page
- monthly order count chart per integration plus total
- monthly order value chart per integration plus total
- DOCS baseline synchronized from .paul/codebase
affects: [statistics, reporting, sidebar-navigation]
tech-stack:
added: [Chart.js 4.4.8 CDN]
patterns: [monthly statistics aggregation, Chart.js view-model, table fallback]
key-files:
created:
- resources/views/statistics/summary.php
- public/assets/js/modules/statistics-summary-charts.js
- DOCS/ARCHITECTURE.md
- DOCS/DB_SCHEMA.md
- DOCS/TECH_CHANGELOG.md
modified:
- src/Modules/Statistics/OrdersStatisticsController.php
- src/Modules/Statistics/OrdersStatisticsRepository.php
- routes/web.php
- resources/views/layouts/app.php
- resources/lang/pl.php
- resources/scss/app.scss
- public/assets/css/app.css
key-decisions:
- "Default summary history starts at 2026-04-01 even if older orders exist."
- "Charts use Chart.js 4.4.8 from CDN for interactive legend and tooltips."
- "Gross order value uses existing statistics gross amount semantics."
patterns-established:
- "Monthly statistics use the same channel/status/effective-date helpers as daily statistics."
- "Charts are backed by HTML table fallbacks."
duration: ~90min
started: 2026-04-28T22:20:00+02:00
completed: 2026-04-28T23:50:00+02:00
---
# Phase 110 Plan 01: Statistics Summary
Monthly statistics summary shipped with two interactive Chart.js line charts, compact filters, per-integration series, total series, and table fallbacks.
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~90min |
| Started | 2026-04-28T22:20:00+02:00 |
| Completed | 2026-04-28T23:50:00+02:00 |
| Tasks | 3 auto tasks + 1 human verification checkpoint |
| Files modified | 18 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Sidebar Navigation | Pass | `Podsumowanie` added first under `Statystyki`; `/statistics/summary` route registered with active state. |
| AC-2: Monthly Order Count Chart | Pass | Count chart model contains one dataset per selected integration plus `Razem`; rendered by Chart.js. |
| AC-3: Monthly Order Value Chart | Pass | Value chart model contains one dataset per selected integration plus `Razem`; values formatted as money in tooltips/table. |
| AC-4: Existing Statistics Semantics Reused | Pass | Controller reuses channel/status filter flow; repository reuses effective date/channel/status/gross SQL helpers. |
| AC-5: Empty and Degraded States | Pass | Empty state shown when no data; tables remain visible as fallback below charts. |
## Accomplishments
- Added authenticated `/statistics/summary` page with monthly order count and order gross value charts.
- Added `OrdersStatisticsRepository::aggregateByMonth()` using prepared parameters and existing statistics SQL helper semantics.
- Added `OrdersStatisticsController::summary()` and a chart/table view-model with total lines.
- Updated sidebar navigation, translations, SCSS, compiled CSS, and Chart.js frontend module.
- Created root `DOCS/` technical documentation required by `AGENTS.md` and synchronized it with `.paul/codebase/`.
## Task Commits
Task-level atomic commits were not used in this inline APPLY. A single phase commit is created during transition.
| Task | Commit | Type | Description |
|------|--------|------|-------------|
| Task 1: Add monthly statistics backend and route | phase commit | feat | Controller summary action, monthly aggregation, `/statistics/summary` route |
| Task 2: Add summary UI, charts, menu item, and translations | phase commit | feat | Summary view, sidebar link, Chart.js charts, SCSS/CSS |
| Task 3: Update technical documentation | phase commit | docs | `DOCS/` and `.paul/codebase/` updates |
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `src/Modules/Statistics/OrdersStatisticsController.php` | Modified | Added summary action, monthly default range from `2026-04-01`, chart/table view-model builders. |
| `src/Modules/Statistics/OrdersStatisticsRepository.php` | Modified | Added `aggregateByMonth()` with existing statistics SQL semantics. |
| `routes/web.php` | Modified | Registered authenticated `GET /statistics/summary`. |
| `resources/views/layouts/app.php` | Modified | Added `Podsumowanie` sidebar link and Chart.js/module scripts. |
| `resources/views/statistics/summary.php` | Created | Summary filters, two charts, and two fallback tables. |
| `resources/lang/pl.php` | Modified | Added navigation and `statistics.summary.*` translations. |
| `public/assets/js/modules/statistics-summary-charts.js` | Created | Chart.js renderer for count/value line charts. |
| `resources/scss/app.scss` | Modified | Added compact two-column desktop layout and chart/table styles. |
| `public/assets/css/app.css` | Modified | Compiled CSS output. |
| `DOCS/ARCHITECTURE.md` | Created | Root architecture docs baseline plus summary feature. |
| `DOCS/DB_SCHEMA.md` | Created | Root schema docs baseline plus reporting usage note. |
| `DOCS/TECH_CHANGELOG.md` | Created | Root technical changelog baseline plus phase 110 entry. |
| `.paul/codebase/architecture.md` | Modified | Documented route, controller flow, Chart.js module. |
| `.paul/codebase/db_schema.md` | Modified | Documented no-migration reporting usage. |
| `.paul/codebase/tech_changelog.md` | Modified | Added phase 110 technical changelog. |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Start history at `2026-04-01` | User requested `04-2026` as hard start despite older data. | Default summary excludes older months unless code changes later. |
| Use Chart.js 4.4.8 CDN | User requested an interactive JS library; project already uses CDN for Quill. | No npm dependency or build pipeline change. |
| Use gross order values | Existing statistics gross semantics are stable and already documented. | Value chart matches current order statistics totals. |
| Keep table fallback | Required degraded state and useful for verification. | Data remains visible without Chart.js/JS. |
## Deviations from Plan
| Type | Count | Impact |
|------|-------|--------|
| Scope adjustments from user feedback | 3 | Improved UI and changed default date semantics. |
| Environment blockers | 3 | Verification limits only; code/build checks passed. |
**Total impact:** Controlled deviations; feature outcome matches latest user request.
### Adjusted During APPLY
**Chart renderer changed to Chart.js**
- Found during user feedback after APPLY.
- Fix: Added Chart.js CDN and rewrote `statistics-summary-charts.js` to use Chart.js legends/tooltips.
- Verification: `node --check`, PHP lint, CSS build, Sonar scan.
**Desktop layout split**
- Found during user feedback after APPLY.
- Fix: Added two-column chart grid and two-column table grid from 1100px.
- Verification: PHP lint and CSS build.
**Default history start**
- Found during user feedback after APPLY.
- Fix: Set summary default `date_from` to `2026-04-01`.
- Verification: PHP lint.
### Deferred Items
- SonarQube issue import into `DOCS/todo.md` was not performed because no SonarQube MCP resources/tools are available in this Codex session.
- Full authenticated HTTP verification was not possible locally because MySQL/XAMPP refused the DB connection.
- PHPUnit was not run because `composer` is not available in PATH and `vendor/` is absent.
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| Local bootstrap failed with MySQL connection refused. | Started PHP dev server anyway; documented DB blocker. |
| `composer test` unavailable. | Documented test blocker; ran available lint/build/static checks. |
| Sonar MCP unavailable. | Ran `sonar-scanner` successfully and documented inability to fetch issue details. |
## Verification Results
| Check | Result |
|-------|--------|
| `php -l src/Modules/Statistics/OrdersStatisticsController.php` | Pass |
| `php -l src/Modules/Statistics/OrdersStatisticsRepository.php` | Pass |
| `php -l routes/web.php` | Pass |
| `php -l resources/views/layouts/app.php` | Pass |
| `php -l resources/views/statistics/summary.php` | Pass |
| `php -l resources/lang/pl.php` | Pass |
| `node --check public/assets/js/modules/statistics-summary-charts.js` | Pass |
| `npm run build:css` | Pass |
| `sonar-scanner` | Pass; report uploaded to SonarQube |
| Local `/statistics/summary` HTTP 200 | Blocked by local MySQL connection refused |
| `composer test` / PHPUnit | Blocked: `composer` not in PATH and `vendor/` absent |
## Skill Audit
| Expected | Invoked | Notes |
|----------|---------|-------|
| `sonar-scanner` | yes | Ran successfully after APPLY changes. |
## Next Phase Readiness
**Ready:**
- Statistics summary page exists and is wired into sidebar navigation.
- Monthly aggregation pattern can be reused for future reporting charts.
- Root `DOCS/` docs now exist for future AGENTS.md-compliant changes.
**Concerns:**
- Chart.js is CDN-based; if offline operation becomes required, vendor locally or add npm build support.
- Local verification depends on XAMPP/MySQL being available.
- Sonar issue import still needs a working SonarQube MCP/tool path.
**Blockers:**
- None for closing Phase 110.
---
*Phase: 110-statistics-summary, Plan: 01*
*Completed: 2026-04-28*