670 lines
26 KiB
Python
670 lines
26 KiB
Python
# Generated by Django 5.2.6 on 2025-09-08 07:28
|
|
|
|
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=[("M", "Male"), ("F", "Female"), ("O", "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"],
|
|
},
|
|
),
|
|
]
|