adding profile

This commit is contained in:
Flatlogic Bot 2026-01-25 10:56:32 +00:00
parent bae3510e83
commit 59f1cf28c3
14 changed files with 247 additions and 31 deletions

View File

@ -1,5 +1,5 @@
from django.contrib import admin
from .models import Profile, Parcel, Country, Governate, City
from .models import Profile, Parcel, Country, Governate, City, PlatformProfile
@admin.register(Country)
class CountryAdmin(admin.ModelAdmin):
@ -29,4 +29,14 @@ class ParcelAdmin(admin.ModelAdmin):
list_display = ('tracking_number', 'shipper', 'carrier', 'status', 'payment_status', 'created_at')
list_filter = ('status', 'payment_status', 'pickup_country', 'delivery_country')
search_fields = ('tracking_number', 'shipper__username', 'carrier__username', 'receiver_name')
readonly_fields = ('tracking_number', 'created_at', 'updated_at')
readonly_fields = ('tracking_number', 'created_at', 'updated_at')
@admin.register(PlatformProfile)
class PlatformProfileAdmin(admin.ModelAdmin):
list_display = ('name', 'phone_number', 'registration_number')
def has_add_permission(self, request):
# Allow adding only if no instance exists
if self.model.objects.exists():
return False
return super().has_add_permission(request)

View File

@ -31,6 +31,11 @@ class UserRegistrationForm(forms.ModelForm):
self.fields['country'].queryset = Country.objects.all().order_by(name_field)
# Default Country logic
oman = Country.objects.filter(name_en='Oman').first()
if oman:
self.fields['country'].initial = oman
if 'country' in self.data:
try:
country_id = int(self.data.get('country'))
@ -39,6 +44,8 @@ class UserRegistrationForm(forms.ModelForm):
pass
elif self.instance.pk and hasattr(self.instance, 'profile') and self.instance.profile.country:
self.fields['governate'].queryset = self.instance.profile.country.governate_set.order_by(name_field)
elif oman:
self.fields['governate'].queryset = Governate.objects.filter(country=oman).order_by(name_field)
if 'governate' in self.data:
try:
@ -122,6 +129,12 @@ class ParcelForm(forms.ModelForm):
# Set querysets for countries
self.fields['pickup_country'].queryset = Country.objects.all().order_by(name_field)
self.fields['delivery_country'].queryset = Country.objects.all().order_by(name_field)
# Default Country logic
oman = Country.objects.filter(name_en='Oman').first()
if oman:
self.fields['pickup_country'].initial = oman
self.fields['delivery_country'].initial = oman
# Pickup
self.fields['pickup_governate'].queryset = Governate.objects.none()
@ -133,6 +146,8 @@ class ParcelForm(forms.ModelForm):
self.fields['pickup_governate'].queryset = Governate.objects.filter(country_id=country_id).order_by(name_field)
except (ValueError, TypeError):
pass
elif oman:
self.fields['pickup_governate'].queryset = Governate.objects.filter(country=oman).order_by(name_field)
if 'pickup_governate' in self.data:
try:
@ -151,10 +166,12 @@ class ParcelForm(forms.ModelForm):
self.fields['delivery_governate'].queryset = Governate.objects.filter(country_id=country_id).order_by(name_field)
except (ValueError, TypeError):
pass
elif oman:
self.fields['delivery_governate'].queryset = Governate.objects.filter(country=oman).order_by(name_field)
if 'delivery_governate' in self.data:
try:
gov_id = int(self.data.get('delivery_governate'))
self.fields['delivery_city'].queryset = City.objects.filter(governate_id=gov_id).order_by(name_field)
except (ValueError, TypeError):
pass
pass

View File

@ -0,0 +1,30 @@
# Generated by Django 5.2.7 on 2026-01-25 10:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0006_alter_city_name_ar_alter_city_name_en_and_more'),
]
operations = [
migrations.CreateModel(
name='PlatformProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, verbose_name='Platform Name')),
('logo', models.ImageField(blank=True, null=True, upload_to='platform_logos/', verbose_name='Logo')),
('slogan', models.CharField(blank=True, max_length=255, verbose_name='Slogan')),
('address', models.TextField(blank=True, verbose_name='Address')),
('phone_number', models.CharField(blank=True, max_length=50, verbose_name='Phone Number')),
('registration_number', models.CharField(blank=True, max_length=100, verbose_name='Registration Number')),
('vat_number', models.CharField(blank=True, max_length=100, verbose_name='VAT Number')),
],
options={
'verbose_name': 'Platform Profile',
'verbose_name_plural': 'Platform Profile',
},
),
]

View File

