922 lines
34 KiB
Python
922 lines
34 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 = [
|
|
("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",
|
|
),
|
|
],
|
|
},
|
|
),
|
|
]
|