558 lines
22 KiB
Python
558 lines
22 KiB
Python
# Generated by Django 5.2.7 on 2025-10-27 10:50
|
|
|
|
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 = [
|
|
("appointments", "0001_initial"),
|
|
("core", "0001_initial"),
|
|
("finance", "0001_initial"),
|
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name="EInvoice",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="Created At")),
|
|
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Updated At")),
|
|
(
|
|
"uuid",
|
|
models.UUIDField(
|
|
help_text="Unique invoice UUID for ZATCA", unique=True, verbose_name="UUID"
|
|
),
|
|
),
|
|
(
|
|
"xml_payload",
|
|
models.TextField(
|
|
blank=True, help_text="Signed XML invoice", verbose_name="XML Payload"
|
|
),
|
|
),
|
|
(
|
|
"qr_base64",
|
|
models.TextField(
|
|
blank=True,
|
|
help_text="Base64-encoded QR code (TLV format)",
|
|
verbose_name="QR Code (Base64)",
|
|
),
|
|
),
|
|
(
|
|
"clearance_status",
|
|
models.CharField(
|
|
choices=[
|
|
("PENDING", "Pending"),
|
|
("CLEARED", "Cleared"),
|
|
("REJECTED", "Rejected"),
|
|
("REPORTED", "Reported"),
|
|
],
|
|
default="PENDING",
|
|
max_length=20,
|
|
verbose_name="Clearance Status",
|
|
),
|
|
),
|
|
(
|
|
"zatca_document_type",
|
|
models.CharField(
|
|
blank=True,
|
|
help_text="ZATCA document type code",
|
|
max_length=50,
|
|
verbose_name="Document Type",
|
|
),
|
|
),
|
|
(
|
|
"submission_mode",
|
|
models.CharField(
|
|
choices=[
|
|
("CLEARANCE", "Clearance (B2B)"),
|
|
("REPORTING", "Reporting (B2C)"),
|
|
],
|
|
max_length=20,
|
|
verbose_name="Submission Mode",
|
|
),
|
|
),
|
|
(
|
|
"response_payload",
|
|
models.JSONField(
|
|
blank=True,
|
|
default=dict,
|
|
help_text="ZATCA API response",
|
|
verbose_name="Response Payload",
|
|
),
|
|
),
|
|
(
|
|
"error_code",
|
|
models.CharField(blank=True, max_length=100, verbose_name="Error Code"),
|
|
),
|
|
("error_message", models.TextField(blank=True, verbose_name="Error Message")),
|
|
(
|
|
"submitted_at",
|
|
models.DateTimeField(blank=True, null=True, verbose_name="Submitted At"),
|
|
),
|
|
(
|
|
"invoice",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="e_invoices",
|
|
to="finance.invoice",
|
|
verbose_name="Invoice",
|
|
),
|
|
),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(app_label)s_%(class)s_related",
|
|
to="core.tenant",
|
|
verbose_name="Tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name": "E-Invoice",
|
|
"verbose_name_plural": "E-Invoices",
|
|
"ordering": ["-created_at"],
|
|
"indexes": [
|
|
models.Index(fields=["invoice"], name="integration_invoice_4943f2_idx"),
|
|
models.Index(
|
|
fields=["clearance_status", "created_at"],
|
|
name="integration_clearan_4a0998_idx",
|
|
),
|
|
models.Index(fields=["uuid"], name="integration_uuid_62e6c9_idx"),
|
|
models.Index(
|
|
fields=["tenant", "created_at"], name="integration_tenant__f948a6_idx"
|
|
),
|
|
],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="ExternalOrder",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="Created At")),
|
|
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Updated At")),
|
|
(
|
|
"order_type",
|
|
models.CharField(
|
|
choices=[("LAB", "Laboratory"), ("RADIOLOGY", "Radiology")],
|
|
max_length=20,
|
|
verbose_name="Order Type",
|
|
),
|
|
),
|
|
(
|
|
"order_details",
|
|
models.JSONField(
|
|
default=dict,
|
|
help_text="Order details (tests, studies, etc.)",
|
|
verbose_name="Order Details",
|
|
),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("ORDERED", "Ordered"),
|
|
("IN_PROGRESS", "In Progress"),
|
|
("COMPLETED", "Completed"),
|
|
("CANCELLED", "Cancelled"),
|
|
],
|
|
default="ORDERED",
|
|
max_length=20,
|
|
verbose_name="Status",
|
|
),
|
|
),
|
|
("result_url", models.URLField(blank=True, verbose_name="Result URL")),
|
|
(
|
|
"result_data",
|
|
models.JSONField(blank=True, default=dict, verbose_name="Result Data"),
|
|
),
|
|
("ordered_at", models.DateTimeField(auto_now_add=True, verbose_name="Ordered At")),
|
|
(
|
|
"completed_at",
|
|
models.DateTimeField(blank=True, null=True, verbose_name="Completed At"),
|
|
),
|
|
(
|
|
"ordered_by",
|
|
models.ForeignKey(
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
related_name="external_orders_made",
|
|
to=settings.AUTH_USER_MODEL,
|
|
verbose_name="Ordered By",
|
|
),
|
|
),
|
|
(
|
|
"patient",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="external_orders",
|
|
to="core.patient",
|
|
verbose_name="Patient",
|
|
),
|
|
),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(app_label)s_%(class)s_related",
|
|
to="core.tenant",
|
|
verbose_name="Tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name": "External Order",
|
|
"verbose_name_plural": "External Orders",
|
|
"ordering": ["-ordered_at"],
|
|
"indexes": [
|
|
models.Index(
|
|
fields=["patient", "order_type"], name="integration_patient_2011c6_idx"
|
|
),
|
|
models.Index(
|
|
fields=["status", "ordered_at"], name="integration_status_02d8be_idx"
|
|
),
|
|
models.Index(
|
|
fields=["tenant", "ordered_at"], name="integration_tenant__cae063_idx"
|
|
),
|
|
],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="NphiesEncounterLink",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"encounter_id",
|
|
models.CharField(
|
|
help_text="NPHIES Encounter ID", max_length=100, verbose_name="Encounter ID"
|
|
),
|
|
),
|
|
(
|
|
"claim_id",
|
|
models.CharField(
|
|
blank=True,
|
|
help_text="NPHIES Claim ID",
|
|
max_length=100,
|
|
verbose_name="Claim ID",
|
|
),
|
|
),
|
|
(
|
|
"claim_response_id",
|
|
models.CharField(
|
|
blank=True,
|
|
help_text="NPHIES Claim Response ID",
|
|
max_length=100,
|
|
verbose_name="Claim Response ID",
|
|
),
|
|
),
|
|
(
|
|
"appointment",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="nphies_encounter_links",
|
|
to="appointments.appointment",
|
|
verbose_name="Appointment",
|
|
),
|
|
),
|
|
(
|
|
"patient",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="nphies_encounter_links",
|
|
to="core.patient",
|
|
verbose_name="Patient",
|
|
),
|
|
),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(app_label)s_%(class)s_related",
|
|
to="core.tenant",
|
|
verbose_name="Tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name": "NPHIES Encounter Link",
|
|
"verbose_name_plural": "NPHIES Encounter Links",
|
|
"unique_together": {("tenant", "encounter_id")},
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="NphiesMessage",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="Created At")),
|
|
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Updated At")),
|
|
(
|
|
"direction",
|
|
models.CharField(
|
|
choices=[("OUTBOUND", "Outbound"), ("INBOUND", "Inbound")],
|
|
max_length=20,
|
|
verbose_name="Direction",
|
|
),
|
|
),
|
|
(
|
|
"resource_type",
|
|
models.CharField(
|
|
choices=[
|
|
("ELIGIBILITY", "Coverage Eligibility"),
|
|
("PRIOR_AUTH", "Prior Authorization"),
|
|
("CLAIM", "Claim"),
|
|
("PAYMENT_NOTICE", "Payment Notice"),
|
|
("PAYMENT_RECONCILIATION", "Payment Reconciliation"),
|
|
],
|
|
max_length=30,
|
|
verbose_name="Resource Type",
|
|
),
|
|
),
|
|
(
|
|
"fhir_json",
|
|
models.JSONField(
|
|
default=dict, help_text="FHIR resource JSON", verbose_name="FHIR JSON"
|
|
),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("QUEUED", "Queued"),
|
|
("SENT", "Sent"),
|
|
("ACK", "Acknowledged"),
|
|
("ERROR", "Error"),
|
|
],
|
|
default="QUEUED",
|
|
max_length=20,
|
|
verbose_name="Status",
|
|
),
|
|
),
|
|
(
|
|
"correlation_id",
|
|
models.CharField(
|
|
blank=True,
|
|
help_text="Correlation ID for request/response matching",
|
|
max_length=100,
|
|
verbose_name="Correlation ID",
|
|
),
|
|
),
|
|
(
|
|
"response_http_status",
|
|
models.PositiveIntegerField(
|
|
blank=True, null=True, verbose_name="Response HTTP Status"
|
|
),
|
|
),
|
|
(
|
|
"error_code",
|
|
models.CharField(blank=True, max_length=100, verbose_name="Error Code"),
|
|
),
|
|
("error_message", models.TextField(blank=True, verbose_name="Error Message")),
|
|
("sent_at", models.DateTimeField(blank=True, null=True, verbose_name="Sent At")),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(app_label)s_%(class)s_related",
|
|
to="core.tenant",
|
|
verbose_name="Tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name": "NPHIES Message",
|
|
"verbose_name_plural": "NPHIES Messages",
|
|
"ordering": ["-created_at"],
|
|
"indexes": [
|
|
models.Index(
|
|
fields=["direction", "resource_type"], name="integration_directi_f3e34d_idx"
|
|
),
|
|
models.Index(
|
|
fields=["status", "created_at"], name="integration_status_28f64c_idx"
|
|
),
|
|
models.Index(fields=["correlation_id"], name="integration_correla_434176_idx"),
|
|
models.Index(
|
|
fields=["tenant", "created_at"], name="integration_tenant__46aa13_idx"
|
|
),
|
|
],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="PayerContract",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="Created At")),
|
|
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Updated At")),
|
|
(
|
|
"payer_code",
|
|
models.CharField(
|
|
help_text="Official payer code", max_length=50, verbose_name="Payer Code"
|
|
),
|
|
),
|
|
("payer_name", models.CharField(max_length=200, verbose_name="Payer Name")),
|
|
(
|
|
"credentials",
|
|
models.JSONField(
|
|
default=dict,
|
|
help_text="Encrypted credentials (OAuth2, mTLS, etc.)",
|
|
verbose_name="Credentials",
|
|
),
|
|
),
|
|
(
|
|
"endpoints",
|
|
models.JSONField(
|
|
default=dict,
|
|
help_text="API endpoints for different operations",
|
|
verbose_name="Endpoints",
|
|
),
|
|
),
|
|
(
|
|
"supports_eligibility",
|
|
models.BooleanField(default=True, verbose_name="Supports Eligibility Check"),
|
|
),
|
|
(
|
|
"supports_prior_auth",
|
|
models.BooleanField(default=True, verbose_name="Supports Prior Authorization"),
|
|
),
|
|
(
|
|
"supports_claims",
|
|
models.BooleanField(default=True, verbose_name="Supports Claims"),
|
|
),
|
|
("is_active", models.BooleanField(default=True, verbose_name="Is Active")),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(app_label)s_%(class)s_related",
|
|
to="core.tenant",
|
|
verbose_name="Tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name": "Payer Contract",
|
|
"verbose_name_plural": "Payer Contracts",
|
|
"ordering": ["payer_name"],
|
|
"unique_together": {("tenant", "payer_code")},
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="ZatcaCredential",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="Created At")),
|
|
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Updated At")),
|
|
(
|
|
"environment",
|
|
models.CharField(
|
|
choices=[
|
|
("SIMULATION", "Simulation"),
|
|
("COMPLIANCE", "Compliance"),
|
|
("PRODUCTION", "Production"),
|
|
],
|
|
max_length=20,
|
|
verbose_name="Environment",
|
|
),
|
|
),
|
|
(
|
|
"csid",
|
|
models.TextField(
|
|
help_text="Cryptographic Stamp Identifier", verbose_name="CSID"
|
|
),
|
|
),
|
|
(
|
|
"certificate",
|
|
models.TextField(
|
|
help_text="X.509 certificate (PEM format)", verbose_name="Certificate"
|
|
),
|
|
),
|
|
(
|
|
"private_key",
|
|
models.TextField(
|
|
help_text="Private key (encrypted, PEM format)", verbose_name="Private Key"
|
|
),
|
|
),
|
|
("is_active", models.BooleanField(default=True, verbose_name="Is Active")),
|
|
(
|
|
"expires_at",
|
|
models.DateTimeField(blank=True, null=True, verbose_name="Expires At"),
|
|
),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(app_label)s_%(class)s_related",
|
|
to="core.tenant",
|
|
verbose_name="Tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name": "ZATCA Credential",
|
|
"verbose_name_plural": "ZATCA Credentials",
|
|
"ordering": ["-created_at"],
|
|
"unique_together": {("tenant", "environment", "is_active")},
|
|
},
|
|
),
|
|
]
|