From 2c4d207adc5e63b17c7a1be2001ee864ab961080 Mon Sep 17 00:00:00 2001 From: Abhiuday Gupta <77210185+cp-Coder@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:24:03 +0530 Subject: [PATCH 1/9] fix: added recommend_discharge as action (#1260) * fix(daily_round): added recommend_discharge as action * feat: added tests for log update API * fix: updated tests to fix CI pipeline * fix: fixed merge conflicts * fix(migrations): added merge migration --- care/facility/api/serializers/daily_round.py | 5 +- ...icalpatientregistration_action_and_more.py | 62 +++++++++++++++++++ .../migrations/0389_merge_20231002_1802.py | 12 ++++ care/facility/models/daily_round.py | 39 +++++++++--- care/facility/models/patient.py | 1 + .../tests/test_patient_daily_rounds_api.py | 30 +++++++++ care/utils/tests/test_utils.py | 3 +- 7 files changed, 139 insertions(+), 13 deletions(-) create mode 100644 care/facility/migrations/0388_alter_historicalpatientregistration_action_and_more.py create mode 100644 care/facility/migrations/0389_merge_20231002_1802.py diff --git a/care/facility/api/serializers/daily_round.py b/care/facility/api/serializers/daily_round.py index 340962d86d..94f1297977 100644 --- a/care/facility/api/serializers/daily_round.py +++ b/care/facility/api/serializers/daily_round.py @@ -211,7 +211,6 @@ def create(self, validated_data): "other_symptoms", "physical_examination_info", "other_details", - "recommend_discharge", "bp", "pulse", "resp", @@ -291,8 +290,8 @@ def create(self, validated_data): self.update_last_daily_round(daily_round_obj) return daily_round_obj - def validate(self, obj): - validated = super().validate(obj) + def validate(self, attrs): + validated = super().validate(attrs) if validated["consultation"].discharge_date: raise ValidationError( diff --git a/care/facility/migrations/0388_alter_historicalpatientregistration_action_and_more.py b/care/facility/migrations/0388_alter_historicalpatientregistration_action_and_more.py new file mode 100644 index 0000000000..c8324749b6 --- /dev/null +++ b/care/facility/migrations/0388_alter_historicalpatientregistration_action_and_more.py @@ -0,0 +1,62 @@ +from django.db import migrations, models + + +def update_recommend_discharge(apps, schema_editor): + patient_model = apps.get_model("facility", "PatientRegistration") + patient_model.objects.filter( + last_consultation__last_daily_round__recommend_discharge=True + ).update(action=90) + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0387_merge_20230911_2303"), + ] + + operations = [ + migrations.AlterField( + model_name="historicalpatientregistration", + name="action", + field=models.IntegerField( + blank=True, + choices=[ + (10, "NO_ACTION"), + (20, "PENDING"), + (30, "SPECIALIST_REQUIRED"), + (40, "PLAN_FOR_HOME_CARE"), + (50, "FOLLOW_UP_NOT_REQUIRED"), + (60, "COMPLETE"), + (70, "REVIEW"), + (80, "NOT_REACHABLE"), + (90, "DISCHARGE_RECOMMENDED"), + ], + default=10, + null=True, + ), + ), + migrations.AlterField( + model_name="patientregistration", + name="action", + field=models.IntegerField( + blank=True, + choices=[ + (10, "NO_ACTION"), + (20, "PENDING"), + (30, "SPECIALIST_REQUIRED"), + (40, "PLAN_FOR_HOME_CARE"), + (50, "FOLLOW_UP_NOT_REQUIRED"), + (60, "COMPLETE"), + (70, "REVIEW"), + (80, "NOT_REACHABLE"), + (90, "DISCHARGE_RECOMMENDED"), + ], + default=10, + null=True, + ), + ), + migrations.RunPython(update_recommend_discharge), + migrations.RemoveField( + model_name="dailyround", + name="recommend_discharge", + ), + ] diff --git a/care/facility/migrations/0389_merge_20231002_1802.py b/care/facility/migrations/0389_merge_20231002_1802.py new file mode 100644 index 0000000000..17a11528c7 --- /dev/null +++ b/care/facility/migrations/0389_merge_20231002_1802.py @@ -0,0 +1,12 @@ +# Generated by Django 4.2.5 on 2023-10-02 12:32 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0388_alter_historicalpatientregistration_action_and_more"), + ("facility", "0388_goal_goalentry_goalproperty_goalpropertyentry"), + ] + + operations = [] diff --git a/care/facility/models/daily_round.py b/care/facility/models/daily_round.py index 89575f5058..83b6f02f18 100644 --- a/care/facility/models/daily_round.py +++ b/care/facility/models/daily_round.py @@ -122,7 +122,9 @@ class InsulinIntakeFrequencyType(enum.Enum): ] consultation = models.ForeignKey( - PatientConsultation, on_delete=models.PROTECT, related_name="daily_rounds" + PatientConsultation, + on_delete=models.PROTECT, + related_name="daily_rounds", ) temperature = models.DecimalField( decimal_places=2, @@ -158,9 +160,6 @@ class InsulinIntakeFrequencyType(enum.Enum): current_health = models.IntegerField( default=0, choices=CURRENT_HEALTH_CHOICES, blank=True ) - recommend_discharge = models.BooleanField( - default=False, verbose_name="Recommend Discharging Patient" - ) other_details = models.TextField(null=True, blank=True) medication_given = JSONField(default=dict) # To be Used Later on @@ -168,7 +167,10 @@ class InsulinIntakeFrequencyType(enum.Enum): created_by_telemedicine = models.BooleanField(default=False) created_by = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, related_name="update_created_user" + User, + on_delete=models.SET_NULL, + null=True, + related_name="update_created_user", ) last_edited_by = models.ForeignKey( @@ -265,7 +267,8 @@ class InsulinIntakeFrequencyType(enum.Enum): rhythm = models.IntegerField(choices=RythmnChoice, default=RythmnType.UNKNOWN.value) rhythm_detail = models.TextField(default=None, null=True, blank=True) ventilator_interface = models.IntegerField( - choices=VentilatorInterfaceChoice, default=VentilatorInterfaceType.UNKNOWN.value + choices=VentilatorInterfaceChoice, + default=VentilatorInterfaceType.UNKNOWN.value, ) ventilator_mode = models.IntegerField( choices=VentilatorModeChoice, default=VentilatorModeType.UNKNOWN.value @@ -339,7 +342,8 @@ class InsulinIntakeFrequencyType(enum.Enum): validators=[MinValueValidator(0), MaxValueValidator(10)], ) pain_scale_enhanced = JSONField( - default=list, validators=[JSONFieldSchemaValidator(PAIN_SCALE_ENHANCED)] + default=list, + validators=[JSONFieldSchemaValidator(PAIN_SCALE_ENHANCED)], ) ph = models.DecimalField( decimal_places=2, @@ -457,9 +461,26 @@ def cztn(self, value): return value def update_pressure_sore(self): - area_interval_points = [0.1, 0.3, 0.7, 1.1, 2.1, 3.1, 4.1, 8.1, 12.1, 25] + area_interval_points = [ + 0.1, + 0.3, + 0.7, + 1.1, + 2.1, + 3.1, + 4.1, + 8.1, + 12.1, + 25, + ] exudate_amounts = ["None", "Light", "Moderate", "Heavy"] - tissue_types = ["Closed", "Epithelial", "Granulation", "Slough", "Necrotic"] + tissue_types = [ + "Closed", + "Epithelial", + "Granulation", + "Slough", + "Necrotic", + ] def cal_push_score(item): push_score = item.get("base_score", 0.0) diff --git a/care/facility/models/patient.py b/care/facility/models/patient.py index 44fe0ee1a6..cd14e5fcfa 100644 --- a/care/facility/models/patient.py +++ b/care/facility/models/patient.py @@ -77,6 +77,7 @@ class ActionEnum(enum.Enum): COMPLETE = 60 REVIEW = 70 NOT_REACHABLE = 80 + DISCHARGE_RECOMMENDED = 90 ActionChoices = [(e.value, e.name) for e in ActionEnum] diff --git a/care/facility/tests/test_patient_daily_rounds_api.py b/care/facility/tests/test_patient_daily_rounds_api.py index cd5a1eb56b..f53562db9a 100644 --- a/care/facility/tests/test_patient_daily_rounds_api.py +++ b/care/facility/tests/test_patient_daily_rounds_api.py @@ -1,6 +1,9 @@ +import datetime + from rest_framework import status from rest_framework.test import APITestCase +from care.facility.models import PatientRegistration from care.utils.tests.test_utils import TestUtils @@ -13,6 +16,10 @@ def setUpTestData(cls) -> None: cls.super_user = cls.create_super_user("su", cls.district) cls.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) cls.user = cls.create_user("staff1", cls.district, home_facility=cls.facility) + cls.patient = cls.create_patient(district=cls.district, facility=cls.facility) + cls.consultation = cls.create_consultation( + facility=cls.facility, patient=cls.patient + ) def get_url(self, external_consultation_id=None): return f"/api/v1/consultation/{external_consultation_id}/daily_rounds/analyse/" @@ -21,3 +28,26 @@ def test_external_consultation_does_not_exists_returns_404(self): sample_uuid = "e4a3d84a-d678-4992-9287-114f029046d8" response = self.client.get(self.get_url(sample_uuid)) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_action_in_log_update( + self, + ): + log_update = { + "clone_last": False, + "rounds_type": "NORMAL", + "patient_category": "Comfort", + "action": "DISCHARGE_RECOMMENDED", + "taken_at": datetime.datetime.now().isoformat(), + } + response = self.client.post( + f"/api/v1/consultation/{self.consultation.external_id}/daily_rounds/", + data=log_update, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(response.data["patient_category"], "Comfort Care") + self.assertEqual(response.data["rounds_type"], "NORMAL") + patient = PatientRegistration.objects.get(id=self.consultation.patient_id) + self.assertEqual( + patient.action, PatientRegistration.ActionEnum.DISCHARGE_RECOMMENDED.value + ) diff --git a/care/utils/tests/test_utils.py b/care/utils/tests/test_utils.py index 0c884afba2..2ba4412dd7 100644 --- a/care/utils/tests/test_utils.py +++ b/care/utils/tests/test_utils.py @@ -220,7 +220,8 @@ def create_facility( "created_by": user, } data.update(kwargs) - return Facility.objects.create(**data) + facility = Facility.objects.create(**data) + return facility @classmethod def get_patient_data(cls, district, state) -> dict: From 14f58f68bae49ba3fa6d6eed1ba89471f14c5e26 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Mon, 16 Oct 2023 18:29:42 +0530 Subject: [PATCH 2/9] Support for archiving medicine administrations (#1630) * Support for archiving medicine administrations * rebase migrations * update tests * improve test coverage * improve test coverage * update test * more test coverage.... --- care/facility/api/serializers/prescription.py | 3 ++ care/facility/api/viewsets/prescription.py | 36 ++++++++-------- ...cineadministration_archived_by_and_more.py | 30 ++++++++++++++ care/facility/models/prescription.py | 7 ++++ .../test_medicine_administrations_api.py | 41 ++++++++++++++++++- 5 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 care/facility/migrations/0389_medicineadministration_archived_by_and_more.py diff --git a/care/facility/api/serializers/prescription.py b/care/facility/api/serializers/prescription.py index 20f74133a4..49ad3d9913 100644 --- a/care/facility/api/serializers/prescription.py +++ b/care/facility/api/serializers/prescription.py @@ -94,6 +94,7 @@ class MedicineAdministrationSerializer(serializers.ModelSerializer): administered_by = UserBaseMinimumSerializer(read_only=True) prescription = PrescriptionSerializer(read_only=True) + archived_by = UserBaseMinimumSerializer(read_only=True) def validate_administered_date(self, value): if value > timezone.now(): @@ -112,6 +113,8 @@ class Meta: read_only_fields = ( "external_id", "administered_by", + "archived_by", + "archived_on", "created_date", "modified_date", "prescription", diff --git a/care/facility/api/viewsets/prescription.py b/care/facility/api/viewsets/prescription.py index b64a6a6f44..5af3a7473f 100644 --- a/care/facility/api/viewsets/prescription.py +++ b/care/facility/api/viewsets/prescription.py @@ -1,4 +1,5 @@ from django.shortcuts import get_object_or_404 +from django.utils import timezone from django_filters import rest_framework as filters from drf_spectacular.utils import extend_schema from rest_framework import mixins, status @@ -34,6 +35,12 @@ def inverse_choices(choices): class MedicineAdminstrationFilter(filters.FilterSet): prescription = filters.UUIDFilter(field_name="prescription__external_id") administered_date = filters.DateFromToRangeFilter(field_name="administered_date") + archived = filters.BooleanFilter(method="archived_filter") + + def archived_filter(self, queryset, name, value): + if value is None: + return queryset + return queryset.exclude(archived_on__isnull=value) class MedicineAdministrationViewSet( @@ -57,6 +64,19 @@ def get_queryset(self): consultation_obj = self.get_consultation_obj() return self.queryset.filter(prescription__consultation_id=consultation_obj.id) + @extend_schema(tags=["prescription_administration"]) + @action(methods=["POST"], detail=True) + def archive(self, request, *args, **kwargs): + instance = self.get_object() + if instance.archived_on: + return Response( + {"error": "Already Archived"}, status=status.HTTP_400_BAD_REQUEST + ) + instance.archived_by = request.user + instance.archived_on = timezone.now() + instance.save() + return Response({}, status=status.HTTP_200_OK) + class ConsultationPrescriptionFilter(filters.FilterSet): is_prn = filters.BooleanFilter() @@ -126,22 +146,6 @@ def administer(self, request, *args, **kwargs): serializer.save(prescription=prescription_obj, administered_by=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED) - # @action(methods=["GET"], detail=True) - # def get_administrations(self, request, *args, **kwargs): - # prescription_obj = self.get_object() - # serializer = MedicineAdministrationSerializer( - # MedicineAdministration.objects.filter(prescription_id=prescription_obj.id), - # many=True) - # return Response(serializer.data) - - # @action(methods=["DELETE"], detail=True) - # def delete_administered(self, request, *args, **kwargs): - # if not request.query_params.get("id", None): - # return Response({"success": False, "error": "id is required"}, status=status.HTTP_400_BAD_REQUEST) - # administered_obj = MedicineAdministration.objects.get(external_id=request.query_params.get("id", None)) - # administered_obj.delete() - # return Response({"success": True}, status=status.HTTP_200_OK) - class MedibaseViewSet(ViewSet): permission_classes = (IsAuthenticated,) diff --git a/care/facility/migrations/0389_medicineadministration_archived_by_and_more.py b/care/facility/migrations/0389_medicineadministration_archived_by_and_more.py new file mode 100644 index 0000000000..4188b48723 --- /dev/null +++ b/care/facility/migrations/0389_medicineadministration_archived_by_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.2 on 2023-09-27 09:38 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("facility", "0388_goal_goalentry_goalproperty_goalpropertyentry"), + ] + + operations = [ + migrations.AddField( + model_name="medicineadministration", + name="archived_by", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="medicineadministration", + name="archived_on", + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/care/facility/models/prescription.py b/care/facility/models/prescription.py index b6aca21eab..fc05467f4e 100644 --- a/care/facility/models/prescription.py +++ b/care/facility/models/prescription.py @@ -156,6 +156,13 @@ class MedicineAdministration(BaseModel): administered_date = models.DateTimeField( null=False, blank=False, default=timezone.now ) + archived_on = models.DateTimeField(null=True, blank=True) + archived_by = models.ForeignKey( + "users.User", + on_delete=models.PROTECT, + null=True, + related_name="+", + ) def __str__(self): return ( diff --git a/care/facility/tests/test_medicine_administrations_api.py b/care/facility/tests/test_medicine_administrations_api.py index 6283543e7a..dd99877261 100644 --- a/care/facility/tests/test_medicine_administrations_api.py +++ b/care/facility/tests/test_medicine_administrations_api.py @@ -36,7 +36,8 @@ def create_prescription(self, **kwargs): **{**data, **kwargs, "prescribed_by": self.user} ) - def test_administer(self): + def test_administer_and_archive(self): + # test administer prescription = self.normal_prescription res = self.client.post( f"/api/v1/consultation/{prescription.consultation.external_id}/prescriptions/{prescription.external_id}/administer/", @@ -44,6 +45,44 @@ def test_administer(self): ) self.assertEqual(res.status_code, status.HTTP_201_CREATED) + administration_id = res.data["id"] + + # test archive + archive_path = f"/api/v1/consultation/{prescription.consultation.external_id}/prescription_administration/{administration_id}/archive/" + res = self.client.post(archive_path, {}) + self.assertEqual(res.status_code, status.HTTP_200_OK) + + # test archive again + res = self.client.post(archive_path, {}) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + + # test list administrations + res = self.client.get( + f"/api/v1/consultation/{prescription.consultation.external_id}/prescription_administration/" + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertTrue( + any([administration_id == x["id"] for x in res.data["results"]]) + ) + + # test archived list administrations + res = self.client.get( + f"/api/v1/consultation/{prescription.consultation.external_id}/prescription_administration/?archived=true" + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertTrue( + any([administration_id == x["id"] for x in res.data["results"]]) + ) + + # test archived list administrations + res = self.client.get( + f"/api/v1/consultation/{prescription.consultation.external_id}/prescription_administration/?archived=false" + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertFalse( + any([administration_id == x["id"] for x in res.data["results"]]) + ) + def test_administer_in_future(self): prescription = self.normal_prescription res = self.client.post( From 0794d080cb8618733c3bf69c4be03237ea730b77 Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:33:52 +0530 Subject: [PATCH 3/9] Implement Middleware Override in AssetLocation (#1642) * Implement Middleware Override in AssetLocation * skip assets without hostname * facility middleware required & location's optional * fix migration * update migration --- care/facility/api/serializers/asset.py | 10 ++++++ care/facility/api/serializers/facility.py | 2 ++ care/facility/api/viewsets/asset.py | 9 ++++- .../0389_assetlocation_middleware_address.py | 17 +++++++++ care/facility/models/asset.py | 4 +++ care/facility/tasks/asset_monitor.py | 15 ++++++-- .../facility/tests/test_asset_location_api.py | 36 +++++++++++++++++-- care/utils/tests/test_utils.py | 7 +++- 8 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 care/facility/migrations/0389_assetlocation_middleware_address.py diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index 57692a8519..d52c46fe34 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -34,12 +34,22 @@ from care.utils.assetintegration.ventilator import VentilatorAsset from care.utils.queryset.facility import get_facility_queryset from config.serializers import ChoiceField +from config.validators import MiddlewareDomainAddressValidator class AssetLocationSerializer(ModelSerializer): facility = FacilityBareMinimumSerializer(read_only=True) id = UUIDField(source="external_id", read_only=True) + def validate_middleware_address(self, value): + value = (value or "").strip() + if not value: + return value + + # Check if the address is valid + MiddlewareDomainAddressValidator()(value) + return value + def validate(self, data): facility = self.context["facility"] if "name" in data: diff --git a/care/facility/api/serializers/facility.py b/care/facility/api/serializers/facility.py index eebd4a5d23..a7ac3820ed 100644 --- a/care/facility/api/serializers/facility.py +++ b/care/facility/api/serializers/facility.py @@ -138,6 +138,8 @@ class Meta: read_only_fields = ("modified_date", "created_date") def validate_middleware_address(self, value): + if not value: + raise serializers.ValidationError("Middleware Address is required") value = value.strip() if not value: return value diff --git a/care/facility/api/viewsets/asset.py b/care/facility/api/viewsets/asset.py index 5f6cea0f24..ae807ac347 100644 --- a/care/facility/api/viewsets/asset.py +++ b/care/facility/api/viewsets/asset.py @@ -321,10 +321,17 @@ def operate_assets(self, request, *args, **kwargs): try: action = request.data["action"] asset: Asset = self.get_object() + middleware_hostname = ( + asset.meta.get( + "middleware_hostname", + asset.current_location.middleware_address, + ) + or asset.current_location.facility.middleware_address + ) asset_class: BaseAssetIntegration = AssetClasses[asset.asset_class].value( { **asset.meta, - "middleware_hostname": asset.current_location.facility.middleware_address, + "middleware_hostname": middleware_hostname, } ) result = asset_class.handle_action(action) diff --git a/care/facility/migrations/0389_assetlocation_middleware_address.py b/care/facility/migrations/0389_assetlocation_middleware_address.py new file mode 100644 index 0000000000..9e162451eb --- /dev/null +++ b/care/facility/migrations/0389_assetlocation_middleware_address.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.2 on 2023-09-29 06:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0388_goal_goalentry_goalproperty_goalpropertyentry"), + ] + + operations = [ + migrations.AddField( + model_name="assetlocation", + name="middleware_address", + field=models.CharField(blank=True, default=None, max_length=200, null=True), + ), + ] diff --git a/care/facility/models/asset.py b/care/facility/models/asset.py index 1ad2d5d772..bbdf39f957 100644 --- a/care/facility/models/asset.py +++ b/care/facility/models/asset.py @@ -46,6 +46,10 @@ class RoomType(enum.Enum): Facility, on_delete=models.PROTECT, null=False, blank=False ) + middleware_address = models.CharField( + null=True, blank=True, default=None, max_length=200 + ) + class AssetType(enum.Enum): INTERNAL = 50 diff --git a/care/facility/tasks/asset_monitor.py b/care/facility/tasks/asset_monitor.py index 3c0b8e2fbe..89210d6892 100644 --- a/care/facility/tasks/asset_monitor.py +++ b/care/facility/tasks/asset_monitor.py @@ -31,10 +31,18 @@ def check_asset_status(): continue try: # Fetching middleware hostname - hostname = asset.meta.get( - "middleware_hostname", - asset.current_location.facility.middleware_address, + hostname = ( + asset.meta.get( + "middleware_hostname", + asset.current_location.middleware_address, + ) + or asset.current_location.facility.middleware_address ) + if not hostname: + logger.warn( + f"Asset {asset.external_id} does not have a middleware hostname" + ) + continue result: Any = None # Checking if middleware status is already cached @@ -62,6 +70,7 @@ def check_asset_status(): asset_class="ONVIF" ).filter( Q(meta__middleware_hostname=hostname) + | Q(current_location__middleware_address=hostname) | Q(current_location__facility__middleware_address=hostname) ) assets_config = [] diff --git a/care/facility/tests/test_asset_location_api.py b/care/facility/tests/test_asset_location_api.py index 0228a5dcb9..b859823c1b 100644 --- a/care/facility/tests/test_asset_location_api.py +++ b/care/facility/tests/test_asset_location_api.py @@ -27,21 +27,51 @@ def test_retrieve_asset_location(self): f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location.external_id}/" ) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertContains(response, self.asset_location.external_id) + self.assertEqual(response.data["id"], str(self.asset_location.external_id)) + self.assertEqual( + response.data["middleware_address"], self.asset_location.middleware_address + ) def test_create_asset_location(self): - sample_data = {"name": "Test Asset Location"} + sample_data = { + "name": "Test Asset Location", + "middleware_address": "example.com", + } response = self.client.post( f"/api/v1/facility/{self.facility.external_id}/asset_location/", sample_data, ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(response.data["name"], sample_data["name"]) + self.assertEqual( + response.data["middleware_address"], sample_data["middleware_address"] + ) def test_update_asset_location(self): - sample_data = {"name": "Updated Test Asset Location"} + sample_data = { + "name": "Updated Test Asset Location", + "middleware_address": "updated.example.com", + } response = self.client.patch( f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location.external_id}/", sample_data, ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["name"], sample_data["name"]) + self.assertEqual( + response.data["middleware_address"], sample_data["middleware_address"] + ) + + def test_create_asset_location_invalid_middleware(self): + sample_data = { + "name": "Test Asset Location", + "middleware_address": "https://invalid.middleware.///", + } + response = self.client.post( + f"/api/v1/facility/{self.facility.external_id}/asset_location/", + sample_data, + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual( + response.data["middleware_address"][0].code, "invalid_domain_name" + ) diff --git a/care/utils/tests/test_utils.py b/care/utils/tests/test_utils.py index 2ba4412dd7..d2b19705d1 100644 --- a/care/utils/tests/test_utils.py +++ b/care/utils/tests/test_utils.py @@ -331,7 +331,12 @@ def create_consultation( @classmethod def create_asset_location(cls, facility: Facility, **kwargs) -> AssetLocation: - data = {"name": "asset1 location", "location_type": 1, "facility": facility} + data = { + "name": "asset1 location", + "location_type": 1, + "facility": facility, + "middleware_address": "example.com", + } data.update(kwargs) return AssetLocation.objects.create(**data) From a1dc62c13ca71f0d9912a27dce1e3dc42ef20b8a Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:35:46 +0530 Subject: [PATCH 4/9] Add Medico-Legal Case Toggle and Filter (#1669) * Add medico-legal case toggle and filter * Add tests --- .../api/serializers/patient_consultation.py | 13 +++-- care/facility/api/viewsets/patient.py | 3 ++ ...0_patientconsultation_medico_legal_case.py | 17 +++++++ care/facility/models/patient_consultation.py | 2 + .../tests/test_patient_consultation_api.py | 51 +++++++++++++++++++ 5 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 care/facility/migrations/0390_patientconsultation_medico_legal_case.py diff --git a/care/facility/api/serializers/patient_consultation.py b/care/facility/api/serializers/patient_consultation.py index bc86b8515e..726facf027 100644 --- a/care/facility/api/serializers/patient_consultation.py +++ b/care/facility/api/serializers/patient_consultation.py @@ -106,6 +106,8 @@ class PatientConsultationSerializer(serializers.ModelSerializer): read_only=True ) + medico_legal_case = serializers.BooleanField(default=False, required=False) + def get_discharge_prescription(self, consultation): return Prescription.objects.filter( consultation=consultation, @@ -153,9 +155,14 @@ def update(self, instance, validated_data): instance.last_edited_by = self.context["request"].user if instance.discharge_date: - raise ValidationError( - {"consultation": ["Discharged Consultation data cannot be updated"]} - ) + if "medico_legal_case" not in validated_data: + raise ValidationError( + {"consultation": ["Discharged Consultation data cannot be updated"]} + ) + else: + instance.medico_legal_case = validated_data.pop("medico_legal_case") + instance.save() + return instance if instance.suggestion == SuggestionChoices.OP: instance.discharge_date = localtime(now()) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 0a502dc06a..2fe2e08954 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -149,6 +149,9 @@ def filter_by_category(self, queryset, name, value): last_consultation_admitted_bed_type_list = MultiSelectFilter( method="filter_by_bed_type", ) + last_consultation_medico_legal_case = filters.BooleanFilter( + field_name="last_consultation__medico_legal_case" + ) def filter_by_bed_type(self, queryset, name, value): if not value: diff --git a/care/facility/migrations/0390_patientconsultation_medico_legal_case.py b/care/facility/migrations/0390_patientconsultation_medico_legal_case.py new file mode 100644 index 0000000000..1e90f034ba --- /dev/null +++ b/care/facility/migrations/0390_patientconsultation_medico_legal_case.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.6 on 2023-10-11 06:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0389_merge_20231005_2247"), + ] + + operations = [ + migrations.AddField( + model_name="patientconsultation", + name="medico_legal_case", + field=models.BooleanField(default=False), + ), + ] diff --git a/care/facility/models/patient_consultation.py b/care/facility/models/patient_consultation.py index c43f6fd5da..6707e967a5 100644 --- a/care/facility/models/patient_consultation.py +++ b/care/facility/models/patient_consultation.py @@ -143,6 +143,8 @@ class PatientConsultation(PatientBaseModel, PatientRelatedPermissionMixin): related_name="patient_assigned_to", ) + medico_legal_case = models.BooleanField(default=False) + deprecated_verified_by = models.TextField(default="", null=True, blank=True) verified_by = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True diff --git a/care/facility/tests/test_patient_consultation_api.py b/care/facility/tests/test_patient_consultation_api.py index 4330ebb170..2ca154bfe5 100644 --- a/care/facility/tests/test_patient_consultation_api.py +++ b/care/facility/tests/test_patient_consultation_api.py @@ -256,3 +256,54 @@ def test_referred_to_external_valid_value(self): referred_to_external=referred_to_external, ) self.assertEqual(res.status_code, status.HTTP_200_OK) + + def test_medico_legal_case(self): + consultation = self.create_admission_consultation( + medico_legal_case=True, + ) + url = self.get_url(consultation) + + data = self.client.get(url) + self.assertEqual(data.status_code, status.HTTP_200_OK) + self.assertEqual(data.data["medico_legal_case"], True) + + # Test Patch + response = self.update_consultation(consultation, medico_legal_case=False) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["medico_legal_case"], False) + + # Test Patch after discharge + response = self.discharge( + consultation, + discharge_reason="REC", + discharge_date="2023-07-01T12:00:00Z", + discharge_notes="Discharged with valid referred_to_external", + medico_legal_case=False, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = self.client.get(url) + self.assertEqual(data.status_code, status.HTTP_200_OK) + self.assertEqual(data.data["medico_legal_case"], False) + + response = self.update_consultation(consultation, medico_legal_case=True) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["medico_legal_case"], True) + + def test_update_consultation_after_discharge(self): + consultation = self.create_admission_consultation( + suggestion="A", + admission_date=make_aware(datetime.datetime(2020, 4, 1, 15, 30, 00)), + ) + res = self.discharge( + consultation, + discharge_reason="REC", + discharge_date="2020-04-02T15:30:00Z", + discharge_notes="Discharge as recovered after admission before future", + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + + res = self.update_consultation( + consultation, symptoms=[1, 2], category="MILD", suggestion="A" + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) From 7d2a033e59869a252e229b1dfdd90af2bf2ead38 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Mon, 16 Oct 2023 22:49:36 +0530 Subject: [PATCH 5/9] merge migrations (#1676) --- .../migrations/0391_merge_20231016_1845.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 care/facility/migrations/0391_merge_20231016_1845.py diff --git a/care/facility/migrations/0391_merge_20231016_1845.py b/care/facility/migrations/0391_merge_20231016_1845.py new file mode 100644 index 0000000000..cce70587d2 --- /dev/null +++ b/care/facility/migrations/0391_merge_20231016_1845.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.5 on 2023-10-16 13:15 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0389_assetlocation_middleware_address"), + ("facility", "0389_medicineadministration_archived_by_and_more"), + ("facility", "0389_merge_20231002_1802"), + ("facility", "0390_patientconsultation_medico_legal_case"), + ] + + operations = [] From cb33897f26227f10523211f040a888888d9ed1c1 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Mon, 16 Oct 2023 22:58:42 +0530 Subject: [PATCH 6/9] feat: docker multiplatform builds (#1646) * docker multiplatform builds * fix concurrency issue --------- Co-authored-by: Vignesh Hari --- .github/workflows/deployment-branch.yaml | 46 +++++++++++------ .github/workflows/deployment.yaml | 66 ++++++++++++++++++------ .github/workflows/test-base.yml | 23 ++++++--- .github/workflows/tests.yml | 2 +- 4 files changed, 99 insertions(+), 38 deletions(-) diff --git a/.github/workflows/deployment-branch.yaml b/.github/workflows/deployment-branch.yaml index de274d679f..776646c1ed 100644 --- a/.github/workflows/deployment-branch.yaml +++ b/.github/workflows/deployment-branch.yaml @@ -5,10 +5,8 @@ on: push: branches: - - abdm - - abdm-m2 - - hcx-communications - - fix-hcx + - abdm-m3 + - hcx_refactors paths-ignore: - "docs/**" @@ -29,33 +27,49 @@ jobs: type=raw,value=${{ github.ref_name}}-${{ github.run_number }} type=raw,value=${{ github.ref_name}} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Cache Docker layers uses: actions/cache@v3 with: path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ hashFiles('r*/base.txt', 'r*/production.txt', 'Dockerfile') }} + key: ${{ runner.os }}-buildx-${{ hashFiles('Pipfile.lock', 'docker/prod.Dockerfile') }} restore-keys: | ${{ runner.os }}-buildx- - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . - file: Dockerfile + file: docker/prod.Dockerfile push: true + provenance: false + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} + build-args: | + APP_VERSION=${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + - name: Create Sentry release + uses: getsentry/action-release@v1 + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + with: + version: ${{ github.sha }} - name: Move cache run: | diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml index ca12a7dd38..f50eafbbee 100644 --- a/.github/workflows/deployment.yaml +++ b/.github/workflows/deployment.yaml @@ -10,7 +10,7 @@ on: - "docs/**" concurrency: - group: ${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: @@ -55,33 +55,46 @@ jobs: flavor: | latest=true + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ hashFiles('Pipfile.lock', 'docker/prod.Dockerfile') }} + restore-keys: | + ${{ runner.os }}-buildx- + - name: Build image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . file: docker/prod.Dockerfile push: true + provenance: false + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} build-args: | APP_VERSION=${{ github.sha }} - cache-from: type=gha,scope=cached-stage - cache-to: type=gha,scope=cached-stage,mode=max + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Create Sentry release uses: getsentry/action-release@v1 @@ -92,6 +105,11 @@ jobs: with: version: ${{ github.sha }} + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + build-production: needs: test name: Build & Push Production to container registries @@ -100,9 +118,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Docker meta id: meta uses: docker/metadata-action@v4 @@ -118,30 +133,46 @@ jobs: flavor: | latest=false + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ hashFiles('Pipfile.lock', 'docker/prod.Dockerfile') }} + restore-keys: | + ${{ runner.os }}-buildx- + - name: Build image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . file: docker/prod.Dockerfile push: true + provenance: false + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} build-args: | APP_VERSION=${{ github.sha }} - cache-from: type=gha,scope=cached-stage - cache-to: type=gha,scope=cached-stage,mode=max + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Create Sentry release uses: getsentry/action-release@v1 @@ -152,6 +183,11 @@ jobs: with: version: ${{ github.sha }} + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + deploy-staging-egov: needs: build-staging name: Deploy to ECS API Egov diff --git a/.github/workflows/test-base.yml b/.github/workflows/test-base.yml index b5ef741be5..87a611f4a0 100644 --- a/.github/workflows/test-base.yml +++ b/.github/workflows/test-base.yml @@ -10,17 +10,23 @@ jobs: - uses: actions/checkout@v4 - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ hashFiles('Pipfile.lock', 'docker/prod.Dockerfile') }} + restore-keys: | + ${{ runner.os }}-buildx- - name: Bake docker images - uses: docker/bake-action@v3.1.0 + uses: docker/bake-action@v4 with: load: true - builder: ${{ steps.buildx.outputs.name }} set: | - *.cache-from=type=gha,scope=cached-stage - *.cache-to=type=gha,scope=cached-stage,mode=max + *.cache-from=type=local,src=/tmp/.buildx-cache + *.cache-to=type=local,dest=/tmp/.buildx-cache-new files: docker-compose.yaml,docker-compose.local.yaml - name: Start services @@ -34,3 +40,8 @@ jobs: - name: Upload coverage report uses: codecov/codecov-action@v3 + + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d2cfbb4aac..e50648ab5a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,7 +4,7 @@ on: pull_request: concurrency: - group: ${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: From c314b11a025c795e70ec29ca4716df19538c33e5 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Wed, 18 Oct 2023 17:21:24 +0530 Subject: [PATCH 7/9] Add commands and docs for loading dummy data (#1682) * add make target to load dummy data for docker * load dummy data on postcreate devcontainer * add docs for loading dummy data * add missing docs dependencies --- .devcontainer/devcontainer.json | 3 +- Makefile | 3 + Pipfile.lock | 336 ++++++++++++++++++++++++++++- README.md | 9 +- docs/local-setup/configuration.rst | 10 +- 5 files changed, 356 insertions(+), 5 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0d38068dc1..795e29dd5c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,11 +12,10 @@ "waitFor": "onCreateCommand", "service": "backend", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", - "postCreateCommand": "python manage.py migrate && python manage.py collectstatic --noinput", + "postCreateCommand": "python manage.py migrate && python manage.py collectstatic --noinput && python manage.py load_dummy_data", "postAttachCommand": { "server": "python manage.py runserver" }, - "customizations": { "vscode": { "extensions": [ diff --git a/Makefile b/Makefile index e3985212d1..2e761cd334 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,9 @@ up: down: docker compose -f docker-compose.yaml -f $(docker_config_file) down +load-dummy-data: + docker compose exec backend bash -c "python manage.py load_dummy_data" + list: docker compose -f docker-compose.yaml -f $(docker_config_file) ps diff --git a/Pipfile.lock b/Pipfile.lock index 2286123a99..656bb61815 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "d091c185be68264550ec77fbc373a708956a5fd6f0068a7f373369d6bbffa8f8" + "sha256": "2418161c41fa4f575c5549b0ea3f3d2501c80869bbf8eee8eed381b07b908451" }, "pipfile-spec": 6, "requires": { @@ -2263,5 +2263,339 @@ "index": "pypi", "version": "==2.3.7" } + }, + "docs": { + "alabaster": { + "hashes": [ + "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3", + "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2" + ], + "markers": "python_version >= '3.6'", + "version": "==0.7.13" + }, + "babel": { + "hashes": [ + "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210", + "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec" + ], + "markers": "python_version >= '3.7'", + "version": "==2.13.0" + }, + "beautifulsoup4": { + "hashes": [ + "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", + "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" + ], + "markers": "python_full_version >= '3.6.0'", + "version": "==4.12.2" + }, + "certifi": { + "hashes": [ + "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", + "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9" + ], + "markers": "python_version >= '3.6'", + "version": "==2023.7.22" + }, + "charset-normalizer": { + "hashes": [ + "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96", + "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c", + "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710", + "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706", + "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020", + "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252", + "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad", + "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329", + "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a", + "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f", + "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6", + "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4", + "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a", + "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46", + "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2", + "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23", + "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace", + "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd", + "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982", + "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10", + "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2", + "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea", + "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09", + "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5", + "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149", + "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489", + "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9", + "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80", + "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592", + "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3", + "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6", + "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed", + "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c", + "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200", + "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a", + "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e", + "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d", + "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6", + "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623", + "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669", + "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3", + "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa", + "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9", + "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2", + "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f", + "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1", + "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4", + "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a", + "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8", + "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3", + "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029", + "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f", + "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959", + "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22", + "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7", + "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952", + "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346", + "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e", + "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d", + "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299", + "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd", + "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a", + "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3", + "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037", + "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94", + "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c", + "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858", + "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a", + "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449", + "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c", + "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918", + "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1", + "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c", + "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", + "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" + ], + "markers": "python_version >= '3.7'", + "version": "==3.2.0" + }, + "docutils": { + "hashes": [ + "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", + "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b" + ], + "markers": "python_version >= '3.7'", + "version": "==0.20.1" + }, + "furo": { + "hashes": [ + "sha256:513092538537dc5c596691da06e3c370714ec99bc438680edc1debffb73e5bfc", + "sha256:5707530a476d2a63b8cad83b4f961f3739a69f4b058bcf38a03a39fa537195b2" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2023.9.10" + }, + "idna": { + "hashes": [ + "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + ], + "markers": "python_version >= '3.5'", + "version": "==3.4" + }, + "imagesize": { + "hashes": [ + "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", + "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.4.1" + }, + "jinja2": { + "hashes": [ + "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", + "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.2" + }, + "markupsafe": { + "hashes": [ + "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e", + "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e", + "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", + "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", + "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c", + "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", + "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc", + "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb", + "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939", + "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c", + "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0", + "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4", + "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", + "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", + "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba", + "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d", + "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd", + "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3", + "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", + "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155", + "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", + "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", + "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", + "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8", + "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b", + "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007", + "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24", + "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea", + "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198", + "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0", + "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee", + "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be", + "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2", + "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1", + "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707", + "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", + "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c", + "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58", + "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823", + "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", + "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636", + "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", + "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", + "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", + "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc", + "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", + "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48", + "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", + "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e", + "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b", + "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", + "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5", + "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e", + "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", + "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", + "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", + "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", + "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc", + "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2", + "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11" + ], + "markers": "python_version >= '3.7'", + "version": "==2.1.3" + }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, + "pygments": { + "hashes": [ + "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692", + "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29" + ], + "markers": "python_version >= '3.7'", + "version": "==2.16.1" + }, + "requests": { + "hashes": [ + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + ], + "index": "pypi", + "version": "==2.31.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", + "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" + ], + "version": "==2.2.0" + }, + "soupsieve": { + "hashes": [ + "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", + "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5" + }, + "sphinx": { + "hashes": [ + "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", + "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==7.2.6" + }, + "sphinx-basic-ng": { + "hashes": [ + "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9", + "sha256:eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.0b2" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d", + "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.7" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212", + "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.5" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a", + "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9" + ], + "markers": "python_version >= '3.9'", + "version": "==2.0.4" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d", + "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.6" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54", + "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1" + ], + "markers": "python_version >= '3.9'", + "version": "==1.1.9" + }, + "urllib3": { + "hashes": [ + "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f", + "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14" + ], + "markers": "python_version >= '3.6'", + "version": "==1.26.16" + } } } diff --git a/README.md b/README.md index b5240a32e9..b1950e85ac 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,14 @@ put the required environment variables in a `.env` file and run: make up ``` -> ⚠️ If you are unable to compose up care in windows, ensure line endings are set to `LF` (`docker-entrypoint.sh` won't +to load dummy data for testing run: + +```bash +make load-dummy-data +``` + +> [!NOTE] +> If you are unable to compose up care in windows, ensure line endings are set to `LF` (`docker-entrypoint.sh` won't > work with `CRLF` line endings). > ``` > git config core.autocrlf false diff --git a/docs/local-setup/configuration.rst b/docs/local-setup/configuration.rst index 4fdb4d187b..dedc83bc99 100644 --- a/docs/local-setup/configuration.rst +++ b/docs/local-setup/configuration.rst @@ -30,8 +30,12 @@ first time, it might take a while depending upon your internet speed and machine $ make up - 2. Open a browser and go to `http://localhost:9000` + 2. To load dummy data for testing run: + .. code-block:: bash + + $ make load-dummy-data + 2. Open a browser and go to `http://localhost:9000` - To stop the development environment: .. code-block:: bash @@ -178,6 +182,10 @@ To copy static files (css, js, images) into the care/care/media directory so tha $ python manage.py collectstatic +To load dummy data for testing run:: + + $ python manage.py load_dummy_data + Type checks ~~~~~~~~~~~ From c96bb138dc9aa07d5900272108d7568e3ed2a15f Mon Sep 17 00:00:00 2001 From: Abhiuday Gupta <77210185+cp-Coder@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:18:54 +0530 Subject: [PATCH 8/9] Daily Rounds: Updated consciousness levels choices and migrated `CANNOT BE ASSESSED` to `UNKNOWN` (#1670) * fix(daily_round): updated consciousness levels * optimize and rebase migrations --------- Co-authored-by: rithviknishad --- ...92_alter_dailyround_consciousness_level.py | 36 +++++++++++++++++++ care/facility/models/daily_round.py | 9 ++--- 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 care/facility/migrations/0392_alter_dailyround_consciousness_level.py diff --git a/care/facility/migrations/0392_alter_dailyround_consciousness_level.py b/care/facility/migrations/0392_alter_dailyround_consciousness_level.py new file mode 100644 index 0000000000..cd20ef2193 --- /dev/null +++ b/care/facility/migrations/0392_alter_dailyround_consciousness_level.py @@ -0,0 +1,36 @@ +# Generated by Django 4.2.5 on 2023-10-18 04:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0391_merge_20231016_1845"), + ] + + def migrate_consciousness_level(apps, schema_editor): + DailyRound = apps.get_model("facility", "DailyRound") + # Migrate `CANNOT_BE_ASSESSED` to `UNKNOWN` + DailyRound.objects.filter(consciousness_level=25).update(consciousness_level=0) + + operations = [ + migrations.RunPython( + migrate_consciousness_level, reverse_code=migrations.RunPython.noop + ), + migrations.AlterField( + model_name="dailyround", + name="consciousness_level", + field=models.IntegerField( + choices=[ + (0, "UNKNOWN"), + (5, "ALERT"), + (10, "RESPONDS_TO_VOICE"), + (15, "RESPONDS_TO_PAIN"), + (20, "UNRESPONSIVE"), + (25, "AGITATED_OR_CONFUSED"), + (30, "ONSET_OF_AGITATION_AND_CONFUSION"), + ], + default=0, + ), + ), + ] diff --git a/care/facility/models/daily_round.py b/care/facility/models/daily_round.py index 83b6f02f18..daf1ba4d4c 100644 --- a/care/facility/models/daily_round.py +++ b/care/facility/models/daily_round.py @@ -44,10 +44,11 @@ class RoundsType(enum.Enum): class ConsciousnessType(enum.Enum): UNKNOWN = 0 ALERT = 5 - DROWSY = 10 - STUPOROUS = 15 - COMATOSE = 20 - CANNOT_BE_ASSESSED = 25 + RESPONDS_TO_VOICE = 10 + RESPONDS_TO_PAIN = 15 + UNRESPONSIVE = 20 + AGITATED_OR_CONFUSED = 25 + ONSET_OF_AGITATION_AND_CONFUSION = 30 ConsciousnessChoice = [(e.value, e.name) for e in ConsciousnessType] From 0daef7f6632a108aa4b91f5a0129d51d96bc4acc Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Fri, 20 Oct 2023 17:21:14 +0530 Subject: [PATCH 9/9] fix typo in docs for local dev installation (#1683) --- docs/local-setup/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/local-setup/configuration.rst b/docs/local-setup/configuration.rst index dedc83bc99..a59e3d6557 100644 --- a/docs/local-setup/configuration.rst +++ b/docs/local-setup/configuration.rst @@ -116,7 +116,7 @@ Pre-Commit is a package manager and tool for running and organising your git hoo * Install pre-commit pre-commit is installed while you run :: - pipenv install --categories "package dev-packages" + pipenv install --categories "packages dev-packages" * Setup this installs all the git-hooks ::