alternative-backend-service/booking_system/views.py
saani a7d451702f docs(api): refactor appointments endpoint documentation structure
Enhanced the API root documentation for the appointments system with improved formatting and updated description to include "flexible availability" feature. Restructured the endpoint documentation for better readability and maintainability while preserving all endpoint information including Jitsi meeting integration details.
2025-11-26 19:30:26 +00:00

550 lines
28 KiB
Python

from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
@api_view(['GET'])
@permission_classes([AllowAny])
def api_root(request, format=None):
base_url = request.build_absolute_uri('/api/')
endpoints = {
'authentication': {
'description': 'User authentication and management endpoints',
'base_path': '/api/auth/',
'endpoints': {
'register': {
'description': 'Register a new user and send verification OTP',
'url': request.build_absolute_uri('/api/auth/register/'),
'methods': ['POST'],
'required_fields': ['email', 'first_name', 'last_name', 'password', 'password2'],
'example_request': {
'email': 'user@example.com',
'first_name': 'John',
'last_name': 'Doe',
'phone_number': '+1234567890',
'password': 'SecurePassword123',
'password2': 'SecurePassword123'
}
},
'verify_otp': {
'description': 'Verify email address using OTP',
'url': request.build_absolute_uri('/api/auth/verify-otp/'),
'methods': ['POST'],
'required_fields': ['email', 'otp'],
'example_request': {
'email': 'user@example.com',
'otp': '123456'
}
},
'login': {
'description': 'Authenticate user and return JWT tokens',
'url': request.build_absolute_uri('/api/auth/login/'),
'methods': ['POST'],
'required_fields': ['email', 'password'],
'example_request': {
'email': 'user@example.com',
'password': 'SecurePassword123'
}
},
'resend_otp': {
'description': 'Resend OTP for email verification or password reset',
'url': request.build_absolute_uri('/api/auth/resend-otp/'),
'methods': ['POST'],
'required_fields': ['email'],
'optional_fields': ['context (registration/password_reset)'],
'example_request': {
'email': 'user@example.com',
'context': 'registration'
}
},
'forgot_password': {
'description': 'Initiate password reset process',
'url': request.build_absolute_uri('/api/auth/forgot-password/'),
'methods': ['POST'],
'required_fields': ['email'],
'example_request': {
'email': 'user@example.com'
}
},
'verify_password_reset_otp': {
'description': 'Verify OTP for password reset',
'url': request.build_absolute_uri('/api/auth/verify-password-reset-otp/'),
'methods': ['POST'],
'required_fields': ['email', 'otp'],
'example_request': {
'email': 'user@example.com',
'otp': '123456'
}
},
'reset_password': {
'description': 'Reset password after OTP verification',
'url': request.build_absolute_uri('/api/auth/reset-password/'),
'methods': ['POST'],
'required_fields': ['email', 'otp', 'new_password', 'confirm_password'],
'example_request': {
'email': 'user@example.com',
'otp': '123456',
'new_password': 'NewSecurePassword123',
'confirm_password': 'NewSecurePassword123'
}
},
'token_refresh': {
'description': 'Refresh access token using refresh token',
'url': request.build_absolute_uri('/api/auth/token/refresh/'),
'methods': ['POST'],
'required_fields': ['refresh'],
'example_request': {
'refresh': 'your_refresh_token_here'
}
},
"update_profile": {
"description": "Update user profile (Authenticated users only)",
"url": request.build_absolute_uri("/api/auth/profile/update/"),
"methods": ["PATCH"],
"authentication": "Required (Authenticated users only)",
"required_fields": ["first_name", "last_name", "phone_number"],
"example_request": {
"first_name": "John",
"last_name": "Doe",
"phone_number": "+1234567890"
}
},
"get_profile": {
"description": "Get user profile (Authenticated users only)",
"url": request.build_absolute_uri("/api/auth/profile/"),
"methods": ["GET"],
"authentication": "Required (Authenticated users only)",
"response_fields": {
"user": "User object"
}
},
"all-users": {
"description": "Get all users (Admin only)",
"url": request.build_absolute_uri("/api/auth/all-users/"),
"methods": ["GET"],
"authentication": "Required (Admin users only)",
"response_fields": {
"users": "List of user objects"
}
},
"activate-deactivate-user": {
"description": "Activate or deactivate a user (Admin only)",
"url": request.build_absolute_uri("/api/auth/activate-deactivate-user/<uuid:pk>/"),
"methods": ["GET"],
"authentication": "Required (Admin users only)",
"response_fields": {
"user": "User object"
}
},
"delete-user": {
"description": "Delete a user (Admin only)",
"url": request.build_absolute_uri("/api/auth/delete-user/<uuid:pk>/"),
"methods": ["GET"],
"authentication": "Required (Admin users only)",
"response_fields": {
"user": "User object"
}
}
}
},
"appointments": {
"description": "Appointment request and management system with Jitsi video meetings and flexible availability",
"base_path": "/api/meetings/",
"endpoints": {
"admin_availability": {
"description": "Get or update admin weekly availability with day-time combinations (Admin only)",
"url": request.build_absolute_uri("/api/meetings/admin/availability/"),
"methods": ["GET", "PUT", "PATCH"],
"authentication": "Required (Staff users only)",
"response_fields": {
"availability_schedule": "Dictionary with days as keys and time slots as values",
"availability_schedule_display": "Human-readable availability schedule",
"all_available_slots": "All available day-time combinations"
},
"example_request": {
"availability_schedule": {
"0": ["morning", "evening"],
"1": ["morning", "afternoon"],
"3": ["afternoon", "evening"]
}
}
},
"availability_config": {
"description": "Get availability configuration for frontend (Public)",
"url": request.build_absolute_uri("/api/meetings/availability/config/"),
"methods": ["GET"],
"authentication": "None required",
"response": "Default availability configuration with all days and time slots"
},
"check_date_availability": {
"description": "Check available time slots for a specific date (Public)",
"url": request.build_absolute_uri("/api/meetings/availability/check/"),
"methods": ["POST"],
"authentication": "None required",
"required_fields": ["date (YYYY-MM-DD)"],
"example_request": {
"date": "2024-01-15"
},
"response_fields": {
"date": "The checked date",
"day_name": "Day of the week",
"available_slots": "List of available time slots",
"available_slots_display": "Human-readable time slots",
"is_available": "Boolean indicating if any slots are available"
}
},
"weekly_availability": {
"description": "Get complete weekly availability overview (Public)",
"url": request.build_absolute_uri("/api/meetings/availability/weekly/"),
"methods": ["GET"],
"authentication": "None required",
"response": "Array of days with their available time slots for the entire week"
},
"availability_overview": {
"description": "Get public availability overview and next available dates (Public)",
"url": request.build_absolute_uri("/api/meetings/availability/overview/"),
"methods": ["GET"],
"authentication": "None required",
"response_fields": {
"available": "Boolean indicating if admin has any availability",
"total_available_slots": "Total number of available day-time slots",
"available_days": "List of days with availability",
"next_available_dates": "Next 7 days with availability information"
}
},
"available_dates": {
"description": "Get available appointment dates with time slots for the next 30 days (Public)",
"url": request.build_absolute_uri("/api/meetings/appointments/available-dates/"),
"methods": ["GET"],
"authentication": "None required",
"response": "List of available dates with their available time slots"
},
"create_appointment": {
"description": "Create a new appointment request with availability validation (Public)",
"url": request.build_absolute_uri("/api/meetings/appointments/create/"),
"methods": ["POST"],
"authentication": "Required (User only)",
"required_fields": [
"first_name", "last_name", "email",
"selected_slots"
],
"optional_fields": ["phone", "reason"],
"validation": [
"Selected slots must match admin availability",
"At least one time slot must be selected"
],
"example_request": {
"first_name": "Shani",
"last_name": "Iddi",
"email": "saanii929@gmail.com",
"phone": "+233552732025",
"reason": "Therapy session",
"selected_slots": [
{"day": 1, "time_slot": "morning"},
{"day": 1, "time_slot": "afternoon"},
{"day": 3, "time_slot": "afternoon"},
{"day": 3, "time_slot": "evening"},
{"day": 4, "time_slot": "evening"}
]
},
"response_includes": {
"appointment_id": "UUID of the created appointment",
"message": "Success message"
}
},
"list_appointments": {
"description": "List appointment requests (Admin sees all, users see their own)",
"url": request.build_absolute_uri("/api/meetings/appointments/"),
"methods": ["GET"],
"authentication": "Required",
"response_fields": {
"jitsi_meet_url": "Jitsi meeting URL (only for scheduled appointments)",
"jitsi_room_id": "Jitsi room ID",
"has_jitsi_meeting": "Boolean indicating if meeting is created",
"can_join_meeting": "Boolean indicating if meeting can be joined now",
"meeting_status": "Current meeting status",
"matching_availability": "Date-time combinations that match admin availability",
"are_preferences_available": "Boolean indicating if preferences match availability"
}
},
"appointment_detail": {
"description": "Get detailed information about a specific appointment",
"url": request.build_absolute_uri("/api/meetings/appointments/<uuid:pk>/"),
"methods": ["GET"],
"authentication": "Required",
"url_parameter": "pk (UUID of the appointment)",
"response_includes": "Jitsi meeting information and availability matching data"
},
"matching_availability": {
"description": "Get matching availability for a specific appointment request",
"url": request.build_absolute_uri("/api/meetings/appointments/<uuid:pk>/matching-availability/"),
"methods": ["GET"],
"authentication": "Required",
"response_fields": {
"appointment_id": "UUID of the appointment",
"preferences_match_availability": "Boolean indicating if preferences match",
"matching_slots": "List of date-time combinations that match",
"total_matching_slots": "Number of matching combinations"
}
},
"user_appointments": {
"description": "Get appointments for the authenticated user",
"url": request.build_absolute_uri("/api/meetings/user/appointments/"),
"methods": ["GET"],
"authentication": "Required",
"response": "List of user's appointment requests with enhanced availability data"
},
"schedule_appointment": {
"description": "Schedule an appointment and automatically create Jitsi meeting (Admin only)",
"url": request.build_absolute_uri("/api/meetings/appointments/<uuid:pk>/schedule/"),
"methods": ["POST"],
"authentication": "Required (Staff users only)",
"required_fields": ["scheduled_datetime"],
"optional_fields": ["scheduled_duration", "date_str", "time_slot"],
"prerequisites": "Appointment must be in 'pending_review' status",
"scheduling_options": {
"direct_datetime": {
"example": {"scheduled_datetime": "2024-01-15T10:00:00Z", "scheduled_duration": 60}
},
"date_and_slot": {
"example": {"date_str": "2024-01-15", "time_slot": "morning", "scheduled_duration": 60}
}
},
"validation": "Validates against admin availability when using date_str + time_slot",
"side_effects": [
"Updates status to 'scheduled'",
"Automatically generates Jitsi meeting room",
"Creates unique Jitsi room ID and URL",
"Sends confirmation email to user with meeting link",
"Clears rejection reason if any"
],
"response_includes": {
"jitsi_meet_url": "Generated Jitsi meeting URL",
"jitsi_room_id": "Unique Jitsi room ID",
"has_jitsi_meeting": "true"
}
},
"reject_appointment": {
"description": "Reject an appointment request (Admin only)",
"url": request.build_absolute_uri("/api/meetings/appointments/<uuid:pk>/reject/"),
"methods": ["POST"],
"authentication": "Required (Staff users only)",
"optional_fields": ["rejection_reason"],
"prerequisites": "Appointment must be in 'pending_review' status",
"example_request": {
"rejection_reason": "No availability for preferred dates"
},
"side_effects": [
"Updates status to 'rejected'",
"Clears Jitsi meeting information",
"Sends rejection email to user",
"Clears scheduled datetime if any"
]
},
"appointment_stats": {
"description": "Get appointment statistics and analytics with availability metrics (Admin only)",
"url": request.build_absolute_uri("/api/meetings/appointments/stats/"),
"methods": ["GET"],
"authentication": "Required (Staff users only)",
"response_fields": {
"total_requests": "Total number of appointment requests",
"pending_review": "Number of pending review requests",
"scheduled": "Number of scheduled appointments",
"rejected": "Number of rejected requests",
"completed": "Number of completed appointments",
"completion_rate": "Percentage of requests that were scheduled",
"availability_coverage": "Percentage of week covered by availability",
"available_days_count": "Number of days with availability set"
}
},
"user_appointment_stats": {
"description": "Get appointment statistics for a specific user",
"url": request.build_absolute_uri("/api/meetings/user/appointments/stats/"),
"methods": ["POST"],
"authentication": "Required",
"required_fields": ["email"],
"response_fields": {
"total_requests": "Total number of appointment requests",
"pending_review": "Number of pending review requests",
"scheduled": "Number of scheduled appointments",
"rejected": "Number of rejected requests",
"completed": "Number of completed appointments",
"completion_rate": "Percentage of requests that were scheduled",
"email": "User email address"
}
}
},
"availability_system": {
"description": "Flexible day-time availability management",
"features": [
"Different time slots for each day of the week",
"Real-time availability validation",
"Matching preference detection",
"Weekly availability overview"
],
"time_slots": {
"morning": "Morning (9AM - 12PM)",
"afternoon": "Afternoon (1PM - 5PM)",
"evening": "Evening (6PM - 9PM)"
},
"days_of_week": {
"0": "Monday",
"1": "Tuesday",
"2": "Wednesday",
"3": "Thursday",
"4": "Friday",
"5": "Saturday",
"6": "Sunday"
}
},
"jitsi_integration": {
"description": "Automatic Jitsi video meeting integration",
"features": [
"Automatic meeting room generation when appointment is scheduled",
"Unique room IDs for each therapy session",
"No setup required for clients - just click and join",
"Meeting availability based on scheduled time",
"Secure, encrypted video sessions"
],
"meeting_lifecycle": {
"pending": "No Jitsi meeting created",
"scheduled": "Jitsi meeting automatically generated with unique URL",
"active": "Meeting can be joined 10 minutes before scheduled time",
"completed": "Meeting ends 15 minutes after scheduled duration"
},
"join_conditions": [
"Appointment must be in 'scheduled' status",
"Current time must be within 10 minutes before to 15 minutes after scheduled end",
"Both client and therapist can join using the same URL"
]
}
}
}
return Response({
'message': 'Therapy Appointment API with Enhanced Availability System',
'version': '2.0.0',
'base_url': base_url,
'new_features': [
'Flexible day-time availability management',
'Real-time availability validation',
'Matching preference detection',
'Enhanced scheduling options',
'Availability statistics and coverage metrics'
],
'project_structure': {
'admin': '/admin/ - Django admin interface',
'authentication': '/api/auth/ - User authentication and management',
'appointments': '/api/meetings/ - Enhanced appointment booking system'
},
'endpoints': endpoints,
'appointment_workflows': {
'client_booking_flow': [
'1. GET /api/meetings/availability/weekly/ - Check weekly availability',
'2. POST /api/meetings/availability/check/ - Check specific date availability',
'3. GET /api/meetings/appointments/available-dates/ - See next available dates',
'4. POST /api/meetings/appointments/create/ - Submit appointment request',
'5. GET /api/meetings/user/appointments/ - Track request status',
'6. GET /api/meetings/appointments/{id}/matching-availability/ - See matching options',
'7. Receive email notification when scheduled/rejected'
],
'admin_management_flow': [
'1. PUT /api/meetings/admin/availability/ - Set flexible day-time availability',
'2. GET /api/meetings/appointments/ - Review pending requests',
'3. GET /api/meetings/appointments/stats/ - Check availability coverage',
'4. POST /api/meetings/appointments/{id}/schedule/ - Schedule with date+slot OR direct datetime',
'5. POST /api/meetings/appointments/{id}/reject/ - Reject with reason'
],
'status_lifecycle': [
'pending_review → scheduled (with datetime)',
'pending_review → rejected (with optional reason)',
'scheduled → completed (after meeting)',
'scheduled → cancelled (if needed)'
]
},
'availability_examples': {
'monday_evening_only': {
"availability_schedule": {
"0": ["evening"]
}
},
'weekday_mornings_afternoons': {
"availability_schedule": {
"0": ["morning", "afternoon"],
"1": ["morning", "afternoon"],
"2": ["morning", "afternoon"],
"3": ["morning", "afternoon"],
"4": ["morning", "afternoon"]
}
},
'flexible_schedule': {
"availability_schedule": {
"0": ["morning", "evening"],
"1": ["afternoon"],
"3": ["morning", "afternoon"],
"5": ["morning"]
}
}
},
'quick_start': {
'for_users': [
'1. Register: POST /api/auth/register/',
'2. Verify email: POST /api/auth/verify-otp/',
'3. Login: POST /api/auth/login/',
'4. Check weekly availability: GET /api/meetings/availability/weekly/',
'5. Check specific date: POST /api/meetings/availability/check/',
'6. Book appointment: POST /api/meetings/appointments/create/'
],
'for_admins': [
'1. Login to Django admin: /admin/',
'2. Set flexible availability: PUT /api/meetings/admin/availability/',
'3. Check availability coverage: GET /api/meetings/appointments/stats/',
'4. Manage appointments: GET /api/meetings/appointments/',
'5. Schedule/Reject: Use specific appointment endpoints'
]
},
'data_specifications': {
'appointment': {
'status_choices': [
'pending_review - Initial state, awaiting admin action',
'scheduled - Approved with specific date/time',
'rejected - Not accepted, with optional reason',
'completed - Meeting has been completed',
'cancelled - Appointment was cancelled'
],
'time_slot_choices': [
'morning - 9AM to 12PM',
'afternoon - 1PM to 5PM',
'evening - 6PM to 9PM'
],
'preferred_dates_format': 'YYYY-MM-DD (array of strings)',
'encrypted_fields': [
'first_name', 'last_name', 'email', 'phone',
'reason', 'rejection_reason'
]
},
'availability': {
'day_format': '0=Monday, 1=Tuesday, ..., 6=Sunday',
'time_slot_format': 'morning, afternoon, evening',
'schedule_format': 'Dictionary: {"0": ["morning", "evening"], "1": ["afternoon"]}'
}
},
'authentication_notes': {
'token_usage': 'Include JWT token in Authorization header: Bearer <token>',
'token_refresh': 'Use refresh token to get new access token when expired',
'permissions': {
'public_endpoints': 'No authentication required (availability checks, overview)',
'user_endpoints': 'Valid JWT token required',
'admin_endpoints': 'Staff user with valid JWT token required'
}
}
})