Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrating feature field to array field #2223

Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b11ae4
migrating feature to array field
DraKen0009 Jun 3, 2024
e0e6042
updated serializer for feature field
DraKen0009 Jun 3, 2024
5223a9c
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Jun 3, 2024
817108e
Added validations and tests
DraKen0009 Jun 4, 2024
f61b9c6
Added tests
DraKen0009 Jun 4, 2024
061427e
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Jun 6, 2024
33a1937
Merge remote-tracking branch 'origin/updating-feature-to-arrayfield-i…
DraKen0009 Jun 6, 2024
a8f9aa3
added integer choice enum for features
DraKen0009 Jun 7, 2024
26cfb6b
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Jun 7, 2024
a5e083d
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Jun 19, 2024
a632c94
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Jul 9, 2024
8ad1e59
fixed migrations
DraKen0009 Jul 12, 2024
a647759
deleted merge migration and updated the numbers
DraKen0009 Jul 13, 2024
10dda7c
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Jul 13, 2024
1df9e5f
Merge branch 'coronasafe:develop' into updating-feature-to-arrayfield…
DraKen0009 Jul 20, 2024
643562e
fixed dummy data in facility.json
DraKen0009 Jul 20, 2024
5a814c4
fixed dummy data in facility.json
DraKen0009 Jul 20, 2024
3e45b7c
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Aug 8, 2024
06149a8
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
DraKen0009 Aug 16, 2024
8c5b4a6
updated migration number
DraKen0009 Aug 16, 2024
fe4994f
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
vigneshhari Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions care/facility/api/serializers/facility.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ class FacilityBasicInfoSerializer(serializers.ModelSerializer):
state_object = StateSerializer(source="state", read_only=True)
facility_type = serializers.SerializerMethodField()
read_cover_image_url = serializers.CharField(read_only=True)
features = serializers.MultipleChoiceField(choices=FEATURE_CHOICES)
features = serializers.ListField(
child=serializers.ChoiceField(choices=FEATURE_CHOICES),
required=False,
)
patient_count = serializers.SerializerMethodField()
bed_count = serializers.SerializerMethodField()

Expand Down Expand Up @@ -96,7 +99,10 @@ class FacilitySerializer(FacilityBasicInfoSerializer):
# }
read_cover_image_url = serializers.URLField(read_only=True)
# location = PointField(required=False)
features = serializers.MultipleChoiceField(choices=FEATURE_CHOICES)
features = serializers.ListField(
child=serializers.ChoiceField(choices=FEATURE_CHOICES),
required=False,
)
sainak marked this conversation as resolved.
Show resolved Hide resolved
bed_count = serializers.SerializerMethodField()

class Meta:
Expand Down Expand Up @@ -148,6 +154,13 @@ def validate_middleware_address(self, value):
MiddlewareDomainAddressValidator()(value)
return value

def validate_features(self, value):
if len(value) != len(set(value)):
raise serializers.ValidationError(
"Features should not contain duplicate values."
)
return value

def create(self, validated_data):
validated_data["created_by"] = self.context["request"].user
return super().create(validated_data)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 4.2.10 on 2024-06-03 06:24

import django.contrib.postgres.fields
from django.db import migrations, models


def convert_features_to_array(apps, schema_editor):
Facility = apps.get_model("facility", "Facility")

facilities_to_update = Facility.objects.filter(old_features__isnull=False)

updated_facilities = []

for facility in facilities_to_update:
try:
facility.features = list(facility.old_features)
updated_facilities.append(facility)
except ValueError:
print(f"facility '{facility.name}' has invalid facility features")

if updated_facilities:
Facility.objects.bulk_update(updated_facilities, ["features"])


class Migration(migrations.Migration):
dependencies = [
("facility", "0446_alter_notification_event"),
]

operations = [
migrations.RenameField(
model_name="facility",
old_name="features",
new_name="old_features",
),
migrations.AddField(
model_name="facility",
name="features",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.SmallIntegerField(
choices=[
(1, "CT Scan Facility"),
(2, "Maternity Care"),
(3, "X-Ray Facility"),
(4, "Neonatal Care"),
(5, "Operation Theater"),
(6, "Blood Bank"),
]
),
blank=True,
null=True,
size=None,
),
),
migrations.RunPython(convert_features_to_array),
]
27 changes: 25 additions & 2 deletions care/facility/models/facility.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.postgres.fields import ArrayField
from django.core.validators import MinValueValidator
from django.db import models
from multiselectfield import MultiSelectField
Expand Down Expand Up @@ -38,6 +39,7 @@
(70, "KASP Ventilator beds"),
]

