Files
vontor-cz/backend/thirdparty/deutschepost/serializers.py
Brunobrno 2213e115c6 Integrate Deutsche Post shipping API and models
Added Deutsche Post as a shipping carrier, including new models, admin, serializers, and API client integration. Updated Carrier and SiteConfiguration models to support Deutsche Post, including shipping price and API credentials. Added requirements for the Deutsche Post API client and dependencies.
2026-01-11 16:32:51 +01:00

163 lines
6.8 KiB
Python

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import DeutschePostOrder, DeutschePostBulkOrder
class DeutschePostOrderSerializer(serializers.ModelSerializer):
commerce_order_id = serializers.IntegerField(write_only=True, required=False)
state_display = serializers.CharField(source='get_state_display', read_only=True)
class Meta:
model = DeutschePostOrder
fields = [
'id', 'created_at', 'state', 'state_display', 'commerce_order', 'commerce_order_id',
'order_id', 'customer_ekp',
'recipient_name', 'recipient_phone', 'recipient_email',
'address_line1', 'address_line2', 'address_line3',
'city', 'address_state', 'postal_code', 'destination_country',
'product_type', 'service_level', 'shipment_gross_weight',
'shipment_amount', 'shipment_currency',
'sender_tax_id', 'importer_tax_id', 'return_item_wanted',
'cust_ref', 'awb_number', 'barcode', 'tracking_url',
'metadata', 'last_error'
]
read_only_fields = [
'id', 'created_at', 'order_id', 'awb_number', 'barcode',
'tracking_url', 'metadata', 'last_error'
]
def validate_commerce_order_id(self, value):
"""Validate that commerce order exists and uses Deutsche Post delivery."""
try:
from commerce.models import Order
order = Order.objects.get(id=value)
if not order.carrier:
raise ValidationError("Commerce order must have a carrier assigned")
if order.carrier.shipping_method != "deutschepost":
raise ValidationError("Commerce order must use Deutsche Post delivery method")
if order.status != Order.OrderStatus.COMPLETED:
raise ValidationError("Commerce order must be completed before creating Deutsche Post order")
return value
except Order.DoesNotExist:
raise ValidationError("Commerce order does not exist")
def validate_destination_country(self, value):
"""Validate country code format."""
if len(value) != 2:
raise ValidationError("Country code must be 2 characters (ISO format)")
return value.upper()
def validate_shipment_gross_weight(self, value):
"""Validate weight is reasonable."""
if value <= 0:
raise ValidationError("Shipment weight must be greater than 0")
if value > 30000: # 30kg limit for most Deutsche Post products
raise ValidationError("Shipment weight cannot exceed 30kg (30000g)")
return value
def create(self, validated_data):
commerce_order_id = validated_data.pop('commerce_order_id', None)
if commerce_order_id:
from commerce.models import Order
validated_data['commerce_order'] = Order.objects.get(id=commerce_order_id)
return super().create(validated_data)
class DeutschePostBulkOrderSerializer(serializers.ModelSerializer):
deutschepost_order_ids = serializers.ListField(
child=serializers.IntegerField(),
write_only=True,
required=True,
help_text="List of DeutschePostOrder IDs to include in bulk order"
)
status_display = serializers.CharField(source='get_status_display', read_only=True)
orders_count = serializers.SerializerMethodField(read_only=True)
tracking_url = serializers.SerializerMethodField(read_only=True)
status_url = serializers.SerializerMethodField(read_only=True)
class Meta:
model = DeutschePostBulkOrder
fields = [
'id', 'created_at', 'status', 'status_display',
'bulk_order_id', 'bulk_order_type', 'description',
'deutschepost_orders', 'deutschepost_order_ids', 'orders_count',
'tracking_url', 'status_url',
'metadata', 'last_error'
]
read_only_fields = [
'id', 'created_at', 'bulk_order_id', 'deutschepost_orders',
'metadata', 'last_error'
]
def get_orders_count(self, obj):
return obj.deutschepost_orders.count()
def get_tracking_url(self, obj):
return obj.get_tracking_url()
def get_status_url(self, obj):
return obj.get_bulk_status_url()
def validate_deutschepost_order_ids(self, value):
"""Validate that all orders exist and are eligible for bulk processing."""
if not value:
raise ValidationError("At least one Deutsche Post order is required")
errors = []
orders = DeutschePostOrder.objects.filter(id__in=value)
if len(orders) != len(value):
missing_ids = set(value) - set(orders.values_list('id', flat=True))
errors.append(f"Orders not found: {missing_ids}")
for order in orders:
# Check if order is created remotely
if not order.order_id:
errors.append(f"Order {order.id} not created remotely")
# Check if commerce order uses Deutsche Post
if order.commerce_order:
if not order.commerce_order.carrier:
errors.append(f"Commerce order {order.commerce_order.id} has no carrier")
elif order.commerce_order.carrier.shipping_method != "deutschepost":
errors.append(f"Commerce order {order.commerce_order.id} doesn't use Deutsche Post")
elif order.commerce_order.status != order.commerce_order.OrderStatus.COMPLETED:
errors.append(f"Commerce order {order.commerce_order.id} is not completed")
# Check if order is already in another bulk order
if order.bulk_orders.exists():
errors.append(f"Order {order.id} already in bulk order")
if errors:
raise ValidationError(errors)
return value
def create(self, validated_data):
order_ids = validated_data.pop('deutschepost_order_ids')
bulk_order = super().create(validated_data)
# Add orders to bulk order
orders = DeutschePostOrder.objects.filter(id__in=order_ids)
bulk_order.deutschepost_orders.set(orders)
return bulk_order
class DeutschePostTrackingSerializer(serializers.Serializer):
"""Serializer for tracking information response."""
order_id = serializers.CharField(read_only=True)
awb_number = serializers.CharField(read_only=True)
barcode = serializers.CharField(read_only=True)
tracking_url = serializers.URLField(read_only=True)
state = serializers.CharField(read_only=True)
last_updated = serializers.DateTimeField(read_only=True)
tracking_events = serializers.JSONField(read_only=True)