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:
2026-01-23 00:47:19 +01:00
parent 963ba6b824
commit 3a7044d551
5 changed files with 1492 additions and 121 deletions

View File

@@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Deutsche Post Bulk Shipping Labels</title>
<style>
@page {
size: A4;
margin: 1cm;
}
body {
font-family: Arial, sans-serif;
font-size: 11px;
line-height: 1.3;
margin: 0;
padding: 0;
}
.bulk-header {
text-align: center;
font-size: 16px;
font-weight: bold;
margin-bottom: 20px;
border-bottom: 2px solid #FF0000;
padding-bottom: 10px;
color: #FF0000;
}
.bulk-info {
background-color: #f5f5f5;
padding: 10px;
margin-bottom: 20px;
border-radius: 5px;
display: flex;
justify-content: space-between;
}
.bulk-info-left,
.bulk-info-right {
width: 48%;
}
.info-row {
margin-bottom: 5px;
}
.label {
font-weight: bold;
display: inline-block;
width: 100px;
}
.order-item {
border: 1px solid #ddd;
margin-bottom: 15px;
padding: 10px;
background-color: #fff;
page-break-inside: avoid;
}
.order-header {
background-color: #f0f0f0;
padding: 8px;
margin: -10px -10px 10px -10px;
font-weight: bold;
font-size: 12px;
border-bottom: 1px solid #ddd;
}
.order-content {
display: flex;
justify-content: space-between;
}
.order-left,
.order-right {
width: 48%;
}
.recipient-name {
font-weight: bold;
font-size: 12px;
margin-bottom: 5px;
color: #333;
}
.address-line {
margin-bottom: 3px;
}
.country {
font-weight: bold;
color: #FF0000;
}
.service-badge {
display: inline-block;
padding: 2px 6px;
background-color: #FF0000;
color: white;
border-radius: 3px;
font-weight: bold;
text-transform: uppercase;
font-size: 9px;
}
.priority {
background-color: #FF6600;
}
.standard {
background-color: #0066CC;
}
.tracking-number {
font-family: 'Courier New', monospace;
font-weight: bold;
background-color: #f9f9f9;
padding: 3px 5px;
border: 1px solid #ccc;
font-size: 10px;
}
.page-break {
page-break-before: always;
}
.summary-footer {
margin-top: 30px;
text-align: center;
font-size: 10px;
color: #666;
border-top: 1px solid #ddd;
padding-top: 10px;
}
.orders-per-page {
/* Adjust based on content - roughly 4-5 orders per page */
}
.order-item:nth-of-type(5n+1) {
page-break-before: always;
}
.order-item:nth-of-type(1) {
page-break-before: auto; /* Don't break before first item */
}
</style>
</head>
<body>
<div class="bulk-header">
Deutsche Post - Bulk Shipment Labels
</div>
<div class="bulk-info">
<div class="bulk-info-left">
<div class="info-row">
<span class="label">Bulk Order ID:</span>
<span>{{ bulk_order.bulk_order_id|default:'Pending' }}</span>
</div>
<div class="info-row">
<span class="label">Order Type:</span>
<span>{{ bulk_order.bulk_order_type }}</span>
</div>
<div class="info-row">
<span class="label">Description:</span>
<span>{{ bulk_order.description|default:'N/A' }}</span>
</div>
</div>
<div class="bulk-info-right">
<div class="info-row">
<span class="label">Total Orders:</span>
<span>{{ orders.count }}</span>
</div>
<div class="info-row">
<span class="label">Total Weight:</span>
<span>{{ total_weight_kg|floatformat:2 }} kg</span>
</div>
<div class="info-row">
<span class="label">Created:</span>
<span>{{ bulk_order.created_at|date:"d.m.Y H:i" }}</span>
</div>
</div>
</div>
{% for order in orders %}
<div class="order-item">
<div class="order-header">
Order #{{ forloop.counter }} - {{ order.order_id|default:'Pending' }}
<span style="float: right;">
<span class="service-badge {% if order.service_level == 'PRIORITY' %}priority{% else %}standard{% endif %}">
{{ order.service_level }}
</span>
</span>
</div>
<div class="order-content">
<div class="order-left">
<div class="recipient-name">{{ order.recipient_name }}</div>
<div class="address-line">{{ order.address_line1 }}</div>
{% if order.address_line2 %}
<div class="address-line">{{ order.address_line2 }}</div>
{% endif %}
<div class="address-line">{{ order.postal_code }} {{ order.city }}</div>
{% if order.address_state %}
<div class="address-line">{{ order.address_state }}</div>
{% endif %}
<div class="address-line country">{{ order.destination_country }}</div>
{% if order.recipient_phone %}
<div style="margin-top: 5px; font-size: 10px;">Tel: {{ order.recipient_phone }}</div>
{% endif %}
</div>
<div class="order-right">
<div class="info-row">
<span class="label">Weight:</span>
<span>{{ order.shipment_gross_weight }}g</span>
</div>
<div class="info-row">
<span class="label">Value:</span>
<span>{{ order.shipment_amount }} {{ order.shipment_currency }}</span>
</div>
<div class="info-row">
<span class="label">Product:</span>
<span>{{ order.product_type }}</span>
</div>
{% if order.awb_number %}
<div class="info-row" style="margin-top: 8px;">
<span class="label">AWB:</span><br>
<span class="tracking-number">{{ order.awb_number }}</span>
</div>
{% elif order.barcode %}
<div class="info-row" style="margin-top: 8px;">
<span class="label">Barcode:</span><br>
<span class="tracking-number">{{ order.barcode }}</span>
</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
<div class="summary-footer">
<div>Total: {{ orders.count }} orders | {{ total_weight_kg|floatformat:2 }} kg</div>
<div>Generated: {{ now|date:"d.m.Y H:i:s" }} | Deutsche Post International Shipping API</div>
<div>Bulk Order: {{ bulk_order.bulk_order_id|default:'Pending' }}</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,264 @@
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Deutsche Post Shipping Label</title>
<style>
@page {
size: A4;
margin: 1cm;
}
body {
font-family: Arial, sans-serif;
font-size: 12px;
line-height: 1.4;
margin: 0;
padding: 0;
}
.header {
text-align: center;
font-size: 18px;
font-weight: bold;
margin-bottom: 30px;
border-bottom: 2px solid #333;
padding-bottom: 10px;
}
.logo {
color: #FF0000;
font-size: 20px;
}
.order-info {
margin-bottom: 30px;
background-color: #f5f5f5;
padding: 15px;
border-radius: 5px;
}
.order-info h3 {
margin-top: 0;
color: #333;
font-size: 14px;
}
.info-row {
margin-bottom: 8px;
}
.label {
font-weight: bold;
display: inline-block;
width: 120px;
}
.recipient-section {
margin-bottom: 30px;
border: 2px solid #333;
padding: 20px;
background-color: #fff;
}
.recipient-section h3 {
margin-top: 0;
font-size: 16px;
font-weight: bold;
text-transform: uppercase;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
}
.recipient-address {
font-size: 14px;
line-height: 1.6;
margin-top: 15px;
}
.recipient-name {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.shipment-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
}
.shipment-column {
width: 48%;
background-color: #f9f9f9;
padding: 15px;
border-radius: 5px;
}
.shipment-column h4 {
margin-top: 0;
color: #333;
font-size: 14px;
border-bottom: 1px solid #ddd;
padding-bottom: 5px;
}
.barcode-section {
text-align: center;
margin-top: 30px;
padding: 20px;
background-color: #f0f0f0;
border-radius: 5px;
}
.barcode {
font-family: 'Courier New', monospace;
font-size: 24px;
font-weight: bold;
letter-spacing: 2px;
padding: 10px;
background-color: #fff;
border: 1px solid #333;
display: inline-block;
margin: 10px 0;
}
.tracking-info {
text-align: center;
margin-top: 20px;
font-size: 10px;
color: #666;
}
.service-badge {
display: inline-block;
padding: 5px 10px;
background-color: #FF0000;
color: white;
border-radius: 3px;
font-weight: bold;
text-transform: uppercase;
}
.priority {
background-color: #FF6600;
}
.standard {
background-color: #0066CC;
}
</style>
</head>
<body>
<div class="header">
<div class="logo">Deutsche Post</div>
<div>International Shipping Label</div>
</div>
<div class="order-info">
<h3>Informace o objednávce / Order Information</h3>
<div class="info-row">
<span class="label">Order ID:</span>
<span>{{ order.order_id|default:'Pending' }}</span>
</div>
<div class="info-row">
<span class="label">AWB Number:</span>
<span>{{ order.awb_number|default:'N/A' }}</span>
</div>
<div class="info-row">
<span class="label">Barcode:</span>
<span>{{ order.barcode|default:'N/A' }}</span>
</div>
<div class="info-row">
<span class="label">Customer Ref:</span>
<span>{{ order.cust_ref|default:'N/A' }}</span>
</div>
<div class="info-row">
<span class="label">Service Level:</span>
<span class="service-badge {% if order.service_level == 'PRIORITY' %}priority{% else %}standard{% endif %}">
{{ order.service_level }}
</span>
</div>
</div>
<div class="recipient-section">
<h3>Příjemce / Recipient</h3>
<div class="recipient-address">
<div class="recipient-name">{{ order.recipient_name }}</div>
<div>{{ order.address_line1 }}</div>
{% if order.address_line2 %}
<div>{{ order.address_line2 }}</div>
{% endif %}
{% if order.address_line3 %}
<div>{{ order.address_line3 }}</div>
{% endif %}
<div>{{ order.postal_code }} {{ order.city }}</div>
{% if order.address_state %}
<div>{{ order.address_state }}</div>
{% endif %}
<div><strong>{{ order.destination_country }}</strong></div>
{% if order.recipient_phone %}
<div>Tel: {{ order.recipient_phone }}</div>
{% endif %}
{% if order.recipient_email %}
<div>Email: {{ order.recipient_email }}</div>
{% endif %}
</div>
</div>
<div class="shipment-details">
<div class="shipment-column">
<h4>Detaily zásilky / Shipment Details</h4>
<div class="info-row">
<span class="label">Product:</span>
<span>{{ order.product_type }}</span>
</div>
<div class="info-row">
<span class="label">Weight:</span>
<span>{{ order.shipment_gross_weight }}g</span>
</div>
<div class="info-row">
<span class="label">Value:</span>
<span>{{ order.shipment_amount }} {{ order.shipment_currency }}</span>
</div>
{% if order.sender_tax_id %}
<div class="info-row">
<span class="label">IOSS:</span>
<span>{{ order.sender_tax_id }}</span>
</div>
{% endif %}
</div>
<div class="shipment-column">
<h4>Doručení / Delivery</h4>
<div class="info-row">
<span class="label">Est. Days:</span>
<span>{{ estimated_delivery_days }} days</span>
</div>
<div class="info-row">
<span class="label">Return:</span>
<span>{% if order.return_item_wanted %}Yes{% else %}No{% endif %}</span>
</div>
<div class="info-row">
<span class="label">Created:</span>
<span>{{ order.created_at|date:"d.m.Y H:i" }}</span>
</div>
</div>
</div>
{% if order.awb_number or order.barcode %}
<div class="barcode-section">
<div>Tracking Number / Sledovací číslo</div>
<div class="barcode">{{ order.awb_number|default:order.barcode }}</div>
<div class="tracking-info">
Track at: https://www.deutschepost.de/de/sendungsverfolgung.html
</div>
</div>
{% endif %}
<div class="tracking-info">
Generated: {{ now|date:"d.m.Y H:i:s" }} | Deutsche Post International Shipping API
</div>
</body>
</html>