192 lines
8.7 KiB
Python
192 lines
8.7 KiB
Python
from django.contrib import admin
|
|
from django.urls import path
|
|
from django.shortcuts import render
|
|
from django.http import HttpResponseRedirect
|
|
from django.contrib import messages
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.utils import timezone
|
|
from django.utils.html import format_html
|
|
import os
|
|
from .models import Profile, Truck, Shipment, Bid, Message, WhatsAppConfig, Country, City, TruckType, AppSetting, Banner, HomeSection
|
|
from .whatsapp import send_whatsapp_message
|
|
|
|
@admin.register(Country)
|
|
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', 'phone_number', 'subscription_plan', 'subscription_expiry', 'subscription_status')
|
|
list_filter = ('role', 'subscription_plan', 'is_subscription_active')
|
|
search_fields = ('user__username', 'phone_number')
|
|
|
|
def subscription_status(self, obj):
|
|
if obj.subscription_plan == 'NONE':
|
|
return format_html('<span style="color: gray;">{}</span>', _('No Plan'))
|
|
|
|
if obj.is_expired():
|
|
return format_html('<span style="color: red; font-weight: bold;">{}</span>', _('Expired'))
|
|
|
|
# Profile model might not have days_until_expiry, let's check
|
|
# Based on models.py read earlier, it doesn't have it.
|
|
# It has a commented out section that seems to be a start of it.
|
|
# I'll use inline calculation
|
|
if not obj.subscription_expiry:
|
|
return format_html('<span style="color: red; font-weight: bold;">{}</span>', _('No Expiry'))
|
|
|
|
days = (obj.subscription_expiry - timezone.now().date()).days
|
|
if days <= 7:
|
|
return format_html('<span style="color: orange; font-weight: bold;">{} ({} {})</span>', _('Expiring soon'), days, _('days'))
|
|
|
|
return format_html('<span style="color: green; font-weight: bold;">{}</span>', _('Active'))
|
|
|
|
subscription_status.short_description = _('Subscription Status')
|
|
|
|
@admin.register(Truck)
|
|
class TruckAdmin(admin.ModelAdmin):
|
|
list_display = ('display_truck_type', 'model', 'plate_no', 'owner', 'load_capacity', 'is_approved')
|
|
search_fields = ('plate_no', 'owner__username', 'model')
|
|
list_filter = ('truck_type_link', 'is_approved')
|
|
readonly_fields = ('truck_picture_preview', 'registration_front_preview', 'registration_back_preview', 'driver_license_front_preview', 'driver_license_back_preview')
|
|
|
|
def truck_picture_preview(self, obj):
|
|
if obj.truck_picture:
|
|
return format_html('<img src="{}" style="max-height: 200px;"/>', obj.truck_picture.url)
|
|
return "-"
|
|
truck_picture_preview.short_description = _("Truck Picture Preview")
|
|
|
|
def _file_preview(self, field):
|
|
if not field:
|
|
return "-"
|
|
url = field.url
|
|
ext = os.path.splitext(field.name)[1].lower()
|
|
if ext in ['.jpg', '.jpeg', '.png', '.webp', '.gif']:
|
|
return format_html('<a href="{}" target="_blank"><img src="{}" style="max-height: 200px;"/></a>', url, url)
|
|
elif ext == '.pdf':
|
|
return format_html('<a href="{}" target="_blank"><i class="fa fa-file-pdf" style="font-size: 48px; color: red;"></i><br>{}</a>', url, _("View PDF Document"))
|
|
return format_html('<a href="{}" target="_blank">{}</a>', url, _("View File"))
|
|
|
|
def registration_front_preview(self, obj):
|
|
return self._file_preview(obj.registration_front)
|
|
registration_front_preview.short_description = _("Registration Front Preview")
|
|
|
|
def registration_back_preview(self, obj):
|
|
return self._file_preview(obj.registration_back)
|
|
registration_back_preview.short_description = _("Registration Back Preview")
|
|
|
|
def driver_license_front_preview(self, obj):
|
|
return self._file_preview(obj.driver_license_front)
|
|
driver_license_front_preview.short_description = _("Driver License Front Preview")
|
|
|
|
def driver_license_back_preview(self, obj):
|
|
return self._file_preview(obj.driver_license_back)
|
|
driver_license_back_preview.short_description = _("Driver License Back Preview")
|
|
|
|
fieldsets = (
|
|
(None, {'fields': ('owner', 'truck_type_link', 'is_approved')}),
|
|
(_('Details (EN)'), {'fields': ('truck_type', 'model', 'load_capacity', 'color', 'year', 'plate_no', 'registration_expiry_date')}),
|
|
(_('Details (AR)'), {'fields': ('truck_type_ar', 'model_ar', 'load_capacity_ar', 'color_ar')}),
|
|
(_('Pictures & Documents'), {'fields': (
|
|
'truck_picture', 'truck_picture_preview',
|
|
'registration_front', 'registration_front_preview',
|
|
'registration_back', 'registration_back_preview',
|
|
'driver_license_front', 'driver_license_front_preview',
|
|
'driver_license_back', 'driver_license_back_preview'
|
|
)}),
|
|
)
|
|
|
|
@admin.register(Shipment)
|
|
class ShipmentAdmin(admin.ModelAdmin):
|
|
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__description', 'truck_owner__username')
|
|
|
|
@admin.register(Message)
|
|
class MessageAdmin(admin.ModelAdmin):
|
|
list_display = ('shipment', 'sender', 'timestamp')
|
|
search_fields = ('content', 'sender__username')
|
|
|
|
@admin.register(WhatsAppConfig)
|
|
class WhatsAppConfigAdmin(admin.ModelAdmin):
|
|
list_display = ('__str__', 'is_active')
|
|
|
|
def has_add_permission(self, request):
|
|
# Only allow one configuration record
|
|
if self.model.objects.exists():
|
|
return False
|
|
return super().has_add_permission(request)
|
|
|
|
def get_urls(self):
|
|
urls = super().get_urls()
|
|
custom_urls = [
|
|
path('send-test/', self.admin_site.admin_view(self.send_test_message), name='send_test_whatsapp'),
|
|
]
|
|
return custom_urls + urls
|
|
|
|
def send_test_message(self, request):
|
|
if request.method == 'POST':
|
|
phone = request.POST.get('phone')
|
|
message = request.POST.get('message')
|
|
if phone and message:
|
|
success = send_whatsapp_message(phone, message)
|
|
if success:
|
|
self.message_user(request, _("Test message sent successfully!"))
|
|
else:
|
|
self.message_user(request, _("Failed to send test message. Check your API credentials and logs."), level=messages.ERROR)
|
|
return HttpResponseRedirect("../")
|
|
|
|
context = dict(
|
|
self.admin_site.each_context(request),
|
|
title=_("Send Test WhatsApp Message"),
|
|
opts=self.model._meta,
|
|
)
|
|
return render(request, "admin/core/whatsapp_test.html", context)
|
|
|
|
@admin.register(AppSetting)
|
|
class AppSettingAdmin(admin.ModelAdmin):
|
|
list_display = ('app_name', 'contact_phone', 'contact_email', 'subscription_enabled')
|
|
fieldsets = (
|
|
(None, {'fields': ('app_name', 'logo', 'slogan')}),
|
|
(_('Contact Information'), {'fields': ('contact_phone', 'contact_email', 'contact_address')}),
|
|
(_('Legal'), {'fields': ('registration_number', 'tax_number', 'terms_of_service', 'privacy_policy')}),
|
|
(_('Subscription Status'), {'fields': ('subscription_enabled', 'thawani_enabled')}),
|
|
(_('Shipper Subscription Fees'), {'fields': ('shipper_monthly_fee', 'shipper_annual_fee')}),
|
|
(_('Truck Owner Subscription Fees'), {'fields': ('truck_owner_monthly_fee', 'truck_owner_annual_fee')}),
|
|
)
|
|
|
|
def has_add_permission(self, request):
|
|
# Only allow one configuration record
|
|
if self.model.objects.exists():
|
|
return False
|
|
return super().has_add_permission(request)
|
|
|
|
@admin.register(Banner)
|
|
class BannerAdmin(admin.ModelAdmin):
|
|
list_display = ('title', 'order', 'is_active', 'created_at')
|
|
list_editable = ('order', 'is_active')
|
|
search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar')
|
|
|
|
@admin.register(HomeSection)
|
|
class HomeSectionAdmin(admin.ModelAdmin):
|
|
list_display = ('title', 'section_type', 'order', 'is_active')
|
|
list_editable = ('order', 'is_active')
|
|
list_filter = ('section_type', 'is_active', 'background_color')
|
|
search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar', 'content', 'content_ar') |