90 lines
3.3 KiB
Python
90 lines
3.3 KiB
Python
from rest_framework import serializers
|
|
from drf_spectacular.utils import extend_schema_field
|
|
from .models import Category, Product, ProductImage, DiscountCode, Order, OrderItem, Carrier
|
|
|
|
# NOTE: Carrier intentionally skipped per request (TODO below)
|
|
|
|
class CategorySerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Category
|
|
fields = ["id", "name", "url", "parent", "description", "image"]
|
|
|
|
|
|
class ProductImageSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = ProductImage
|
|
fields = ["id", "image", "alt_text", "is_main"]
|
|
|
|
|
|
class ProductSerializer(serializers.ModelSerializer):
|
|
images = ProductImageSerializer(many=True, read_only=True)
|
|
available = serializers.BooleanField(read_only=True)
|
|
|
|
class Meta:
|
|
model = Product
|
|
fields = [
|
|
"id","name","description","code","category","price","currency","url","stock","is_active","limited_to","default_carrier","available","images","created_at","updated_at"
|
|
]
|
|
read_only_fields = ["created_at","updated_at","available"]
|
|
|
|
|
|
class DiscountCodeSerializer(serializers.ModelSerializer):
|
|
is_valid = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = DiscountCode
|
|
fields = ["id","code","description","percent","amount","valid_from","valid_to","active","usage_limit","used_count","specific_products","specific_categories","is_valid"]
|
|
read_only_fields = ["used_count","is_valid"]
|
|
|
|
def get_is_valid(self, obj):
|
|
return obj.is_valid()
|
|
|
|
|
|
class OrderItemSerializer(serializers.ModelSerializer):
|
|
product = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all())
|
|
line_total = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = OrderItem
|
|
fields = ["id","product","quantity","line_total"]
|
|
read_only_fields = ["line_total"]
|
|
|
|
def get_line_total(self, obj):
|
|
# Uses existing model logic for discount via order context (kept minimal)
|
|
# Since discount resolution logic is custom & currently incomplete, just returns base price * qty
|
|
return obj.product.price * obj.quantity
|
|
|
|
|
|
class OrderSerializer(serializers.ModelSerializer):
|
|
items = OrderItemSerializer(many=True)
|
|
total_price = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
|
|
|
|
class Meta:
|
|
model = Order
|
|
fields = [
|
|
"id","user","status","total_price","currency","first_name","last_name","email","phone","address","city","postal_code","country","note","discount","items","created_at","updated_at"
|
|
]
|
|
read_only_fields = ["total_price","created_at","updated_at"]
|
|
|
|
def create(self, validated_data):
|
|
items_data = validated_data.pop("items", [])
|
|
order = Order.objects.create(**validated_data)
|
|
for item in items_data:
|
|
OrderItem.objects.create(order=order, **item)
|
|
order.total_price = order.calculate_total_price() if hasattr(order, "calculate_total_price") else order.total_price
|
|
order.save()
|
|
return order
|
|
|
|
def update(self, instance, validated_data):
|
|
items_data = validated_data.pop("items", None)
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
if items_data is not None:
|
|
instance.items.all().delete()
|
|
for item in items_data:
|
|
OrderItem.objects.create(order=instance, **item)
|
|
instance.total_price = instance.calculate_total_price() if hasattr(instance, "calculate_total_price") else instance.total_price
|
|
instance.save()
|
|
return instance
|
|
|
|
# TODO: CarrierSerializer (Carrier API not requested yet) |