Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

12 — API Mapping (Staff Module)

Exact endpoints from src/modules/staff/controllers/**; envelopes per 00-shared/07_API_Conventions.md (exact wire contract from response-envelope.interceptor.ts:11-62 and http-exception.filter.ts:27-82). Base /api/v1; Bearer JWT; tenantId from token only (client never sends it — base.repository.ts:32-36 writes it server-side).

1. Staff (staff.controller.ts)

#MethodPathQuery/BodySuccessErrors (source)Permission (intended)
E1POST/staffBody CreateStaffDto (create-staff.dto.ts:4-38)201 envelope data=Staff doc (staff.service.ts:37-55)400 validation; 409 dup employeeNumber (staff.service.ts:32-36); 401staff.create (permissions.constants.ts:20)
E2GET/staffpage, limit (1–100, default 20), sort, q (pagination-query.dto.ts:5-30)200 data=Staff[], meta={page,limit,totalItems,totalPages,hasNext,hasPrevious} (staff.service.ts:64-76; pagination-query.dto.ts:32-55)400 (page/limit); 401staff.read (line 19)
E3GET/staff/:id200 data=Staff doc404 RESOURCE_NOT_FOUND (staff.service.ts:58-62); 400 invalid id (CastError → http-exception.filter.ts:47-48,91-92); 401staff.read
E4PATCH/staff/:idBody UpdateStaffDto (update-staff.dto.ts:4-42)200 data=updated doc (staff.service.ts:78-91); StaffUpdated → audit-write (event-queue-map.ts:35)404 (line 79); 400; 401staff.update (line 21)
E5DELETE/staff/:id200 data=empty (soft-delete: isDeleted/deletedAt/deletedBy + version++ — base.repository.ts:68-74); StaffDeleted → audit-write (event-queue-map.ts:36)404 (line 94-95); 401staff.delete (line 22)

Staff doc shape (response datastaff.schema.ts:21-52 + base.schema.ts:8-35):

{
  "_id": "…", "tenantId": "…",
  "userId": "ObjectId", "employeeNumber": "STF001",
  "departmentId": "ObjectId?", "designationId": "ObjectId?",
  "employmentType": "full_time", "joiningDate": "ISO?", "salaryGrade": "…?",
  "status": "active", "metadata": { },
  "createdBy": "ObjectId?", "updatedBy": "ObjectId?",
  "isDeleted": false, "deletedAt": null, "deletedBy": null, "version": 0,
  "createdAt": "ISO", "updatedAt": "ISO"
}

2. Departments (department.controller.ts)

#MethodPathBodySuccessErrorsPermission
E6POST/departmentsCreateDepartmentDto (department.dto.ts:4-18)201 data=doc, status:'active' (department.service.ts:22-30)400; 409 dup name (department.service.ts:23-25); 401department.manage (permissions.constants.ts:23)
E7GET/departmentspage, limit, sort, q200 data+meta (department.service.ts:38-50)400; 401department.manage
E8GET/departments/:id200 data=doc404 (department.service.ts:32-36); 400; 401department.manage
E9PATCH/departments/:idUpdateDepartmentDto (lines 20-39)200 data=updated404 (line 57-58); 400; 401department.manage
E10DELETE/departments/:id200 soft-delete (no member guard — OQ-4)404 (line 63-64); 401department.manage

Department doc shape (department.schema.ts:7-19): name, code?, headId? (ref Staff), status (string, default 'active') + BaseSchema fields. No events on any department operation (department.service.ts:19-20).

3. Designations (designation.controller.ts)

#MethodPathBodySuccessErrorsPermission
E11POST/designationsCreateDesignationDto (designation.dto.ts:4-18)201 data=doc, status:'active', level default 0 (designation.service.ts:25-32; designation.schema.ts:15-16,18-19)400 (incl. level non-int); 409 dup name (designation.service.ts:25-28); 401designation.manage (permissions.constants.ts:24)
E12GET/designationspage, limit, sort, q200 data+meta (designation.service.ts:41-50)400; 401designation.manage
E13GET/designations/:id200 data=doc404 (designation.service.ts:35-39); 400; 401designation.manage
E14PATCH/designations/:idUpdateDesignationDto (lines 20-39)200 data=updated404 (line 60-61); 400; 401designation.manage
E15DELETE/designations/:id200 soft-delete404 (line 66-67); 401designation.manage

Designation doc shape (designation.schema.ts:7-19): departmentId? (ref Department), name, level (int, default 0), status (string, default 'active') + BaseSchema fields. No events (designation.service.ts:22-23).

4. Error codes this module can produce

HTTPCodeProducer
400VALIDATION_ERRORDTO validators (all endpoints); CastError on :id (http-exception.filter.ts:47-48)
401UNAUTHENTICATEDJwtAuthGuard missing/expired token (jwt-auth.guard.ts:36-59)
403PERMISSION_DENIEDRbacGuard where applied — not yet wired on these controllers (staff.controller.ts:21; OQ-1)
404RESOURCE_NOT_FOUNDmissing staff/department/designation (staff.service.ts:60,81,95; department.service.ts:34,58,64; designation.service.ts:37,61,67)
409DUPLICATE_RESOURCEdup employeeNumber / dept name / designation name (staff.service.ts:32-36; department.service.ts:23-25; designation.service.ts:25-28); unique indexes (staff.schema.ts:57-58, department.schema.ts:24, designation.schema.ts:24)
429RATE_LIMITEDplatform rate limiter (auth 10/min, api 100/min, admin 500/min — 00-shared/07 §4)
5xxINTERNAL_SERVER_ERRORunexpected (http-exception.filter.ts:50-55,60-65)

422 BUSINESS_RULE_VIOLATION is defined by the filter (http-exception.filter.ts:33) but no staff-module code path produces it.

5. Envelope examples

Success (paginated E2):

{ "success": true, "message": "OK",
  "data": [ { "_id": "…", "employeeNumber": "STF001", "status": "active", … } ],
  "meta": { "page": 1, "limit": 20, "totalItems": 3, "totalPages": 1,
            "hasNext": false, "hasPrevious": false },
  "timestamp": "…", "requestId": "…" }

Error (duplicate employee number E1):

{ "success": false,
  "message": "Employee number \"STF001\" already exists.",
  "error": { "code": "DUPLICATE_RESOURCE" },
  "timestamp": "…", "requestId": "…" }

Source of 409 message: staff.service.ts:34-36 (ConflictException string); error envelope: http-exception.filter.ts:73-81; DUPLICATE_RESOURCE mapping: http-exception.filter.ts:32.

6. Cross-module endpoints the client needs (joins (proposed))

PurposeEndpointSource
User picker + name join (S3/S2)GET /users, GET /users/:idUsers module
Head display (S7)GET /staff/:id on headIddepartment.schema.ts:15-16
Dept/designation name resolution (S2)GET /departments/:id, GET /designations/:idrefs staff.schema.ts:29-33
Member counts (S7/S10)GET /staff filtered client-sideno server-side filter (staff.service.ts:64-76)

7. Query-param reality check

  • sort and q are accepted by PaginationQueryDto (pagination-query.dto.ts:21-29) but unused by all three list services (staff.service.ts:64-76, department.service.ts:38-50, designation.service.ts:41-50) — server-side search/sort is (planned) (OQ-2). No filter params exist for status, employmentType, departmentId, or designationId.