changes19

This commit is contained in:
Flatlogic Bot 2026-01-23 15:13:31 +00:00
parent 459f38ada6
commit 3da5d477df
12 changed files with 132 additions and 31 deletions

View File

@ -4,7 +4,7 @@ from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.utils.translation import gettext_lazy as _
from .models import Profile, Truck, Shipment, Bid, Message, WhatsAppConfig, Country
from .models import Profile, Truck, Shipment, Bid, Message, WhatsAppConfig, Country, City, TruckType
from .whatsapp import send_whatsapp_message
@admin.register(Country)
@ -12,6 +12,17 @@ class CountryAdmin(admin.ModelAdmin):
list_display = ('name', 'code', 'is_default')
list_editable = ('is_default',)
@admin.register(City)
class CityAdmin(admin.ModelAdmin):
list_display = ('name', 'country')
list_filter = ('country',)
search_fields = ('name',)
@admin.register(TruckType)
class TruckTypeAdmin(admin.ModelAdmin):
list_display = ('name', 'name_ar')
search_fields = ('name', 'name_ar')
@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'role', 'country_code', 'phone_number')
@ -20,20 +31,21 @@ class ProfileAdmin(admin.ModelAdmin):
@admin.register(Truck)
class TruckAdmin(admin.ModelAdmin):
list_display = ('truck_type', 'model', 'plate_no', 'owner', 'load_capacity')
search_fields = ('plate_no', 'owner__username', 'truck_type')
list_display = ('display_truck_type', 'model', 'plate_no', 'owner', 'load_capacity')
search_fields = ('plate_no', 'owner__username', 'model')
list_filter = ('truck_type_link', 'is_approved')
@admin.register(Shipment)
class ShipmentAdmin(admin.ModelAdmin):
list_display = ('origin', 'destination', 'shipper', 'status', 'delivery_date')
list_filter = ('status', 'delivery_date')
search_fields = ('origin', 'destination', 'shipper__username')
list_display = ('display_origin', 'display_destination', 'shipper', 'status', 'delivery_date')
list_filter = ('status', 'delivery_date', 'required_truck_type_link')
search_fields = ('origin', 'destination', 'shipper__username', 'description')
@admin.register(Bid)
class BidAdmin(admin.ModelAdmin):
list_display = ('shipment', 'truck_owner', 'amount', 'status')
list_filter = ('status',)
search_fields = ('shipment__origin', 'shipment__destination', 'truck_owner__username')
search_fields = ('shipment__description', 'truck_owner__username')
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):

View File