# to be removed in further PR
FEATURE_CHOICES = [
(1, "CT Scan Facility"),
(2, "Maternity Care"),
Expand All @@ -47,9 +49,20 @@
(6, "Blood Bank"),
]


class FacilityFeature(models.IntegerChoices):
CT_SCAN_FACILITY = 1, "CT Scan Facility"
MATERNITY_CARE = 2, "Maternity Care"
X_RAY_FACILITY = 3, "X-Ray Facility"
NEONATAL_CARE = 4, "Neonatal Care"
OPERATION_THEATER = 5, "Operation Theater"
BLOOD_BANK = 6, "Blood Bank"


ROOM_TYPES.extend(BASE_ROOM_TYPES)

REVERSE_ROOM_TYPES = reverse_choices(ROOM_TYPES)
REVERSE_FEATURE_CHOICES = reverse_choices(FEATURE_CHOICES)
sainak marked this conversation as resolved.
Show resolved Hide resolved

FACILITY_TYPES = [
(1, "Educational Inst"),
Expand Down Expand Up @@ -160,13 +173,17 @@ class Facility(FacilityBaseModel, FacilityPermissionMixin):
verified = models.BooleanField(default=False)
facility_type = models.IntegerField(choices=FACILITY_TYPES)
kasp_empanelled = models.BooleanField(default=False, blank=False, null=False)
features = MultiSelectField(
features = ArrayField(
models.SmallIntegerField(choices=FacilityFeature.choices),
blank=True,
null=True,
)
old_features = MultiSelectField(
choices=FEATURE_CHOICES,
null=True,
blank=True,
max_length=get_max_length(FEATURE_CHOICES, None),
)

longitude = models.DecimalField(
max_digits=22, decimal_places=16, null=True, blank=True
)
Expand Down Expand Up @@ -243,6 +260,12 @@ def save(self, *args, **kwargs) -> None:
facility=self, user=self.created_by, created_by=self.created_by
)

@property
def get_features_display(self):
if not self.features:
return []
return [FacilityFeature(f).label for f in self.features]

CSV_MAPPING = {
"name": "Facility Name",
"facility_type": "Facility Type",
Expand Down
60 changes: 58 additions & 2 deletions care/facility/tests/test_facility_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ def test_listing(self):

def test_create(self):
dist_admin = self.create_user("dist_admin", self.district, user_type=30)
sample_data = {
self.client.force_authenticate(user=dist_admin)

sample_data_with_empty_feature_list = {
"name": "Hospital X",
"district": self.district.pk,
"state": self.state.pk,
Expand All @@ -33,7 +35,61 @@ def test_create(self):
"pincode": 390024,
"features": [],
}
self.client.force_authenticate(user=dist_admin)
response = self.client.post(
"/api/v1/facility/", sample_data_with_empty_feature_list
)
self.assertIs(response.status_code, status.HTTP_201_CREATED)

sample_data_with_invalid_choice = {
"name": "Hospital X",
"district": self.district.pk,
"state": self.state.pk,
"local_body": self.local_body.pk,
"facility_type": "Educational Inst",
"address": "Nearby",
"pincode": 390024,
"features": [1020, 2, 4, 5],
}
response = self.client.post(
"/api/v1/facility/", sample_data_with_invalid_choice
)

self.assertIs(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data["features"][0][0].code, "invalid_choice")
self.assertEqual(
response.data["features"][0][0], '"1020" is not a valid choice.'
)

sample_data_with_duplicate_choices = {
"name": "Hospital X",
"district": self.district.pk,
"state": self.state.pk,
"local_body": self.local_body.pk,
"facility_type": "Educational Inst",
"address": "Nearby",
"pincode": 390024,
"features": [1, 1],
}
response = self.client.post(
"/api/v1/facility/", sample_data_with_duplicate_choices
)

self.assertIs(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.data["features"][0],
"Features should not contain duplicate values.",
)

sample_data = {
"name": "Hospital X",
"district": self.district.pk,
"state": self.state.pk,
"local_body": self.local_body.pk,
"facility_type": "Educational Inst",
"address": "Nearby",
"pincode": 390024,
"features": [1, 2],
}
response = self.client.post("/api/v1/facility/", sample_data)
self.assertIs(response.status_code, status.HTTP_201_CREATED)
fac_id = response.data["id"]
Expand Down
Loading