674 lines
26 KiB
Python
674 lines
26 KiB
Python
# Generated by Django 5.2.6 on 2025-09-19 10:58
|
|
|
|
import django.core.validators
|
|
import django.db.models.deletion
|
|
from django.conf import settings
|
|
from django.db import migrations, models
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
initial = True
|
|
|
|
dependencies = [
|
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name="BloodComponent",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"name",
|
|
models.CharField(
|
|
choices=[
|
|
("WHOLE_BLOOD", "Whole Blood"),
|
|
("PACKED_RBC", "Packed Red Blood Cells"),
|
|
("FRESH_FROZEN_PLASMA", "Fresh Frozen Plasma"),
|
|
("PLATELETS", "Platelets"),
|
|
("CRYOPRECIPITATE", "Cryoprecipitate"),
|
|
("GRANULOCYTES", "Granulocytes"),
|
|
],
|
|
max_length=50,
|
|
unique=True,
|
|
),
|
|
),
|
|
("description", models.TextField()),
|
|
("shelf_life_days", models.PositiveIntegerField()),
|
|
("storage_temperature", models.CharField(max_length=50)),
|
|
("volume_ml", models.PositiveIntegerField()),
|
|
("is_active", models.BooleanField(default=True)),
|
|
],
|
|
options={
|
|
"ordering": ["name"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="BloodTest",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"test_type",
|
|
models.CharField(
|
|
choices=[
|
|
("ABO_RH", "ABO/Rh Typing"),
|
|
("ANTIBODY_SCREEN", "Antibody Screening"),
|
|
("HIV", "HIV"),
|
|
("HBV", "Hepatitis B"),
|
|
("HCV", "Hepatitis C"),
|
|
("SYPHILIS", "Syphilis"),
|
|
("HTLV", "HTLV"),
|
|
("CMV", "CMV"),
|
|
("MALARIA", "Malaria"),
|
|
],
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"result",
|
|
models.CharField(
|
|
choices=[
|
|
("POSITIVE", "Positive"),
|
|
("NEGATIVE", "Negative"),
|
|
("INDETERMINATE", "Indeterminate"),
|
|
("PENDING", "Pending"),
|
|
],
|
|
default="PENDING",
|
|
max_length=15,
|
|
),
|
|
),
|
|
("test_date", models.DateTimeField()),
|
|
("equipment_used", models.CharField(blank=True, max_length=100)),
|
|
("lot_number", models.CharField(blank=True, max_length=50)),
|
|
("notes", models.TextField(blank=True)),
|
|
("verified_at", models.DateTimeField(blank=True, null=True)),
|
|
],
|
|
options={
|
|
"ordering": ["-test_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="BloodUnit",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("unit_number", models.CharField(max_length=20, unique=True)),
|
|
("collection_date", models.DateTimeField()),
|
|
("expiry_date", models.DateTimeField()),
|
|
("volume_ml", models.PositiveIntegerField()),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("COLLECTED", "Collected"),
|
|
("TESTING", "Testing"),
|
|
("QUARANTINE", "Quarantine"),
|
|
("AVAILABLE", "Available"),
|
|
("RESERVED", "Reserved"),
|
|
("ISSUED", "Issued"),
|
|
("TRANSFUSED", "Transfused"),
|
|
("EXPIRED", "Expired"),
|
|
("DISCARDED", "Discarded"),
|
|
],
|
|
default="COLLECTED",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("location", models.CharField(max_length=100)),
|
|
("bag_type", models.CharField(max_length=50)),
|
|
("anticoagulant", models.CharField(default="CPDA-1", max_length=50)),
|
|
("collection_site", models.CharField(max_length=100)),
|
|
("notes", models.TextField(blank=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
],
|
|
options={
|
|
"ordering": ["-collection_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="CrossMatch",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"test_type",
|
|
models.CharField(
|
|
choices=[
|
|
("MAJOR", "Major Crossmatch"),
|
|
("MINOR", "Minor Crossmatch"),
|
|
("IMMEDIATE_SPIN", "Immediate Spin"),
|
|
("ANTIGLOBULIN", "Antiglobulin Test"),
|
|
],
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"compatibility",
|
|
models.CharField(
|
|
choices=[
|
|
("COMPATIBLE", "Compatible"),
|
|
("INCOMPATIBLE", "Incompatible"),
|
|
("PENDING", "Pending"),
|
|
],
|
|
default="PENDING",
|
|
max_length=15,
|
|
),
|
|
),
|
|
("test_date", models.DateTimeField()),
|
|
("temperature", models.CharField(default="37°C", max_length=20)),
|
|
("incubation_time", models.PositiveIntegerField(default=15)),
|
|
("notes", models.TextField(blank=True)),
|
|
("verified_at", models.DateTimeField(blank=True, null=True)),
|
|
],
|
|
options={
|
|
"ordering": ["-test_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Donor",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("donor_id", models.CharField(max_length=20, unique=True)),
|
|
("first_name", models.CharField(max_length=100)),
|
|
("last_name", models.CharField(max_length=100)),
|
|
("date_of_birth", models.DateField()),
|
|
(
|
|
"gender",
|
|
models.CharField(
|
|
choices=[
|
|
("MALE", "Male"),
|
|
("FEMALE", "Female"),
|
|
("OTHER", "Other"),
|
|
],
|
|
max_length=10,
|
|
),
|
|
),
|
|
("national_id", models.CharField(max_length=10, unique=True)),
|
|
("phone", models.CharField(max_length=20)),
|
|
("email", models.EmailField(blank=True, max_length=254)),
|
|
("address", models.TextField()),
|
|
("emergency_contact_name", models.CharField(max_length=100)),
|
|
("emergency_contact_phone", models.CharField(max_length=20)),
|
|
(
|
|
"donor_type",
|
|
models.CharField(
|
|
choices=[
|
|
("VOLUNTARY", "Voluntary"),
|
|
("REPLACEMENT", "Replacement"),
|
|
("AUTOLOGOUS", "Autologous"),
|
|
("DIRECTED", "Directed"),
|
|
],
|
|
default="VOLUNTARY",
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("ACTIVE", "Active"),
|
|
("DEFERRED", "Deferred"),
|
|
("PERMANENTLY_DEFERRED", "Permanently Deferred"),
|
|
("INACTIVE", "Inactive"),
|
|
],
|
|
default="ACTIVE",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("registration_date", models.DateTimeField(auto_now_add=True)),
|
|
("last_donation_date", models.DateTimeField(blank=True, null=True)),
|
|
("total_donations", models.PositiveIntegerField(default=0)),
|
|
(
|
|
"weight",
|
|
models.FloatField(
|
|
validators=[django.core.validators.MinValueValidator(45.0)]
|
|
),
|
|
),
|
|
(
|
|
"height",
|
|
models.FloatField(
|
|
validators=[django.core.validators.MinValueValidator(140.0)]
|
|
),
|
|
),
|
|
("notes", models.TextField(blank=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
],
|
|
options={
|
|
"ordering": ["-registration_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="InventoryLocation",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("name", models.CharField(max_length=100, unique=True)),
|
|
(
|
|
"location_type",
|
|
models.CharField(
|
|
choices=[
|
|
("REFRIGERATOR", "Refrigerator"),
|
|
("FREEZER", "Freezer"),
|
|
("PLATELET_AGITATOR", "Platelet Agitator"),
|
|
("QUARANTINE", "Quarantine"),
|
|
("TESTING", "Testing Area"),
|
|
],
|
|
max_length=20,
|
|
),
|
|
),
|
|
("temperature_range", models.CharField(max_length=50)),
|
|
("temperature", models.FloatField(blank=True, null=True)),
|
|
("capacity", models.PositiveIntegerField()),
|
|
("current_stock", models.PositiveIntegerField(default=0)),
|
|
("is_active", models.BooleanField(default=True)),
|
|
("notes", models.TextField(blank=True)),
|
|
],
|
|
options={
|
|
"ordering": ["name"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="QualityControl",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"test_type",
|
|
models.CharField(
|
|
choices=[
|
|
("TEMPERATURE_MONITORING", "Temperature Monitoring"),
|
|
("EQUIPMENT_CALIBRATION", "Equipment Calibration"),
|
|
("REAGENT_TESTING", "Reagent Testing"),
|
|
("PROFICIENCY_TESTING", "Proficiency Testing"),
|
|
("PROCESS_VALIDATION", "Process Validation"),
|
|
],
|
|
max_length=30,
|
|
),
|
|
),
|
|
("test_date", models.DateTimeField()),
|
|
("equipment_tested", models.CharField(blank=True, max_length=100)),
|
|
("parameters_tested", models.TextField()),
|
|
("expected_results", models.TextField()),
|
|
("actual_results", models.TextField()),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("PASS", "Pass"),
|
|
("FAIL", "Fail"),
|
|
("PENDING", "Pending"),
|
|
],
|
|
max_length=10,
|
|
),
|
|
),
|
|
("review_date", models.DateTimeField(blank=True, null=True)),
|
|
("review_notes", models.TextField(blank=True)),
|
|
("corrective_action", models.TextField(blank=True)),
|
|
("next_test_date", models.DateTimeField(blank=True, null=True)),
|
|
("capa_initiated", models.BooleanField(default=False)),
|
|
("capa_number", models.CharField(blank=True, max_length=50)),
|
|
(
|
|
"capa_priority",
|
|
models.CharField(
|
|
blank=True,
|
|
choices=[
|
|
("LOW", "Low"),
|
|
("MEDIUM", "Medium"),
|
|
("HIGH", "High"),
|
|
],
|
|
max_length=10,
|
|
),
|
|
),
|
|
("capa_date", models.DateTimeField(blank=True, null=True)),
|
|
("capa_assessment", models.TextField(blank=True)),
|
|
(
|
|
"capa_status",
|
|
models.CharField(
|
|
blank=True,
|
|
choices=[
|
|
("OPEN", "Open"),
|
|
("IN_PROGRESS", "In Progress"),
|
|
("CLOSED", "Closed"),
|
|
],
|
|
max_length=20,
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"ordering": ["-test_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Transfusion",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("start_time", models.DateTimeField()),
|
|
("end_time", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("STARTED", "Started"),
|
|
("IN_PROGRESS", "In Progress"),
|
|
("COMPLETED", "Completed"),
|
|
("STOPPED", "Stopped"),
|
|
("ADVERSE_REACTION", "Adverse Reaction"),
|
|
],
|
|
default="STARTED",
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"volume_transfused",
|
|
models.PositiveIntegerField(blank=True, null=True),
|
|
),
|
|
("transfusion_rate", models.CharField(blank=True, max_length=50)),
|
|
("pre_transfusion_vitals", models.JSONField(default=dict)),
|
|
("post_transfusion_vitals", models.JSONField(default=dict)),
|
|
("vital_signs_history", models.JSONField(default=list)),
|
|
("current_blood_pressure", models.CharField(blank=True, max_length=20)),
|
|
("current_heart_rate", models.IntegerField(blank=True, null=True)),
|
|
("current_temperature", models.FloatField(blank=True, null=True)),
|
|
(
|
|
"current_respiratory_rate",
|
|
models.IntegerField(blank=True, null=True),
|
|
),
|
|
(
|
|
"current_oxygen_saturation",
|
|
models.IntegerField(blank=True, null=True),
|
|
),
|
|
("last_vitals_check", models.DateTimeField(blank=True, null=True)),
|
|
("patient_consent", models.BooleanField(default=False)),
|
|
("consent_date", models.DateTimeField(blank=True, null=True)),
|
|
("notes", models.TextField(blank=True)),
|
|
("stop_reason", models.TextField(blank=True)),
|
|
("completion_notes", models.TextField(blank=True)),
|
|
],
|
|
options={
|
|
"ordering": ["-start_time"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="AdverseReaction",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"reaction_type",
|
|
models.CharField(
|
|
choices=[
|
|
("FEBRILE", "Febrile Non-Hemolytic"),
|
|
("ALLERGIC", "Allergic"),
|
|
("HEMOLYTIC_ACUTE", "Acute Hemolytic"),
|
|
("HEMOLYTIC_DELAYED", "Delayed Hemolytic"),
|
|
("ANAPHYLACTIC", "Anaphylactic"),
|
|
("SEPTIC", "Septic"),
|
|
("CIRCULATORY_OVERLOAD", "Circulatory Overload"),
|
|
("LUNG_INJURY", "Transfusion-Related Acute Lung Injury"),
|
|
("OTHER", "Other"),
|
|
],
|
|
max_length=30,
|
|
),
|
|
),
|
|
(
|
|
"severity",
|
|
models.CharField(
|
|
choices=[
|
|
("MILD", "Mild"),
|
|
("MODERATE", "Moderate"),
|
|
("SEVERE", "Severe"),
|
|
("LIFE_THREATENING", "Life Threatening"),
|
|
],
|
|
max_length=20,
|
|
),
|
|
),
|
|
("onset_time", models.DateTimeField()),
|
|
("symptoms", models.TextField()),
|
|
("treatment_given", models.TextField()),
|
|
("outcome", models.TextField()),
|
|
("investigation_notes", models.TextField(blank=True)),
|
|
("regulatory_reported", models.BooleanField(default=False)),
|
|
("report_date", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"investigated_by",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.PROTECT,
|
|
related_name="investigated_reactions",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"reported_by",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.PROTECT,
|
|
related_name="reported_reactions",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"ordering": ["-onset_time"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="BloodGroup",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"abo_type",
|
|
models.CharField(
|
|
choices=[("A", "A"), ("B", "B"), ("AB", "AB"), ("O", "O")],
|
|
max_length=2,
|
|
),
|
|
),
|
|
(
|
|
"rh_factor",
|
|
models.CharField(
|
|
choices=[("POS", "Positive"), ("NEG", "Negative")], max_length=8
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"ordering": ["abo_type", "rh_factor"],
|
|
"unique_together": {("abo_type", "rh_factor")},
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="BloodIssue",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("issue_date", models.DateTimeField(auto_now_add=True)),
|
|
("expiry_time", models.DateTimeField()),
|
|
("returned", models.BooleanField(default=False)),
|
|
("return_date", models.DateTimeField(blank=True, null=True)),
|
|
("return_reason", models.TextField(blank=True)),
|
|
("notes", models.TextField(blank=True)),
|
|
(
|
|
"issued_by",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.PROTECT,
|
|
related_name="issued_units",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"issued_to",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.PROTECT,
|
|
related_name="received_units",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"ordering": ["-issue_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="BloodRequest",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("request_number", models.CharField(max_length=20, unique=True)),
|
|
(
|
|
"units_requested",
|
|
models.PositiveIntegerField(
|
|
validators=[django.core.validators.MinValueValidator(1)]
|
|
),
|
|
),
|
|
(
|
|
"urgency",
|
|
models.CharField(
|
|
choices=[
|
|
("ROUTINE", "Routine"),
|
|
("URGENT", "Urgent"),
|
|
("EMERGENCY", "Emergency"),
|
|
],
|
|
default="ROUTINE",
|
|
max_length=10,
|
|
),
|
|
),
|
|
("indication", models.TextField()),
|
|
("special_requirements", models.TextField(blank=True)),
|
|
("hemoglobin_level", models.FloatField(blank=True, null=True)),
|
|
("platelet_count", models.IntegerField(blank=True, null=True)),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("PENDING", "Pending"),
|
|
("PROCESSING", "Processing"),
|
|
("READY", "Ready"),
|
|
("ISSUED", "Issued"),
|
|
("COMPLETED", "Completed"),
|
|
("CANCELLED", "Cancelled"),
|
|
],
|
|
default="PENDING",
|
|
max_length=15,
|
|
),
|
|
),
|
|
("request_date", models.DateTimeField(auto_now_add=True)),
|
|
("required_by", models.DateTimeField()),
|
|
("processed_at", models.DateTimeField(blank=True, null=True)),
|
|
("notes", models.TextField(blank=True)),
|
|
("cancellation_reason", models.TextField(blank=True)),
|
|
("cancellation_date", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"cancelled_by",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.PROTECT,
|
|
related_name="cancelled_requests",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"component_requested",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.PROTECT,
|
|
to="blood_bank.bloodcomponent",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"ordering": ["-request_date"],
|
|
},
|
|
),
|
|
]
|