-
Notifications
You must be signed in to change notification settings - Fork 336
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migration for Orgs, Facility, Patients and Consultations
- Loading branch information
Showing
5 changed files
with
308 additions
and
2 deletions.
There are no files selected for viewing
280 changes: 280 additions & 0 deletions
280
...acility/migrations/0477_historicalpatientregistration_migrated_emr_patient_id_and_more.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,280 @@ | ||
# Generated by Django 5.1.4 on 2025-01-14 09:20 | ||
|
||
import django.db.models.deletion | ||
from django.db import migrations, models | ||
|
||
import logging | ||
from django.core.paginator import Paginator | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
MIGRARION_ID = 413370 | ||
COUNTRY = "India" | ||
|
||
def _get_org(Organization, obj): | ||
if obj.ward_id: | ||
return Organization.objects.get(name=obj.ward.name) | ||
elif obj.local_body_id: | ||
return Organization.objects.get(name=obj.local_body.name) | ||
elif obj.district_id: | ||
return Organization.objects.get(name=obj.district.name) | ||
elif obj.state_id: | ||
return Organization.objects.get(name=obj.state.name) | ||
return None | ||
|
||
def migrate_organizations(apps, schema_editor): | ||
Organization = apps.get_model("emr", "Organization") | ||
State = apps.get_model("users", "State") | ||
District = apps.get_model("users", "District") | ||
LocalBody = apps.get_model("users", "LocalBody") | ||
Ward = apps.get_model("users", "Ward") | ||
|
||
logger.debug("Migrating Organization") | ||
for state_obj in State.objects.all(): | ||
state_org = Organization.objects.create( | ||
name=state_obj.name, | ||
org_type="govt", | ||
system_generated=True, | ||
metadata={ | ||
"country": COUNTRY, | ||
"govt_org_type": "state", | ||
"govt_org_children_type": "district", | ||
}, | ||
meta= {"migration_id": MIGRARION_ID}, | ||
) | ||
logger.debug(f"Created State: {state_org.name=}") | ||
for district_obj in District.objects.filter(state=state_obj): | ||
district_org = Organization.objects.create( | ||
name=district_obj.name, | ||
root_org=state_org, | ||
parent=state_org, | ||
org_type="govt", | ||
system_generated=True, | ||
metadata={ | ||
"country": COUNTRY, | ||
"govt_org_type": "district", | ||
"govt_org_children_type": "local_body", | ||
}, | ||
meta= {"migration_id": MIGRARION_ID}, | ||
) | ||
logger.debug(f"Created District: {state_org.name=}, {district_org.name=}") | ||
for local_body_obj in LocalBody.objects.filter(district=district_obj): | ||
local_body_org = Organization.objects.create( | ||
name=local_body_obj.name, | ||
root_org=state_org, | ||
parent=district_org, | ||
org_type="govt", | ||
system_generated=True, | ||
metadata={ | ||
#TODO: add old types | ||
"country": COUNTRY, | ||
"govt_org_type": "local_body", | ||
"govt_org_children_type": "ward", | ||
}, | ||
meta= {"migration_id": MIGRARION_ID}, | ||
) | ||
logger.debug(f"Created Local Body: {state_org.name=}, \ | ||
{district_org.name=}, {local_body_org.name=}") | ||
for ward_obj in Ward.objects.filter(local_body=local_body_obj): | ||
ward_org = Organization.objects.create( | ||
name=ward_obj.name, | ||
root_org=state_org, | ||
parent=local_body_org, | ||
org_type="govt", | ||
system_generated=True, | ||
metadata={ | ||
#TODO: add ward numbers | ||
"country": COUNTRY, | ||
"govt_org_type": "ward", | ||
}, | ||
meta= {"migration_id": MIGRARION_ID}, | ||
) | ||
logger.debug(f"Created Ward: {state_org.name=}, \ | ||
{district_org.name=}, {local_body_org.name=}, \ | ||
{ward_org.name=}") | ||
|
||
|
||
def reverse_migrate_organizations(apps, schema_editor): | ||
logger.debug("Reversing Migration Organization") | ||
schema_editor.execute("DELETE FROM emr_organization WHERE meta->>'migration_id' = %s", [MIGRARION_ID]) | ||
|
||
|
||
def migrate_users(apps, schema_editor): | ||
User = apps.get_model("users", "User") | ||
Organization = apps.get_model("emr", "Organization") | ||
logger.debug("Migrating Users") | ||
bulk_update = [] | ||
for user in User.objects.all().select_related("state", "district", "local_body", "ward"): | ||
if user.geo_organization: | ||
continue | ||
geo_org = _get_org(Organization, user) | ||
if not geo_org: | ||
continue | ||
user.geo_organization = geo_org | ||
logger.debug(f"User: {user.name=}, {geo_org.name=}") | ||
bulk_update.append(user) | ||
User.objects.bulk_update(bulk_update, ["geo_organization"]) | ||
|
||
def reverse_migrate_users(apps, schema_editor): | ||
User = apps.get_model("users", "User") | ||
User.objects.filter( | ||
geo_organization__meta__migration_id=MIGRARION_ID | ||
).update( | ||
geo_organization=None | ||
) | ||
|
||
|
||
def migrate_facilities(apps, schema_editor): | ||
Facility = apps.get_model("facility", "Facility") | ||
Organization = apps.get_model("emr", "Organization") | ||
bulk_update = [] | ||
for facility in Facility.objects.all().select_related("state", "district", "local_body", "ward"): | ||
if facility.geo_organization: | ||
continue | ||
geo_org = _get_org(Organization, facility) | ||
if not geo_org: | ||
continue | ||
facility.geo_organization = geo_org | ||
#TODO: create facility organization | ||
bulk_update.append(facility) | ||
Facility.objects.bulk_update(bulk_update, ["geo_organization"]) | ||
|
||
def reverse_migrate_facilities(apps, schema_editor): | ||
Facility = apps.get_model("facility", "Facility") | ||
Facility.objects.filter( | ||
geo_organization__meta__migration_id=MIGRARION_ID | ||
).update( | ||
geo_organization=None | ||
) | ||
|
||
def migrate_patient_registrations(apps, schema_editor): | ||
PatientRegistration = apps.get_model("facility", "PatientRegistration") | ||
Patient = apps.get_model("emr", "Patient") | ||
Organization = apps.get_model("emr", "Organization") | ||
|
||
gender_map = { | ||
1: "male", | ||
2: "female", | ||
3: "non_binary", | ||
} | ||
blood_group_map = { | ||
"A+": "A_positive", | ||
"A-": "A_negative", | ||
"B+": "B_positive", | ||
"B-": "B_negative", | ||
"AB+": "AB_positive", | ||
"AB-": "AB_negative", | ||
"O+": "O_positive", | ||
"O-": "O_negative", | ||
"UNK": "unknown", | ||
} | ||
|
||
logger.debug("Migrating Patient Registrations") | ||
patient_registrations = PatientRegistration.objects.all() | ||
paginator = Paginator(patient_registrations, 2000) | ||
|
||
for page_number in paginator.page_range: | ||
page = paginator.page(page_number) | ||
bulk = [] | ||
for patient_registration in page.object_list: | ||
patient = Patient.objects.create( | ||
name=patient_registration.name, | ||
gender=gender_map.get(patient_registration.gender, ""), | ||
phone_number=patient_registration.phone_number, | ||
emergency_phone_number=patient_registration.emergency_phone_number, | ||
address=patient_registration.address, | ||
permanent_address=patient_registration.permanent_address, | ||
pincode=patient_registration.pincode, | ||
date_of_birth=patient_registration.date_of_birth, | ||
year_of_birth=patient_registration.year_of_birth, | ||
deceased_datetime=patient_registration.death_datetime, | ||
blood_group=blood_group_map.get(patient_registration.blood_group, ""), | ||
geo_organization=_get_org(Organization, patient_registration), | ||
meta={ | ||
"migration_id": MIGRARION_ID, | ||
}, | ||
created_by=patient_registration.created_by, | ||
updated_by=patient_registration.updated_by, | ||
created_at=patient_registration.created_at, | ||
updated_at=patient_registration.updated_at, | ||
) | ||
patient_registration.migrated_emr_patient_id = patient.id | ||
bulk.append(patient_registration) | ||
logger.debug(f"Created Patient: {patient.name=}") | ||
PatientRegistration.objects.bulk_update(bulk, ["migrated_emr_patient_id"]) | ||
|
||
def reverse_migrate_patient_registrations(apps, schema_editor): | ||
PatientRegistration = apps.get_model("facility", "PatientRegistration") | ||
PatientRegistration.objects.update(migrated_emr_patient_id=None) | ||
schema_editor.execute("DELETE FROM emr_patient WHERE meta->>'migration_id' = %s", [MIGRARION_ID]) | ||
|
||
|
||
def migrate_consultations(apps, schema_editor): | ||
PatientConsultation = apps.get_model("facility", "PatientConsultation") | ||
Encounter = apps.get_model("emr", "Encounter") | ||
|
||
paginator = Paginator(PatientConsultation.objects.all(), 2000) | ||
|
||
for page_number in paginator.page_range: | ||
page = paginator.page(page_number) | ||
bulk = [] | ||
for patient_consultation in page.object_list: | ||
encounter = Encounter.objects.create( | ||
meta={ | ||
"migration_id": MIGRARION_ID, | ||
}, | ||
created_by=patient_consultation.created_by, | ||
updated_by=patient_consultation.updated_by, | ||
created_at=patient_consultation.created_at, | ||
updated_at=patient_consultation.updated_at, | ||
) | ||
patient_consultation.migrated_emr_encounter_id = encounter.id | ||
bulk.append(patient_consultation) | ||
logger.debug(f"Created Encounter: {encounter.id=}") | ||
PatientConsultation.objects.bulk_update(bulk, ["migrated_emr_encounter_id"]) | ||
|
||
|
||
|
||
def reverse_migrate_consultations(apps, schema_editor): | ||
pass | ||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('contenttypes', '0002_remove_content_type_name'), | ||
('facility', '0476_facility_default_internal_organization_and_more'), | ||
] | ||
|
||
operations = [ | ||
migrations.DeleteModel( | ||
name='HistoricalPatientRegistration', | ||
), | ||
migrations.AddField( | ||
model_name='patientconsultation', | ||
name='migrated_emr_encounter_id', | ||
field=models.BigIntegerField(blank=True, null=True), | ||
), | ||
migrations.AddField( | ||
model_name='patientregistration', | ||
name='migrated_emr_patient_id', | ||
field=models.BigIntegerField(blank=True, null=True), | ||
), | ||
migrations.CreateModel( | ||
name='MigrationTracking', | ||
fields=[ | ||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('old_model_obj_id', models.BigIntegerField()), | ||
('new_model_obj_id', models.BigIntegerField()), | ||
('field', models.CharField(max_length=255)), | ||
('data', models.TimeField()), | ||
('new_model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='new_model', to='contenttypes.contenttype')), | ||
('old_model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_model', to='contenttypes.contenttype')), | ||
], | ||
), | ||
migrations.RunPython(migrate_organizations, reverse_migrate_organizations), | ||
migrations.RunPython(migrate_users, reverse_migrate_users), | ||
migrations.RunPython(migrate_facilities, reverse_migrate_facilities), | ||
migrations.RunPython(migrate_patient_registrations, reverse_migrate_patient_registrations), | ||
migrations.RunPython(migrate_consultations, reverse_migrate_consultations), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from django.contrib.contenttypes.models import ContentType | ||
from django.db import models | ||
|
||
|
||
class MigrationTracking(models.Model): | ||
""" | ||
Model to track the migrations that have been run on the database. | ||
""" | ||
|
||
old_model = models.ForeignKey( | ||
ContentType, on_delete=models.CASCADE, related_name="old_model" | ||
) | ||
old_model_obj_id = models.BigIntegerField() | ||
new_model = models.ForeignKey( | ||
ContentType, on_delete=models.CASCADE, related_name="new_model" | ||
) | ||
new_model_obj_id = models.BigIntegerField() | ||
field = models.CharField(max_length=255) | ||
data = models.TimeField() | ||
|
||
def __str__(self): | ||
return f"{self.old_model}({self.old_model_obj_id}) -> {self.new_model} : {self.field}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters