Use Cases and How Models Interact
Below, each use case shows:
- which models are touched
- the status transitions that occur
- side effects (notifications, billing triggers, etc.)
1.0 End-to-End Happy Path
Scenario
McDonald's Orchard needs 3 Service Crew workers for a shift next Tuesday (9am–6pm, $12/hr). The Job already exists on the platform. The employer adds a new Shift, talent apply, workers are selected, they complete the shift, and get paid.
Step-by-step
Step 1 — Employer adds a Shift to an existing Job
Actor: Org::UserProfile (employer)
Models touched: Gig::Shift
- Employer selects an existing
Gig::Job("Service Crew at McDonald's Orchard, $12/hr") - Employer enters:
starts_at,ends_at,headcount = 3 - System creates
Gig::Shiftwith statusdraft - If employer's location requires approval → status becomes
pending_approval - If no approval required → status becomes
open Listings::Jobis updated to reflect the new open shift
Step 2 — Talent applies to the Shift
Actor: Talent::Profile (talent)
Models touched: Gig::Application
- Talent browses marketplace, finds the Job via
Listings::Job, and selects a Shift - System checks: talent is not suspended, has no time overlap with existing Assignments
- System creates
Gig::Applicationwith statuspending - System recalculates rankings for all
pendingApplications on this Shift
Step 3 — Employer accepts applicants
Actor: Org::UserProfile (employer)
Models touched: Gig::Application
- Employer views ranked applicant list for the Shift
- Employer accepts 3 applicants (up to headcount)
- For each accepted applicant:
Gig::Application.status→accepted - Each accepted talent receives a notification: "You've been selected for Tuesday's shift"
- Remaining applicants stay in
pending— they may still be selected if an accepted talent declines
Step 4 — Talent confirms acceptance
Actor: Talent::Profile (talent)
Models touched: Gig::Application, Gig::Assignment
- Talent opens the notification and confirms: "Yes, I will work this shift"
Gig::Application.status→confirmed- System creates
Gig::Assignmentwith statusconfirmed, linking the talent to the Shift - System checks for time overlaps with the talent's other Applications → conflicting Applications auto-rejected
- Shift's filled count increases (e.g., 1/3 → 2/3)
If the talent does not confirm within the deadline, Gig::Application.status → expired, and the employer can select the next ranked applicant.
Step 5 — Shift becomes active
Actor: System (time-based trigger)
Models touched: Gig::Shift
- When
Gig::Shift.starts_atis reached,Gig::Shift.status→active - System begins no-show monitoring for all
confirmedAssignments on this Shift
Step 6 — Talent clocks in
Actor: Talent::Profile (talent) + Org::UserProfile (employer)
Models touched: Gig::QrCode, Gig::Assignment
- Employer generates a clock-in
Gig::QrCodefor the Shift (one QR for all workers) - QR code has an expiry (configurable, e.g., 15 minutes)
- Talent scans the QR code
- System records
actual_clock_intimestamp (immutable) Gig::Assignment.status→clocked_in
Step 7 — Talent clocks out
Actor: Talent::Profile (talent) + Org::UserProfile (employer)
Models touched: Gig::QrCode, Gig::Assignment
- Employer generates a clock-out
Gig::QrCodefor the Shift - Employer fills in the initial time confirmation form:
billable_clock_in,billable_clock_out,billable_break_minutes - Talent scans the clock-out QR code
- System records
actual_clock_outtimestamp (immutable) billable_*fields are set from the employer's form (defaults to actual times if employer skips the form)Gig::Assignment.status→clocked_out
Step 8 — Settlement window and verification
Actor: System + Org::UserProfile (employer, optional)
Models touched: Gig::Assignment, Gig::AssignmentAdjustment, Gig::Payment
- The settlement window opens (from clock-out until 9:00am the next day)
- Employer may adjust billable times during this window — each change creates an immutable
Gig::AssignmentAdjustmentrecord - At 9:00am the next day (or earlier if employer explicitly locks):
Gig::Assignment.billable_locked_atis setGig::Assignment.status→verified
- System calculates wage:
billable_hours × hourly_rate = gross_wage - System creates
Gig::Paymentwith statuspendingand the calculated wage - System triggers Billing domain to consume gig credits from the employer's entitlement lots
Step 9 — Shift completes
Actor: System
Models touched: Gig::Shift
- When all Assignments for the Shift reach a terminal state (
verified,cancelled, orno_show):Gig::Shift.status→completed
- The Job remains
active— employer can add new Shifts at any time
Step 10 — Payment disbursement
Actor: System + Finance team
Models touched: Gig::Payment
- System generates bank instruction file including all
pendingPayments Gig::Payment.status→processing- Finance uploads the file to the bank for GIRO disbursement
- Once confirmed:
Gig::Payment.status→paid
2.0 Posting a New Job (First Time)
Scenario
A new client (Subway) wants to post their first gig job. No Gig::Job exists yet.
Steps
- Employer enters Job details: title, description, requirements, hourly rate, location
- System creates
Gig::Jobwith statusactive - System snapshots the role via
Org::JobRoleVersion(if job roles are configured) - Employer adds a Shift to the Job (same as Step 1 in 1.0)
Business rules:
- A Job must belong to exactly one
Org::Company - Job title, description, and hourly rate are required
- The same Job is reused for all future Shifts — employer does not need to re-enter details
2.1 Posting a Shift with Approval Required
Scenario
An NTUC outlet requires HQ approval before shifts are published.
Steps
- Location manager creates a Shift under an existing Job
- System creates
Gig::Shiftwith statuspending_approval - Approver (HQ or area manager) is notified
- Approver reviews and approves →
Gig::Shift.status→open - Or approver rejects →
Gig::Shift.status→cancelled
Business rules:
- Approval requirement is a per-location configuration
- The Shift is not visible on the marketplace until approved
- The approver hierarchy depends on
Org::UserProfilerole/permission design (open question)
3.0 Auto-Selection
Scenario
An employer posted a Shift needing 2 workers. 5 talent applied but the employer hasn't selected anyone. The auto-select deadline arrives.
Preconditions
- Auto-selection is enabled for this location (per-location configuration)
- Shift has
pendingApplications with rankings
Steps
- Auto-select deadline arrives (AM shifts: 9am previous day, PM shifts: 5pm previous day)
- System retrieves all
pendingApplications for the Shift, ordered bytalent_rankascending (rank 1 = best) - System selects the top N applicants (where N =
headcount - current_filled_count) - For each selected Application:
Gig::Application.status→accepted- Talent is notified: "You've been auto-selected"
- Talent must still confirm (same as Step 4 in 1.0) — auto-selection does not skip the confirmation step
- Remaining unselected Applications:
Gig::Application.status→rejected
Business rules:
- Auto-selection only selects talent who have not been suspended and have no time overlaps
- If the top-ranked talent has a conflict, the system skips to the next ranked talent
- If there are fewer applicants than headcount, the system selects all available applicants
4.0 Talent Cancels Application Before Selection
Scenario
A talent applied to a shift but changed their mind before the employer made a selection.
Steps
- Talent requests cancellation of their
pendingApplication Gig::Application.status→withdrawn- Shift's applicant count decreases
- System recalculates rankings for remaining applicants
Business rules:
- No penalty, no document required
- Available at any time while Application is in
pendingstatus - Cancellation reason is optional
4.1 Talent Cancels Assignment (>48 Hours Before Shift)
Scenario
A talent was confirmed for a Tuesday shift but cancels on Saturday (>48 hours before).
Steps
- Talent requests cancellation of their
confirmedAssignment - Talent provides a mandatory cancellation reason (via
Taxonomy::GigStatusReason) Gig::Assignment.status→cancelled- The corresponding
Gig::Application.status→cancelled - Shift's filled count decreases (e.g., 3/3 → 2/3)
- If Shift is still
openand before cutoff, new talent can apply to fill the position - Employer is notified: "A confirmed worker has cancelled"
Business rules:
- No penalty — cancellation is outside the 48-hour window
- No supporting document required
- Cancellation reason is mandatory
4.2 Talent Cancels Assignment (3–48 Hours Before Shift)
Scenario
A talent was confirmed for a Tuesday 9am shift but cancels on Monday at 2pm (~19 hours before).
Steps
1–7: Same as 4.1
- System evaluates the talent's suspension history:
- 1st offense: Warning notification sent. Incident recorded. No suspension.
- 2nd offense: Pending suspension created. Talent has 24 hours to submit appeal with supporting document.
- 3rd offense: Pending suspension created (30 days). Same 24-hour appeal window.
- 4th+ offense: Pending suspension created (90 days). Same 24-hour appeal window.
Business rules:
- Cancellation reason is mandatory
- Supporting document is recommended but not required in this window
- Talent enters progressive suspension discipline (see Suspension use cases 7.0–7.2)
4.3 Talent Cancels Assignment (0–3 Hours Before Shift) — Urgent Cancellation
Scenario
A talent was confirmed for a 9am shift and cancels at 7:30am (1.5 hours before).
Steps
- Talent requests cancellation
- System requires: cancellation reason + supporting document (e.g., MC)
- If no document provided → cancellation is blocked
- If document provided:
- Steps 3–7 from 4.1 apply
- Step 8 from 4.2 applies (progressive suspension discipline)
Business rules:
- Supporting document is mandatory for urgent cancellations
- Cancellation is blocked if the talent cannot provide a document
- After shift start time, cancellation is blocked entirely — the talent is treated as a no-show
5.0 Employer Cancels a Shift
Scenario
An employer posted a Shift for Tuesday but no longer needs the manpower.
Steps
- Employer requests cancellation of the Shift
- Employer provides a mandatory cancellation reason (via
Taxonomy::GigStatusReason) - All
pendingandacceptedApplications on the Shift →cancelled - All
confirmedAssignments on the Shift →cancelled Gig::Shift.status→cancelled- Affected talent are notified: "The shift you were confirmed for has been cancelled"
Billing impact (if Assignments existed):
If any Assignments were in confirmed status (talent had already confirmed), the employer's gig credits are deducted based on how late the cancellation is:
| Window | Credit deduction |
|---|---|
>48 hours before shift | No deduction |
| 24–48 hours | Progressive deduction (low) |
| 12–24 hours | Progressive deduction (moderate) |
| 3–12 hours | Progressive deduction (high) |
| 0–3 hours | Progressive deduction (very high) |
| After shift start | Full shift value consumed |
Specific deduction percentages are a configuration decision (see open questions in Overview).
5.1 Employer Rejects a Specific Assignment
Scenario
An employer selected 3 workers for a shift but decides to remove one specific worker before the shift starts.
Steps
- Employer selects the Assignment to reject
- Employer provides a mandatory rejection reason (via
Taxonomy::GigStatusReason) Gig::Assignment.status→cancelled- The corresponding
Gig::Application.status→rejected - Shift's filled count decreases
- Talent is notified: "You have been removed from this shift"
- If Shift is still open, new talent can apply
Billing impact:
Same progressive credit deduction as 5.0, based on timing of the rejection relative to shift start.
Business rules:
- Rejection reason is mandatory (addresses the legacy data quality issue where 93% of rejections had no reason)
- If the Assignment is
clocked_in(talent is already working), the employer can still reject but payment for hours worked is an open question (seeGig::Paymentmodel spec)
6.0 No-Show Detection
Scenario
A talent was confirmed for a 9am shift but does not clock in.
Steps
Gig::Shifttransitions toactiveatstarts_at(9:00am)- System monitors all
confirmedAssignments for clock-in activity - After a configured no-show window (e.g., shift ends + grace period):
Gig::Assignment.status→no_show
- No
Gig::Paymentis created for this Assignment - The talent enters the progressive suspension discipline (same as 4.2 step 8)
- Employer is notified: "Worker did not show up for the shift"
Business rules:
- No-show detection is system-triggered (not manual)
- The no-show window is configurable (legacy used 24 hours after shift end; this may be shortened)
- A no-show counts as an offense in the progressive suspension policy
6.1 Shift Expiration — No Applicants
Scenario
An employer posted a Shift but no talent applied before the cutoff time.
Steps
- Cutoff time arrives (configured hours before shift start)
Gig::Shift.status→expired- No Applications or Assignments exist, so no notifications needed
6.2 Shift Expiration — No Selection
Scenario
5 talent applied to a Shift but the employer never selected anyone and auto-selection is disabled.
Steps
- Cutoff time arrives
- All
pendingApplications →expired Gig::Shift.status→expired- Talent are notified: "The shift you applied for has expired"
7.0 Suspension — Warning (1st Offense)
Scenario
A talent cancels an Assignment within 48 hours of shift start for the first time.
Steps
- Cancellation processed (per 4.2)
- System checks talent's suspension history: no prior incidents
- System creates an incident record (warning)
- Talent receives a notification: "This is a warning — repeated late cancellations or no-shows will result in suspension"
- No restrictions applied — talent can continue to apply and work normally
7.1 Suspension — Pending with Appeal Window (2nd+ Offense)
Scenario
A talent cancels an Assignment within 48 hours for the second time. They have a valid MC.
Steps
- Cancellation processed (per 4.2)
- System checks talent's suspension history: 1 prior incident (warning)
- System creates a pending suspension (7-day) with a 24-hour appeal window
- Talent is notified: "Your account is pending suspension. Submit a supporting document within 24 hours to appeal."
- During the 24-hour window:
- Talent cannot apply to new shifts
- Existing confirmed Assignments are preserved
- Talent can still work their confirmed shifts
- Talent submits MC via in-app document upload
- Appeal is routed to ops for review
7.2 Suspension — Appeal Review
Scenario
Ops reviews a pending suspension appeal.
Steps — Approved
- Ops reviews the supporting document
- Ops approves the appeal
- Pending suspension is cleared
- Talent regains full access — can apply to new shifts
- The incident is recorded but does not count toward escalation
Steps — Rejected
- Ops reviews the supporting document
- Ops rejects the appeal
- Suspension takes effect immediately:
- Talent cannot apply to new shifts
- Assignments within the suspension period are cancelled
- Assignments scheduled after the suspension ends are preserved
- Suspension lifts automatically when the period expires (7 / 30 / 90 days)
Steps — No Appeal Submitted
- 24-hour appeal window expires with no document submitted
- Suspension takes effect automatically (same as rejection above)
8.0 Employer Adjusts Billable Times After Clock-Out
Scenario
An employer filled in the clock-out form at 6pm with incorrect break time. At 8am the next morning, they want to correct it.
Steps
- Employer navigates to the Assignment (status:
clocked_out) - Employer modifies
billable_break_minutesfrom 30 → 60 and provides a reason - System creates an immutable
Gig::AssignmentAdjustmentrecord:field_changed: break_minutesold_value: 30new_value: 60reason: "Worker took a 1-hour break, not 30 minutes"adjusted_by: Org::UserProfile#456
Gig::Assignment.billable_break_minutesupdated from 30 → 60- The adjustment is visible in the audit trail for this Assignment
Business rules:
- Adjustments are only allowed while
Gig::Assignment.status = clocked_out(before verification deadline) - Each adjustment creates an immutable audit record — the
billable_*fields on Assignment are the current fact, the adjustments are the event history - After
billable_locked_atis set (verification), no further adjustments are allowed unless overridden by an admin
8.1 Admin Adjusts Billable Times on Behalf of Employer
Scenario
An employer sends a WhatsApp message to ops at 8:30am asking to change a worker's clock-in time. Ops enters the adjustment on their behalf.
Steps
- Admin navigates to the Assignment
- Admin modifies
billable_clock_inand provides a reason: "Per employer WhatsApp request" - System creates a
Gig::AssignmentAdjustmentrecord withadjusted_by=Identities::Admin - Assignment updated
Business rules:
- Same as 8.0, but
adjusted_byreferences an admin instead of an employer - The reason field captures the communication channel ("Per employer WhatsApp request") for audit
9.0 Time Overlap Auto-Rejection
Scenario
A talent confirms a Tuesday 9am–6pm shift. They had also applied to another Tuesday 10am–4pm shift.
Steps
- Talent confirms Assignment for Shift A (9am–6pm)
- System scans all other
pendingApplications for this talent - System detects overlap: Shift B (10am–4pm) overlaps with Shift A
Gig::Applicationfor Shift B →rejected(reason: time overlap)- Talent is notified: "Your application for [Shift B] was automatically withdrawn due to a scheduling conflict"
Business rules:
- Overlap detection runs when an Assignment is created (Application confirmed)
- Only
pendingandacceptedApplications are checked — confirmed Assignments are not cancelled (first-confirmed wins) - Overlap is determined by comparing
starts_at/ends_atof the shifts
10.0 External Integration — Shift Created from UKG
Scenario
A shift is created in UKG (external workforce management system) and needs to appear in Jod.
Steps
- Integration layer receives shift data from UKG via API or webhook
- System maps the external shift to a
Gig::Job(by role and location match) or creates a new one - System creates a
Gig::Shiftwith:starts_at,ends_at,headcountfrom external datasource = 'ukg'andsource_idreferencing the external shift ID
- Shift follows the normal flow from
openonward
Business rules:
- Externally sourced shifts cannot be cancelled from Jod — they must be cancelled in the source system
- Selection and attendance data is synced back to the external system when assignments are confirmed / clocked in / clocked out
- The integration layer is designed to support multiple providers (not UKG-specific in the domain model)