diff --git a/DESIGN.md b/DESIGN.md index efb2f5c..a5a69e6 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,7 +1,7 @@ # Design System — ZarinPal Merchant Analytics - Status: Draft baseline for approval -- Version: 0.1.7 +- Version: 0.1.8 - Last updated: 2026-08-20 - Direction: Persian-first RTL @@ -93,7 +93,7 @@ Navigation labels should describe merchant tasks, not internal database concepts ## Core component contracts -- **App shell:** sidebar/drawer, utility header, page title, merchant identity, analytics progress/status. First access opens an authenticated SSE stream and starts all analytics sections; the page reveals each section independently as it becomes ready. +- **App shell:** sidebar/drawer, utility header, page title, merchant identity, analytics progress/status. First access idempotently starts a run, then opens its authenticated SSE stream; the page reveals overview, payment performance, fees, and peer comparison independently as each becomes ready. - **Metric card:** label, formatted value/unit, comparison and period, semantic trend, definition link, independent queued/calculating/ready/failed states. - **Chart card:** title, period/filter controls, concise takeaway, plot, legend, accessible tabular alternative, provenance link, and section-local loading/error behavior. - **Insight card:** deterministic finding, numeric evidence, suggested merchant action, confidence/limitation; AI-generated copy is visibly labeled later. @@ -144,6 +144,7 @@ Navigation labels should describe merchant tasks, not internal database concepts | Version | Date | Decision | |---|---|---| +| 0.1.8 | 2026-08-20 | Fixed the four parallel section ids, 30-day cache, idempotent start/SSE flow, and section timeout/retry behavior. | | 0.1.7 | 2026-08-20 | Moved analytics results to high-TTL Redis and defined partial, parallel section delivery through authenticated SSE. | | 0.1.6 | 2026-08-20 | Replaced time-based analytics freshness with lazy first-access calculation and revision-based merchant/cohort cache states; defined Saturday–Friday weeks. | | 0.1.5 | 2026-08-20 | Removed holiday/event reporting; limited period controls to daily, weekly, Jalali-month, and Persian-season views. | diff --git a/docs/DASHBOARD-SPEC.md b/docs/DASHBOARD-SPEC.md index 19063d3..ee9d811 100644 --- a/docs/DASHBOARD-SPEC.md +++ b/docs/DASHBOARD-SPEC.md @@ -27,9 +27,11 @@ Give a non-technical merchant a fast, trustworthy Persian RTL view of payment pe 9. Merchant-facing dates use the Jalali calendar in `Asia/Tehran`; API instants remain explicit ISO-8601 UTC and filtering sends unambiguous boundaries. 10. Approved reporting periods are daily, weekly, Jalali-month, and Persian-season views. Weekly periods run Saturday through Friday in `Asia/Tehran`. Every comparison states its exact period and baseline. 11. Only source session status `Verified` counts as a confirmed successful payment. `Paid` appears as a separate operational state until an approved metric-catalogue revision defines it otherwise. -12. The first relevant dashboard access starts all approved analytics-section jobs in bounded parallel. The app opens an authenticated, merchant-scoped SSE stream and renders each section as soon as its `ready` event arrives. A failed section has its own retry/error state and does not hide successful siblings. -13. Later equivalent requests reuse current high-TTL Redis entries. PostgreSQL merchant/cohort revision changes select new cache keys and cause only missing sections to be recalculated; cache age alone does not make static data stale. -14. SSE reconnect uses stable event ids/resume semantics, shows a connection-recovery state, and never exposes job status or analytics for another merchant. +12. The first relevant dashboard access sends an idempotent authenticated `POST` that creates or returns the current analytics run and starts four sections in bounded parallel: overview, payment performance, fees, and peer comparison. +13. The app then opens the run's authenticated `GET` SSE stream and renders each section as soon as its `ready` event arrives. A failed section has its own retry/error state and does not hide successful siblings. +14. Later equivalent requests reuse 30-day Redis entries. PostgreSQL merchant/cohort revision changes select new cache keys and cause only missing sections to be recalculated; cache age alone does not make static data stale. +15. SSE reconnect uses stable event ids/resume semantics, shows a connection-recovery state, and never exposes job status or analytics for another merchant. +16. Each section attempt times out after 60 seconds. The backend may perform at most two automatic transient retries using exponential backoff/jitter; the UI represents the section as calculating during automatic retries and exposes failure/retry only after exhaustion or a non-retryable error. ## Frontend architecture baseline @@ -49,8 +51,10 @@ Give a non-technical merchant a fast, trustworthy Persian RTL view of payment pe - Values visibly specify period and unit; missing/suppressed/zero states are distinct. - Confirmed-success views include only `Verified`; `Paid` is separately labeled and testable. - All core sections begin on first access and become visible independently in completion order without blocking the whole dashboard. +- The start request is idempotent and always maps equivalent concurrent starts to the same current run. - A second equivalent access reuses current Redis entries, and concurrent first accesses do not enqueue duplicate equivalent section jobs. - One section failure is isolated, retryable, and accessible; already-ready sections remain usable. +- A section does not remain indefinitely loading: each attempt is bounded to 60 seconds and no more than two automatic exponential-backoff retries occur. - Disconnecting and reconnecting the SSE stream resumes safely without cross-merchant data or duplicated final sections. - Daily, weekly, Jalali-month, and Persian-season filters use the same explicit boundaries as the API and database. - Production build passes type checking, linting, unit/component tests, and Playwright critical-flow tests.