Marwan Alwali 4d06ca4b5e update
2025-09-20 14:26:19 +03:00

1568 lines
59 KiB
Python

# Generated by Django 5.2.6 on 2025-09-19 10:58
import django.core.validators
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="AppointmentTemplate",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(help_text="Template name", max_length=200)),
(
"description",
models.TextField(
blank=True, help_text="Template description", null=True
),
),
(
"appointment_type",
models.CharField(
help_text="Default appointment type", max_length=50
),
),
(
"specialty",
models.CharField(help_text="Medical specialty", max_length=100),
),
(
"duration_minutes",
models.PositiveIntegerField(
help_text="Default duration in minutes"
),
),
(
"advance_booking_days",
models.PositiveIntegerField(
default=30, help_text="Maximum advance booking days"
),
),
(
"minimum_notice_hours",
models.PositiveIntegerField(
default=24, help_text="Minimum notice required in hours"
),
),
(
"insurance_verification_required",
models.BooleanField(
default=False, help_text="Insurance verification required"
),
),
(
"authorization_required",
models.BooleanField(
default=False, help_text="Prior authorization required"
),
),
(
"pre_appointment_instructions",
models.TextField(
blank=True,
help_text="Pre-appointment instructions for patient",
null=True,
),
),
(
"post_appointment_instructions",
models.TextField(
blank=True,
help_text="Post-appointment instructions template",
null=True,
),
),
(
"required_forms",
models.JSONField(
blank=True,
default=list,
help_text="Required forms for this appointment type",
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Template is active"),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Appointment Template",
"verbose_name_plural": "Appointment Templates",
"db_table": "appointments_appointment_template",
"ordering": ["specialty", "name"],
},
),
migrations.CreateModel(
name="QueueEntry",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"entry_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique entry identifier",
unique=True,
),
),
(
"queue_position",
models.PositiveIntegerField(help_text="Position in queue"),
),
(
"priority_score",
models.FloatField(
default=1.0, help_text="Priority score for queue ordering"
),
),
(
"joined_at",
models.DateTimeField(
auto_now_add=True, help_text="Time patient joined queue"
),
),
(
"estimated_service_time",
models.DateTimeField(
blank=True, help_text="Estimated service time", null=True
),
),
(
"called_at",
models.DateTimeField(
blank=True, help_text="Time patient was called", null=True
),
),
(
"served_at",
models.DateTimeField(
blank=True, help_text="Time patient was served", null=True
),
),
(
"status",
models.CharField(
choices=[
("WAITING", "Waiting"),
("CALLED", "Called"),
("IN_SERVICE", "In Service"),
("COMPLETED", "Completed"),
("LEFT", "Left Queue"),
("NO_SHOW", "No Show"),
],
default="WAITING",
help_text="Queue entry status",
max_length=20,
),
),
(
"notification_sent",
models.BooleanField(
default=False, help_text="Notification sent to patient"
),
),
(
"notification_method",
models.CharField(
blank=True,
choices=[
("SMS", "SMS"),
("EMAIL", "Email"),
("PHONE", "Phone Call"),
("PAGER", "Pager"),
("APP", "Mobile App"),
],
help_text="Notification method used",
max_length=20,
null=True,
),
),
(
"notes",
models.TextField(
blank=True, help_text="Additional notes", null=True
),
),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Queue Entry",
"verbose_name_plural": "Queue Entries",
"db_table": "appointments_queue_entry",
"ordering": ["queue", "priority_score", "joined_at"],
},
),
migrations.CreateModel(
name="SlotAvailability",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"slot_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique slot identifier",
unique=True,
),
),
("date", models.DateField(help_text="Availability date")),
("start_time", models.TimeField(help_text="Slot start time")),
("end_time", models.TimeField(help_text="Slot end time")),
(
"duration_minutes",
models.PositiveIntegerField(help_text="Slot duration in minutes"),
),
(
"availability_type",
models.CharField(
choices=[
("REGULAR", "Regular Hours"),
("EXTENDED", "Extended Hours"),
("EMERGENCY", "Emergency"),
("ON_CALL", "On Call"),
("TELEMEDICINE", "Telemedicine Only"),
],
default="REGULAR",
help_text="Type of availability",
max_length=20,
),
),
(
"max_appointments",
models.PositiveIntegerField(
default=1, help_text="Maximum appointments for this slot"
),
),
(
"booked_appointments",
models.PositiveIntegerField(
default=0, help_text="Number of booked appointments"
),
),
(
"location",
models.CharField(help_text="Appointment location", max_length=200),
),
(
"room_number",
models.CharField(
blank=True, help_text="Room number", max_length=50, null=True
),
),
(
"specialty",
models.CharField(
help_text="Medical specialty for this slot", max_length=100
),
),
(
"appointment_types",
models.JSONField(
default=list,
help_text="Allowed appointment types for this slot",
),
),
(
"patient_restrictions",
models.JSONField(
blank=True,
default=dict,
help_text="Patient restrictions (age, gender, etc.)",
),
),
(
"insurance_restrictions",
models.JSONField(
blank=True, default=list, help_text="Accepted insurance types"
),
),
(
"supports_telemedicine",
models.BooleanField(
default=False,
help_text="Slot supports telemedicine appointments",
),
),
(
"telemedicine_only",
models.BooleanField(
default=False, help_text="Telemedicine only slot"
),
),
(
"is_active",
models.BooleanField(
default=True, help_text="Slot is active and bookable"
),
),
(
"is_blocked",
models.BooleanField(
default=False, help_text="Slot is temporarily blocked"
),
),
(
"block_reason",
models.CharField(
blank=True,
help_text="Reason for blocking slot",
max_length=200,
null=True,
),
),
(
"is_recurring",
models.BooleanField(
default=False, help_text="Slot is part of recurring pattern"
),
),
(
"recurrence_pattern",
models.JSONField(
blank=True,
default=dict,
help_text="Recurrence pattern configuration",
),
),
(
"recurrence_end_date",
models.DateField(
blank=True,
help_text="End date for recurring pattern",
null=True,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Slot Availability",
"verbose_name_plural": "Slot Availability",
"db_table": "appointments_slot_availability",
"ordering": ["date", "start_time"],
},
),
migrations.CreateModel(
name="TelemedicineSession",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"session_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique session identifier",
unique=True,
),
),
(
"platform",
models.CharField(
choices=[
("ZOOM", "Zoom"),
("TEAMS", "Microsoft Teams"),
("WEBEX", "Cisco Webex"),
("DOXY", "Doxy.me"),
("CUSTOM", "Custom Platform"),
("OTHER", "Other"),
],
help_text="Telemedicine platform",
max_length=50,
),
),
("meeting_url", models.URLField(help_text="Meeting URL")),
(
"meeting_id",
models.CharField(
help_text="Meeting ID or room number", max_length=100
),
),
(
"meeting_password",
models.CharField(
blank=True,
help_text="Meeting password",
max_length=100,
null=True,
),
),
(
"waiting_room_enabled",
models.BooleanField(default=True, help_text="Waiting room enabled"),
),
(
"recording_enabled",
models.BooleanField(
default=False, help_text="Session recording enabled"
),
),
(
"recording_consent",
models.BooleanField(
default=False, help_text="Patient consent for recording"
),
),
(
"encryption_enabled",
models.BooleanField(
default=True, help_text="End-to-end encryption enabled"
),
),
(
"password_required",
models.BooleanField(
default=True, help_text="Password required to join"
),
),
(
"status",
models.CharField(
choices=[
("SCHEDULED", "Scheduled"),
("READY", "Ready to Start"),
("IN_PROGRESS", "In Progress"),
("COMPLETED", "Completed"),
("CANCELLED", "Cancelled"),
("FAILED", "Failed"),
],
default="SCHEDULED",
help_text="Session status",
max_length=20,
),
),
(
"scheduled_start",
models.DateTimeField(help_text="Scheduled start time"),
),
("scheduled_end", models.DateTimeField(help_text="Scheduled end time")),
(
"actual_start",
models.DateTimeField(
blank=True, help_text="Actual start time", null=True
),
),
(
"actual_end",
models.DateTimeField(
blank=True, help_text="Actual end time", null=True
),
),
(
"provider_joined_at",
models.DateTimeField(
blank=True, help_text="Provider join time", null=True
),
),
(
"patient_joined_at",
models.DateTimeField(
blank=True, help_text="Patient join time", null=True
),
),
(
"connection_quality",
models.CharField(
blank=True,
choices=[
("EXCELLENT", "Excellent"),
("GOOD", "Good"),
("FAIR", "Fair"),
("POOR", "Poor"),
],
help_text="Connection quality",
max_length=20,
null=True,
),
),
(
"technical_issues",
models.TextField(
blank=True, help_text="Technical issues encountered", null=True
),
),
(
"recording_url",
models.URLField(blank=True, help_text="Recording URL", null=True),
),
(
"recording_duration_minutes",
models.PositiveIntegerField(
blank=True, help_text="Recording duration in minutes", null=True
),
),
(
"session_notes",
models.TextField(blank=True, help_text="Session notes", null=True),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Telemedicine Session",
"verbose_name_plural": "Telemedicine Sessions",
"db_table": "appointments_telemedicine_session",
"ordering": ["-scheduled_start"],
},
),
migrations.CreateModel(
name="WaitingList",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"waiting_list_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique waiting list entry identifier",
unique=True,
),
),
(
"appointment_type",
models.CharField(
choices=[
("CONSULTATION", "Consultation"),
("FOLLOW_UP", "Follow-up"),
("PROCEDURE", "Procedure"),
("SURGERY", "Surgery"),
("DIAGNOSTIC", "Diagnostic"),
("THERAPY", "Therapy"),
("VACCINATION", "Vaccination"),
("SCREENING", "Screening"),
("EMERGENCY", "Emergency"),
("TELEMEDICINE", "Telemedicine"),
("OTHER", "Other"),
],
help_text="Type of appointment requested",
max_length=50,
),
),
(
"specialty",
models.CharField(
choices=[
("FAMILY_MEDICINE", "Family Medicine"),
("INTERNAL_MEDICINE", "Internal Medicine"),
("PEDIATRICS", "Pediatrics"),
("CARDIOLOGY", "Cardiology"),
("DERMATOLOGY", "Dermatology"),
("ENDOCRINOLOGY", "Endocrinology"),
("GASTROENTEROLOGY", "Gastroenterology"),
("NEUROLOGY", "Neurology"),
("ONCOLOGY", "Oncology"),
("ORTHOPEDICS", "Orthopedics"),
("PSYCHIATRY", "Psychiatry"),
("RADIOLOGY", "Radiology"),
("SURGERY", "Surgery"),
("UROLOGY", "Urology"),
("GYNECOLOGY", "Gynecology"),
("OPHTHALMOLOGY", "Ophthalmology"),
("ENT", "Ear, Nose & Throat"),
("EMERGENCY", "Emergency Medicine"),
("OTHER", "Other"),
],
help_text="Medical specialty required",
max_length=100,
),
),
(
"priority",
models.CharField(
choices=[
("ROUTINE", "Routine"),
("URGENT", "Urgent"),
("STAT", "STAT"),
("EMERGENCY", "Emergency"),
],
default="ROUTINE",
help_text="Clinical priority level",
max_length=20,
),
),
(
"urgency_score",
models.PositiveIntegerField(
default=1,
help_text="Clinical urgency score (1-10, 10 being most urgent)",
validators=[
django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(10),
],
),
),
(
"clinical_indication",
models.TextField(
help_text="Clinical reason for appointment request"
),
),
(
"diagnosis_codes",
models.JSONField(
blank=True, default=list, help_text="ICD-10 diagnosis codes"
),
),
(
"preferred_date",
models.DateField(
blank=True,
help_text="Patient preferred appointment date",
null=True,
),
),
(
"preferred_time",
models.TimeField(
blank=True,
help_text="Patient preferred appointment time",
null=True,
),
),
(
"flexible_scheduling",
models.BooleanField(
default=True,
help_text="Patient accepts alternative dates/times",
),
),
(
"earliest_acceptable_date",
models.DateField(
blank=True,
help_text="Earliest acceptable appointment date",
null=True,
),
),
(
"latest_acceptable_date",
models.DateField(
blank=True,
help_text="Latest acceptable appointment date",
null=True,
),
),
(
"acceptable_days",
models.JSONField(
blank=True,
default=list,
help_text="Acceptable days of week (0=Monday, 6=Sunday)",
null=True,
),
),
(
"acceptable_times",
models.JSONField(
blank=True, default=list, help_text="Acceptable time ranges"
),
),
(
"contact_method",
models.CharField(
choices=[
("PHONE", "Phone"),
("EMAIL", "Email"),
("SMS", "SMS"),
("PORTAL", "Patient Portal"),
("MAIL", "Mail"),
],
default="PHONE",
help_text="Preferred contact method",
max_length=20,
),
),
(
"contact_phone",
models.CharField(
blank=True,
help_text="Contact phone number",
max_length=20,
null=True,
),
),
(
"contact_email",
models.EmailField(
blank=True,
help_text="Contact email address",
max_length=254,
null=True,
),
),
(
"status",
models.CharField(
choices=[
("ACTIVE", "Active"),
("CONTACTED", "Contacted"),
("OFFERED", "Appointment Offered"),
("SCHEDULED", "Scheduled"),
("CANCELLED", "Cancelled"),
("EXPIRED", "Expired"),
("TRANSFERRED", "Transferred"),
],
default="ACTIVE",
help_text="Waiting list status",
max_length=20,
),
),
(
"position",
models.PositiveIntegerField(
blank=True,
help_text="Position in waiting list queue",
null=True,
),
),
(
"estimated_wait_time",
models.PositiveIntegerField(
blank=True, help_text="Estimated wait time in days", null=True
),
),
(
"last_contacted",
models.DateTimeField(
blank=True,
help_text="Last contact attempt date/time",
null=True,
),
),
(
"contact_attempts",
models.PositiveIntegerField(
default=0, help_text="Number of contact attempts made"
),
),
(
"max_contact_attempts",
models.PositiveIntegerField(
default=3, help_text="Maximum contact attempts before expiring"
),
),
(
"appointments_offered",
models.PositiveIntegerField(
default=0, help_text="Number of appointments offered"
),
),
(
"appointments_declined",
models.PositiveIntegerField(
default=0, help_text="Number of appointments declined"
),
),
(
"last_offer_date",
models.DateTimeField(
blank=True,
help_text="Date of last appointment offer",
null=True,
),
),
(
"requires_interpreter",
models.BooleanField(
default=False, help_text="Patient requires interpreter services"
),
),
(
"interpreter_language",
models.CharField(
blank=True,
help_text="Required interpreter language",
max_length=50,
null=True,
),
),
(
"accessibility_requirements",
models.TextField(
blank=True,
help_text="Special accessibility requirements",
null=True,
),
),
(
"transportation_needed",
models.BooleanField(
default=False,
help_text="Patient needs transportation assistance",
),
),
(
"insurance_verified",
models.BooleanField(
default=False, help_text="Insurance coverage verified"
),
),
(
"authorization_required",
models.BooleanField(
default=False, help_text="Prior authorization required"
),
),
(
"authorization_status",
models.CharField(
choices=[
("NOT_REQUIRED", "Not Required"),
("PENDING", "Pending"),
("APPROVED", "Approved"),
("DENIED", "Denied"),
("EXPIRED", "Expired"),
],
default="NOT_REQUIRED",
help_text="Authorization status",
max_length=20,
),
),
(
"authorization_number",
models.CharField(
blank=True,
help_text="Authorization number",
max_length=100,
null=True,
),
),
(
"referring_provider",
models.CharField(
blank=True,
help_text="Referring provider name",
max_length=200,
null=True,
),
),
(
"referral_date",
models.DateField(
blank=True, help_text="Date of referral", null=True
),
),
(
"referral_urgency",
models.CharField(
choices=[
("ROUTINE", "Routine"),
("URGENT", "Urgent"),
("STAT", "STAT"),
],
default="ROUTINE",
help_text="Referral urgency level",
max_length=20,
),
),
(
"removal_reason",
models.CharField(
blank=True,
choices=[
("SCHEDULED", "Appointment Scheduled"),
("PATIENT_CANCELLED", "Patient Cancelled"),
("PROVIDER_CANCELLED", "Provider Cancelled"),
("NO_RESPONSE", "No Response to Contact"),
("INSURANCE_ISSUE", "Insurance Issue"),
("TRANSFERRED", "Transferred to Another Provider"),
("EXPIRED", "Entry Expired"),
("DUPLICATE", "Duplicate Entry"),
("OTHER", "Other"),
],
help_text="Reason for removal from waiting list",
max_length=50,
null=True,
),
),
(
"removal_notes",
models.TextField(
blank=True,
help_text="Additional notes about removal",
null=True,
),
),
(
"removed_at",
models.DateTimeField(
blank=True,
help_text="Date/time removed from waiting list",
null=True,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"notes",
models.TextField(
blank=True, help_text="Additional notes and comments", null=True
),
),
],
options={
"verbose_name": "Waiting List Entry",
"verbose_name_plural": "Waiting List Entries",
"db_table": "appointments_waiting_list",
"ordering": ["priority", "urgency_score", "created_at"],
},
),
migrations.CreateModel(
name="WaitingListContactLog",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"contact_date",
models.DateTimeField(
auto_now_add=True, help_text="Date and time of contact attempt"
),
),
(
"contact_method",
models.CharField(
choices=[
("PHONE", "Phone Call"),
("EMAIL", "Email"),
("SMS", "SMS"),
("PORTAL", "Patient Portal Message"),
("MAIL", "Mail"),
("IN_PERSON", "In Person"),
],
help_text="Method of contact used",
max_length=20,
),
),
(
"contact_outcome",
models.CharField(
choices=[
("SUCCESSFUL", "Successful Contact"),
("NO_ANSWER", "No Answer"),
("BUSY", "Line Busy"),
("VOICEMAIL", "Left Voicemail"),
("EMAIL_SENT", "Email Sent"),
("EMAIL_BOUNCED", "Email Bounced"),
("SMS_SENT", "SMS Sent"),
("SMS_FAILED", "SMS Failed"),
("WRONG_NUMBER", "Wrong Number"),
("DECLINED", "Patient Declined"),
],
help_text="Outcome of contact attempt",
max_length=20,
),
),
(
"appointment_offered",
models.BooleanField(
default=False,
help_text="Appointment was offered during contact",
),
),
(
"offered_date",
models.DateField(
blank=True, help_text="Date of offered appointment", null=True
),
),
(
"offered_time",
models.TimeField(
blank=True, help_text="Time of offered appointment", null=True
),
),
(
"patient_response",
models.CharField(
blank=True,
choices=[
("ACCEPTED", "Accepted Appointment"),
("DECLINED", "Declined Appointment"),
("REQUESTED_DIFFERENT", "Requested Different Time"),
("WILL_CALL_BACK", "Will Call Back"),
("NO_LONGER_NEEDED", "No Longer Needed"),
("INSURANCE_ISSUE", "Insurance Issue"),
("NO_RESPONSE", "No Response"),
],
help_text="Patient response to contact",
max_length=20,
null=True,
),
),
(
"notes",
models.TextField(
blank=True, help_text="Notes from contact attempt", null=True
),
),
(
"next_contact_date",
models.DateField(
blank=True,
help_text="Scheduled date for next contact attempt",
null=True,
),
),
],
options={
"verbose_name": "Waiting List Contact Log",
"verbose_name_plural": "Waiting List Contact Logs",
"db_table": "appointments_waiting_list_contact_log",
"ordering": ["-contact_date"],
},
),
migrations.CreateModel(
name="WaitingQueue",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"queue_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique queue identifier",
unique=True,
),
),
("name", models.CharField(help_text="Queue name", max_length=200)),
(
"description",
models.TextField(
blank=True, help_text="Queue description", null=True
),
),
(
"queue_type",
models.CharField(
choices=[
("PROVIDER", "Provider Queue"),
("SPECIALTY", "Specialty Queue"),
("LOCATION", "Location Queue"),
("PROCEDURE", "Procedure Queue"),
("EMERGENCY", "Emergency Queue"),
],
help_text="Type of queue",
max_length=20,
),
),
(
"specialty",
models.CharField(
blank=True,
help_text="Medical specialty",
max_length=100,
null=True,
),
),
(
"location",
models.CharField(
blank=True,
help_text="Queue location",
max_length=200,
null=True,
),
),
(
"max_queue_size",
models.PositiveIntegerField(
default=50, help_text="Maximum queue size"
),
),
(
"average_service_time_minutes",
models.PositiveIntegerField(
default=30, help_text="Average service time in minutes"
),
),
(
"priority_weights",
models.JSONField(
default=dict, help_text="Priority weights for queue ordering"
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Queue is active"),
),
(
"is_accepting_patients",
models.BooleanField(
default=True, help_text="Queue is accepting new patients"
),
),
(
"operating_hours",
models.JSONField(
default=dict, help_text="Queue operating hours by day"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Waiting Queue",
"verbose_name_plural": "Waiting Queues",
"db_table": "appointments_waiting_queue",
"ordering": ["name"],
},
),
migrations.CreateModel(
name="AppointmentRequest",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"request_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique appointment request identifier",
unique=True,
),
),
(
"appointment_type",
models.CharField(
choices=[
("CONSULTATION", "Consultation"),
("FOLLOW_UP", "Follow-up"),
("PROCEDURE", "Procedure"),
("SURGERY", "Surgery"),
("DIAGNOSTIC", "Diagnostic"),
("THERAPY", "Therapy"),
("VACCINATION", "Vaccination"),
("SCREENING", "Screening"),
("EMERGENCY", "Emergency"),
("TELEMEDICINE", "Telemedicine"),
("OTHER", "Other"),
],
help_text="Type of appointment",
max_length=50,
),
),
(
"specialty",
models.CharField(
choices=[
("FAMILY_MEDICINE", "Family Medicine"),
("INTERNAL_MEDICINE", "Internal Medicine"),
("PEDIATRICS", "Pediatrics"),
("CARDIOLOGY", "Cardiology"),
("DERMATOLOGY", "Dermatology"),
("ENDOCRINOLOGY", "Endocrinology"),
("GASTROENTEROLOGY", "Gastroenterology"),
("NEUROLOGY", "Neurology"),
("ONCOLOGY", "Oncology"),
("ORTHOPEDICS", "Orthopedics"),
("PSYCHIATRY", "Psychiatry"),
("RADIOLOGY", "Radiology"),
("SURGERY", "Surgery"),
("UROLOGY", "Urology"),
("GYNECOLOGY", "Gynecology"),
("OPHTHALMOLOGY", "Ophthalmology"),
("ENT", "Ear, Nose & Throat"),
("EMERGENCY", "Emergency Medicine"),
("OTHER", "Other"),
],
help_text="Medical specialty",
max_length=100,
),
),
(
"preferred_date",
models.DateField(help_text="Patient preferred appointment date"),
),
(
"preferred_time",
models.TimeField(
blank=True,
help_text="Patient preferred appointment time",
null=True,
),
),
(
"duration_minutes",
models.PositiveIntegerField(
default=30,
help_text="Appointment duration in minutes",
validators=[
django.core.validators.MinValueValidator(15),
django.core.validators.MaxValueValidator(480),
],
),
),
(
"flexible_scheduling",
models.BooleanField(
default=True, help_text="Patient accepts alternative times"
),
),
(
"earliest_acceptable_date",
models.DateField(
blank=True,
help_text="Earliest acceptable appointment date",
null=True,
),
),
(
"latest_acceptable_date",
models.DateField(
blank=True,
help_text="Latest acceptable appointment date",
null=True,
),
),
(
"acceptable_times",
models.JSONField(
blank=True,
default=list,
help_text="Acceptable time slots (JSON array)",
),
),
(
"priority",
models.CharField(
choices=[
("ROUTINE", "Routine"),
("URGENT", "Urgent"),
("STAT", "STAT"),
("EMERGENCY", "Emergency"),
],
default="ROUTINE",
help_text="Appointment priority",
max_length=20,
),
),
(
"urgency_score",
models.PositiveIntegerField(
default=1,
help_text="Urgency score (1-10, 10 being most urgent)",
validators=[
django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(10),
],
),
),
(
"chief_complaint",
models.TextField(
help_text="Patient chief complaint or reason for visit"
),
),
(
"clinical_notes",
models.TextField(
blank=True, help_text="Additional clinical notes", null=True
),
),
(
"referring_provider",
models.CharField(
blank=True,
help_text="Referring provider name",
max_length=200,
null=True,
),
),
(
"insurance_verified",
models.BooleanField(
default=False, help_text="Insurance coverage verified"
),
),
(
"authorization_required",
models.BooleanField(
default=False, help_text="Prior authorization required"
),
),
(
"authorization_number",
models.CharField(
blank=True,
help_text="Authorization number",
max_length=100,
null=True,
),
),
(
"status",
models.CharField(
choices=[
("PENDING", "Pending"),
("SCHEDULED", "Scheduled"),
("CONFIRMED", "Confirmed"),
("CHECKED_IN", "Checked In"),
("IN_PROGRESS", "In Progress"),
("COMPLETED", "Completed"),
("CANCELLED", "Cancelled"),
("NO_SHOW", "No Show"),
("RESCHEDULED", "Rescheduled"),
],
default="PENDING",
help_text="Appointment status",
max_length=20,
),
),
(
"scheduled_datetime",
models.DateTimeField(
blank=True,
help_text="Scheduled appointment date and time",
null=True,
),
),
(
"scheduled_end_datetime",
models.DateTimeField(
blank=True,
help_text="Scheduled appointment end time",
null=True,
),
),
(
"location",
models.CharField(
blank=True,
help_text="Appointment location",
max_length=200,
null=True,
),
),
(
"room_number",
models.CharField(
blank=True, help_text="Room number", max_length=50, null=True
),
),
(
"is_telemedicine",
models.BooleanField(
default=False, help_text="Telemedicine appointment"
),
),
(
"telemedicine_platform",
models.CharField(
blank=True,
choices=[
("ZOOM", "Zoom"),
("TEAMS", "Microsoft Teams"),
("WEBEX", "Cisco Webex"),
("DOXY", "Doxy.me"),
("CUSTOM", "Custom Platform"),
("OTHER", "Other"),
],
help_text="Telemedicine platform",
max_length=50,
null=True,
),
),
(
"meeting_url",
models.URLField(
blank=True, help_text="Telemedicine meeting URL", null=True
),
),
(
"meeting_id",
models.CharField(
blank=True,
help_text="Meeting ID or room number",
max_length=100,
null=True,
),
),
(
"meeting_password",
models.CharField(
blank=True,
help_text="Meeting password",
max_length=100,
null=True,
),
),
(
"checked_in_at",
models.DateTimeField(
blank=True, help_text="Patient check-in time", null=True
),
),
(
"completed_at",
models.DateTimeField(
blank=True, help_text="Appointment completion time", null=True
),
),
(
"actual_duration_minutes",
models.PositiveIntegerField(
blank=True, help_text="Actual appointment duration", null=True
),
),
(
"cancelled_at",
models.DateTimeField(
blank=True, help_text="Cancellation timestamp", null=True
),
),
(
"cancellation_reason",
models.TextField(
blank=True, help_text="Reason for cancellation", null=True
),
),
(
"reminder_preferences",
models.JSONField(
blank=True,
default=dict,
help_text="Reminder preferences (email, SMS, phone)",
),
),
(
"special_requirements",
models.TextField(
blank=True,
help_text="Special requirements or accommodations",
null=True,
),
),
(
"interpreter_needed",
models.BooleanField(
default=False, help_text="Interpreter services needed"
),
),
(
"interpreter_language",
models.CharField(
blank=True,
help_text="Required interpreter language",
max_length=50,
null=True,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"cancelled_by",
models.ForeignKey(
blank=True,
help_text="User who cancelled appointment",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cancelled_appointments",
to=settings.AUTH_USER_MODEL,
),
),
(
"checked_in_by",
models.ForeignKey(
blank=True,
help_text="Staff member who checked in patient",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="checked_in_appointments",
to=settings.AUTH_USER_MODEL,
),
),
(
"created_by",
models.ForeignKey(
blank=True,
help_text="User who created the appointment request",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_appointments",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Appointment Request",
"verbose_name_plural": "Appointment Requests",
"db_table": "appointments_appointment_request",
"ordering": ["-created_at"],
},
),
]