Coverage for apps/orders/serializers.py: 95%
154 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-10-12 15:51 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-10-12 15:51 -0600
1from django.db import transaction
2from django.db.models import Sum
3from rest_framework import serializers
5from api.serializers import ToRepresentationMixin
6from apps.catalogues.serializers import WeekSerializer
7from apps.products.serializers import BasicProductSerializer, ProductVariationSerializer
8from apps.sales.serializers import BasicSalesPersonSerializer
9from apps.suppliers.serializers import SupplierSerializer
10from apps.users.serializers import UserSerializer
12from .models import Icon, Order, OrderComment, OrderIcon, OrderItem, OrderItemSize
15class IconSerializer(serializers.ModelSerializer):
16 """
17 Serializer for Icon
18 """
20 class Meta:
21 model = Icon
22 read_only_fields = ["random_slug"]
23 fields = read_only_fields + ["name", "color", "iconify_icon"]
26class OrderIconSerializer(serializers.ModelSerializer):
27 """
28 Serializer for Order Icon
29 """
31 icon = IconSerializer()
33 class Meta:
34 model = OrderIcon
35 read_only_fields = ["random_slug", "icon"]
36 fields = read_only_fields + ["is_active"]
39class OrderItemSizeSerializer(serializers.ModelSerializer):
40 """
41 Serializer for Order Item Size
42 """
44 class Meta:
45 model = OrderItemSize
46 read_only_fields = ["random_slug", "status", "delivered_amount", "pending_amount"]
47 fields = read_only_fields + ["order_item", "amount", "size"]
48 extra_kwargs = {"order_item": {"required": False}}
51class OrderItemSerializer(ToRepresentationMixin):
52 """
53 Serializer for Order Item
54 """
56 REPRESENTATION_FIELDS = [
57 ["product_variation", ProductVariationSerializer, False],
58 ["sales_person", BasicSalesPersonSerializer, False],
59 ]
61 sizes = OrderItemSizeSerializer(many=True)
62 total_cost = serializers.SerializerMethodField()
63 total_amount = serializers.SerializerMethodField()
64 product_detail = serializers.SerializerMethodField()
66 class Meta:
67 model = OrderItem
68 read_only_fields = ["random_slug"]
69 fields = read_only_fields + [
70 "order",
71 "product_variation",
72 "product_detail",
73 "sales_person",
74 "description",
75 "cost",
76 "total_cost",
77 "total_amount",
78 "status",
79 "sizes",
80 ]
81 extra_kwargs = {"order": {"required": False}}
83 def get_total_cost(self, instance):
84 return instance.sizes.aggregate(total_amount=Sum("amount")).get("total_amount") or 0 * instance.cost
86 def get_total_amount(self, instance):
87 return instance.sizes.aggregate(total_amount=Sum("amount")).get("total_amount") or 0
89 def get_product_detail(self, instance):
90 return BasicProductSerializer(instance.product_variation.product, context=self.context).data
92 def validate(self, attrs):
93 product_variation = attrs.get("product_variation", None)
94 sizes = attrs.get("sizes", [])
95 for order_item_size in sizes:
96 size = order_item_size.get("size")
97 if product_variation: 97 ↛ 95line 97 didn't jump to line 95, because the condition on line 97 was never false
98 if size not in product_variation.sizes:
99 raise serializers.ValidationError(
100 {
101 "sizes": f"El tamaño {size} no es un tamaño valido para {product_variation.product.name} [{product_variation.initial}, {product_variation.final}, {product_variation.step}]"
102 }
103 )
104 return attrs
106 def create(self, validated_data):
107 sizes = validated_data.pop("sizes", [])
109 order_item = super().create(validated_data)
111 for size in sizes:
112 size["order_item"] = order_item
113 order_item_size_serializer = OrderItemSizeSerializer(size)
114 order_item_size_serializer.create(size)
116 return order_item
118 def update(self, instance, validated_data):
119 product_variation = validated_data.pop("product_variation", None)
120 sizes = validated_data.pop("sizes", [])
122 order_item = super().update(instance, validated_data)
124 if product_variation: 124 ↛ 135line 124 didn't jump to line 135, because the condition on line 124 was never false
125 instance.product_variation = product_variation
126 instance.save()
128 instance.sizes.all().delete()
130 for size in sizes:
131 size["order_item"] = order_item
132 order_item_size_serializer = OrderItemSizeSerializer(size)
133 order_item_size_serializer.create(size)
135 return instance
138class OrderSerializer(ToRepresentationMixin):
139 """
140 Serializers for Order
141 """
143 REPRESENTATION_FIELDS = [["supplier", SupplierSerializer, False], ["week", WeekSerializer, False]]
145 items = OrderItemSerializer(many=True)
146 icons = OrderIconSerializer(source="ordericon_set", many=True, read_only=True)
148 class Meta:
149 model = Order
150 read_only_fields = ["random_slug", "created_at", "icons"]
151 fields = read_only_fields + [
152 "supplier",
153 "week",
154 "delivery_date",
155 "cancellation_date",
156 "description",
157 "order_id",
158 "status",
159 "items",
160 "original_order",
161 ]
163 def create(self, validated_data):
164 with transaction.atomic():
165 items = validated_data.pop("items", [])
167 order = super().create(validated_data)
169 for item in items:
170 item["order"] = order
171 order_item_serializer = OrderItemSerializer(item)
172 order_item_serializer.create(item)
174 return order
177class BasicOrderSerializer(serializers.ModelSerializer):
178 """
179 Serializer for Order with minimum data
180 """
182 class Meta:
183 model = Order
184 read_only_fields = ["random_slug", "order_id", "created_at", "delivery_date", "cancellation_date", "status"]
185 fields = read_only_fields + []
188class OrderItemSizeSplitSerializer(serializers.Serializer):
189 """
190 Serializer for OrderItemSize split
191 """
193 order_item_size = serializers.PrimaryKeyRelatedField(
194 queryset=OrderItemSize.objects.exclude(status=OrderItemSize.Status.DELIVERED)
195 )
196 amount = serializers.IntegerField()
198 class Meta:
199 fields = ["order_item_size", "amount"]
201 def validate(self, attrs):
202 amount = attrs.get("amount")
203 order_item_size = attrs.get("order_item_size")
205 if amount > order_item_size.pending_amount: 205 ↛ 206line 205 didn't jump to line 206, because the condition on line 205 was never true
206 raise serializers.ValidationError(
207 {"amount": f"Solo hay {order_item_size.pending_amount} elementos para separar."}
208 )
210 return attrs
213class OrderItemSplitSerializer(serializers.Serializer):
214 """
215 Serializer for OrderItem split
216 """
218 order_item = serializers.PrimaryKeyRelatedField(
219 queryset=OrderItem.objects.exclude(status=OrderItem.Status.DELIVERED)
220 )
221 sizes = OrderItemSizeSplitSerializer(many=True)
223 class Meta:
224 fields = ["order_item", "sizes"]
227class OrderSplitSerializer(serializers.Serializer):
228 """
229 Serializer for Order split
230 """
232 order = serializers.PrimaryKeyRelatedField(queryset=Order.objects.exclude(status=Order.Status.DELIVERED))
233 items = OrderItemSplitSerializer(many=True)
235 class Meta:
236 fields = ["order", "items"]
238 def create(self, validated_data):
239 with transaction.atomic():
240 order = validated_data.get("order")
241 order.original_order = order
242 order.random_slug = None
243 order.status = Order.Status.PENDING
244 order.save()
246 items = validated_data.get("items")
248 for item in items:
249 order_item = item.get("order_item")
250 order_item.random_slug = None
251 order_item.order = order
252 order_item.save()
254 sizes = item.get("sizes")
256 for size in sizes:
257 order_item_size = size.get("order_item_size")
258 amount = size.get("amount")
259 order_item_size.amount -= amount
260 order_item_size.save()
261 order_item_size.random_slug = None
262 order_item_size.order_item = order_item
263 order_item_size.amount = amount
264 order_item_size.save()
266 return order
269class OrderCommentSerializer(serializers.ModelSerializer):
270 """
271 Serializer for OrderComment
272 """
274 author = UserSerializer(read_only=True)
275 children_comments = serializers.SerializerMethodField()
277 class Meta:
278 model = OrderComment
279 read_only_fields = ["random_slug", "created_at", "author", "children_comments"]
280 fields = read_only_fields + ["order", "parent_comment", "comment"]
282 def get_children_comments(self, instance):
283 return OrderCommentSerializer(instance.children_comments.all(), many=True).data
285 def validate_parent_comment(self, value):
286 if value.parent_comment is not None:
287 raise serializers.ValidationError("No puede haber comentarios de mas de un nivel.")
288 return value