Пример #1
0
    def bulk_upsert(self, request):
        """
        Upserts based on case insensitive name (after stripping off blank spaces) and district.
        Check serializer for more.

        Request:
        [
            {
                "name": "Name",
                "district": 1,
                "facility_type": 2,
                "address": "Address",
                "phone_number": "Phone",
                "capacity": [
                    {
                        "room_type": 0,
                        "total_capacity": "350",
                        "current_capacity": "350"
                    },
                    {
                        "room_type": 1,
                        "total_capacity": 0,
                        "current_capacity": 0
                    }
                ]
            }
        ]
        :param request:
        :return:
        """
        data = request.data
        if not isinstance(data, list):
            data = [data]

        serializer = FacilityUpsertSerializer(data=data, many=True)
        serializer.is_valid(raise_exception=True)

        serializer.context["user"] = self.request.user
        with transaction.atomic():
            serializer.create(serializer.validated_data)
        return Response(status=status.HTTP_204_NO_CONTENT)
Пример #2
0
    def bulk_upsert(self, request):
        """
        Upserts based on case insensitive name (after stripping off blank spaces) and district.
        Check serializer for more.

        Request:
        [
            {
                "name": "Name",
                "district": 1,
                "facility_type": 2,
                "address": "Address",
                "phone_number": "Phone",
                "capacity": [
                    {
                        "room_type": 0,
                        "total_capacity": "350",
                        "current_capacity": "350"
                    },
                    {
                        "room_type": 1,
                        "total_capacity": 0,
                        "current_capacity": 0
                    }
                ]
            }
        ]
        :param request:
        :return:
        """
        data = request.data
        if not isinstance(data, list):
            data = [data]

        serializer = FacilityUpsertSerializer(data=data, many=True)
        serializer.is_valid(raise_exception=True)

        district_id = request.data[0]["district"]
        facilities = (Facility.objects.filter(
            district_id=district_id).select_related(
                "local_body", "district", "state", "created_by__district",
                "created_by__state").prefetch_related("facilitycapacity_set"))

        facility_map = {f.name.lower(): f for f in facilities}
        facilities_to_update = []
        facilities_to_create = []

        for f in serializer.validated_data:
            f["district_id"] = f.pop("district")
            if f["name"].lower() in facility_map:
                facilities_to_update.append(f)
            else:
                f["created_by_id"] = request.user.id
                facilities_to_create.append(f)

        with transaction.atomic():
            capacity_create_objs = []
            for f in facilities_to_create:
                capacity = f.pop("facilitycapacity_set")
                f_obj = Facility.objects.create(**f)
                for c in capacity:
                    capacity_create_objs.append(
                        FacilityCapacity(facility=f_obj, **c))
            for f in facilities_to_update:
                capacity = f.pop("facilitycapacity_set")
                f_obj = facility_map.get(f["name"].lower())
                changed = False
                for k, v in f.items():
                    if getattr(f_obj, k) != v:
                        setattr(f_obj, k, v)
                        changed = True
                if changed:
                    f_obj.save()
                capacity_map = {
                    c.room_type: c
                    for c in f_obj.facilitycapacity_set.all()
                }
                for c in capacity:
                    changed = False
                    if c["room_type"] in capacity_map:
                        c_obj = capacity_map.get(c["room_type"])
                        for k, v in c.items():
                            if getattr(c_obj, k) != v:
                                setattr(c_obj, k, v)
                                changed = True
                        if changed:
                            c_obj.save()
                    else:
                        capacity_create_objs.append(
                            FacilityCapacity(facility=f_obj, **c))

            bulk_create_with_history(capacity_create_objs,
                                     FacilityCapacity,
                                     batch_size=500)

        return Response(status=status.HTTP_204_NO_CONTENT)