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

1860 lines
69 KiB
Python

# Generated by Django 5.2.6 on 2025-09-19 10:58
import django.core.validators
import django.db.models.deletion
import django.utils.timezone
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("core", "0001_initial"),
("hr", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="ConsentTemplate",
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
),
),
(
"category",
models.CharField(
choices=[
("TREATMENT", "Treatment Consent"),
("PROCEDURE", "Procedure Consent"),
("SURGERY", "Surgical Consent"),
("ANESTHESIA", "Anesthesia Consent"),
("RESEARCH", "Research Consent"),
("PRIVACY", "Privacy Consent"),
("FINANCIAL", "Financial Consent"),
("ADMISSION", "Admission Consent"),
("DISCHARGE", "Discharge Consent"),
("OTHER", "Other"),
],
help_text="Consent category",
max_length=50,
),
),
("content", models.TextField(help_text="Consent form content")),
(
"requires_signature",
models.BooleanField(
default=True, help_text="Requires patient signature"
),
),
(
"requires_witness",
models.BooleanField(
default=False, help_text="Requires witness signature"
),
),
(
"requires_guardian",
models.BooleanField(
default=False,
help_text="Requires guardian signature for minors",
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Template is active"),
),
(
"version",
models.CharField(
default="1.0", help_text="Template version", max_length=20
),
),
(
"effective_date",
models.DateField(
default=django.utils.timezone.now,
help_text="Template effective date",
),
),
(
"expiry_date",
models.DateField(
blank=True, help_text="Template expiry date", null=True
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"created_by",
models.ForeignKey(
blank=True,
help_text="User who created the template",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_consent_templates",
to=settings.AUTH_USER_MODEL,
),
),
(
"tenant",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="consent_templates",
to="core.tenant",
),
),
],
options={
"verbose_name": "Consent Template",
"verbose_name_plural": "Consent Templates",
"db_table": "patients_consent_template",
"ordering": ["category", "name"],
},
),
migrations.CreateModel(
name="InsuranceClaim",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"claim_number",
models.CharField(
help_text="Unique claim number", max_length=50, unique=True
),
),
(
"claim_type",
models.CharField(
choices=[
("MEDICAL", "Medical"),
("DENTAL", "Dental"),
("VISION", "Vision"),
("PHARMACY", "Pharmacy"),
("EMERGENCY", "Emergency"),
("INPATIENT", "Inpatient"),
("OUTPATIENT", "Outpatient"),
("PREVENTIVE", "Preventive Care"),
("MATERNITY", "Maternity"),
("MENTAL_HEALTH", "Mental Health"),
("REHABILITATION", "Rehabilitation"),
("DIAGNOSTIC", "Diagnostic"),
("SURGICAL", "Surgical"),
("CHRONIC_CARE", "Chronic Care"),
],
default="MEDICAL",
help_text="Type of claim",
max_length=20,
),
),
(
"status",
models.CharField(
choices=[
("DRAFT", "Draft"),
("SUBMITTED", "Submitted"),
("UNDER_REVIEW", "Under Review"),
("APPROVED", "Approved"),
("PARTIALLY_APPROVED", "Partially Approved"),
("DENIED", "Denied"),
("PAID", "Paid"),
("CANCELLED", "Cancelled"),
("APPEALED", "Appealed"),
("RESUBMITTED", "Resubmitted"),
],
default="DRAFT",
help_text="Current claim status",
max_length=20,
),
),
(
"priority",
models.CharField(
choices=[
("LOW", "Low"),
("NORMAL", "Normal"),
("HIGH", "High"),
("URGENT", "Urgent"),
("EMERGENCY", "Emergency"),
],
default="NORMAL",
help_text="Claim priority",
max_length=10,
),
),
(
"service_date",
models.DateField(help_text="Date when service was provided"),
),
(
"service_provider",
models.CharField(
help_text="Healthcare provider who provided the service",
max_length=200,
),
),
(
"service_provider_license",
models.CharField(
blank=True,
help_text="Provider license number (Saudi Medical License)",
max_length=50,
null=True,
),
),
(
"facility_name",
models.CharField(
blank=True,
help_text="Healthcare facility name",
max_length=200,
null=True,
),
),
(
"facility_license",
models.CharField(
blank=True,
help_text="Facility license number (MOH License)",
max_length=50,
null=True,
),
),
(
"primary_diagnosis_code",
models.CharField(
help_text="Primary diagnosis code (ICD-10)", max_length=20
),
),
(
"primary_diagnosis_description",
models.TextField(help_text="Primary diagnosis description"),
),
(
"secondary_diagnosis_codes",
models.JSONField(
blank=True,
default=list,
help_text="Secondary diagnosis codes and descriptions",
),
),
(
"procedure_codes",
models.JSONField(
blank=True,
default=list,
help_text="Procedure codes (CPT/HCPCS) and descriptions",
),
),
(
"billed_amount",
models.DecimalField(
decimal_places=2,
help_text="Total amount billed (SAR)",
max_digits=12,
),
),
(
"approved_amount",
models.DecimalField(
decimal_places=2,
default=0,
help_text="Amount approved by insurance (SAR)",
max_digits=12,
),
),
(
"paid_amount",
models.DecimalField(
decimal_places=2,
default=0,
help_text="Amount actually paid (SAR)",
max_digits=12,
),
),
(
"patient_responsibility",
models.DecimalField(
decimal_places=2,
default=0,
help_text="Patient copay/deductible amount (SAR)",
max_digits=12,
),
),
(
"discount_amount",
models.DecimalField(
decimal_places=2,
default=0,
help_text="Discount applied (SAR)",
max_digits=12,
),
),
(
"submitted_date",
models.DateTimeField(
blank=True,
help_text="Date claim was submitted to insurance",
null=True,
),
),
(
"processed_date",
models.DateTimeField(
blank=True, help_text="Date claim was processed", null=True
),
),
(
"payment_date",
models.DateTimeField(
blank=True, help_text="Date payment was received", null=True
),
),
(
"saudi_id_number",
models.CharField(
blank=True,
help_text="Saudi National ID or Iqama number",
max_length=10,
null=True,
),
),
(
"insurance_card_number",
models.CharField(
blank=True,
help_text="Insurance card number",
max_length=50,
null=True,
),
),
(
"authorization_number",
models.CharField(
blank=True,
help_text="Prior authorization number if required",
max_length=50,
null=True,
),
),
(
"denial_reason",
models.TextField(
blank=True,
help_text="Reason for denial if applicable",
null=True,
),
),
(
"denial_code",
models.CharField(
blank=True,
help_text="Insurance denial code",
max_length=20,
null=True,
),
),
(
"appeal_date",
models.DateTimeField(
blank=True, help_text="Date appeal was filed", null=True
),
),
(
"appeal_reason",
models.TextField(
blank=True, help_text="Reason for appeal", null=True
),
),
(
"notes",
models.TextField(
blank=True,
help_text="Additional notes about the claim",
null=True,
),
),
(
"attachments",
models.JSONField(
blank=True, default=list, help_text="List of attached documents"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"created_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_claims",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Insurance Claim",
"verbose_name_plural": "Insurance Claims",
"db_table": "patients_insurance_claim",
"ordering": ["-created_at"],
},
),
migrations.CreateModel(
name="ClaimStatusHistory",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"from_status",
models.CharField(
blank=True,
choices=[
("DRAFT", "Draft"),
("SUBMITTED", "Submitted"),
("UNDER_REVIEW", "Under Review"),
("APPROVED", "Approved"),
("PARTIALLY_APPROVED", "Partially Approved"),
("DENIED", "Denied"),
("PAID", "Paid"),
("CANCELLED", "Cancelled"),
("APPEALED", "Appealed"),
("RESUBMITTED", "Resubmitted"),
],
help_text="Previous status",
max_length=20,
null=True,
),
),
(
"to_status",
models.CharField(
choices=[
("DRAFT", "Draft"),
("SUBMITTED", "Submitted"),
("UNDER_REVIEW", "Under Review"),
("APPROVED", "Approved"),
("PARTIALLY_APPROVED", "Partially Approved"),
("DENIED", "Denied"),
("PAID", "Paid"),
("CANCELLED", "Cancelled"),
("APPEALED", "Appealed"),
("RESUBMITTED", "Resubmitted"),
],
help_text="New status",
max_length=20,
),
),
(
"reason",
models.TextField(
blank=True, help_text="Reason for status change", null=True
),
),
(
"notes",
models.TextField(
blank=True, help_text="Additional notes", null=True
),
),
("changed_at", models.DateTimeField(auto_now_add=True)),
(
"changed_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
),
),
(
"claim",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="status_history",
to="patients.insuranceclaim",
),
),
],
options={
"verbose_name": "Claim Status History",
"verbose_name_plural": "Claim Status Histories",
"db_table": "patients_claim_status_history",
"ordering": ["-changed_at"],
},
),
migrations.CreateModel(
name="ClaimDocument",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"document_type",
models.CharField(
choices=[
("MEDICAL_REPORT", "Medical Report"),
("LAB_RESULT", "Laboratory Result"),
("RADIOLOGY_REPORT", "Radiology Report"),
("PRESCRIPTION", "Prescription"),
("INVOICE", "Invoice"),
("RECEIPT", "Receipt"),
("AUTHORIZATION", "Prior Authorization"),
("REFERRAL", "Referral Letter"),
("DISCHARGE_SUMMARY", "Discharge Summary"),
("OPERATIVE_REPORT", "Operative Report"),
("PATHOLOGY_REPORT", "Pathology Report"),
("INSURANCE_CARD", "Insurance Card Copy"),
("ID_COPY", "ID Copy"),
("OTHER", "Other"),
],
help_text="Type of document",
max_length=20,
),
),
("title", models.CharField(help_text="Document title", max_length=200)),
(
"description",
models.TextField(
blank=True, help_text="Document description", null=True
),
),
(
"file_path",
models.CharField(
help_text="Path to the document file", max_length=500
),
),
(
"file_size",
models.PositiveIntegerField(help_text="File size in bytes"),
),
(
"mime_type",
models.CharField(help_text="MIME type of the file", max_length=100),
),
("uploaded_at", models.DateTimeField(auto_now_add=True)),
(
"uploaded_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
),
),
(
"claim",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="documents",
to="patients.insuranceclaim",
),
),
],
options={
"verbose_name": "Claim Document",
"verbose_name_plural": "Claim Documents",
"db_table": "patients_claim_document",
"ordering": ["-uploaded_at"],
},
),
migrations.CreateModel(
name="InsuranceInfo",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"insurance_type",
models.CharField(
choices=[
("PRIMARY", "Primary"),
("SECONDARY", "Secondary"),
("TERTIARY", "Tertiary"),
],
default="PRIMARY",
help_text="Insurance type",
max_length=20,
),
),
(
"insurance_company",
models.CharField(
help_text="Insurance company name", max_length=200
),
),
(
"plan_name",
models.CharField(
blank=True,
help_text="Insurance plan name",
max_length=200,
null=True,
),
),
(
"plan_type",
models.CharField(
blank=True,
choices=[
("HMO", "Health Maintenance Organization"),
("PPO", "Preferred Provider Organization"),
("EPO", "Exclusive Provider Organization"),
("POS", "Point of Service"),
("HDHP", "High Deductible Health Plan"),
("MEDICARE", "Medicare"),
("MEDICAID", "Medicaid"),
("TRICARE", "TRICARE"),
("WORKERS_COMP", "Workers Compensation"),
("AUTO", "Auto Insurance"),
("OTHER", "Other"),
],
help_text="Plan type",
max_length=50,
null=True,
),
),
(
"status",
models.CharField(
choices=[
("PENDING", "Pending"),
("APPROVED", "Approved"),
("DENIED", "Denied"),
],
default="PENDING",
help_text="Insurance status",
max_length=20,
),
),
(
"policy_number",
models.CharField(
help_text="Policy/Member ID number", max_length=100
),
),
(
"group_number",
models.CharField(
blank=True, help_text="Group number", max_length=100, null=True
),
),
(
"subscriber_name",
models.CharField(help_text="Subscriber name", max_length=200),
),
(
"subscriber_relationship",
models.CharField(
choices=[
("SELF", "Self"),
("SPOUSE", "Spouse"),
("CHILD", "Child"),
("PARENT", "Parent"),
("OTHER", "Other"),
],
default="SELF",
help_text="Relationship to subscriber",
max_length=20,
),
),
(
"subscriber_dob",
models.DateField(
blank=True, help_text="Subscriber date of birth", null=True
),
),
(
"subscriber_id_number",
models.CharField(
blank=True,
help_text="Saudi National ID (10 digits)",
max_length=10,
null=True,
unique=True,
validators=[
django.core.validators.RegexValidator(
message="Saudi National ID must be exactly 10 digits",
regex="^\\d{10}$",
)
],
),
),
(
"effective_date",
models.DateField(help_text="Coverage effective date"),
),
(
"termination_date",
models.DateField(
blank=True, help_text="Coverage termination date", null=True
),
),
(
"copay_amount",
models.DecimalField(
blank=True,
decimal_places=2,
help_text="Copay amount",
max_digits=10,
null=True,
),
),
(
"deductible_amount",
models.DecimalField(
blank=True,
decimal_places=2,
help_text="Deductible amount",
max_digits=10,
null=True,
),
),
(
"out_of_pocket_max",
models.DecimalField(
blank=True,
decimal_places=2,
help_text="Out of pocket maximum",
max_digits=10,
null=True,
),
),
(
"is_verified",
models.BooleanField(
default=False, help_text="Insurance has been verified"
),
),
(
"verification_date",
models.DateTimeField(
blank=True, help_text="Date insurance was verified", null=True
),
),
(
"requires_authorization",
models.BooleanField(
default=False, help_text="Requires prior authorization"
),
),
(
"authorization_number",
models.CharField(
blank=True,
help_text="Authorization number",
max_length=100,
null=True,
),
),
(
"authorization_expiry",
models.DateField(
blank=True, help_text="Authorization expiry date", null=True
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Insurance is active"),
),
(
"is_primary",
models.BooleanField(default=False, help_text="Primary insurance"),
),
(
"notes",
models.TextField(
blank=True,
help_text="Additional notes about this insurance",
null=True,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"verified_by",
models.ForeignKey(
blank=True,
help_text="User who verified insurance",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="verified_insurance",
to="hr.employee",
),
),
],
options={
"verbose_name": "Insurance Information",
"verbose_name_plural": "Insurance Information",
"db_table": "patients_insurance_info",
"ordering": ["insurance_type", "insurance_company"],
},
),
migrations.AddField(
model_name="insuranceclaim",
name="insurance_info",
field=models.ForeignKey(
help_text="Insurance policy used for this claim",
on_delete=django.db.models.deletion.CASCADE,
related_name="claims",
to="patients.insuranceinfo",
),
),
migrations.CreateModel(
name="PatientProfile",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"patient_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique patient identifier",
unique=True,
),
),
(
"mrn",
models.CharField(
help_text="Medical Record Number", max_length=50, unique=True
),
),
(
"first_name",
models.CharField(help_text="First name", max_length=150),
),
("last_name", models.CharField(help_text="Last name", max_length=150)),
(
"middle_name",
models.CharField(
blank=True, help_text="Middle name", max_length=150, null=True
),
),
(
"preferred_name",
models.CharField(
blank=True,
help_text="Preferred name",
max_length=150,
null=True,
),
),
(
"suffix",
models.CharField(
blank=True,
help_text="Name suffix (Jr., Sr., III, etc.)",
max_length=20,
null=True,
),
),
("date_of_birth", models.DateField(help_text="Date of birth")),
(
"gender",
models.CharField(
choices=[
("MALE", "Male"),
("FEMALE", "Female"),
("OTHER", "Other"),
("UNKNOWN", "Unknown"),
("PREFER_NOT_TO_SAY", "Prefer not to say"),
],
help_text="Gender",
max_length=20,
),
),
(
"email",
models.EmailField(
blank=True, help_text="Email address", max_length=254, null=True
),
),
(
"phone_number",
models.CharField(
blank=True,
help_text="Primary phone number",
max_length=20,
null=True,
validators=[
django.core.validators.RegexValidator(
message='Phone number must be entered in the format: "+999999999". Up to 15 digits allowed.',
regex="^\\+?1?\\d{9,15}$",
)
],
),
),
(
"mobile_number",
models.CharField(
blank=True,
help_text="Mobile phone number",
max_length=20,
null=True,
validators=[
django.core.validators.RegexValidator(
message='Phone number must be entered in the format: "+999999999". Up to 15 digits allowed.',
regex="^\\+?1?\\d{9,15}$",
)
],
),
),
(
"address_line_1",
models.CharField(
blank=True,
help_text="Address line 1",
max_length=255,
null=True,
),
),
(
"address_line_2",
models.CharField(
blank=True,
help_text="Address line 2",
max_length=255,
null=True,
),
),
(
"city",
models.CharField(
blank=True, help_text="City", max_length=100, null=True
),
),
(
"state",
models.CharField(
blank=True, help_text="State/Province", max_length=50, null=True
),
),
(
"zip_code",
models.CharField(
blank=True,
help_text="ZIP/Postal code",
max_length=20,
null=True,
),
),
(
"country",
models.CharField(
default="Saudi Arabia", help_text="Country", max_length=100
),
),
(
"id_number",
models.CharField(
blank=True,
help_text="Saudi National ID (10 digits)",
max_length=10,
null=True,
unique=True,
validators=[
django.core.validators.RegexValidator(
message="Saudi National ID must be exactly 10 digits",
regex="^\\d{10}$",
)
],
),
),
(
"marital_status",
models.CharField(
blank=True,
choices=[
("SINGLE", "Single"),
("MARRIED", "Married"),
("DIVORCED", "Divorced"),
("WIDOWED", "Widowed"),
("SEPARATED", "Separated"),
("DOMESTIC_PARTNER", "Domestic Partner"),
("OTHER", "Other"),
("UNKNOWN", "Unknown"),
],
help_text="Marital status",
max_length=20,
null=True,
),
),
(
"primary_language",
models.CharField(
default="Arabic", help_text="Primary language", max_length=50
),
),
(
"interpreter_needed",
models.BooleanField(
default=False, help_text="Interpreter services needed"
),
),
(
"communication_preference",
models.CharField(
choices=[
("PHONE", "Phone"),
("EMAIL", "Email"),
("SMS", "SMS"),
("MAIL", "Mail"),
("PORTAL", "Patient Portal"),
],
default="PHONE",
help_text="Preferred communication method",
max_length=20,
),
),
(
"employer",
models.CharField(
blank=True, help_text="Employer", max_length=200, null=True
),
),
(
"occupation",
models.CharField(
blank=True, help_text="Occupation", max_length=100, null=True
),
),
(
"primary_care_physician",
models.CharField(
blank=True,
help_text="Primary care physician",
max_length=200,
null=True,
),
),
(
"referring_physician",
models.CharField(
blank=True,
help_text="Referring physician",
max_length=200,
null=True,
),
),
(
"allergies",
models.TextField(
blank=True, help_text="Known allergies", null=True
),
),
(
"medical_alerts",
models.TextField(
blank=True, help_text="Medical alerts and warnings", null=True
),
),
(
"has_advance_directive",
models.BooleanField(
default=False, help_text="Has advance directive on file"
),
),
(
"advance_directive_type",
models.CharField(
blank=True,
choices=[
("LIVING_WILL", "Living Will"),
("HEALTHCARE_PROXY", "Healthcare Proxy"),
("DNR", "Do Not Resuscitate"),
("POLST", "POLST"),
("OTHER", "Other"),
],
help_text="Type of advance directive",
max_length=50,
null=True,
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Patient is active"),
),
(
"is_deceased",
models.BooleanField(default=False, help_text="Patient is deceased"),
),
(
"date_of_death",
models.DateField(blank=True, help_text="Date of death", null=True),
),
(
"is_vip",
models.BooleanField(
default=False,
help_text="VIP patient requiring special handling",
),
),
(
"confidential_patient",
models.BooleanField(
default=False,
help_text="Confidential patient with restricted access",
),
),
(
"registration_date",
models.DateTimeField(
auto_now_add=True, help_text="Initial registration date"
),
),
(
"photo",
models.ImageField(
blank=True,
help_text="Patient photo",
null=True,
upload_to="patient_photos/",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"last_visit_date",
models.DateTimeField(
blank=True, help_text="Last visit date", null=True
),
),
(
"registered_by",
models.ForeignKey(
blank=True,
help_text="User who registered the patient",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="registered_patients",
to=settings.AUTH_USER_MODEL,
),
),
(
"tenant",
models.ForeignKey(
help_text="Organization tenant",
on_delete=django.db.models.deletion.CASCADE,
related_name="patients",
to="core.tenant",
),
),
],
options={
"verbose_name": "Patient Profile",
"verbose_name_plural": "Patient Profiles",
"db_table": "patients_patient_profile",
"ordering": ["last_name", "first_name"],
},
),
migrations.CreateModel(
name="PatientNote",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"note_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique note identifier",
unique=True,
),
),
("title", models.CharField(help_text="Note title", max_length=200)),
("content", models.TextField(help_text="Note content")),
(
"category",
models.CharField(
choices=[
("GENERAL", "General"),
("ADMINISTRATIVE", "Administrative"),
("CLINICAL", "Clinical"),
("BILLING", "Billing"),
("INSURANCE", "Insurance"),
("SOCIAL", "Social"),
("DISCHARGE", "Discharge Planning"),
("FOLLOW_UP", "Follow-up"),
("ALERT", "Alert"),
("OTHER", "Other"),
],
default="GENERAL",
help_text="Note category",
max_length=50,
),
),
(
"priority",
models.CharField(
choices=[
("LOW", "Low"),
("NORMAL", "Normal"),
("HIGH", "High"),
("URGENT", "Urgent"),
],
default="NORMAL",
help_text="Note priority",
max_length=20,
),
),
(
"is_confidential",
models.BooleanField(
default=False, help_text="Note is confidential"
),
),
(
"is_alert",
models.BooleanField(default=False, help_text="Note is an alert"),
),
(
"is_active",
models.BooleanField(default=True, help_text="Note is active"),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"created_by",
models.ForeignKey(
blank=True,
help_text="User who created the note",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_patient_notes",
to=settings.AUTH_USER_MODEL,
),
),
(
"patient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="patient_notes",
to="patients.patientprofile",
),
),
],
options={
"verbose_name": "Patient Note",
"verbose_name_plural": "Patient Notes",
"db_table": "patients_patient_note",
"ordering": ["-created_at"],
},
),
migrations.AddField(
model_name="insuranceinfo",
name="patient",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="insurance_info",
to="patients.patientprofile",
),
),
migrations.AddField(
model_name="insuranceclaim",
name="patient",
field=models.ForeignKey(
help_text="Patient associated with this claim",
on_delete=django.db.models.deletion.CASCADE,
related_name="insurance_claims",
to="patients.patientprofile",
),
),
migrations.CreateModel(
name="EmergencyContact",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"first_name",
models.CharField(help_text="First name", max_length=150),
),
("last_name", models.CharField(help_text="Last name", max_length=150)),
(
"relationship",
models.CharField(
choices=[
("SPOUSE", "Spouse"),
("PARENT", "Parent"),
("CHILD", "Child"),
("SIBLING", "Sibling"),
("GRANDPARENT", "Grandparent"),
("GRANDCHILD", "Grandchild"),
("AUNT_UNCLE", "Aunt/Uncle"),
("COUSIN", "Cousin"),
("FRIEND", "Friend"),
("NEIGHBOR", "Neighbor"),
("CAREGIVER", "Caregiver"),
("GUARDIAN", "Guardian"),
("OTHER", "Other"),
],
help_text="Relationship to patient",
max_length=50,
),
),
(
"phone_number",
models.CharField(
help_text="Primary phone number",
max_length=20,
validators=[
django.core.validators.RegexValidator(
message='Phone number must be entered in the format: "+999999999". Up to 15 digits allowed.',
regex="^\\+?1?\\d{9,15}$",
)
],
),
),
(
"mobile_number",
models.CharField(
blank=True,
help_text="Mobile phone number",
max_length=20,
null=True,
validators=[
django.core.validators.RegexValidator(
message='Phone number must be entered in the format: "+999999999". Up to 15 digits allowed.',
regex="^\\+?1?\\d{9,15}$",
)
],
),
),
(
"email",
models.EmailField(
blank=True, help_text="Email address", max_length=254, null=True
),
),
(
"address_line_1",
models.CharField(
blank=True,
help_text="Address line 1",
max_length=255,
null=True,
),
),
(
"address_line_2",
models.CharField(
blank=True,
help_text="Address line 2",
max_length=255,
null=True,
),
),
(
"city",
models.CharField(
blank=True, help_text="City", max_length=100, null=True
),
),
(
"state",
models.CharField(
blank=True, help_text="State/Province", max_length=50, null=True
),
),
(
"zip_code",
models.CharField(
blank=True,
help_text="ZIP/Postal code",
max_length=20,
null=True,
),
),
(
"priority",
models.PositiveIntegerField(
default=1, help_text="Contact priority (1 = highest)"
),
),
(
"is_authorized_for_medical_decisions",
models.BooleanField(
default=False, help_text="Authorized to make medical decisions"
),
),
(
"is_authorized_for_financial_decisions",
models.BooleanField(
default=False,
help_text="Authorized to make financial decisions",
),
),
(
"is_authorized_for_information",
models.BooleanField(
default=True,
help_text="Authorized to receive medical information",
),
),
(
"is_primary",
models.BooleanField(
default=False, help_text="Primary emergency contact"
),
),
(
"authorization_number",
models.CharField(
blank=True,
help_text="Authorization number",
max_length=100,
null=True,
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Contact is active"),
),
(
"notes",
models.TextField(
blank=True,
help_text="Additional notes about this contact",
null=True,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"patient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="emergency_contacts",
to="patients.patientprofile",
),
),
],
options={
"verbose_name": "Emergency Contact",
"verbose_name_plural": "Emergency Contacts",
"db_table": "patients_emergency_contact",
"ordering": ["priority", "last_name", "first_name"],
},
),
migrations.CreateModel(
name="ConsentForm",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"consent_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique consent identifier",
unique=True,
),
),
(
"status",
models.CharField(
choices=[
("PENDING", "Pending"),
("SIGNED", "Signed"),
("DECLINED", "Declined"),
("EXPIRED", "Expired"),
("REVOKED", "Revoked"),
],
default="PENDING",
help_text="Consent status",
max_length=20,
),
),
(
"patient_signature",
models.TextField(
blank=True, help_text="Patient digital signature", null=True
),
),
(
"patient_signed_at",
models.DateTimeField(
blank=True, help_text="Patient signature timestamp", null=True
),
),
(
"patient_ip_address",
models.GenericIPAddressField(
blank=True,
help_text="Patient IP address when signed",
null=True,
),
),
(
"guardian_signature",
models.TextField(
blank=True, help_text="Guardian digital signature", null=True
),
),
(
"guardian_signed_at",
models.DateTimeField(
blank=True, help_text="Guardian signature timestamp", null=True
),
),
(
"guardian_name",
models.CharField(
blank=True, help_text="Guardian name", max_length=200, null=True
),
),
(
"guardian_relationship",
models.CharField(
blank=True,
help_text="Guardian relationship to patient",
max_length=50,
null=True,
),
),
(
"witness_signature",
models.TextField(
blank=True, help_text="Witness digital signature", null=True
),
),
(
"witness_signed_at",
models.DateTimeField(
blank=True, help_text="Witness signature timestamp", null=True
),
),
(
"witness_name",
models.CharField(
blank=True, help_text="Witness name", max_length=200, null=True
),
),
(
"witness_title",
models.CharField(
blank=True, help_text="Witness title", max_length=100, null=True
),
),
(
"provider_name",
models.CharField(
blank=True, help_text="Provider name", max_length=200, null=True
),
),
(
"provider_signature",
models.TextField(
blank=True, help_text="Provider digital signature", null=True
),
),
(
"provider_signed_at",
models.DateTimeField(
blank=True, help_text="Provider signature timestamp", null=True
),
),
(
"effective_date",
models.DateTimeField(
default=django.utils.timezone.now,
help_text="Consent effective date",
),
),
(
"expiry_date",
models.DateTimeField(
blank=True, help_text="Consent expiry date", null=True
),
),
(
"revoked_at",
models.DateTimeField(
blank=True, help_text="Consent revocation timestamp", null=True
),
),
(
"revocation_reason",
models.TextField(
blank=True, help_text="Reason for revocation", null=True
),
),
(
"notes",
models.TextField(
blank=True,
help_text="Additional notes about this consent",
null=True,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"created_by",
models.ForeignKey(
blank=True,
help_text="User who created the consent form",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_consent_forms",
to=settings.AUTH_USER_MODEL,
),
),
(
"revoked_by",
models.ForeignKey(
blank=True,
help_text="User who revoked the consent",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="revoked_consents",
to="hr.employee",
),
),
(
"template",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="consent_forms",
to="patients.consenttemplate",
),
),
(
"patient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="consent_forms",
to="patients.patientprofile",
),
),
],
options={
"verbose_name": "Consent Form",
"verbose_name_plural": "Consent Forms",
"db_table": "patients_consent_form",
"ordering": ["-created_at"],
},
),
migrations.AddIndex(
model_name="consenttemplate",
index=models.Index(
fields=["tenant", "category"], name="patients_co_tenant__4ccb5c_idx"
),
),
migrations.AddIndex(
model_name="consenttemplate",
index=models.Index(
fields=["is_active"], name="patients_co_is_acti_e0ed6d_idx"
),
),
migrations.AddIndex(
model_name="patientprofile",
index=models.Index(
fields=["tenant", "mrn"], name="patients_pa_tenant__6d5dc5_idx"
),
),
migrations.AddIndex(
model_name="patientprofile",
index=models.Index(
fields=["last_name", "first_name"],
name="patients_pa_last_na_64c318_idx",
),
),
migrations.AddIndex(
model_name="patientprofile",
index=models.Index(
fields=["date_of_birth"], name="patients_pa_date_of_3c830c_idx"
),
),
migrations.AddIndex(
model_name="patientprofile",
index=models.Index(
fields=["id_number"], name="patients_pa_id_numb_37a581_idx"
),
),
migrations.AddIndex(
model_name="patientprofile",
index=models.Index(
fields=["mobile_number"], name="patients_pa_mobile__f5d849_idx"
),
),
migrations.AddIndex(
model_name="patientprofile",
index=models.Index(fields=["email"], name="patients_pa_email_1660f1_idx"),
),
migrations.AlterUniqueTogether(
name="patientprofile",
unique_together={("tenant", "mrn")},
),
migrations.AddIndex(
model_name="patientnote",
index=models.Index(
fields=["patient", "category"], name="patients_pa_patient_7df519_idx"
),
),
migrations.AddIndex(
model_name="patientnote",
index=models.Index(
fields=["priority"], name="patients_pa_priorit_f3d3a2_idx"
),
),
migrations.AddIndex(
model_name="patientnote",
index=models.Index(
fields=["is_alert"], name="patients_pa_is_aler_c82cb5_idx"
),
),
migrations.AddIndex(
model_name="insuranceinfo",
index=models.Index(
fields=["patient", "insurance_type"],
name="patients_in_patient_9447df_idx",
),
),
migrations.AddIndex(
model_name="insuranceinfo",
index=models.Index(
fields=["policy_number"], name="patients_in_policy__6f8287_idx"
),
),
migrations.AddIndex(
model_name="insuranceinfo",
index=models.Index(
fields=["is_verified"], name="patients_in_is_veri_d53f1a_idx"
),
),
migrations.AddIndex(
model_name="insuranceclaim",
index=models.Index(
fields=["claim_number"], name="patients_in_claim_n_3b3114_idx"
),
),
migrations.AddIndex(
model_name="insuranceclaim",
index=models.Index(
fields=["patient", "service_date"],
name="patients_in_patient_5d8b72_idx",
),
),
migrations.AddIndex(
model_name="insuranceclaim",
index=models.Index(
fields=["status", "priority"], name="patients_in_status_41f139_idx"
),
),
migrations.AddIndex(
model_name="insuranceclaim",
index=models.Index(
fields=["submitted_date"], name="patients_in_submitt_75aa55_idx"
),
),
migrations.AddIndex(
model_name="insuranceclaim",
index=models.Index(
fields=["insurance_info"], name="patients_in_insuran_f48b26_idx"
),
),
migrations.AddIndex(
model_name="emergencycontact",
index=models.Index(
fields=["patient", "priority"], name="patients_em_patient_6496bc_idx"
),
),
migrations.AddIndex(
model_name="emergencycontact",
index=models.Index(
fields=["phone_number"], name="patients_em_phone_n_8dce36_idx"
),
),
migrations.AddIndex(
model_name="consentform",
index=models.Index(
fields=["patient", "status"], name="patients_co_patient_3ce0cf_idx"
),
),
migrations.AddIndex(
model_name="consentform",
index=models.Index(
fields=["template"], name="patients_co_templat_af89d3_idx"
),
),
migrations.AddIndex(
model_name="consentform",
index=models.Index(
fields=["consent_id"], name="patients_co_consent_4c355d_idx"
),
),
]