Enhance Deutsche Post integration with API and label support
Expanded DeutschePostOrder and DeutschePostBulkOrder models to support full Deutsche Post API integration, including authentication, order creation, finalization, tracking, cancellation, and label/document generation. Added new fields for label PDFs and bulk paperwork, improved country mapping, and implemented comprehensive validation and utility methods. Updated serializers to expose new fields and computed properties. Added HTML templates for individual and bulk shipping labels.
This commit is contained in:
85
backend/thirdparty/deutschepost/serializers.py
vendored
85
backend/thirdparty/deutschepost/serializers.py
vendored
@@ -5,13 +5,19 @@ 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)
|
||||
label_size_display = serializers.CharField(source='get_label_size_display', read_only=True)
|
||||
tracking_url = serializers.SerializerMethodField(read_only=True)
|
||||
estimated_delivery_days = serializers.SerializerMethodField(read_only=True)
|
||||
shipping_cost_estimate = serializers.SerializerMethodField(read_only=True)
|
||||
can_be_finalized = serializers.SerializerMethodField(read_only=True)
|
||||
can_be_cancelled = serializers.SerializerMethodField(read_only=True)
|
||||
is_trackable = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = DeutschePostOrder
|
||||
fields = [
|
||||
'id', 'created_at', 'state', 'state_display', 'commerce_order', 'commerce_order_id',
|
||||
'id', 'created_at', 'state', 'state_display',
|
||||
'order_id', 'customer_ekp',
|
||||
'recipient_name', 'recipient_phone', 'recipient_email',
|
||||
'address_line1', 'address_line2', 'address_line3',
|
||||
@@ -20,31 +26,33 @@ class DeutschePostOrderSerializer(serializers.ModelSerializer):
|
||||
'shipment_amount', 'shipment_currency',
|
||||
'sender_tax_id', 'importer_tax_id', 'return_item_wanted',
|
||||
'cust_ref', 'awb_number', 'barcode', 'tracking_url',
|
||||
'metadata', 'last_error'
|
||||
'label_pdf', 'label_size', 'label_size_display',
|
||||
'metadata', 'last_error',
|
||||
'estimated_delivery_days', 'shipping_cost_estimate',
|
||||
'can_be_finalized', 'can_be_cancelled', 'is_trackable'
|
||||
]
|
||||
read_only_fields = [
|
||||
'id', 'created_at', 'order_id', 'awb_number', 'barcode',
|
||||
'tracking_url', 'metadata', 'last_error'
|
||||
'tracking_url', 'metadata', 'last_error', 'label_pdf'
|
||||
]
|
||||
|
||||
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 get_tracking_url(self, obj):
|
||||
return obj.get_tracking_url()
|
||||
|
||||
def get_estimated_delivery_days(self, obj):
|
||||
return obj.get_estimated_delivery_days()
|
||||
|
||||
def get_shipping_cost_estimate(self, obj):
|
||||
return float(obj.get_shipping_cost_estimate())
|
||||
|
||||
def get_can_be_finalized(self, obj):
|
||||
return obj.can_be_finalized()
|
||||
|
||||
def get_can_be_cancelled(self, obj):
|
||||
return obj.can_be_cancelled()
|
||||
|
||||
def get_is_trackable(self, obj):
|
||||
return obj.is_trackable()
|
||||
|
||||
def validate_destination_country(self, value):
|
||||
"""Validate country code format."""
|
||||
@@ -60,14 +68,20 @@ class DeutschePostOrderSerializer(serializers.ModelSerializer):
|
||||
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)
|
||||
def validate(self, attrs):
|
||||
"""Validate the complete order data."""
|
||||
# Check required fields for shipping
|
||||
required_fields = ['recipient_name', 'address_line1', 'city', 'postal_code', 'destination_country']
|
||||
missing_fields = [field for field in required_fields if not attrs.get(field)]
|
||||
|
||||
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)
|
||||
if missing_fields:
|
||||
raise ValidationError(f"Required fields missing: {', '.join(missing_fields)}")
|
||||
|
||||
# Check contact information
|
||||
if not attrs.get('recipient_email') and not attrs.get('recipient_phone'):
|
||||
raise ValidationError("Either recipient email or phone is required for delivery notifications")
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
class DeutschePostBulkOrderSerializer(serializers.ModelSerializer):
|
||||
@@ -79,8 +93,10 @@ class DeutschePostBulkOrderSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
status_display = serializers.CharField(source='get_status_display', read_only=True)
|
||||
orders_count = serializers.SerializerMethodField(read_only=True)
|
||||
total_weight_kg = serializers.SerializerMethodField(read_only=True)
|
||||
tracking_url = serializers.SerializerMethodField(read_only=True)
|
||||
status_url = serializers.SerializerMethodField(read_only=True)
|
||||
can_be_cancelled = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = DeutschePostBulkOrder
|
||||
@@ -88,23 +104,30 @@ class DeutschePostBulkOrderSerializer(serializers.ModelSerializer):
|
||||
'id', 'created_at', 'status', 'status_display',
|
||||
'bulk_order_id', 'bulk_order_type', 'description',
|
||||
'deutschepost_orders', 'deutschepost_order_ids', 'orders_count',
|
||||
'tracking_url', 'status_url',
|
||||
'total_weight_kg', 'tracking_url', 'status_url', 'can_be_cancelled',
|
||||
'bulk_label_pdf', 'paperwork_pdf',
|
||||
'metadata', 'last_error'
|
||||
]
|
||||
read_only_fields = [
|
||||
'id', 'created_at', 'bulk_order_id', 'deutschepost_orders',
|
||||
'metadata', 'last_error'
|
||||
'bulk_label_pdf', 'paperwork_pdf', 'metadata', 'last_error'
|
||||
]
|
||||
|
||||
def get_orders_count(self, obj):
|
||||
return obj.deutschepost_orders.count()
|
||||
|
||||
def get_total_weight_kg(self, obj):
|
||||
return obj.get_total_weight_kg()
|
||||
|
||||
def get_tracking_url(self, obj):
|
||||
return obj.get_tracking_url()
|
||||
|
||||
def get_status_url(self, obj):
|
||||
return obj.get_bulk_status_url()
|
||||
|
||||
def get_can_be_cancelled(self, obj):
|
||||
return obj.can_be_cancelled()
|
||||
|
||||
def validate_deutschepost_order_ids(self, value):
|
||||
"""Validate that all orders exist and are eligible for bulk processing."""
|
||||
if not value:
|
||||
|
||||
Reference in New Issue
Block a user