Shifts (الورديات)
Shift definitions with automatic working hours calculation and per-shift attendance rules. Supports night shifts that cross midnight.
Attributes
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
name_ar | string | Arabic name |
name_en | string | English name (nullable) |
start_time | time | Shift start (HH:mm) |
end_time | time | Shift end (HH:mm) |
break_duration_minutes | integer | Break duration in minutes (default 60) |
working_hours | decimal | Auto-calculated working hours |
is_night_shift | boolean | Night shift flag |
grace_period_minutes | integer | Legacy grace period (default 15) |
overtime_start_after_minutes | integer | Minutes after shift before overtime starts |
late_threshold_minutes | integer | Minutes before counting as late (default 60) |
late_counts_full | boolean | If true: late = all minutes from shift start. If false: only excess beyond threshold (default true) |
max_late_before_absent | integer | Maximum late minutes before auto-absent (default 180) |
early_leave_threshold_minutes | integer | Early leave grace minutes (default 30) |
early_leave_counts_full | boolean | Same logic as late_counts_full for early leave (default true) |
flexibility_minutes | integer | Flex time — can come late and compensate at end of day (default 0) |
hours_per_day | decimal(4,1) | How many hours equal one full day (default 6.0) |
nursing_extra_minutes | integer | Extra late threshold for nursing employees (default 60) |
special_needs_extra_minutes | integer | Extra threshold for special-needs employees (default 60) |
presence_check_enabled | boolean | Whether presence verification punch is required during shift (default false) |
presence_check_interval | integer | Minutes between required presence checks (default 120) |
color | string | Color code for UI |
status | string | active or inactive |
API Endpoints
| Method | URL | Description |
|---|---|---|
GET | /api/hr/shifts | List shifts (paginated) |
POST | /api/hr/shifts | Create shift |
GET | /api/hr/shifts/{id} | Show shift |
PUT | /api/hr/shifts/{id} | Update shift |
DELETE | /api/hr/shifts/{id} | Delete shift |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by active or inactive |
Attendance Rules
Each shift has its own attendance settings that control how lateness and early leave are calculated:
Late Arrival Logic
- Employee checks in at
actual_time - Effective threshold =
late_threshold_minutes+ nursing bonus + special-needs bonus - If
actual_time - shift_start > effective_threshold:- If
late_counts_full = true→ late_minutes = total minutes from shift start - If
late_counts_full = false→ late_minutes = minutes beyond threshold only
- If
- If
actual_time - shift_start > max_late_before_absent→ marked as absent
Early Leave Logic
- Employee checks out at
actual_time - Effective threshold =
early_leave_threshold_minutes+ special-needs bonus - If
shift_end - actual_time > effective_threshold:- If
early_leave_counts_full = true→ early_leave_minutes = total early minutes - If
early_leave_counts_full = false→ early_leave_minutes = minutes beyond threshold only
- If
Nursing & Special Needs Exemptions
- Nursing employees (
is_nursing = true): getnursing_extra_minutesadded to their late threshold - Special-needs employees (
is_special_needs = true): getspecial_needs_extra_minutesadded to both late and early-leave thresholds
Examples
bash
# Create a shift with attendance rules
curl -X POST "https://moon-erp.elbaset.com/api/hr/shifts" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name_ar": "وردية صباحية",
"name_en": "Morning Shift",
"start_time": "08:00",
"end_time": "16:00",
"break_duration_minutes": 60,
"late_threshold_minutes": 30,
"late_counts_full": true,
"max_late_before_absent": 120,
"early_leave_threshold_minutes": 15,
"hours_per_day": 7.0,
"nursing_extra_minutes": 60,
"special_needs_extra_minutes": 60,
"status": "active"
}'dart
final response = await dio.post('/api/hr/shifts', data: {
'name_ar': 'وردية صباحية',
'name_en': 'Morning Shift',
'start_time': '08:00',
'end_time': '16:00',
'break_duration_minutes': 60,
'late_threshold_minutes': 30,
'late_counts_full': true,
'max_late_before_absent': 120,
'early_leave_threshold_minutes': 15,
'hours_per_day': 7.0,
'nursing_extra_minutes': 60,
'special_needs_extra_minutes': 60,
'status': 'active',
});Business Rules
working_hoursis auto-calculated:(end_time - start_time - break) / 60- Night shifts crossing midnight are handled automatically (end_time < start_time adds 24h)
- Cannot delete a shift that has future schedule assignments
- All attendance settings have sensible defaults — existing shifts work without changes
- Morning shift example: 08:00–16:00 with 60min break = 7.0 hours
- Night shift example: 22:00–06:00 with 30min break = 7.5 hours