Skip to main content

Contractor Assignments

Manages contractor assignments to service bookings — linking external suppliers/contractors to specific services with full financial detail, payment breakdown, and PDF document generation.

Domain Concepts​

ConceptDescription
Contractor AssignmentA record that assigns a supplier (contractor) to a service booking with a defined role, line-item detail, and payment terms.
Service BookingThe parent event/job that contractors are assigned to.
SupplierThe external contractor entity (from the suppliers module).
Statusdraft → submitted → reviewed. Transitioning to submitted or reviewed triggers AP bill creation.
Payout StatusTracks whether the contractor has been paid (pending, etc.).
Document NumberAuto-generated sequential number per business.

Architecture​

contractor-assignments/
├── domain/
│ └── contractor-assignments-repository.domain.ts # Port interface + sortable keys
├── application/
│ ├── contractor-assignments.service.ts # Use cases
│ └── events/
│ ├── on-create-contractor-assignment.event.ts
│ └── on-update-contractor-assignment.event.ts
├── infrastructure/
│ └── contractor-assignments.repository.ts # Kysely adapter
└── interfaces/
├── contractor-assignments.controller.ts # HTTP endpoints
├── dtos/
│ ├── create-contractor-assignment.dto.ts
│ └── update-contractor-assignment.dto.ts
└── query/
└── paginate-contractor-assignments.query.ts

Dependency injection uses a Symbol token (CONTRACTOR_ASSIGNMENTS_REPOSITORY) so the service depends only on the domain interface, not the concrete Kysely implementation.

API Endpoints​

MethodPathDescription
POST/contractor-assignmentsCreate a new contractor assignment
GET/contractor-assignmentsList with pagination and search
GET/contractor-assignments/searchSearch with filters (business, status, date range, booking)
GET/contractor-assignments/:idGet by ID
GET/contractor-assignments/:id/pdfGenerate PDF download
GET/contractor-assignments/:id/printGenerate HTML print preview
PATCH/contractor-assignments/:idUpdate
DELETE/contractor-assignments/:idDelete

All endpoints require Bearer authentication.

Search Filters​

The /search endpoint supports these query parameters:

  • businessId — UUID, filter by business
  • status — draft, submitted, or reviewed
  • serviceBookingId — UUID, filter by parent service booking
  • createdAtFrom / createdAtTo — ISO 8601 date range
  • search — free-text search across role, note, supplier name/tax info, booking external ref
  • page, size — pagination
  • orderBy — sortable field (role)
  • order — asc or desc

PDF Options (query params on /pdf)​

  • pageSize — default A4
  • marginTop, marginRight, marginBottom, marginLeft — default 20
  • printBackground — default true
  • timeout — default 30000ms
  • templateId — custom template UUID
  • locationId — location-specific template
  • useLocationTemplate — true/false

Event Integration​

When a contractor assignment is created or transitions from draft to submitted/reviewed, an event is emitted:

  • contractorAssignment.create → OnCreateContractorAssignmentEvent
  • contractorAssignment.update → OnUpdateContractorAssignmentEvent

The accounts-payable-bills module listens to these events and automatically creates AP bill records for payment methods that generate accounts payable.

Database​

Table: contractor_assignment

Key foreign keys:

  • business_id → business (CASCADE)
  • service_booking_id → service_booking (CASCADE)
  • supplier_id → supplier (RESTRICT)
  • currency_id → currency (RESTRICT)
  • accounts_payable_bill_id → accounts_payable_bill (SET NULL)

Enum: ContractorAssignmentStatus — draft, submitted, reviewed (defined in packages/global/enums/contractor-assignment.enums.ts)

Design Decisions​

  1. JSON columns for detail/paymentDetail — Line items and payment breakdown are stored as JSON to allow flexible schemas without additional join tables.
  2. Event-driven AP integration — Decouples contractor assignments from AP bill creation. The assignment module does not know about AP bills directly.
  3. Transaction-wrapped mutations — Create and update operations use database transactions to ensure atomicity with document number generation.
  4. Hard delete — Assignments are hard-deleted (not soft-deleted). Consider whether a soft-delete approach is needed for audit trails.