docs: align dashboard payment semantics
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# Design System — ZarinPal Merchant Analytics
|
# Design System — ZarinPal Merchant Analytics
|
||||||
|
|
||||||
- Status: Draft baseline for approval
|
- Status: Draft baseline for approval
|
||||||
- Version: 0.1.9
|
- Version: 0.2.0
|
||||||
- Last updated: 2026-08-20
|
- Last updated: 2026-08-20
|
||||||
- Direction: Persian-first RTL
|
- Direction: Persian-first RTL
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ Initial authenticated routes:
|
|||||||
1. ورود (login)
|
1. ورود (login)
|
||||||
2. پیشخوان (overview)
|
2. پیشخوان (overview)
|
||||||
3. عملکرد پرداخت (success, retries, failures, timing)
|
3. عملکرد پرداخت (success, retries, failures, timing)
|
||||||
4. کارمزد و درآمد (relative fee/cost analytics, clearly qualified)
|
4. کارمزد و درآمد (real merchant fee amounts and rates in Rial)
|
||||||
5. مقایسه با همگروهها (anonymized category/cohort benchmark)
|
5. مقایسه با همگروهها (anonymized category/cohort benchmark)
|
||||||
6. کیفیت داده / درباره شاخصها (definitions, freshness, limitations)
|
6. کیفیت داده / درباره شاخصها (definitions, freshness, limitations)
|
||||||
7. حساب کاربری / خروج
|
7. حساب کاربری / خروج
|
||||||
@@ -113,7 +113,8 @@ Navigation labels should describe merchant tasks, not internal database concepts
|
|||||||
- Charts have a textual summary and downloadable/visible data table when practical.
|
- Charts have a textual summary and downloadable/visible data table when practical.
|
||||||
- Zero, unavailable, suppressed, and not-yet-calculated are visually and linguistically distinct.
|
- Zero, unavailable, suppressed, and not-yet-calculated are visually and linguistically distinct.
|
||||||
- A ready section appears immediately without layout-shifting or blocking on unfinished siblings. Overall progress remains understandable without relying on animation.
|
- A ready section appears immediately without layout-shifting or blocking on unfinished siblings. Overall progress remains understandable without relying on animation.
|
||||||
- Only source status `Verified` is presented as a confirmed successful payment. `Paid` is a separate operational state and is never merged into success or failure without a later approved metric-definition change.
|
- Source statuses `Paid` and `Verified` both count as successful bank payments because funds were deducted. Keep them visually distinguishable: `Paid` means merchant verification is incomplete and is an actionable gap; `Verified` is finalized.
|
||||||
|
- Present `fee_amount_rial` as the merchant's real fee, summed once per session. Never multiply it by retry attempts or label it as obfuscated/relative-only in the product.
|
||||||
|
|
||||||
## Motion
|
## Motion
|
||||||
|
|
||||||
@@ -145,12 +146,12 @@ Navigation labels should describe merchant tasks, not internal database concepts
|
|||||||
|
|
||||||
| Version | Date | Decision |
|
| Version | Date | Decision |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| 0.2.0 | 2026-08-20 | Corrected payment lifecycle semantics from CTO guidance: `Paid` and `Verified` are bank-payment successes, `Paid` remains unverified, and session-level fees are real Rial amounts. |
|
||||||
| 0.1.9 | 2026-08-20 | Added rate-limit UX, 15-second SSE heartbeat/recovery, one-hour replay, and failed-section-only manual retry. |
|
| 0.1.9 | 2026-08-20 | Added rate-limit UX, 15-second SSE heartbeat/recovery, one-hour replay, and failed-section-only manual retry. |
|
||||||
| 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.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.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.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. |
|
| 0.1.5 | 2026-08-20 | Removed holiday/event reporting; limited period controls to daily, weekly, Jalali-month, and Persian-season views. |
|
||||||
| 0.1.4 | 2026-08-20 | Kept `Paid` separate from confirmed `Verified` success. |
|
|
||||||
| 0.1.2 | 2026-08-20 | Added the insufficient-data state and visibility threshold for anonymized peer comparisons. |
|
| 0.1.2 | 2026-08-20 | Added the insufficient-data state and visibility threshold for anonymized peer comparisons. |
|
||||||
| 0.1.1 | 2026-08-20 | Fixed merchant-facing time presentation to the Jalali calendar in `Asia/Tehran`, with explicit UTC API instants. |
|
| 0.1.1 | 2026-08-20 | Fixed merchant-facing time presentation to the Jalali calendar in `Asia/Tehran`, with explicit UTC API instants. |
|
||||||
| 0.1.0 | 2026-08-20 | Established ZarinPal-inspired RTL foundation from supplied public/panel screenshots; fixed SvelteKit/Svelte/TypeScript/Tailwind stack; defined responsive shell, core components, accessibility, chart, and motion rules. |
|
| 0.1.0 | 2026-08-20 | Established ZarinPal-inspired RTL foundation from supplied public/panel screenshots; fixed SvelteKit/Svelte/TypeScript/Tailwind stack; defined responsive shell, core components, accessibility, chart, and motion rules. |
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Give a non-technical merchant a fast, trustworthy Persian RTL view of payment pe
|
|||||||
8. Responsive behavior and component contracts follow `DESIGN.md`.
|
8. Responsive behavior and component contracts follow `DESIGN.md`.
|
||||||
9. Merchant-facing dates use the Jalali calendar in `Asia/Tehran`; API instants remain explicit ISO-8601 UTC and filtering sends unambiguous boundaries.
|
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.
|
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.
|
11. `Paid` and `Verified` both count as successful bank payments. `Paid` means funds were deducted but merchant verification is incomplete; `Verified` is finalized. Success and paid-volume metrics include both, while verification-health metrics show them separately.
|
||||||
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.
|
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.
|
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.
|
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.
|
||||||
@@ -35,6 +35,8 @@ Give a non-technical merchant a fast, trustworthy Persian RTL view of payment pe
|
|||||||
17. SSE expects a heartbeat every 15 seconds and supports authorized replay for one hour. After replay expires, the app fetches the current run snapshot before reopening the stream.
|
17. SSE expects a heartbeat every 15 seconds and supports authorized replay for one hour. After replay expires, the app fetches the current run snapshot before reopening the stream.
|
||||||
18. Manual retry targets only one exhausted failed section. It is disabled while active, never restarts ready siblings, and handles a typed `429` by honoring `Retry-After`.
|
18. Manual retry targets only one exhausted failed section. It is disabled while active, never restarts ready siblings, and handles a typed `429` by honoring `Retry-After`.
|
||||||
19. Analytics starts, manual retries, and concurrent SSE connections expose accessible rate-limited states without discarding already-ready content or retrying in a tight loop.
|
19. Analytics starts, manual retries, and concurrent SSE connections expose accessible rate-limited states without discarding already-ready content or retrying in a tight loop.
|
||||||
|
20. Paid amount and fee totals count each eligible session once. Merchant fees are shown as real Rial amounts/rates; retry attempts cannot multiply a session fee.
|
||||||
|
21. Retry recovery may finish in either `Paid` or `Verified`. Timing cards show p50, p95, sample size, and non-null coverage.
|
||||||
|
|
||||||
## Frontend architecture baseline
|
## Frontend architecture baseline
|
||||||
|
|
||||||
@@ -52,7 +54,9 @@ Give a non-technical merchant a fast, trustworthy Persian RTL view of payment pe
|
|||||||
- Critical flows work at 360 px, 768 px, 1024 px, and a wide desktop viewport in RTL.
|
- Critical flows work at 360 px, 768 px, 1024 px, and a wide desktop viewport in RTL.
|
||||||
- Login, navigation drawer, filters, chart alternatives, and logout are keyboard complete and screen-reader understandable.
|
- Login, navigation drawer, filters, chart alternatives, and logout are keyboard complete and screen-reader understandable.
|
||||||
- Values visibly specify period and unit; missing/suppressed/zero states are distinct.
|
- Values visibly specify period and unit; missing/suppressed/zero states are distinct.
|
||||||
- Confirmed-success views include only `Verified`; `Paid` is separately labeled and testable.
|
- Success views include `Paid` plus `Verified`, verification-completion views separate them, and unverified paid sessions are never styled or described as failures.
|
||||||
|
- Paid volume and merchant fee values reconcile at session grain; fee totals remain unchanged when a session has additional attempts.
|
||||||
|
- Retry recovery includes eventual `Paid` or `Verified`, and timing percentiles never treat missing values as zero.
|
||||||
- All core sections begin on first access and become visible independently in completion order without blocking the whole dashboard.
|
- 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.
|
- 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.
|
- A second equivalent access reuses current Redis entries, and concurrent first accesses do not enqueue duplicate equivalent section jobs.
|
||||||
|
|||||||
Reference in New Issue
Block a user