POST /api/schedules/leave-requests
Request Body:
{
"leave_type_id": "uuid-here",
"start_date": "2026-04-20",
"end_date": "2026-04-22",
"reason": "Personal matter",
"category": "NORMAL" // NEW: NORMAL or EMERGENCY
}Response (200):
{
"request_id": "uuid-here",
"employee_id": "uuid-here",
"employee_name": "John Doe",
"leave_type_id": "uuid-here",
"leave_type_name": "Annual Leave",
"start_date": "2026-04-20",
"end_date": "2026-04-22",
"status": "PENDING",
"category": "NORMAL", // NEW
"reason": "Personal matter",
"review_comment": null, // NEW
"reviewed_by": null, // NEW
"reviewed_at": null, // NEW
"created_at": "2026-04-15T09:00:00Z"
}GET /api/schedules/leave-requests/my
Response (200):
[
{
"request_id": "uuid-here",
"employee_id": "uuid-here",
"employee_name": "John Doe",
"leave_type_id": "uuid-here",
"leave_type_name": "Annual Leave",
"start_date": "2026-04-20",
"end_date": "2026-04-22",
"status": "APPROVED",
"category": "NORMAL",
"reason": "Personal matter",
"review_comment": "Approved. Have a nice trip!", // NEW: Admin feedback
"reviewed_by": "uuid-of-admin", // NEW
"reviewed_at": "2026-04-15T10:30:00Z", // NEW
"created_at": "2026-04-15T09:00:00Z"
}
]GET /api/schedules/leave-requests?status=PENDING
Query Parameters:
status(optional): PENDING, APPROVED, REJECTED
Response (200): Array of LeaveRequestResponse objects (same as above)
Notes:
- Employees see only their own requests
- HR/Admins see all requests in system
GET /api/schedules/leave-calendar?month=2026-04
Query Parameters:
month(optional): Format YYYY-MM (defaults to current month)
Response (200):
[
{
"request_id": "uuid-here",
"employee_id": "uuid-here",
"employee_name": "John Doe",
"leave_type_name": "Annual Leave",
"start_date": "2026-04-20",
"end_date": "2026-04-22",
"status": "APPROVED"
}
]PUT /api/schedules/leave-requests/{request_id}/status
Query Parameters:
status(required): APPROVED or REJECTEDcomment(optional): Feedback message for employee
Example:
PUT /api/schedules/leave-requests/abc-123/status?status=APPROVED&comment=Approved%20for%20the%20dates
Response (200):
{
"message": "Leave request has been approved"
}Error Responses:
- 403: Not authorized (not HR/Admin)
- 400: Invalid status or request not pending
- 404: Leave request not found
- Approval Timeline: Up to 1 week
- Use Cases: Vacation, planned personal days
- Priority: Standard
- Color: Blue
- Approval Timeline: 1-2 working days
- Use Cases: Urgent personal matters, emergencies
- Priority: High
- Color: Red
| Type | Max Days/Year | Paid | Requires Approval |
|---|---|---|---|
| Annual Leave | 20 | Yes | Yes |
| Sick Leave | 14 | Yes | Yes |
| Emergency Leave | Unlimited | Yes | Yes |
| Unpaid Leave | Unlimited | No | Yes |
| Work From Home | Unlimited | Yes | Yes |
| Status | Meaning | Admin Action Required |
|---|---|---|
| PENDING | Waiting for approval | Yes |
| APPROVED | Approved by HR/Admin | No |
| REJECTED | Rejected by HR/Admin | No |
| CANCELLED | Cancelled by employee | No |
{
"detail": "Start date must be before end date"
}{
"detail": "Category must be NORMAL or EMERGENCY"
}{
"detail": "Insufficient permissions"
}{
"detail": "Leave request not found"
}- ✅ POST: Submit own leave request
- ✅ GET: View own leave requests only
- ✅ GET: View own leaves on calendar only
- ❌ PUT: Cannot approve/reject requests
- ✅ POST: Submit own leave request (if HR)
- ✅ GET: View all leave requests
- ✅ GET: View all leaves on calendar
- ✅ PUT: Approve/reject any request
- ✅ POST: Submit own leave request
- ✅ GET: View all leave requests
- ✅ GET: View all leaves on calendar
- ✅ PUT: Approve/reject any request
When a leave request is approved/rejected, the employee receives:
Title: Leave Request APPROVED
Message: Your leave request from 2026-04-20 to 2026-04-22 was approved.
Comment: [Admin's comment if provided]
Type: LEAVE_UPDATE
POST /api/schedules/leave-requests
{
"leave_type_id": "annual-uuid",
"start_date": "2026-04-20",
"end_date": "2026-04-22",
"reason": "Spring vacation",
"category": "NORMAL"
}Response: status: PENDING
GET /api/schedules/leave-requests?status=PENDINGResponse: List includes the new request
PUT /api/schedules/leave-requests/abc-123/status?status=APPROVED&comment=Enjoy%20your%20vacationResponse: Success message
- Notification sent to employee
- Status changed to APPROVED
- Comment visible in their leave request
GET /api/schedules/leave-requests/myResponse:
{
...
"status": "APPROVED",
"review_comment": "Enjoy your vacation",
"reviewed_by": "admin-uuid",
"reviewed_at": "2026-04-15T11:00:00Z"
}- All endpoints use async/await for concurrency
- Eager loading of relationships for efficiency
- Indexed queries for fast retrieval
- Proper pagination ready for future implementation
-- Add to leave_requests table:
ALTER TABLE leave_requests ADD COLUMN category VARCHAR(20) NOT NULL DEFAULT 'NORMAL';
ALTER TABLE leave_requests ADD COLUMN reviewed_at TIMESTAMP WITH TIME ZONE;
-- These columns already exist but need to support NULL:
-- reviewed_by, review_comment (already nullable)- All existing API responses still work
- New fields are additive only
- Backward compatible with old clients
Submit Leave:
curl -X POST http://localhost:8000/api/schedules/leave-requests \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"leave_type_id": "type-uuid",
"start_date": "2026-04-20",
"end_date": "2026-04-22",
"reason": "Vacation",
"category": "NORMAL"
}'Approve Leave:
curl -X PUT "http://localhost:8000/api/schedules/leave-requests/request-uuid/status?status=APPROVED&comment=Approved" \
-H "Authorization: Bearer HR_TOKEN"Get Calendar:
curl -X GET "http://localhost:8000/api/schedules/leave-calendar?month=2026-04" \
-H "Authorization: Bearer YOUR_TOKEN"✨ category: Leave urgency (NORMAL or EMERGENCY) ✨ review_comment: Admin feedback on decision ✨ reviewed_by: Who made the decision ✨ reviewed_at: When decision was made ✨ Enhanced PUT endpoint for approval with comments ✨ Full audit trail for leave requests ✨ Better role-based access control