@ -1,5 +1,5 @@
from django import forms
from .models import Truck, Shipment, Bid, Profile, Country, OTPCode, City
from .models import Truck, Shipment, Bid, Profile, Country, OTPCode, City, TruckType
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
@ -64,13 +64,12 @@ class TruckForm(forms.ModelForm):
class Meta:
model = Truck
fields = [
'truck_type', 'truck_type_ar', 'model', 'model_ar', 'year', 'plate_no',
'truck_type_link', 'model', 'model_ar', 'year', 'plate_no',
'load_capacity', 'load_capacity_ar', 'color', 'color_ar', 'registration_expiry_date',
'truck_picture', 'registration_front', 'registration_back', 'driver_license'
]
widgets = {
'truck_type': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('e.g. Flatbed')}),
'truck_type_ar': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('مثلا سطحة')}),
'truck_type_link': forms.Select(attrs={'class': 'form-select'}),
'model': forms.TextInput(attrs={'class': 'form-control'}),
'model_ar': forms.TextInput(attrs={'class': 'form-control'}),
'year': forms.NumberInput(attrs={'class': 'form-control'}),
@ -85,12 +84,16 @@ class TruckForm(forms.ModelForm):
'registration_back': forms.FileInput(attrs={'class': 'form-control'}),
'driver_license': forms.FileInput(attrs={'class': 'form-control'}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['truck_type_link'].label = _("Truck Type")
class ShipmentForm(forms.ModelForm):
class Meta:
model = Shipment
fields = [
'description', 'weight',
'description', 'weight', 'required_truck_type_link',
'origin_country', 'origin_city',
'destination_country', 'destination_city',
'delivery_date'
@ -98,12 +101,17 @@ class ShipmentForm(forms.ModelForm):
widgets = {
'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'weight': forms.TextInput(attrs={'class': 'form-control'}),
'required_truck_type_link': forms.Select(attrs={'class': 'form-select'}),
'origin_country': forms.Select(attrs={'class': 'form-select location-selector', 'data-type': 'origin'}),
'origin_city': forms.Select(attrs={'class': 'form-select'}),
'destination_country': forms.Select(attrs={'class': 'form-select location-selector', 'data-type': 'destination'}),
'destination_city': forms.Select(attrs={'class': 'form-select'}),
'delivery_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['required_truck_type_link'].label = _("Truck Type")
class BidForm(forms.ModelForm):
class Meta:
@ -127,6 +135,7 @@ class BidForm(forms.ModelForm):
class ShipperOfferForm(forms.Form):
description = forms.CharField(label=_('Goods Description'), widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}))
weight = forms.CharField(label=_('Weight/Volume'), widget=forms.TextInput(attrs={'class': 'form-control'}))
required_truck_type_link = forms.ModelChoiceField(label=_('Required Truck Type'), queryset=TruckType.objects.all(), widget=forms.Select(attrs={'class': 'form-select'}))
origin_country = forms.ModelChoiceField(queryset=Country.objects.all(), widget=forms.Select(attrs={'class': 'form-select location-selector', 'data-type': 'origin'}))
origin_city = forms.ModelChoiceField(queryset=City.objects.all(), widget=forms.Select(attrs={'class': 'form-select'}))

View File

@ -0,0 +1,41 @@
# Generated by Django 5.2.7 on 2026-01-23 15:12
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0010_shipment_destination_country_shipment_origin_country_and_more'),
]
operations = [
migrations.CreateModel(
name='TruckType',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, verbose_name='Name (EN)')),
('name_ar', models.CharField(blank=True, max_length=100, verbose_name='Name (AR)')),
],
options={
'verbose_name': 'Truck Type',
'verbose_name_plural': 'Truck Types',
},
),
migrations.AlterField(
model_name='truck',
name='truck_type',
field=models.CharField(blank=True, max_length=100, verbose_name='Truck Type (EN)'),
),
migrations.AddField(
model_name='shipment',
name='required_truck_type_link',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.trucktype', verbose_name='Required Truck Type'),
),
migrations.AddField(
model_name='truck',
name='truck_type_link',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.trucktype', verbose_name='Truck Type (New)'),
),
]

View File

@ -32,6 +32,19 @@ class City(models.Model):
def __str__(self):
return f"{self.name} ({self.country.name})"
class TruckType(models.Model):
name = models.CharField(_('Name (EN)'), max_length=100)
name_ar = models.CharField(_('Name (AR)'), max_length=100, blank=True)
class Meta:
verbose_name = _('Truck Type')
verbose_name_plural = _('Truck Types')
def __str__(self):
if get_language() == 'ar' and self.name_ar:
return self.name_ar
return self.name
class Profile(models.Model):
ROLE_CHOICES = (
('SHIPPER', _('Shipper (Need Goods Moved)')),
@ -73,8 +86,11 @@ class OTPCode(models.Model):
class Truck(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='trucks')
# Using a fresh name to avoid conflict with partially created fields
truck_type_link = models.ForeignKey(TruckType, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('Truck Type (New)'))
# English fields
truck_type = models.CharField(_('Truck Type (EN)'), max_length=100)
truck_type = models.CharField(_('Truck Type (EN)'), max_length=100, blank=True)
model = models.CharField(_('Model (EN)'), max_length=100)
load_capacity = models.CharField(_('Load Capacity (EN)'), max_length=100)
color = models.CharField(_('Color (EN)'), max_length=50)
@ -99,10 +115,14 @@ class Truck(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.display_truck_type} - {self.plate_no}"
if self.truck_type_link:
return f"{self.truck_type_link} - {self.plate_no}"
return f"{self.truck_type} - {self.plate_no}"
@property
def display_truck_type(self):
if self.truck_type_link:
return str(self.truck_type_link)
if get_language() == 'ar' and self.truck_type_ar:
return self.truck_type_ar
return self.truck_type
@ -136,6 +156,9 @@ class Shipment(models.Model):
description = models.TextField(_('Goods Description'))
weight = models.CharField(_('Weight/Volume'), max_length=100)
# Using a fresh name
required_truck_type_link = models.ForeignKey(TruckType, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('Required Truck Type'))
origin_country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, related_name='shipments_origin')
origin_city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True, related_name='shipments_origin')
destination_country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, related_name='shipments_destination')

