Fix distance calculation and display in Admin, Dashboards, and Notifications
This commit is contained in:
parent
bc518a1fbf
commit
d43de11987
@ -191,6 +191,29 @@ class Parcel(models.Model):
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.tracking_number:
|
||||
self.tracking_number = str(uuid.uuid4().hex[:10]).upper()
|
||||
|
||||
# Calculate Distance and Price if Lat/Lng provided and price is 0 (or always update to ensure accuracy)
|
||||
# We only recalculate if status is pending or if it's a new object to avoid changing history for completed trips
|
||||
is_new = self.pk is None
|
||||
if (is_new or self.status == 'pending') and self.pickup_lat and self.pickup_lng and self.delivery_lat and self.delivery_lng:
|
||||
# Local import to avoid circular dependency
|
||||
from .pricing import calculate_haversine_distance, get_pricing_breakdown
|
||||
|
||||
# Calculate Distance
|
||||
dist = calculate_haversine_distance(
|
||||
self.pickup_lat, self.pickup_lng,
|
||||
self.delivery_lat, self.delivery_lng
|
||||
)
|
||||
self.distance_km = dist
|
||||
|
||||
# Calculate Price
|
||||
breakdown = get_pricing_breakdown(self.distance_km, self.weight)
|
||||
if not breakdown.get('error'):
|
||||
self.price = breakdown['price']
|
||||
self.platform_fee = breakdown['platform_fee']
|
||||
self.platform_fee_percentage = breakdown['platform_fee_percentage']
|
||||
self.driver_amount = breakdown['driver_amount']
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@ -38,13 +38,13 @@ DEFAULT_TEMPLATES = {
|
||||
},
|
||||
'shipment_created_shipper': {
|
||||
'description': 'Sent to Shipper when they create a shipment',
|
||||
'variables': '{{ name }}, {{ description }}, {{ tracking_number }}, {{ status }}',
|
||||
'variables': '{{ name }}, {{ description }}, {{ tracking_number }}, {{ status }}, {{ distance }}, {{ price }}',
|
||||
'subject_en': 'Shipment Request Received - {{ tracking_number }}',
|
||||
'subject_ar': 'تم استلام طلب الشحنة - {{ tracking_number }}',
|
||||
'email_body_en': "Hello {{ name }},\n\nYour shipment request for '{{ description }}' has been received.\nTracking Number: {{ tracking_number }}\nStatus: {{ status }}\n\nPlease proceed to payment to make it visible to drivers.",
|
||||
'email_body_ar': "مرحباً {{ name }}،\n\nتم استلام طلب الشحنة '{{ description }}'.\nرقم التتبع: {{ tracking_number }}\nالحالة: {{ status }}\n\nيرجى متابعة الدفع لجعلها مرئية للسائقين.",
|
||||
'whatsapp_body_en': "Hello {{ name }},\nYour shipment request for '{{ description }}' has been received.\nTracking Number: {{ tracking_number }}\nStatus: {{ status }}\nPlease proceed to payment.",
|
||||
'whatsapp_body_ar': "مرحباً {{ name }}،\nتم استلام طلب الشحنة '{{ description }}'.\nرقم التتبع: {{ tracking_number }}\nالحالة: {{ status }}\nيرجى الدفع.",
|
||||
'email_body_en': "Hello {{ name }},\n\nYour shipment request for '{{ description }}' has been received.\nTracking Number: {{ tracking_number }}\nDistance: {{ distance }} km\nPrice: {{ price }} OMR\nStatus: {{ status }}\n\nPlease proceed to payment to make it visible to drivers.",
|
||||
'email_body_ar': "مرحباً {{ name }}،\n\nتم استلام طلب الشحنة '{{ description }}'.\nرقم التتبع: {{ tracking_number }}\nالمسافة: {{ distance }} كم\nالسعر: {{ price }} ر.ع\nالحالة: {{ status }}\n\nيرجى متابعة الدفع لجعلها مرئية للسائقين.",
|
||||
'whatsapp_body_en': "Hello {{ name }}\nYour shipment request for '{{ description }}' has been received.\nTracking Number: {{ tracking_number }}\nDistance: {{ distance }} km\nPrice: {{ price }} OMR\nStatus: {{ status }}\nPlease proceed to payment.",
|
||||
'whatsapp_body_ar': "مرحباً {{ name }}،\nتم استلام طلب الشحنة '{{ description }}'.\nرقم التتبع: {{ tracking_number }}\nالمسافة: {{ distance }} كم\nالسعر: {{ price }} ر.ع\nالحالة: {{ status }}\nيرجى الدفع.",
|
||||
},
|
||||
'payment_success_shipper': {
|
||||
'description': 'Sent to Shipper after payment',
|
||||
@ -88,13 +88,13 @@ DEFAULT_TEMPLATES = {
|
||||
},
|
||||
'driver_pickup_driver': {
|
||||
'description': 'Sent to Driver upon acceptance',
|
||||
'variables': '{{ tracking_number }}, {{ shipper_name }}, {{ pickup_address }}, {{ delivery_address }}, {{ price }}',
|
||||
'variables': '{{ tracking_number }}, {{ shipper_name }}, {{ pickup_address }}, {{ delivery_address }}, {{ price }}, {{ distance }}',
|
||||
'subject_en': 'Shipment Accepted - {{ tracking_number }}',
|
||||
'subject_ar': 'تم قبول الشحنة - {{ tracking_number }}',
|
||||
'email_body_en': 'You have successfully accepted Shipment {{ tracking_number }}.\nShipper: {{ shipper_name }}\nPickup: {{ pickup_address }}\nDelivery: {{ delivery_address }}\nPrice: {{ price }} OMR',
|
||||
'email_body_ar': 'لقد قبلت الشحنة {{ tracking_number }} بنجاح.\nالشاحن: {{ shipper_name }}\nالاستلام: {{ pickup_address }}\nالتوصيل: {{ delivery_address }}\nالسعر: {{ price }} ر.ع',
|
||||
'whatsapp_body_en': 'You have successfully accepted Shipment {{ tracking_number }}.\nShipper: {{ shipper_name }}\nPickup: {{ pickup_address }}\nDelivery: {{ delivery_address }}\nPrice/Bid: {{ price }} OMR',
|
||||
'whatsapp_body_ar': 'لقد قبلت الشحنة {{ tracking_number }} بنجاح.\nالشاحن: {{ shipper_name }}\nالاستلام: {{ pickup_address }}\nالتوصيل: {{ delivery_address }}\nالسعر: {{ price }} ر.ع',
|
||||
'email_body_en': 'You have successfully accepted Shipment {{ tracking_number }}.\nShipper: {{ shipper_name }}\nPickup: {{ pickup_address }}\nDelivery: {{ delivery_address }}\nDistance: {{ distance }} km\nPrice: {{ price }} OMR',
|
||||
'email_body_ar': 'لقد قبلت الشحنة {{ tracking_number }} بنجاح.\nالشاحن: {{ shipper_name }}\nالاستلام: {{ pickup_address }}\nالتوصيل: {{ delivery_address }}\nالمسافة: {{ distance }} كم\nالسعر: {{ price }} ر.ع',
|
||||
'whatsapp_body_en': 'You have successfully accepted Shipment {{ tracking_number }}.\nShipper: {{ shipper_name }}\nPickup: {{ pickup_address }}\nDelivery: {{ delivery_address }}\nDistance: {{ distance }} km\nPrice/Bid: {{ price }} OMR',
|
||||
'whatsapp_body_ar': 'لقد قبلت الشحنة {{ tracking_number }} بنجاح.\nالشاحن: {{ shipper_name }}\nالاستلام: {{ pickup_address }}\nالتوصيل: {{ delivery_address }}\nالمسافة: {{ distance }} كم\nالسعر: {{ price }} ر.ع',
|
||||
},
|
||||
'shipment_status_update': {
|
||||
'description': 'Sent on general status change (In Transit, Delivered)',
|
||||
@ -108,13 +108,13 @@ DEFAULT_TEMPLATES = {
|
||||
},
|
||||
'admin_alert_driver_accept': {
|
||||
'description': 'Sent to Admin when driver accepts shipment',
|
||||
'variables': '{{ driver_name }}, {{ car_plate_number }}, {{ tracking_number }}, {{ shipper_name }}, {{ price }}',
|
||||
'variables': '{{ driver_name }}, {{ car_plate_number }}, {{ tracking_number }}, {{ shipper_name }}, {{ price }}, {{ distance }}',
|
||||
'subject_en': 'Shipment Accepted ({{ tracking_number }})',
|
||||
'subject_ar': 'تم قبول الشحنة ({{ tracking_number }})',
|
||||
'email_body_en': 'Driver {{ driver_name }} ({{ car_plate_number }}) accepted shipment {{ tracking_number }} from {{ shipper_name }}.\nPrice: {{ price }} OMR',
|
||||
'email_body_ar': 'قام السائق {{ driver_name }} ({{ car_plate_number }}) بقبول الشحنة {{ tracking_number }} من {{ shipper_name }}.\nالسعر: {{ price }} ر.ع',
|
||||
'whatsapp_body_en': 'Driver {{ driver_name }} ({{ car_plate_number }}) accepted shipment {{ tracking_number }} from {{ shipper_name }}.\nPrice: {{ price }} OMR',
|
||||
'whatsapp_body_ar': 'قام السائق {{ driver_name }} ({{ car_plate_number }}) بقبول الشحنة {{ tracking_number }} من {{ shipper_name }}.\nالسعر: {{ price }} ر.ع',
|
||||
'email_body_en': 'Driver {{ driver_name }} ({{ car_plate_number }}) accepted shipment {{ tracking_number }} from {{ shipper_name }}.\nDistance: {{ distance }} km\nPrice: {{ price }} OMR',
|
||||
'email_body_ar': 'قام السائق {{ driver_name }} ({{ car_plate_number }}) بقبول الشحنة {{ tracking_number }} من {{ shipper_name }}.\nالمسافة: {{ distance }} كم\nالسعر: {{ price }} ر.ع',
|
||||
'whatsapp_body_en': 'Driver {{ driver_name }} ({{ car_plate_number }}) accepted shipment {{ tracking_number }} from {{ shipper_name }}.\nDistance: {{ distance }} km\nPrice: {{ price }} OMR',
|
||||
'whatsapp_body_ar': 'قام السائق {{ driver_name }} ({{ car_plate_number }}) بقبول الشحنة {{ tracking_number }} من {{ shipper_name }}.\nالمسافة: {{ distance }} كم\nالسعر: {{ price }} ر.ع',
|
||||
},
|
||||
'contact_form_admin': {
|
||||
'description': 'Sent to Admin when contact form is submitted',
|
||||
|
||||
@ -66,6 +66,7 @@
|
||||
<p class="card-text mb-3 small"><strong>{% trans "Delivery" %}:</strong> {{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}</p>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="text-muted small"><strong>{% trans "Distance" %}:</strong> {{ parcel.distance_km }} km</span>
|
||||
<span class="text-muted small"><strong>{% trans "Weight" %}:</strong> {{ parcel.weight }} kg</span>
|
||||
</div>
|
||||
|
||||
@ -103,6 +104,9 @@
|
||||
<i class="bi bi-geo-alt-fill text-danger"></i>
|
||||
<strong>{% trans "To" %}:</strong> {{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}
|
||||
</span>
|
||||
<span class="d-flex align-items-center gap-1">
|
||||
<i class="bi bi-signpost-2"></i> {{ parcel.distance_km }} km
|
||||
</span>
|
||||
<span class="d-flex align-items-center gap-1">
|
||||
<i class="bi bi-box-seam"></i> {{ parcel.weight }} kg
|
||||
</span>
|
||||
@ -228,6 +232,7 @@
|
||||
<th>{% trans "Tracking ID" %}</th>
|
||||
<th>{% trans "From" %}</th>
|
||||
<th>{% trans "To" %}</th>
|
||||
<th>{% trans "Distance" %}</th>
|
||||
<th>{% trans "Price" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
</tr>
|
||||
@ -239,6 +244,7 @@
|
||||
<td><span class="badge bg-light text-dark">#{{ parcel.tracking_number }}</span></td>
|
||||
<td>{{ parcel.pickup_governate.name }} / {{ parcel.pickup_city.name }}</td>
|
||||
<td>{{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}</td>
|
||||
<td>{{ parcel.distance_km }} km</td>
|
||||
<td>{{ parcel.price }} OMR</td>
|
||||
<td>
|
||||
<span class="badge bg-success">
|
||||
@ -272,6 +278,7 @@
|
||||
<th>{% trans "Tracking ID" %}</th>
|
||||
<th>{% trans "From" %}</th>
|
||||
<th>{% trans "To" %}</th>
|
||||
<th>{% trans "Distance" %}</th>
|
||||
<th>{% trans "Price" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
</tr>
|
||||
@ -283,6 +290,7 @@
|
||||
<td><span class="badge bg-light text-dark">#{{ parcel.tracking_number }}</span></td>
|
||||
<td>{{ parcel.pickup_governate.name }} / {{ parcel.pickup_city.name }}</td>
|
||||
<td>{{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}</td>
|
||||
<td>{{ parcel.distance_km }} km</td>
|
||||
<td>{{ parcel.price }} OMR</td>
|
||||
<td>
|
||||
<span class="badge bg-danger">
|
||||
|
||||
@ -196,7 +196,7 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">
|
||||
<th width="40%">
|
||||
Description
|
||||
<span class="ar ar-text">الوصف</span>
|
||||
</th>
|
||||
@ -204,6 +204,10 @@
|
||||
Tracking No
|
||||
<span class="ar ar-text">رقم التتبع</span>
|
||||
</th>
|
||||
<th>
|
||||
Distance
|
||||
<span class="ar ar-text">المسافة</span>
|
||||
</th>
|
||||
<th>
|
||||
Weight
|
||||
<span class="ar ar-text">الوزن</span>
|
||||
@ -221,13 +225,14 @@
|
||||
<small>{{ parcel.description|truncatechars:50 }}</small>
|
||||
</td>
|
||||
<td>{{ parcel.tracking_number }}</td>
|
||||
<td>{{ parcel.distance_km }} km</td>
|
||||
<td>{{ parcel.weight }} kg</td>
|
||||
<td class="text-right">{{ parcel.price }} OMR / <span class="ar-text">ر.ع.</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="total-row">
|
||||
<td colspan="3" class="text-right">
|
||||
<td colspan="4" class="text-right">
|
||||
TOTAL / الإجمالي
|
||||
</td>
|
||||
<td class="text-right">{{ parcel.price }} OMR / <span class="ar-text">ر.ع.</span></td>
|
||||
|
||||
@ -55,7 +55,8 @@
|
||||
</div>
|
||||
<h5 class="card-title">{{ parcel.description|truncatechars:30 }}</h5>
|
||||
<p class="card-text mb-1 small text-muted"><i class="fas fa-map-marker-alt"></i> <strong>{% trans "From" %}:</strong> {{ parcel.pickup_governate.name }} / {{ parcel.pickup_city.name }}</p>
|
||||
<p class="card-text mb-3 small text-muted"><i class="fas fa-flag-checkered"></i> <strong>{% trans "To" %}:</strong> {{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}</p>
|
||||
<p class="card-text mb-1 small text-muted"><i class="fas fa-flag-checkered"></i> <strong>{% trans "To" %}:</strong> {{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}</p>
|
||||
<p class="card-text mb-3 small text-muted"><i class="fas fa-road"></i> <strong>{% trans "Distance" %}:</strong> {{ parcel.distance_km }} km</p>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span class="text-primary fw-bold">{{ parcel.price }} OMR</span>
|
||||
@ -124,6 +125,9 @@
|
||||
<i class="bi bi-geo-alt-fill text-danger"></i>
|
||||
<strong>{% trans "To" %}:</strong> {{ parcel.delivery_governate.name }} / {{ parcel.delivery_city.name }}
|
||||
</span>
|
||||
<span class="d-flex align-items-center gap-1">
|
||||
<i class="bi bi-signpost-2"></i> {{ parcel.distance_km }} km
|
||||
</span>
|
||||
<span class="d-flex align-items-center gap-1">
|
||||
<i class="bi bi-truck"></i>
|
||||
{% if parcel.carrier %}{{ parcel.carrier.get_full_name|default:parcel.carrier.username }}{% else %}{% trans "Waiting" %}{% endif %}
|
||||
@ -237,6 +241,7 @@
|
||||
<th>{% trans "Tracking ID" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th>{% trans "Carrier" %}</th>
|
||||
<th>{% trans "Distance" %}</th>
|
||||
<th>{% trans "Bid/Price" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Action" %}</th>
|
||||
@ -256,6 +261,7 @@
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ parcel.distance_km }} km</td>
|
||||
<td>{{ parcel.price }} OMR</td>
|
||||
<td>
|
||||
<span class="badge bg-success">
|
||||
@ -310,6 +316,7 @@
|
||||
<th>{% trans "Tracking ID" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th>{% trans "Carrier" %}</th>
|
||||
<th>{% trans "Distance" %}</th>
|
||||
<th>{% trans "Bid/Price" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Action" %}</th>
|
||||
@ -328,6 +335,7 @@
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ parcel.distance_km }} km</td>
|
||||
<td>{{ parcel.price }} OMR</td>
|
||||
<td>
|
||||
<span class="badge bg-danger">
|
||||
|
||||
@ -147,7 +147,9 @@ def notify_shipment_created(parcel):
|
||||
'name': shipper_name,
|
||||
'description': parcel.description,
|
||||
'tracking_number': parcel.tracking_number,
|
||||
'status': parcel.get_status_display()
|
||||
'status': parcel.get_status_display(),
|
||||
'distance': parcel.distance_km,
|
||||
'price': parcel.price
|
||||
}
|
||||
|
||||
# Render for Shipper (check user language preference? For now assume session/request unavailable so maybe default or EN,
|
||||
@ -241,7 +243,8 @@ def notify_driver_assigned(parcel):
|
||||
'shipper_name': shipper_name,
|
||||
'pickup_address': parcel.pickup_address,
|
||||
'delivery_address': parcel.delivery_address,
|
||||
'price': parcel.price
|
||||
'price': parcel.price,
|
||||
'distance': parcel.distance_km
|
||||
}
|
||||
subj_d, email_d, wa_d = get_notification_content('driver_pickup_driver', context_driver)
|
||||
|
||||
@ -257,7 +260,8 @@ def notify_driver_assigned(parcel):
|
||||
'car_plate_number': car_plate,
|
||||
'tracking_number': parcel.tracking_number,
|
||||
'shipper_name': shipper_name,
|
||||
'price': parcel.price
|
||||
'price': parcel.price,
|
||||
'distance': parcel.distance_km
|
||||
}
|
||||
notify_admin_alert('admin_alert_driver_accept', context_admin)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user