2025-08-12 13:33:25 +03:00

1193 lines
44 KiB
Python

# Generated by Django 5.2.4 on 2025-08-04 04:41
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 = [
("contenttypes", "0002_remove_content_type_name"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Tenant",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"tenant_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique tenant identifier",
unique=True,
),
),
(
"name",
models.CharField(help_text="Organization name", max_length=200),
),
(
"display_name",
models.CharField(
help_text="Display name for the organization", max_length=200
),
),
(
"description",
models.TextField(
blank=True, help_text="Organization description", null=True
),
),
(
"organization_type",
models.CharField(
choices=[
("HOSPITAL", "Hospital"),
("CLINIC", "Clinic"),
("HEALTH_SYSTEM", "Health System"),
("AMBULATORY", "Ambulatory Care"),
("SPECIALTY", "Specialty Practice"),
("URGENT_CARE", "Urgent Care"),
("REHABILITATION", "Rehabilitation Center"),
("LONG_TERM_CARE", "Long-term Care"),
],
default="HOSPITAL",
max_length=50,
),
),
(
"address_line1",
models.CharField(help_text="Address line 1", max_length=200),
),
(
"address_line2",
models.CharField(
blank=True,
help_text="Address line 2",
max_length=200,
null=True,
),
),
("city", models.CharField(help_text="City", max_length=100)),
(
"state",
models.CharField(help_text="State or province", max_length=100),
),
(
"postal_code",
models.CharField(help_text="Postal code", max_length=20),
),
(
"country",
models.CharField(
default="United States", help_text="Country", max_length=100
),
),
(
"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}$",
)
],
),
),
(
"email",
models.EmailField(
help_text="Primary email address", max_length=254
),
),
(
"website",
models.URLField(
blank=True, help_text="Organization website", null=True
),
),
(
"license_number",
models.CharField(
blank=True,
help_text="Healthcare license number",
max_length=100,
null=True,
),
),
(
"accreditation_body",
models.CharField(
blank=True,
help_text="Accreditation body (e.g., Joint Commission)",
max_length=100,
null=True,
),
),
(
"accreditation_number",
models.CharField(
blank=True,
help_text="Accreditation number",
max_length=100,
null=True,
),
),
(
"accreditation_expiry",
models.DateField(
blank=True, help_text="Accreditation expiry date", null=True
),
),
(
"timezone",
models.CharField(
default="UTC", help_text="Organization timezone", max_length=50
),
),
(
"locale",
models.CharField(
default="en-US", help_text="Organization locale", max_length=10
),
),
(
"currency",
models.CharField(
default="USD",
help_text="Organization currency code",
max_length=3,
),
),
(
"subscription_plan",
models.CharField(
choices=[
("BASIC", "Basic"),
("STANDARD", "Standard"),
("PREMIUM", "Premium"),
("ENTERPRISE", "Enterprise"),
],
default="BASIC",
max_length=50,
),
),
(
"max_users",
models.PositiveIntegerField(
default=50, help_text="Maximum number of users allowed"
),
),
(
"max_patients",
models.PositiveIntegerField(
default=1000, help_text="Maximum number of patients allowed"
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Tenant is active"),
),
(
"is_trial",
models.BooleanField(default=False, help_text="Tenant is on trial"),
),
(
"trial_expires_at",
models.DateTimeField(
blank=True, help_text="Trial expiration date", null=True
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Tenant",
"verbose_name_plural": "Tenants",
"db_table": "core_tenant",
"ordering": ["name"],
},
),
migrations.CreateModel(
name="SystemNotification",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"notification_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique notification identifier",
unique=True,
),
),
(
"title",
models.CharField(help_text="Notification title", max_length=200),
),
("message", models.TextField(help_text="Notification message")),
(
"notification_type",
models.CharField(
choices=[
("INFO", "Information"),
("WARNING", "Warning"),
("ERROR", "Error"),
("SUCCESS", "Success"),
("MAINTENANCE", "Maintenance"),
("SECURITY", "Security Alert"),
("FEATURE", "New Feature"),
("UPDATE", "System Update"),
],
max_length=30,
),
),
(
"priority",
models.CharField(
choices=[
("LOW", "Low"),
("MEDIUM", "Medium"),
("HIGH", "High"),
("URGENT", "Urgent"),
],
default="MEDIUM",
max_length=20,
),
),
(
"target_audience",
models.CharField(
choices=[
("ALL_USERS", "All Users"),
("ADMINISTRATORS", "Administrators"),
("CLINICAL_STAFF", "Clinical Staff"),
("SUPPORT_STAFF", "Support Staff"),
("SPECIFIC_ROLES", "Specific Roles"),
("SPECIFIC_USERS", "Specific Users"),
],
default="ALL_USERS",
max_length=30,
),
),
(
"target_roles",
models.JSONField(
default=list,
help_text="Target user roles (if target_audience is SPECIFIC_ROLES)",
),
),
(
"is_dismissible",
models.BooleanField(
default=True, help_text="Users can dismiss this notification"
),
),
(
"auto_dismiss_after",
models.PositiveIntegerField(
blank=True, help_text="Auto-dismiss after X seconds", null=True
),
),
(
"show_on_login",
models.BooleanField(
default=False, help_text="Show notification on user login"
),
),
(
"start_date",
models.DateTimeField(
default=django.utils.timezone.now,
help_text="Notification start date",
),
),
(
"end_date",
models.DateTimeField(
blank=True, help_text="Notification end date", null=True
),
),
(
"action_url",
models.URLField(
blank=True,
help_text="Action URL for the notification",
null=True,
),
),
(
"action_text",
models.CharField(
blank=True,
help_text="Action button text",
max_length=100,
null=True,
),
),
(
"is_active",
models.BooleanField(
default=True, help_text="Notification is active"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
(
"created_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_notifications",
to=settings.AUTH_USER_MODEL,
),
),
(
"target_users",
models.ManyToManyField(
blank=True,
related_name="targeted_notifications",
to=settings.AUTH_USER_MODEL,
),
),
(
"tenant",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="notifications",
to="core.tenant",
),
),
],
options={
"verbose_name": "System Notification",
"verbose_name_plural": "System Notifications",
"db_table": "core_system_notification",
"ordering": ["-priority", "-created_at"],
},
),
migrations.CreateModel(
name="SystemConfiguration",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"key",
models.CharField(help_text="Configuration key", max_length=200),
),
("value", models.TextField(help_text="Configuration value")),
(
"data_type",
models.CharField(
choices=[
("STRING", "String"),
("INTEGER", "Integer"),
("FLOAT", "Float"),
("BOOLEAN", "Boolean"),
("JSON", "JSON"),
("DATE", "Date"),
("DATETIME", "DateTime"),
],
default="STRING",
max_length=20,
),
),
(
"category",
models.CharField(
help_text="Configuration category", max_length=100
),
),
(
"description",
models.TextField(
blank=True, help_text="Configuration description", null=True
),
),
(
"validation_rules",
models.JSONField(
default=dict,
help_text="Validation rules for the configuration value",
),
),
(
"default_value",
models.TextField(blank=True, help_text="Default value", null=True),
),
(
"is_sensitive",
models.BooleanField(
default=False, help_text="Configuration contains sensitive data"
),
),
(
"is_encrypted",
models.BooleanField(
default=False, help_text="Configuration value is encrypted"
),
),
(
"required_permission",
models.CharField(
blank=True,
help_text="Permission required to modify this configuration",
max_length=100,
null=True,
),
),
(
"is_active",
models.BooleanField(
default=True, help_text="Configuration is active"
),
),
(
"is_readonly",
models.BooleanField(
default=False, help_text="Configuration is read-only"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"updated_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="updated_configurations",
to=settings.AUTH_USER_MODEL,
),
),
(
"tenant",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="configurations",
to="core.tenant",
),
),
],
options={
"verbose_name": "System Configuration",
"verbose_name_plural": "System Configurations",
"db_table": "core_system_configuration",
"ordering": ["category", "key"],
"unique_together": {("tenant", "key")},
},
),
migrations.CreateModel(
name="IntegrationLog",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"log_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique log identifier",
unique=True,
),
),
(
"integration_type",
models.CharField(
choices=[
("HL7", "HL7 Message"),
("DICOM", "DICOM Communication"),
("API", "API Call"),
("DATABASE", "Database Sync"),
("FILE_TRANSFER", "File Transfer"),
("WEBHOOK", "Webhook"),
("EMAIL", "Email"),
("SMS", "SMS"),
],
max_length=30,
),
),
(
"direction",
models.CharField(
choices=[("INBOUND", "Inbound"), ("OUTBOUND", "Outbound")],
max_length=10,
),
),
(
"external_system",
models.CharField(help_text="External system name", max_length=200),
),
(
"endpoint",
models.CharField(
blank=True,
help_text="Integration endpoint",
max_length=500,
null=True,
),
),
(
"message_type",
models.CharField(
blank=True,
help_text="Message type (e.g., HL7 message type)",
max_length=100,
null=True,
),
),
(
"message_id",
models.CharField(
blank=True,
help_text="Message identifier",
max_length=200,
null=True,
),
),
(
"correlation_id",
models.UUIDField(
blank=True,
help_text="Correlation ID for tracking related messages",
null=True,
),
),
(
"request_data",
models.TextField(
blank=True, help_text="Request data sent", null=True
),
),
(
"response_data",
models.TextField(
blank=True, help_text="Response data received", null=True
),
),
(
"status",
models.CharField(
choices=[
("SUCCESS", "Success"),
("FAILED", "Failed"),
("PENDING", "Pending"),
("TIMEOUT", "Timeout"),
("RETRY", "Retry"),
],
max_length=20,
),
),
(
"error_code",
models.CharField(
blank=True, help_text="Error code", max_length=50, null=True
),
),
(
"error_message",
models.TextField(blank=True, help_text="Error message", null=True),
),
(
"processing_time_ms",
models.PositiveIntegerField(
blank=True,
help_text="Processing time in milliseconds",
null=True,
),
),
(
"timestamp",
models.DateTimeField(
default=django.utils.timezone.now, help_text="Log timestamp"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
(
"tenant",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="integration_logs",
to="core.tenant",
),
),
],
options={
"verbose_name": "Integration Log",
"verbose_name_plural": "Integration Logs",
"db_table": "core_integration_log",
"ordering": ["-timestamp"],
"indexes": [
models.Index(
fields=["tenant", "integration_type", "timestamp"],
name="core_integr_tenant__b44419_idx",
),
models.Index(
fields=["external_system", "status"],
name="core_integr_externa_11a6db_idx",
),
models.Index(
fields=["correlation_id"], name="core_integr_correla_d72107_idx"
),
],
},
),
migrations.CreateModel(
name="Department",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"department_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique department identifier",
unique=True,
),
),
(
"code",
models.CharField(
help_text="Department code (e.g., CARD, EMER, SURG)",
max_length=20,
),
),
("name", models.CharField(help_text="Department name", max_length=100)),
(
"description",
models.TextField(
blank=True, help_text="Department description", null=True
),
),
(
"department_type",
models.CharField(
choices=[
("CLINICAL", "Clinical Department"),
("ANCILLARY", "Ancillary Services"),
("SUPPORT", "Support Services"),
("ADMINISTRATIVE", "Administrative"),
("DIAGNOSTIC", "Diagnostic Services"),
("THERAPEUTIC", "Therapeutic Services"),
("EMERGENCY", "Emergency Services"),
("SURGICAL", "Surgical Services"),
("MEDICAL", "Medical Services"),
("NURSING", "Nursing Services"),
("PHARMACY", "Pharmacy"),
("LABORATORY", "Laboratory"),
("RADIOLOGY", "Radiology"),
("REHABILITATION", "Rehabilitation"),
("MENTAL_HEALTH", "Mental Health"),
("PEDIATRIC", "Pediatric"),
("OBSTETRIC", "Obstetric"),
("ONCOLOGY", "Oncology"),
("CARDIOLOGY", "Cardiology"),
("NEUROLOGY", "Neurology"),
("ORTHOPEDIC", "Orthopedic"),
("OTHER", "Other"),
],
help_text="Type of department",
max_length=30,
),
),
(
"phone",
models.CharField(
blank=True,
help_text="Department phone number",
max_length=20,
null=True,
),
),
(
"extension",
models.CharField(
blank=True,
help_text="Phone extension",
max_length=10,
null=True,
),
),
(
"email",
models.EmailField(
blank=True,
help_text="Department email",
max_length=254,
null=True,
),
),
(
"building",
models.CharField(
blank=True,
help_text="Building name or number",
max_length=50,
null=True,
),
),
(
"floor",
models.CharField(
blank=True,
help_text="Floor number or name",
max_length=20,
null=True,
),
),
(
"wing",
models.CharField(
blank=True,
help_text="Wing or section",
max_length=20,
null=True,
),
),
(
"room_numbers",
models.CharField(
blank=True,
help_text="Room numbers (e.g., 101-110, 201A-205C)",
max_length=100,
null=True,
),
),
(
"is_active",
models.BooleanField(default=True, help_text="Department is active"),
),
(
"is_24_hour",
models.BooleanField(
default=False, help_text="Department operates 24 hours"
),
),
(
"operating_hours",
models.JSONField(
blank=True,
default=dict,
help_text="Operating hours by day of week",
),
),
(
"cost_center_code",
models.CharField(
blank=True,
help_text="Cost center code for financial tracking",
max_length=20,
null=True,
),
),
(
"budget_code",
models.CharField(
blank=True, help_text="Budget code", max_length=20, null=True
),
),
(
"authorized_positions",
models.PositiveIntegerField(
default=0, help_text="Number of authorized positions"
),
),
(
"current_staff_count",
models.PositiveIntegerField(
default=0, help_text="Current number of staff members"
),
),
(
"accreditation_required",
models.BooleanField(
default=False,
help_text="Department requires special accreditation",
),
),
(
"accreditation_body",
models.CharField(
blank=True,
help_text="Accrediting body (e.g., Joint Commission, CAP)",
max_length=100,
null=True,
),
),
(
"last_inspection_date",
models.DateField(
blank=True, help_text="Last inspection date", null=True
),
),
(
"next_inspection_date",
models.DateField(
blank=True,
help_text="Next scheduled inspection 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 department",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_departments",
to=settings.AUTH_USER_MODEL,
),
),
(
"department_head",
models.ForeignKey(
blank=True,
help_text="Department head/manager",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="headed_departments",
to=settings.AUTH_USER_MODEL,
),
),
(
"parent_department",
models.ForeignKey(
blank=True,
help_text="Parent department (for hierarchical structure)",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="sub_departments",
to="core.department",
),
),
(
"tenant",
models.ForeignKey(
help_text="Organization tenant",
on_delete=django.db.models.deletion.CASCADE,
related_name="departments",
to="core.tenant",
),
),
],
options={
"verbose_name": "Department",
"verbose_name_plural": "Departments",
"db_table": "core_department",
"ordering": ["name"],
"indexes": [
models.Index(
fields=["tenant", "department_type"],
name="core_depart_tenant__ef3e04_idx",
),
models.Index(fields=["code"], name="core_depart_code_5a5745_idx"),
models.Index(
fields=["is_active"], name="core_depart_is_acti_ae42f9_idx"
),
models.Index(
fields=["parent_department"],
name="core_depart_parent__70dda4_idx",
),
],
"unique_together": {("tenant", "code")},
},
),
migrations.CreateModel(
name="AuditLogEntry",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"log_id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique log identifier",
unique=True,
),
),
(
"event_type",
models.CharField(
choices=[
("CREATE", "Create"),
("READ", "Read"),
("UPDATE", "Update"),
("DELETE", "Delete"),
("LOGIN", "Login"),
("LOGOUT", "Logout"),
("ACCESS", "Access"),
("EXPORT", "Export"),
("PRINT", "Print"),
("SHARE", "Share"),
("SYSTEM", "System Event"),
("ERROR", "Error"),
("SECURITY", "Security Event"),
],
max_length=50,
),
),
(
"event_category",
models.CharField(
choices=[
("AUTHENTICATION", "Authentication"),
("AUTHORIZATION", "Authorization"),
("DATA_ACCESS", "Data Access"),
("DATA_MODIFICATION", "Data Modification"),
("SYSTEM_ADMINISTRATION", "System Administration"),
("PATIENT_DATA", "Patient Data"),
("CLINICAL_DATA", "Clinical Data"),
("FINANCIAL_DATA", "Financial Data"),
("SECURITY", "Security"),
("INTEGRATION", "Integration"),
("REPORTING", "Reporting"),
],
max_length=50,
),
),
(
"user_email",
models.EmailField(
blank=True,
help_text="User email at time of event",
max_length=254,
null=True,
),
),
(
"user_role",
models.CharField(
blank=True,
help_text="User role at time of event",
max_length=50,
null=True,
),
),
(
"session_key",
models.CharField(
blank=True, help_text="Session key", max_length=40, null=True
),
),
(
"ip_address",
models.GenericIPAddressField(
blank=True, help_text="IP address", null=True
),
),
(
"user_agent",
models.TextField(
blank=True, help_text="User agent string", null=True
),
),
("object_id", models.PositiveIntegerField(blank=True, null=True)),
(
"object_repr",
models.CharField(
blank=True,
help_text="String representation of the object",
max_length=200,
null=True,
),
),
(
"action",
models.CharField(help_text="Action performed", max_length=200),
),
(
"description",
models.TextField(help_text="Detailed description of the event"),
),
(
"changes",
models.JSONField(
default=dict, help_text="Field changes (before/after values)"
),
),
(
"additional_data",
models.JSONField(default=dict, help_text="Additional event data"),
),
(
"patient_id",
models.CharField(
blank=True,
help_text="Patient identifier if applicable",
max_length=50,
null=True,
),
),
(
"patient_mrn",
models.CharField(
blank=True,
help_text="Patient MRN if applicable",
max_length=50,
null=True,
),
),
(
"risk_level",
models.CharField(
choices=[
("LOW", "Low"),
("MEDIUM", "Medium"),
("HIGH", "High"),
("CRITICAL", "Critical"),
],
default="LOW",
max_length=20,
),
),
(
"hipaa_relevant",
models.BooleanField(
default=False, help_text="Event is HIPAA relevant"
),
),
(
"gdpr_relevant",
models.BooleanField(
default=False, help_text="Event is GDPR relevant"
),
),
(
"is_successful",
models.BooleanField(default=True, help_text="Event was successful"),
),
(
"error_message",
models.TextField(
blank=True, help_text="Error message if event failed", null=True
),
),
(
"timestamp",
models.DateTimeField(
default=django.utils.timezone.now, help_text="Event timestamp"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
(
"content_type",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="contenttypes.contenttype",
),
),
(
"user",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="audit_logs",
to=settings.AUTH_USER_MODEL,
),
),
(
"tenant",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="audit_logs",
to="core.tenant",
),
),
],
options={
"verbose_name": "Audit Log Entry",
"verbose_name_plural": "Audit Log Entries",
"db_table": "core_audit_log_entry",
"ordering": ["-timestamp"],
"indexes": [
models.Index(
fields=["tenant", "event_type", "timestamp"],
name="core_audit__tenant__96449c_idx",
),
models.Index(
fields=["user", "timestamp"],
name="core_audit__user_id_4190d3_idx",
),
models.Index(
fields=["patient_mrn", "timestamp"],
name="core_audit__patient_9afecd_idx",
),
models.Index(
fields=["content_type", "object_id"],
name="core_audit__content_4866d0_idx",
),
models.Index(
fields=["risk_level", "timestamp"],
name="core_audit__risk_le_b2cf34_idx",
),
],
},
),
]