View File

@ -20,13 +20,18 @@
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="col-md-4">
<label class="form-label fw-bold">{% trans "Weight/Volume" %}</label>
{{ form.weight }}
{% if form.weight.errors %}<div class="text-danger small">{{ form.weight.errors }}</div>{% endif %}
</div>
<div class="col-md-6">
<label class="form-label fw-bold">{% trans "Requested Delivery Date" %}</label>
<div class="col-md-4">
<label class="form-label fw-bold">{% trans "Truck Type" %}</label>
{{ form.required_truck_type_link }}
{% if form.required_truck_type_link.errors %}<div class="text-danger small">{{ form.required_truck_type_link.errors }}</div>{% endif %}
</div>
<div class="col-md-4">
<label class="form-label fw-bold">{% trans "Delivery Date" %}</label>
{{ form.delivery_date }}
{% if form.delivery_date.errors %}<div class="text-danger small">{{ form.delivery_date.errors }}</div>{% endif %}
</div>

View File

@ -17,11 +17,21 @@
<h5 class="text-muted small text-uppercase fw-bold">{% trans "Shipment Details" %}</h5>
<p class="lead fw-normal">{{ shipment.description }}</p>
<div class="row mt-4">
<div class="col-6 mb-3">
<div class="col-md-4 mb-3">
<small class="text-muted d-block text-uppercase small">{% trans "Weight / Volume" %}</small>
<strong class="fs-5">{{ shipment.weight }}</strong>
</div>
<div class="col-6 mb-3">
<div class="col-md-4 mb-3">
<small class="text-muted d-block text-uppercase small">{% trans "Required Truck Type" %}</small>
<strong class="fs-5">
{% if shipment.required_truck_type_link %}
{{ shipment.required_truck_type_link }}
{% else %}
<span class="text-muted opacity-50">{% trans "Any" %}</span>
{% endif %}
</strong>
</div>
<div class="col-md-4 mb-3">
<small class="text-muted d-block text-uppercase small">{% trans "Requested Delivery Date" %}</small>
<strong class="fs-5">{{ shipment.delivery_date }}</strong>
</div>
@ -141,4 +151,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@ -26,14 +26,20 @@
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="row mb-4">
<div class="col-12">
<div class="card bg-light border-0 p-3">
<label class="form-label fw-bold">{% trans "Truck Type" %}</label>
{{ form.truck_type_link }}
{{ form.truck_type_link.errors }}
<small class="text-muted">{% trans "Select the type of your truck from the list." %}</small>
</div>
</div>
</div>
<div class="row {% if CURRENT_LANGUAGE == "ar" %}flex-row-reverse{% endif %}">
<div class="col-md-6 {% if CURRENT_LANGUAGE == "ar" %}border-start{% else %}border-end{% endif %}">
<h5 class="mb-3 text-primary">{% trans "English Details" %}</h5>
<div class="mb-3">
<label class="form-label">{% trans "Truck Type" %}</label>
{{ form.truck_type }}
{{ form.truck_type.errors }}
</div>
<div class="mb-3">
<label class="form-label">{% trans "Model" %}</label>
{{ form.model }}
@ -53,11 +59,6 @@
<div class="col-md-6">
<h5 class="mb-3 text-success">{% trans "التفاصيل باللغة العربية" %}</h5>
<div class="mb-3">
<label class="form-label">{% trans "نوع الشاحنة" %}</label>
{{ form.truck_type_ar }}
{{ form.truck_type_ar.errors }}
</div>
<div class="mb-3">
<label class="form-label">{% trans "الموديل" %}</label>
{{ form.model_ar }}
@ -157,4 +158,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}