PRD: Sales reports & access
| Module | Reports | PRD ID | PRD-SLS-001 |
| Status | Ready to dev | FEAT | SLS |
| Epic | — | Plane | BANA-1517 |
| Date | 2026-05-28 | Version | v1.0 |
| Packages | @nx/sale | URD | SLS |
| Surface | Client · Owner/MgrBO · Ops | ||
| Owner | Phát Nguyễn | ||
TL;DR
Read-only views over what actually sold: how much per day, which products and categories drive revenue, and how purchase spending stacks up against it. Every report is scoped to the user's merchant, needs a date range, and counts only completed orders - so the numbers an owner runs the merchant on are always right and never leak across merchants.
1. Context & Problem
An owner needs trustworthy read-only views over the business: daily sales, top products and categories, and how purchasing spend compares to revenue. Orders and purchase orders already exist as transactional records, but nothing aggregates them - so an owner can't answer "how much did I sell yesterday", "what sells best", or "how does cost compare to revenue" without counting by hand.
This increment builds the read-side on top of completed sale and purchase orders, scoping every aggregation to the requesting user's own merchant and surfacing it through revenue-report screens. Aggregation runs efficiently in the data layer, not row-by-row; reports never mutate data.
2. Goals & Non-Goals
Goals
- Daily sales summary - per-day gross, tax, discount, net, and order count over a from-to date range.
- Product sales report - top products ranked by revenue and quantity.
- Category sales report with single-category drill-down.
- Purchase summary - supplier / purchase-order spending for cost comparison.
- Strict scoping - every report confined to the user's merchant access, requiring a date range, counting only completed orders, with empty result sets rendering as zero totals rather than errors.
Non-Goals
- Shift X / Z reports and cash reconciliation - owned by the separate
SHFfeature (URD-SHF), still in-progress. - Profit & loss / margin analytics, inventory valuation, customer retention analytics - owned by
ADV(URD-ADV). - Export to PDF / CSV / Excel and scheduled auto-generated reports.
- Tax declaration reports (owned by Tax & Invoice).
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Tenancy isolation | 0 cross-merchant rows in any report response; every report confined to the user's own merchant |
| Figure correctness | Daily totals reconcile against completed orders in range; end date is included in the window |
| Completed-only accuracy | Cancelled / draft orders never contribute to sales figures |
| Empty-state robustness | A range with no matching orders returns zero totals, never an error |
4. Personas & Use Cases
| Persona | Goal in this feature |
|---|---|
| Owner | See daily sales, best sellers, category mix, and cost-vs-revenue across the merchant |
| Manager | Review sales / product / category / purchase reports for the merchant |
Core scenarios: pick a from-to date range → view the daily sales summary → rank products by revenue and quantity → break down by category and drill into one → review purchase spending for cost comparison - all scoped to the user's merchant.
5. User Stories
- As an owner, I want a daily sales summary over a date range, so that I can see gross, tax, discount, net, and order count per day.
- As a manager, I want top products ranked by revenue and quantity, so that I know what sells best.
- As a manager, I want sales broken down by category, so that I can compare category performance.
- As a manager, I want to drill into a single category, so that I can inspect its detail.
- As an owner, I want a purchase summary by supplier / purchase order, so that I can compare cost against revenue.
- As an owner, I want every report scoped to my merchant and to count only completed orders, so that the figures are always correct and never leak across merchants.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Daily sales summary: per-day gross / tax / discount / net / order count over a from-to range | URD-SLS-001 |
| FR-2 | Product sales: top products ranked by revenue and quantity | URD-SLS-002 |
| FR-3 | Category sales: totals broken down by product category | URD-SLS-003 |
| FR-4 | Category drill-down: detail for a single chosen category | URD-SLS-004 |
| FR-5 | Purchase summary: supplier / purchase-order spending for cost comparison | URD-SLS-005 |
| FR-6 | Every query scoped to the user's merchant access; no cross-merchant leakage | URD-ACC-001 |
| FR-7 | Sales reports require a from-to date range; the end date is included in the window | URD-ACC-002 |
| FR-8 | Only completed sale orders and completed / received purchase orders are aggregated; cancelled / draft are excluded | URD-ACC-003 |
| FR-9 | Empty result sets render gracefully as zero totals, not an error | URD-ACC-004 |
Full requirement text and acceptance criteria live in the Reports URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Read-only | Reports aggregate over completed orders and never mutate data |
| Tenancy & authz | Every aggregation confined to the user's own merchant; no cross-merchant rows |
| Date semantics | A from-to range is mandatory; the window is inclusive of the end date |
| Performance / scale | Aggregation computed efficiently in the data layer over completed orders, not row-by-row |
| Robustness | Empty result sets resolve to zero totals, not errors |
| i18n | User-facing labels are bilingual (English and Vietnamese) |
8. UX & Flows
Key screens: the revenue-report dashboard with charts and the report filters (date-range, reset state), on their own report route.
9. Data & Domain
The reporting capability exposes four logical read-only report views. Each computes aggregates over completed orders within the requested date range and is confined to the user's own merchant:
| Report view | What it computes |
|---|---|
| Daily summary | Per-day gross, tax, discount, net, and order count over the from-to range |
| Product ranking | Top products ranked by revenue and quantity |
| Category breakdown + drill-down | Totals grouped by product category, with detail for a single chosen category |
| Purchase summary | Spending grouped by supplier / purchase order for cost comparison |
Conceptual only - full schema and query detail in the sale domain model.
10. Dependencies & Assumptions
Depends on
- Orders - completed sale orders are the source of every sales figure.
- Product / category data - product and category names drive the product / category breakdowns.
- Order monetary totals - order totals feed the summaries.
- Purchase orders - completed purchase orders feed the purchase summary.
Assumptions
- The requesting user has a resolvable merchant scope.
- Completed orders carry the monetary fields (gross, tax, discount, net) the summaries aggregate.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Cross-merchant leakage in aggregation | Every report confined to the user's own merchant; scoping enforced on the read path |
| Off-by-one on the date window | Window is inclusive of the end date for completed sale and purchase orders |
| Large date ranges scanning many orders | Aggregation computed efficiently in the data layer rather than row-by-row |
| Inconsistent status filtering across report types | Cancelled / draft orders are excluded from every report; sale reports count completed orders, purchase reports count completed and received orders |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 - see URD feature catalog (SLS and ACC Built) |
| Rollout | All merchants; no feature flag |
| Migration | None (read-only aggregation over existing orders) |
| Launch criteria | Daily / product / category / purchase reports return correct totals; merchant scoping verified; empty ranges return zero totals; end date included |
| Monitoring | Report request volume, query latency over large ranges, cross-merchant isolation checks |
13. FAQ
Which orders count toward sales figures? Only completed orders - cancelled and draft orders are excluded from every sales report.
Is the date range optional? No - sales reports require a from-to range, and the window includes the end date.
Can I see another merchant's figures? No - every report is scoped to the user's merchant access; cross-merchant data is never returned.
What happens when there are no matching orders? The report returns zero totals rather than raising an error.
Where are shift X / Z reports? Those belong to the separate SHF Shift Reports feature, not this increment.
References
- URD: Reports - Sales Reports · Access & Scoping
- Related: Shift Reports · Advanced Analytics
- Module: Reports - URD
- Developer: Sale · Sales Report