diff --git a/assets/pasted-20260201-154837-60ba680b.png b/assets/pasted-20260201-154837-60ba680b.png new file mode 100644 index 0000000..59b5193 Binary files /dev/null and b/assets/pasted-20260201-154837-60ba680b.png differ diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index f06e27f..a41ab66 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index 08813f3..e3eb9ff 100644 Binary files a/core/__pycache__/forms.cpython-311.pyc and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 7fb33b1..92a5f4b 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/pricing.cpython-311.pyc b/core/__pycache__/pricing.cpython-311.pyc index ac1ab6c..979af60 100644 Binary files a/core/__pycache__/pricing.cpython-311.pyc and b/core/__pycache__/pricing.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 28a9da4..c75b3ce 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 3ac0780..e1dab42 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User -from .models import Profile, Parcel, Country, Governate, City, PlatformProfile, Testimonial, DriverRating, NotificationTemplate, PricingRule, DriverReport, DriverRejection +from .models import Profile, Parcel, Country, Governate, City, PlatformProfile, Testimonial, DriverRating, NotificationTemplate, PricingRule, DriverReport, DriverRejection, ParcelType from django.utils.translation import gettext_lazy as _ from django.urls import path, reverse from django.shortcuts import render, redirect @@ -109,7 +109,7 @@ class CustomUserAdmin(UserAdmin): class ParcelAdmin(admin.ModelAdmin): change_list_template = 'admin/core/parcel/change_list.html' - list_display = ('tracking_number', 'shipper', 'carrier', 'price', 'driver_amount', 'platform_fee', 'distance_km', 'status', 'payment_status', 'created_at') + list_display = ('tracking_number', 'shipper', 'carrier', 'parcel_type', 'price', 'driver_amount', 'platform_fee', 'distance_km', 'status', 'payment_status', 'created_at') list_filter = ( 'status', 'payment_status', @@ -123,7 +123,7 @@ class ParcelAdmin(admin.ModelAdmin): fieldsets = ( (None, { - 'fields': ('tracking_number', 'shipper', 'carrier', 'status', 'payment_status', 'thawani_session_id') + 'fields': ('tracking_number', 'shipper', 'carrier', 'parcel_type', 'status', 'payment_status', 'thawani_session_id') }), (_('Description'), { 'fields': ('description', 'receiver_name', 'receiver_phone') @@ -402,3 +402,4 @@ class NotificationTemplateAdmin(admin.ModelAdmin): return False admin.site.register(NotificationTemplate, NotificationTemplateAdmin) +admin.site.register(ParcelType) diff --git a/core/forms.py b/core/forms.py index 05ff5b3..57cc2dd 100644 --- a/core/forms.py +++ b/core/forms.py @@ -2,7 +2,7 @@ from django import forms from django.contrib.auth.models import User from django.utils.translation import gettext_lazy as _ from django.utils.translation import get_language -from .models import Profile, Parcel, Country, Governate, City, DriverRating, DriverReport +from .models import Profile, Parcel, Country, Governate, City, DriverRating, DriverReport, ParcelType class ContactForm(forms.Form): name = forms.CharField(max_length=100, label=_("Name"), widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Your Name')})) @@ -240,6 +240,7 @@ class ParcelForm(forms.ModelForm): class Meta: model = Parcel fields = [ + 'parcel_type', 'description', 'weight', 'price', 'pickup_country', 'pickup_governate', 'pickup_city', 'pickup_address', 'pickup_lat', 'pickup_lng', @@ -249,6 +250,7 @@ class ParcelForm(forms.ModelForm): 'receiver_name', 'receiver_phone' ] widgets = { + 'parcel_type': forms.Select(attrs={'class': 'form-control'}), 'description': forms.Textarea(attrs={'rows': 3, 'class': 'form-control', 'placeholder': _('What are you sending?')}), 'weight': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.1'}), 'price': forms.TextInput(attrs={'class': 'form-control', 'readonly': 'readonly'}), @@ -276,6 +278,7 @@ class ParcelForm(forms.ModelForm): 'receiver_phone': forms.TextInput(attrs={'class': 'form-control'}), } labels = { + 'parcel_type': _('Parcel Type'), 'description': _('Package Description'), 'weight': _('Weight (kg)'), 'price': _('Calculated Price (OMR)'), @@ -406,4 +409,4 @@ class DriverReportForm(forms.ModelForm): labels = { 'reason': _('Reason for Reporting'), 'description': _('Details'), - } + } \ No newline at end of file diff --git a/core/migrations/0032_parceltype_parcel_parcel_type.py b/core/migrations/0032_parceltype_parcel_parcel_type.py new file mode 100644 index 0000000..7005078 --- /dev/null +++ b/core/migrations/0032_parceltype_parcel_parcel_type.py @@ -0,0 +1,31 @@ +# Generated by Django 5.2.7 on 2026-02-01 17:10 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0031_platformprofile_ticker_bg_color_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='ParcelType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name_en', models.CharField(max_length=100, verbose_name='Name (English)')), + ('name_ar', models.CharField(max_length=100, verbose_name='Name (Arabic)')), + ], + options={ + 'verbose_name': 'Parcel Type', + 'verbose_name_plural': 'Parcel Types', + }, + ), + migrations.AddField( + model_name='parcel', + name='parcel_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.parceltype', verbose_name='Parcel Type'), + ), + ] diff --git a/core/migrations/__pycache__/0032_parceltype_parcel_parcel_type.cpython-311.pyc b/core/migrations/__pycache__/0032_parceltype_parcel_parcel_type.cpython-311.pyc new file mode 100644 index 0000000..7344599 Binary files /dev/null and b/core/migrations/__pycache__/0032_parceltype_parcel_parcel_type.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index baee9fb..c6156d8 100644 --- a/core/models.py +++ b/core/models.py @@ -63,6 +63,23 @@ class City(models.Model): verbose_name = _('City') verbose_name_plural = _('Cities') +class ParcelType(models.Model): + name_en = models.CharField(_('Name (English)'), max_length=100) + name_ar = models.CharField(_('Name (Arabic)'), max_length=100) + + @property + def name(self): + if get_language() == 'ar': + return self.name_ar + return self.name_en + + def __str__(self): + return self.name + + class Meta: + verbose_name = _('Parcel Type') + verbose_name_plural = _('Parcel Types') + class Profile(models.Model): ROLE_CHOICES = ( ("shipper", _("Shipper")), @@ -257,6 +274,7 @@ class Parcel(models.Model): shipper = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_parcels', verbose_name=_('Shipper')) carrier = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='carried_parcels', verbose_name=_('Carrier')) + parcel_type = models.ForeignKey(ParcelType, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('Parcel Type')) description = models.TextField(_('Description')) weight = models.DecimalField(_('Weight (kg)'), max_digits=5, decimal_places=2, help_text=_("Weight in kg")) price = models.DecimalField(_('Total Price (OMR)'), max_digits=10, decimal_places=3, default=Decimal('0.000')) @@ -505,4 +523,4 @@ class DriverRejection(models.Model): class Meta: verbose_name = _('Driver Rejection') verbose_name_plural = _('Driver Rejections') - ordering = ['-created_at'] + ordering = ['-created_at'] \ No newline at end of file diff --git a/core/pricing.py b/core/pricing.py index cebedb5..a33fddc 100644 --- a/core/pricing.py +++ b/core/pricing.py @@ -11,7 +11,7 @@ def calculate_haversine_distance(lat1, lon1, lat2, lon2): return Decimal('0.00') # Convert decimal degrees to radians - lat1, lon1, lat2, lon2 = map(float, [lat1, lon1, lat2, lon2]) + lat1, lon1, lat2, lon2 = map(math.radians, [float(lat1), float(lon1), float(lat2), float(lon2)]) # Haversine formula dlon = lon2 - lon1 diff --git a/core/templates/core/shipment_request.html b/core/templates/core/shipment_request.html index 5ceca8c..3b94464 100644 --- a/core/templates/core/shipment_request.html +++ b/core/templates/core/shipment_request.html @@ -40,6 +40,13 @@
{% trans "Estimated Distance" %}
+{% trans "Total Price" %}
+