From 45a00d323aa8e98903c2f67ebb876116fd4cf439 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 4 Jul 2023 15:22:16 +0530 Subject: [PATCH 1/2] Add: List and Detail serialzier for facility_asset --- care/facility/api/serializers/asset.py | 82 ++++++++++++++++++++++++++ care/facility/api/viewsets/asset.py | 10 +++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index ce8f503af5..649520a88a 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -125,6 +125,88 @@ def update(self, instance, validated_data): cache.delete(f"asset:{instance.external_id}") return updated_instance +class AssetListSerializer(ModelSerializer): + id = UUIDField(source="external_id", read_only=True) + location_object = AssetLocationSerializer(source="current_location", read_only=True) + class Meta: + model = Asset + fields = ["id", "name", "asset_class",\ + "is_working", "location_object"] + read_only_fields = TIMESTAMP_FIELDS + + +class AssetDetailSerializer(AssetListSerializer): + status = ChoiceField(choices=Asset.StatusChoices, read_only=True) + asset_type = ChoiceField(choices=Asset.AssetTypeChoices) + location = UUIDField(write_only=True, required=True) + + class Meta: + model = Asset + exclude = ("deleted", "external_id", "current_location") + read_only_fields = TIMESTAMP_FIELDS + + def validate_qr_code_id(self, value): + value = value or None # treat empty string as null + UniqueValidator( + queryset=Asset.objects.filter(qr_code_id__isnull=False), + message="QR code already assigned", + )(value, self.fields.get("qr_code_id")) + return value + + def validate(self, attrs): + + user = self.context["request"].user + if "location" in attrs: + location = get_object_or_404( + AssetLocation.objects.filter(external_id=attrs["location"]) + ) + + facilities = get_facility_queryset(user) + if not facilities.filter(id=location.facility.id).exists(): + raise PermissionError() + del attrs["location"] + attrs["current_location"] = location + + # validate that warraty date is not in the past + if "warranty_amc_end_of_validity" in attrs: + if ( + attrs["warranty_amc_end_of_validity"] + and attrs["warranty_amc_end_of_validity"] < datetime.now().date() + ): + raise ValidationError( + "Warranty/AMC end of validity cannot be in the past" + ) + + # validate that last serviced date is not in the future + if "last_serviced_on" in attrs and attrs["last_serviced_on"]: + if attrs["last_serviced_on"] > datetime.now().date(): + raise ValidationError("Last serviced on cannot be in the future") + + return super().validate(attrs) + + def update(self, instance, validated_data): + user = self.context["request"].user + with transaction.atomic(): + if ( + "current_location" in validated_data + and instance.current_location != validated_data["current_location"] + ): + if ( + instance.current_location.facility.id + != validated_data["current_location"].facility.id + ): + raise ValidationError( + {"location": "Interfacility transfer is not allowed here"} + ) + AssetTransaction( + from_location=instance.current_location, + to_location=validated_data["current_location"], + asset=instance, + performed_by=user, + ).save() + updated_instance = super().update(instance, validated_data) + cache.delete(f"asset:{instance.external_id}") + return updated_instance class AssetBareMinimumSerializer(ModelSerializer): id = UUIDField(source="external_id", read_only=True) diff --git a/care/facility/api/viewsets/asset.py b/care/facility/api/viewsets/asset.py index c1b28f5ab0..e4755f9b00 100644 --- a/care/facility/api/viewsets/asset.py +++ b/care/facility/api/viewsets/asset.py @@ -27,6 +27,8 @@ from care.facility.api.serializers.asset import ( AssetLocationSerializer, AssetSerializer, + AssetDetailSerializer, + AssetListSerializer, AssetTransactionSerializer, UserDefaultAssetLocationSerializer, ) @@ -145,13 +147,19 @@ class AssetViewSet( .select_related("current_location", "current_location__facility") .order_by("-created_date") ) - serializer_class = AssetSerializer + serializer_class = AssetDetailSerializer lookup_field = "external_id" filter_backends = (filters.DjangoFilterBackend, drf_filters.SearchFilter) search_fields = ["name", "serial_number", "qr_code_id"] permission_classes = [IsAuthenticated] filterset_class = AssetFilter + def get_serializer_class(self): + if self.action == "list": + return AssetListSerializer + else: + return self.serializer_class + def get_queryset(self): user = self.request.user queryset = self.queryset From 6e0500ebcaa90727bf2d1e6d8fdb114f92593671 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 4 Jul 2023 15:38:33 +0530 Subject: [PATCH 2/2] Fix linting issues --- care/facility/api/serializers/asset.py | 10 +++++----- care/facility/api/viewsets/asset.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index 649520a88a..6b9f6949f4 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -71,7 +71,6 @@ def validate_qr_code_id(self, value): return value def validate(self, attrs): - user = self.context["request"].user if "location" in attrs: location = get_object_or_404( @@ -125,15 +124,16 @@ def update(self, instance, validated_data): cache.delete(f"asset:{instance.external_id}") return updated_instance + class AssetListSerializer(ModelSerializer): id = UUIDField(source="external_id", read_only=True) location_object = AssetLocationSerializer(source="current_location", read_only=True) + class Meta: model = Asset - fields = ["id", "name", "asset_class",\ - "is_working", "location_object"] + fields = ["id", "name", "asset_class", "is_working", "location_object"] read_only_fields = TIMESTAMP_FIELDS - + class AssetDetailSerializer(AssetListSerializer): status = ChoiceField(choices=Asset.StatusChoices, read_only=True) @@ -154,7 +154,6 @@ def validate_qr_code_id(self, value): return value def validate(self, attrs): - user = self.context["request"].user if "location" in attrs: location = get_object_or_404( @@ -208,6 +207,7 @@ def update(self, instance, validated_data): cache.delete(f"asset:{instance.external_id}") return updated_instance + class AssetBareMinimumSerializer(ModelSerializer): id = UUIDField(source="external_id", read_only=True) diff --git a/care/facility/api/viewsets/asset.py b/care/facility/api/viewsets/asset.py index e4755f9b00..8af47a136d 100644 --- a/care/facility/api/viewsets/asset.py +++ b/care/facility/api/viewsets/asset.py @@ -25,10 +25,10 @@ from rest_framework.viewsets import GenericViewSet from care.facility.api.serializers.asset import ( - AssetLocationSerializer, - AssetSerializer, AssetDetailSerializer, AssetListSerializer, + AssetLocationSerializer, + AssetSerializer, AssetTransactionSerializer, UserDefaultAssetLocationSerializer, )