Employee Onboarding & Offboarding
Step-by-step runbooks for bringing an employee onto the system and
cleanly removing them when they leave. These flows assume the backing
User row already exists — create it via Filament (/admin → Users → New) before onboarding.
Onboarding
What happens under the hood
POST /api/v1/employees creates two rows in a single transaction:
employees— the thin HR record (employee_code,category, phone,date_of_joining).employee_deployments— the primary posting (organization_id,organization_unit_id,is_primary=true,starts_on = date_of_joining).
Minimum payload
POST /api/v1/employees
{
"user_id": 42,
"employee_code": "E1042",
"category": "permanent",
"phone": "+91...",
"date_of_joining": "2026-05-01",
"organization_id": 1,
"primary_unit_id": 3
}
Checklist for HR
- Create the user in Filament (name, email, initial password, role
employee). - Call
POST /employeeswith the payload above. - Add a device registration invite —
POST /devices/registerfrom the Flutter app, then HR approves viaPOST /devices/{id}/approve. - Assign shifts via
POST /roster(the shift window must not overlap any other planned shift the same day; cross-unit doubles are fine if the windows don't touch). - Optional: add a regularization / onboarding-day leave if they're not starting punching from day 1.
Offboarding
Do NOT just delete the employee row
DELETE /employees/{id} is the legacy path — it only soft-deletes the
employees row. Future shift assignments stay on the roster, devices
stay approved, open leaves stay in approvers' queues, spatie roles
stay granted, the primary deployment still reads as "currently
deployed". Downstream reports treat the person as still on payroll.
Use the offboarding cascade instead
POST /api/v1/employees/{id}/offboard
{
"last_working_day": "2026-05-31",
"reason": "resigned"
}
In a single transaction the service:
- Stamps
employees.last_working_day+exit_reasonand flipsis_active=false. - Closes every open
EmployeeDeploymentby settingends_onto the last working day. - Flips every
plannedShiftAssignmentwithassigned_for > last_working_daytocancelled— roster + heatmap stop showing them. - Revokes every
approved/pendingDeviceand deletes every Sanctum personal access token on the backing User. - Auto-rejects every
pending/shift_manager_approvedLeave whosestarts_on > last_working_daywith a system-origindecision_trailentry. Same for Regularizations. - Strips every spatie role from the User and sets
users.is_active = false. - Soft-deletes the
Employeerow so historical attendance / audit still resolve their FK.
Response is a summary of counts — "cancelled 7 future shifts, revoked 2 devices, rejected 1 pending leave" — so the UI can confirm exactly what happened.
Rescue operations
If you need to undo a recent offboarding, restore via Filament: HR →
Employees → Trashed → Restore. You'll then need to manually reopen the
deployment (PATCH /deployments/{id} with ends_on=null) and
re-approve devices.
Transfer (cross-unit posting change)
Use the /units/{id}/retire flow's transfer map, or manually:
- Close the current primary deployment:
DELETE /deployments/{id}(default mode closes by stampingends_on=today, not hard delete). - Create a new primary deployment:
POST /deploymentswithis_primary=true— the service clears the primary flag on any overlapping row automatically. - Cancel any future shift assignments at the old unit and reassign at the new one.