feat(F-143): completed feature
This commit is contained in:
54
work/artifacts/F-143/documenter.md
Normal file
54
work/artifacts/F-143/documenter.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# F-143 — API contract documentation
|
||||
|
||||
## Resumen del cambio (user-facing)
|
||||
New backoffice **Reporting** module delivering the shared filter contract + RBAC foundation (F-142 §3/§6/§9). No report data is read here (F-144+ owns report data); `GET /reporting/filters/schema` only introspects the contract. Two new endpoints, both backoffice-only (backoffice_session or storefront `mdv_session` via `combinedAuth`):
|
||||
|
||||
## Nuevas rutas
|
||||
| Method | Path | Auth (authenticate) | Permission | Body / Query | 200 response |
|
||||
|--------|------|---------------------|------------|--------------|--------------|
|
||||
| GET | `/reporting/filters/schema` | `combinedAuth` (authenticated) | `REPORTING_VIEW` | n/a | `{ filterSchema, comparison, dataAvailability, permissions }` |
|
||||
| GET | `/reporting/filters/validate` | `combinedAuth` (authenticated) | `REPORTING_SALES` | `?from&to&compare?…` (see below) | `{ ok, filters, comparison: { range } }` |
|
||||
|
||||
## RBAC
|
||||
Permissions are role-based (no permission table yet — F-142 §9 "compatibilidad inicial"):
|
||||
- `admin` — all reporting permissions (incl. `REPORTING_FINANCIAL`, `REPORTING_EXPORT`).
|
||||
- `editor` — VIEW + SALES + PRODUCTS + CUSTOMERS + INVENTORY + DISCOUNTS + REFUNDS + TAXES.
|
||||
- `pos_manager` — VIEW + SALES + PAYMENTS + CASH.
|
||||
- `pos_cashier` — VIEW + SALES.
|
||||
- `customer` — none (403 on both routes).
|
||||
|
||||
A future `backoffice_permissions` migration keeps the `requireReportingPermission(user, perm)` call-site signature.
|
||||
|
||||
## Filter schema (shared contract)
|
||||
Query params parsed by `reportingFiltersSchema` via `parseJson` (→ 400 `VALIDATION_ERROR` on bad input):
|
||||
|
||||
- `from` *(string, required)* — ISO 8601 datetime, **inclusive** start.
|
||||
- `to` *(string, required)* — ISO 8601 datetime, **exclusive** end. `from < to` enforced (400 on inversion).
|
||||
- `compare` — enum `none | previous_equal | previous_calendar` (default `none`).
|
||||
- `channel` — enum `all | ecommerce | pos | admin` (default `all`).
|
||||
- `storeId`, `terminalId`, `cashierId`, `paymentMethodId`, `productId`, `categoryId`, `brandId` — repeatable UUID (single value or repeated).
|
||||
- `customerId` — single UUID (optional; walk-in POS has none).
|
||||
- `state` — repeatable string (e.g. `PAID,SHIPPED`).
|
||||
- `groupBy` — enum `day|week|month|hour|store|channel|terminal|cashier|payment`.
|
||||
- `page` *(int, default 1)*, `pageSize` *(int, 1..200, default 50)*.
|
||||
- `sort` — string (e.g. `-revenue`).
|
||||
|
||||
### Comparison range (`comparisonRange`, `[from,to)`)
|
||||
- `none` → `comparison.range = null`.
|
||||
- `previous_equal` → exact-duration mirror; prior window ends exactly at `range.from`.
|
||||
- `previous_calendar` → UTC-aligned prior window of `ceil(span_days)` days.
|
||||
|
||||
## `dataAvailability` (metadata only — F-142 §4 baseline)
|
||||
Never converted to 0. Currently:
|
||||
- `available`: `grossSales`, `discounts`, `tax`, `unitsSold`, `orders`, `customers`.
|
||||
- `unavailable`: `netSales`, `margin`, `paymentMethod`, `refunds`, `shipping`.
|
||||
|
||||
## Errores
|
||||
- `401` — unauthenticated (`authenticate` rejects).
|
||||
- `403` — authenticated but lacks the route permission.
|
||||
- `400` — malformed query (zod → `VALIDATION_ERROR`), incluyendo `from >= to` e UUIDs inválidos.
|
||||
|
||||
## Implementación
|
||||
- `project/src/modules/reporting/` (domain/application/api + tests + index).
|
||||
- `project/src/app/build-app.ts` — `registerReportingRoutes` registered inside `if (deps.pool)` with `combinedAuth`.
|
||||
No migrations, no DB schema or data-table changes in this ticket.
|
||||
Reference in New Issue
Block a user