@ -144,4 +144,20 @@ class Parcel(models.Model):
class Meta:
verbose_name = _('Parcel')
verbose_name_plural = _('Parcels')
verbose_name_plural = _('Parcels')
class PlatformProfile(models.Model):
name = models.CharField(_('Platform Name'), max_length=100)
logo = models.ImageField(_('Logo'), upload_to='platform_logos/', blank=True, null=True)
slogan = models.CharField(_('Slogan'), max_length=255, blank=True)
address = models.TextField(_('Address'), blank=True)
phone_number = models.CharField(_('Phone Number'), max_length=50, blank=True)
registration_number = models.CharField(_('Registration Number'), max_length=100, blank=True)
vat_number = models.CharField(_('VAT Number'), max_length=100, blank=True)
def __str__(self):
return self.name
class Meta:
verbose_name = _('Platform Profile')
verbose_name_plural = _('Platform Profile')

View File

@ -19,7 +19,11 @@
{% endif %}
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
{% if lang.direction == 'rtl' %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.rtl.min.css">
{% else %}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
{% endif %}
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
@ -28,20 +32,9 @@
{% if lang.direction == 'rtl' %}
<style>
/* Additional RTL overrides if needed */
body {
text-align: right;
}
.ms-auto {
margin-right: auto !important;
margin-left: 0 !important;
}
.me-auto {
margin-left: auto !important;
margin-right: 0 !important;
}
.dropdown-menu-end {
left: 0 !important;
right: auto !important;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Example font suitable for Arabic */
}
</style>
{% endif %}

View File

@ -49,7 +49,7 @@ document.addEventListener('DOMContentLoaded', function() {
citySelect.innerHTML = '<option value="">{% trans "Select City" %}</option>';
if (countryId) {
fetch(`/ajax/get-governates/?country_id=${countryId}`)
fetch(`{% url 'get_governates' %}?country_id=${countryId}`)
.then(response => response.json())
.then(data => {
data.forEach(gov => {
@ -67,7 +67,7 @@ document.addEventListener('DOMContentLoaded', function() {
citySelect.innerHTML = '<option value="">{% trans "Select City" %}</option>';
if (governateId) {
fetch(`/ajax/get-cities/?governate_id=${governateId}`)
fetch(`{% url 'get_cities' %}?governate_id=${governateId}`)
.then(response => response.json())
.then(data => {
data.forEach(city => {

View File

@ -11,15 +11,114 @@
<form method="POST">
{% csrf_token %}
<div class="row g-3">
{% for field in form %}
<div class="{% if field.name == 'description' %}col-12{% else %}col-md-6{% endif %}">
<label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
{% if field.errors %}
<div class="text-danger small">{{ field.errors }}</div>
<!-- General Info -->
<div class="col-12">
<label class="form-label" for="{{ form.description.id_for_label }}">{{ form.description.label }}</label>
{{ form.description }}
{% if form.description.errors %}
<div class="text-danger small">{{ form.description.errors }}</div>
{% endif %}
</div>
{% endfor %}
<div class="col-md-6">
<label class="form-label" for="{{ form.weight.id_for_label }}">{{ form.weight.label }}</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" for="{{ form.price.id_for_label }}">{{ form.price.label }}</label>
{{ form.price }}
{% if form.price.errors %}
<div class="text-danger small">{{ form.price.errors }}</div>
{% endif %}
</div>
<!-- Pickup Details -->
<div class="col-12 mt-4">
<h4 class="mb-3 text-secondary border-bottom pb-2">{% trans "Pickup Details" %}</h4>
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.pickup_country.id_for_label }}">{{ form.pickup_country.label }}</label>
{{ form.pickup_country }}
{% if form.pickup_country.errors %}
<div class="text-danger small">{{ form.pickup_country.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.pickup_governate.id_for_label }}">{{ form.pickup_governate.label }}</label>
{{ form.pickup_governate }}
{% if form.pickup_governate.errors %}
<div class="text-danger small">{{ form.pickup_governate.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.pickup_city.id_for_label }}">{{ form.pickup_city.label }}</label>
{{ form.pickup_city }}
{% if form.pickup_city.errors %}
<div class="text-danger small">{{ form.pickup_city.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.pickup_address.id_for_label }}">{{ form.pickup_address.label }}</label>
{{ form.pickup_address }}
{% if form.pickup_address.errors %}
<div class="text-danger small">{{ form.pickup_address.errors }}</div>
{% endif %}
</div>
<!-- Delivery Details -->
<div class="col-12 mt-4">
<h4 class="mb-3 text-secondary border-bottom pb-2">{% trans "Delivery Details" %}</h4>
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.delivery_country.id_for_label }}">{{ form.delivery_country.label }}</label>
{{ form.delivery_country }}
{% if form.delivery_country.errors %}
<div class="text-danger small">{{ form.delivery_country.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.delivery_governate.id_for_label }}">{{ form.delivery_governate.label }}</label>
{{ form.delivery_governate }}
{% if form.delivery_governate.errors %}
<div class="text-danger small">{{ form.delivery_governate.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.delivery_city.id_for_label }}">{{ form.delivery_city.label }}</label>
{{ form.delivery_city }}
{% if form.delivery_city.errors %}
<div class="text-danger small">{{ form.delivery_city.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.delivery_address.id_for_label }}">{{ form.delivery_address.label }}</label>
{{ form.delivery_address }}
{% if form.delivery_address.errors %}
<div class="text-danger small">{{ form.delivery_address.errors }}</div>
{% endif %}
</div>
<!-- Receiver Details -->
<div class="col-12 mt-4">
<h4 class="mb-3 text-secondary border-bottom pb-2">{% trans "Receiver Details" %}</h4>
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.receiver_name.id_for_label }}">{{ form.receiver_name.label }}</label>
{{ form.receiver_name }}
{% if form.receiver_name.errors %}
<div class="text-danger small">{{ form.receiver_name.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.receiver_phone.id_for_label }}">{{ form.receiver_phone.label }}</label>
{{ form.receiver_phone }}
{% if form.receiver_phone.errors %}
<div class="text-danger small">{{ form.receiver_phone.errors }}</div>
{% endif %}
</div>
<div class="col-12 mt-4">
<button type="submit" class="btn btn-masarx-primary w-100 py-3">{% trans "Submit Request" %}</button>
</div>
@ -45,7 +144,7 @@ document.addEventListener('DOMContentLoaded', function() {
citySelect.innerHTML = '<option value="">{% trans "Select City" %}</option>';
if (val) {
fetch(`/ajax/get-governates/?country_id=${val}`)
fetch(`{% url 'get_governates' %}?country_id=${val}`)
.then(response => response.json())
.then(data => {
data.forEach(item => {
@ -63,7 +162,7 @@ document.addEventListener('DOMContentLoaded', function() {
citySelect.innerHTML = '<option value="">{% trans "Select City" %}</option>';
if (val) {
fetch(`/ajax/get-cities/?governate_id=${val}`)
fetch(`{% url 'get_cities' %}?governate_id=${val}`)
.then(response => response.json())
.then(data => {
data.forEach(item => {
@ -81,4 +180,4 @@ document.addEventListener('DOMContentLoaded', function() {
setupDependentDropdowns('id_delivery_country', 'id_delivery_governate', 'id_delivery_city');
});
</script>
{% endblock %}
{% endblock %}

Binary file not shown.

View File

@ -435,4 +435,54 @@ msgstr "لقد قبلت الشحنة!"
#: core/views.py:91
msgid "Status updated successfully!"
msgstr "تم تحديث الحالة بنجاح!"
msgstr "تم تحديث الحالة بنجاح!"
#: core/templates/core/shipment_request.html:38
msgid "Pickup Details"
msgstr "تفاصيل الاستلام"
#: core/templates/core/shipment_request.html:64
msgid "Delivery Details"
msgstr "تفاصيل التوصيل"
#: core/templates/core/shipment_request.html:90
msgid "Receiver Details"
msgstr "تفاصيل المستلم"
#: core/templates/core/shipment_request.html:113
msgid "Select Governate"
msgstr "اختر المحافظة"
#: core/templates/core/shipment_request.html:114
msgid "Select City"
msgstr "اختر المدينة"
msgid "Shipping Price (OMR)"
msgstr "سعر الشحن (ر.ع)"
msgid "Pickup Country"
msgstr "دولة الاستلام"
msgid "Pickup Governate"
msgstr "محافظة الاستلام"
msgid "Pickup City"
msgstr "مدينة الاستلام"
msgid "Pickup Address (Street/Building)"
msgstr "عنوان الاستلام (الشارع/المبنى)"
msgid "Delivery Country"
msgstr "دولة التوصيل"
msgid "Delivery Governate"
msgstr "محافظة التوصيل"
msgid "Delivery City"
msgstr "مدينة التوصيل"
msgid "Delivery Address (Street/Building)"
msgstr "عنوان التوصيل (الشارع/المبنى)"
msgid "Street/Building"
msgstr "الشارع/المبنى"

View File

@ -1,3 +1,4 @@
Django==5.2.7
mysqlclient==2.2.7
python-dotenv==1.1.1
Pillow