- 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.
5.3 KiB
TrackGo HTTP API
JSON keys are camelCase. IDs are UUID v4. List endpoints return { data, meta }.
List query includes shared pagination (page/limit or offset/limit) plus orderBy (resource field name) and orderType (ASC or DESC, default ASC). Unknown orderBy values are rejected. Defaults when omitted: users username; cycles cycleNumber; plans date; privilege-keys sortOrder then code; other lists code. Foreign keys on list/detail responses are nested objects ({ id, code, name } or { id, username } / { id, code }), not bare UUIDs.
List filters: username, privilegeId, status, search (username), orderBy, orderType.
Auth
POST /auth/register — public — 201
Creates a draft user. Does not issue tokens.
{ "username": "alice", "password": "password123" }
Response: { "id": "uuid", "username": "alice", "status": "draft" }.
Activate with PATCH /users/:id/status { "status": "active" } (or SQL bootstrap) then POST /auth/login.
POST /auth/login — public — 200
Same body as register. Returns { accessToken, refreshToken }.
Login, refresh, and JWT validation require user.status === "active". If the user is assigned to an employee, that employee must also be active. Failures use 401 with a generic credentials message.
POST /auth/refresh — public — 200
POST /auth/revoke — public — 204
GET /auth/me — bearer — 200
Users
Key: USERS. Standard CRUD + import (list, detail, create, update, status, delete, bulk-delete, bulk-status, import). Extra: PATCH /users/:id/privilege.
| Method | Path | Action | Status |
|---|---|---|---|
GET |
/users |
view | 200 |
GET |
/users/:id |
view | 200 |
POST |
/users |
create | 201 |
PATCH |
/users/:id |
update | 200 |
PATCH |
/users/:id/status |
update | 200 |
PATCH |
/users/:id/privilege |
update | 200 |
DELETE |
/users/:id |
delete | 204 |
POST |
/users/bulk-delete |
delete | 200 |
POST |
/users/bulk-status |
update | 200 |
POST |
/users/import |
import | 200 |
Create: { username, password, privilegeId?, status?, employeeId? }. Username 3–32, ^[a-zA-Z0-9_]+$, stored lowercased. Password 8–72, write-only. Omit status → draft. Never send isSuperadmin / passwordHash.
Optional employeeId links an existing employee. Unique assigned user → 409.
Update PATCH /users/:id: username?, password?, privilegeId? (null clears), employeeId? (null unlinks). No status. employeeId reassigns the linked employee.
Privilege: { privilegeId } (null clears). Assigned privilege must be active. Response is the full UserDto.
List filters: username, privilegeId, status, search (username).
DTO:
{
"id": "uuid",
"username": "alice",
"isSuperadmin": false,
"privilege": { "id": "uuid", "code": "ADMIN", "name": "Administrator" },
"employee": { "id": "uuid", "code": "EMP_01", "name": "Ada Lovelace" },
"status": "active",
"createdAt": 1710000000000,
"updatedAt": 1710000000000,
"createdBy": { "id": "uuid", "username": "admin" },
"updatedBy": { "id": "uuid", "username": "admin" }
}
privilege / employee may be null. CSV required: username, password. Optional: privilegeId, status. Delete of a user still referenced as created_by / updated_by → 409.
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).