Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Codefied-CodePix/Karokar-backend/llms.txt

Use this file to discover all available pages before exploring further.

An assignment is the operational bridge between an approved booking and the employee who will receive the vehicle. Rather than linking a booking directly to an employee, KaroKar inserts an explicit Assignment domain in between — a design decision that keeps the Booking domain focused on vendor-corporate negotiations while giving the Assignment domain full control over employee handovers, acceptance workflows, and future reassignment scenarios. Every vehicle handover — whether from a vendor-owned booking or a corporate-owned direct assignment — is tracked through an Assignment record.

Why Assignments Exist as a Separate Domain

The intuitive model would be to store employeeId on the Booking entity. KaroKar deliberately rejects this:
❌ Incorrect:  Booking → Employee
✅ Correct:    Booking → Assignment → Employee
This separation enables capabilities that a direct link cannot support:
  • Reassignments — swap the employee on an active vehicle without touching the booking
  • Pool vehicles — assign a vehicle to a pool rather than a named employee
  • Corporate-owned vehicles — bypass the Booking domain entirely and go straight to Assignment
  • Future driver workflows — assign a driver separately from the beneficiary employee

Assignment Entity

FieldTypeDescription
iduuidUnique assignment identifier (from BaseEntity)
bookingIduuid | nullThe booking this assignment originates from, or null for direct corporate assignments
vehicleIduuidThe vehicle being assigned
corporateOrganizationIduuidThe corporate organization responsible for this assignment
employeeIduuidThe employee receiving the vehicle
statusAssignmentStatusCurrent state of the assignment
startDatetimestamptzWhen the assignment period begins
endDatetimestamptz | nullWhen it ends — null for open-ended assignments
createdAttimestamptzRecord creation timestamp (from BaseEntity)
updatedAttimestamptzLast modification timestamp (from BaseEntity)
bookingId is nullable because corporate-owned vehicles enter the Assignment domain directly — there is no parent booking. For vendor-owned vehicles, bookingId always references the originating Booking record.

Assignment Statuses

StatusMeaning
PENDINGAssignment created and awaiting employee acknowledgement
ACCEPTEDEmployee has accepted the assignment and acknowledged the handover
REJECTEDEmployee declined the assignment
ACTIVEVehicle is in active use by the employee
COMPLETEDAssignment ended as planned
CLOSEDAssignment force-closed, typically due to booking termination

How Assignments Are Created

Assignments are never created directly by a controller call on a booking. Instead, BookingService.assignEmployee() transitions the booking to ASSIGNED and emits a BookingAssignedEvent. The Assignment domain listens for this event and creates the assignment automatically.
// BookingAssignedListener — Assignment domain listener for the booking.assigned event
@OnEvent('booking.assigned')
async handleBookingAssigned(event: DomainEvent): Promise<void> {
  const { payload, aggregateId } = event;

  await this.assignmentService.createAssignment({
    bookingId: aggregateId,
    vehicleId: payload.vehicleId as string,
    corporateOrganizationId: payload.corporateOrganizationId as string,
    employeeId: payload.employeeId as string,
    startDate: new Date(payload.startDate as string),
    endDate: payload.endDate ? new Date(payload.endDate as string) : null,
  });
}
AssignmentService.createAssignment() persists the record with status: PENDING and immediately emits an AssignmentCreatedEvent — notifying downstream consumers such as the Notification domain.

Assignment Lifecycle

1

Assignment Created (PENDING)

Triggered automatically by the BookingAssigned domain event. The assignment is created with status: PENDING. The employee is notified that a vehicle has been assigned to them and their acceptance is required.Domain event emitted: AssignmentCreatedEvent
2

Employee Accepts (ACCEPTED → ACTIVE)

The employee calls:
PATCH /assignments/:id/accept
This requires the assignment.accept permission. AssignmentService.acceptAssignment(id) is responsible for transitioning the assignment and emitting AssignmentAcceptedEvent.
acceptAssignment is not yet implemented and currently throws NotImplementedException. The acceptance workflow is planned for a future phase.
Domain event emitted: AssignmentAcceptedEvent
3

Employee Rejects (REJECTED)

If the employee cannot accept the vehicle, they call:
PATCH /assignments/:id/reject
AssignmentService.rejectAssignment(id) sets the assignment to REJECTED and emits AssignmentRejectedEvent. The corporate admin must take action — either reassigning to another employee or cancelling the booking.
rejectAssignment is not yet implemented and currently throws NotImplementedException. The rejection workflow is planned for a future phase.
Domain event emitted: AssignmentRejectedEvent
4

Assignment Closed (CLOSED)

An active assignment is force-closed when the parent booking is terminated. The BookingTerminated event triggers AssignmentService.closeAssignment(id), which transitions the assignment to CLOSED regardless of its current state.Assignments can also reach COMPLETED through a planned booking completion.Domain event emitted: AssignmentClosedEvent

Relationship to Bookings

The full relationship chain for a vendor-owned vehicle transaction:
Booking (vendor-corporate contract)
    ↓  BookingAssignedEvent
Assignment (vehicle-to-employee handover)
    ↓  AssignmentAcceptedEvent
Active Vehicle Usage
    ↓  BookingTerminatedEvent / BookingCompletedEvent
Assignment Closed / Completed
For corporate-owned vehicles, the Booking layer is absent:
Corporate Decision
    ↓  Direct call to AssignmentService
Assignment (vehicle-to-employee handover)
    ↓  AssignmentAcceptedEvent
Active Vehicle Usage

Booking Termination Closes Active Assignments

When BookingService.terminateBooking() is called, the resulting BookingTerminatedEvent is consumed by the Assignment domain. Any assignment in PENDING, ACCEPTED, or ACTIVE state against the terminated booking is immediately transitioned to CLOSED.
No active assignment may exist against a booking in a terminal state (COMPLETED, TERMINATED, or CANCELLED). The Assignment domain enforces this constraint when processing termination and cancellation events.

Domain Events Summary

EventTriggered ByDescription
AssignmentCreatedEventBookingAssigned event consumedNew assignment created in PENDING
AssignmentAcceptedEventPATCH /assignments/:id/acceptEmployee accepted the vehicle handover
AssignmentRejectedEventPATCH /assignments/:id/rejectEmployee declined the vehicle handover
AssignmentClosedEventBookingTerminated event consumedAssignment force-closed due to booking termination

Required Permissions

ActionRequired Permission
Accept an assignmentassignment.accept
Reject an assignmentassignment.accept
View assignment detailsassignment.read

CreateAssignmentInput

When the Assignment domain creates an assignment in response to a BookingAssigned event, it uses the following input shape:
interface CreateAssignmentInput {
  bookingId?: string | null;         // null for direct corporate assignments
  vehicleId: string;
  corporateOrganizationId: string;
  employeeId: string;
  startDate: Date;
  endDate?: Date | null;             // null for open-ended assignments
}
The resulting assignment is always initialized with status: AssignmentStatus.PENDING.

Build docs developers (and LLMs) love