Add reporting features with new report engine and bookmark management

- Introduced a comprehensive report engine for generating and managing reports, including sales and logistics reports.
- Added new API endpoints for retrieving report configurations, data, and metadata, ensuring secure access with privilege checks.
- Implemented a report bookmarks system to allow users to save and manage report filters and configurations.
- Created database migrations for the `report_bookmarks` table and updated the schema to support new report functionalities.
- Developed services and controllers for handling report queries and bookmarks, including CRUD operations for bookmarks.
- Enhanced API documentation to reflect the new reporting features and endpoints.
- Added unit and integration tests to validate the new functionalities and ensure data integrity across report operations.
This commit is contained in:
shancheas
2026-09-01 08:45:52 +07:00
parent 5579cf6566
commit 2955b974d2
43 changed files with 3257 additions and 1 deletions
+30
View File
@@ -83,3 +83,33 @@ Bootstrap: first user is draft until `UPDATE users SET status = 'active'`.
## Employees
Create/update optional `userId` (assign an existing login user) or nested `user` (`id?`, `username?`, `password?`). Nested `user` without `id` creates a login user (`username` + `password` required) or updates the currently linked username. `user.id` / `userId` links an existing user; `username` may be updated, but `password` is rejected (use `PATCH /users/:id`). Nested `user` cannot set `privilegeId`. `user: null` or `userId: null` unlinks. Users link the other way with `employeeId`. DTO nests `user: { id, username } | null`. List filter `userId`. List filter `position` as one or more of `sales` | `driver` | `crew` (`?position=sales&position=driver`). CSV optional `userId`. Unique assigned user → `409`.
## Reports
Privilege keys: `SALES.REPORT`, `LOGISTICS.REPORT` (seeded in migration `0013_reports`).
### `GET /reports/config` — bearer — `200`
Query: `groupNames` (e.g. `sales_report`). Returns report configs visible to the caller, each with optional `activeFilter` and `activeTableConfig` bookmarks.
### `POST /reports/data` — bearer — `200`
Body: `{ groupName, uniqueName, queryModel }`. Returns row array keyed by column id.
### `POST /reports/meta` — bearer — `200`
Same body as data. Returns `{ totalRow, limit, offset }`.
### Report bookmarks
| Method | Path | Notes |
| --- | --- | --- |
| `GET` | `/report-bookmarks` | List for current user (`@Pagination()`) |
| `GET` | `/report-bookmarks/label-history` | Distinct labels |
| `GET` | `/report-bookmarks/applied` | Query: `groupName`, `uniqueName`, `type` |
| `POST` | `/report-bookmarks` | Create (`201`) |
| `PUT` | `/report-bookmarks/applied/:id` | Apply (unapplies siblings) |
| `PUT` | `/report-bookmarks/unapplied/:id` | Clear applied |
| `DELETE` | `/report-bookmarks/:id` | `204` |
Bookmark `type`: `FILTER_TABLE` | `TABLE_CONFIG`. `configuration` is opaque JSON (filter form values or AG Grid column state).