Marwan Alwali 263292f6be update
2025-11-04 00:50:06 +03:00

922 lines
34 KiB
Python

# Generated by Django 5.2.7 on 2025-10-06 21:15
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="Saudi Arabia", 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="SAR",
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="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",
),
],
},
),
]