new chnages to the sale and purchase report and chnages to the charts label colors
This commit is contained in:
parent
9cfccf5f7e
commit
86792930f0
@ -1308,6 +1308,7 @@ urlpatterns = [
|
||||
views.car_sale_report_view,
|
||||
name="car-sale-report",
|
||||
),
|
||||
path('<slug:dealer_slug>/car-sale-report/get_filtered_choices/',views.get_filtered_choices,name='get_filtered_choices'),
|
||||
path('car-sale-report/<slug:dealer_slug>/csv/', views.car_sale_report_csv_export, name='car-sale-report-csv-export'),
|
||||
|
||||
path('feature/recall/', views.RecallListView.as_view(), name='recall_list'),
|
||||
|
||||
@ -11030,55 +11030,76 @@ class InventoryListView(InventoryListViewBase):
|
||||
permission_required = ["django_ledger.view_purchaseordermodel"]
|
||||
|
||||
@login_required
|
||||
def purchase_report_view(request,dealer_slug):
|
||||
def purchase_report_view(request, dealer_slug):
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
pos = request.entity.get_purchase_orders()
|
||||
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
pos = pos.filter(created__date__gte=start_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
pos = pos.filter(created__date__lte=end_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
data = []
|
||||
total_po_amount=0
|
||||
total_po_cars=0
|
||||
total_po_amount = 0
|
||||
total_po_cars = 0
|
||||
|
||||
for po in pos:
|
||||
items = [{"total":x.total_amount,"q":x.quantity} for x in po.get_itemtxs_data()[0].all()]
|
||||
items = [{"total": x.total_amount, "q": x.quantity} for x in po.get_itemtxs_data()[0].all()]
|
||||
|
||||
po_amount=0
|
||||
po_quantity=0
|
||||
for item in items:
|
||||
po_amount+=item["total"]
|
||||
po_quantity+=item["q"]
|
||||
po_amount = sum(item["total"] for item in items)
|
||||
po_quantity = sum(item["q"] for item in items)
|
||||
|
||||
total_po_amount+=po_amount
|
||||
total_po_cars+=po_quantity
|
||||
bills=po.get_po_bill_queryset()
|
||||
vendors=set([bill.vendor.vendor_name for bill in bills])
|
||||
total_po_amount += po_amount
|
||||
total_po_cars += po_quantity
|
||||
|
||||
bills = po.get_po_bill_queryset()
|
||||
vendors = set([bill.vendor.vendor_name for bill in bills])
|
||||
vendors_str = ", ".join(sorted(list(vendors))) if vendors else "N/A"
|
||||
data.append({"po_number":po.po_number,"po_created":po.created,"po_status":po.po_status,"po_fulfilled_date":po.date_fulfilled,"po_amount":po_amount,
|
||||
"po_quantity":po_quantity,"vendors_str":vendors_str})
|
||||
|
||||
data.append({
|
||||
"po_number": po.po_number,
|
||||
"po_created": po.created,
|
||||
"po_status": po.po_status,
|
||||
"po_fulfilled_date": po.date_fulfilled,
|
||||
"po_amount": po_amount,
|
||||
"po_quantity": po_quantity,
|
||||
"vendors_str": vendors_str
|
||||
})
|
||||
|
||||
current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
context={
|
||||
"dealer":request.entity.name,
|
||||
"time":current_time,
|
||||
"data":data,
|
||||
"total_po_amount":total_po_amount,
|
||||
"total_po_cars":total_po_cars,
|
||||
"current_time":current_time
|
||||
|
||||
context = {
|
||||
"dealer": request.entity.name,
|
||||
"time": current_time,
|
||||
"data": data,
|
||||
"total_po_amount": total_po_amount,
|
||||
"total_po_cars": total_po_cars,
|
||||
"current_time": current_time,
|
||||
"start_date": start_date_str,
|
||||
"end_date": end_date_str,
|
||||
}
|
||||
|
||||
return render(request, 'ledger/reports/purchase_report.html', context)
|
||||
|
||||
|
||||
return render(request,'ledger/reports/purchase_report.html',context)
|
||||
|
||||
|
||||
def purchase_report_csv_export(request,dealer_slug):
|
||||
def purchase_report_csv_export(request, dealer_slug):
|
||||
response = HttpResponse(content_type='text/csv')
|
||||
|
||||
|
||||
current_time = timezone.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
filename = f"purchase_report_{dealer_slug}_{current_time}.csv"
|
||||
response['Content-Disposition'] = f'attachment; filename="{filename}"'
|
||||
|
||||
writer = csv.writer(response)
|
||||
|
||||
|
||||
header = [
|
||||
'PO Number',
|
||||
'Created Date',
|
||||
@ -11089,22 +11110,38 @@ def purchase_report_csv_export(request,dealer_slug):
|
||||
'Vendors'
|
||||
]
|
||||
writer.writerow(header)
|
||||
|
||||
pos = request.entity.get_purchase_orders()
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
pos = pos.filter(created__date__gte=start_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
pos = pos.filter(created__date__lte=end_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
for po in pos:
|
||||
po_amount = 0
|
||||
po_quantity = 0
|
||||
items = [{"total":x.total_amount,"q":x.quantity} for x in po.get_itemtxs_data()[0].all()]
|
||||
items = [{"total": x.total_amount, "q": x.quantity} for x in po.get_itemtxs_data()[0].all()]
|
||||
|
||||
for item in items:
|
||||
po_amount += item["total"]
|
||||
po_quantity += item["q"]
|
||||
|
||||
bills = po.get_po_bill_queryset()
|
||||
vendors = set([bill.vendor.vendor_name for bill in bills ])
|
||||
vendors = set([bill.vendor.vendor_name for bill in bills])
|
||||
vendors_str = ", ".join(sorted(list(vendors))) if vendors else "N/A"
|
||||
|
||||
|
||||
writer.writerow([
|
||||
po.po_number,
|
||||
po.created.strftime("%Y-%m-%d %H:%M:%S") if po.created else '',
|
||||
@ -11117,22 +11154,22 @@ def purchase_report_csv_export(request,dealer_slug):
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@login_required
|
||||
def car_sale_report_view(request, dealer_slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
vat = models.VatRate.objects.filter(dealer=dealer,is_active=True).first()
|
||||
VAT_RATE=vat.rate
|
||||
vat = models.VatRate.objects.filter(dealer=dealer, is_active=True).first()
|
||||
VAT_RATE = vat.rate if vat else 0
|
||||
|
||||
cars_sold = models.Car.objects.filter(dealer=dealer, status='sold')
|
||||
|
||||
|
||||
# Get filter parameters from the request
|
||||
selected_make = request.GET.get('make')
|
||||
selected_model = request.GET.get('model')
|
||||
selected_serie = request.GET.get('serie')
|
||||
selected_year = request.GET.get('year')
|
||||
selected_stock_type=request.GET.get('stock_type')
|
||||
selected_stock_type = request.GET.get('stock_type')
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
# Apply filters to the queryset
|
||||
if selected_make:
|
||||
@ -11145,62 +11182,122 @@ def car_sale_report_view(request, dealer_slug):
|
||||
cars_sold = cars_sold.filter(year=selected_year)
|
||||
if selected_stock_type:
|
||||
cars_sold = cars_sold.filter(stock_type=selected_stock_type)
|
||||
|
||||
# Corrected: Apply date filters using the 'sold_date' field
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
cars_sold = cars_sold.filter(sold_date__gte=start_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
cars_sold = cars_sold.filter(sold_date__lte=end_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
|
||||
# # Calculate summary data for the filtered results
|
||||
total_cars_sold=cars_sold.count()
|
||||
# Calculate summary data for the filtered results
|
||||
total_cars_sold = cars_sold.count()
|
||||
total_revenue_from_cars = cars_sold.aggregate(
|
||||
total=Sum(F('marked_price') - F('discount_amount'))
|
||||
)['total'] or 0
|
||||
|
||||
total_vat_on_cars=cars_sold.annotate(
|
||||
total_vat_on_cars = cars_sold.annotate(
|
||||
final_price=F('marked_price') - F('discount_amount')).aggregate(
|
||||
total=Sum(F('final_price') * VAT_RATE))['total'] or 0
|
||||
|
||||
total_revenue_from_additonals=sum([car.get_additional_services()['total'] for car in cars_sold])
|
||||
total_vat_from_additonals=sum([car.get_additional_services()['services_vat'] for car in cars_sold])
|
||||
total_vat_collected = total_vat_on_cars+total_vat_from_additonals
|
||||
total_revenue_collected=total_revenue_from_cars+total_revenue_from_additonals
|
||||
total_discount = sum([car.discount for car in cars_sold])
|
||||
total_revenue_from_additonals = sum([car.get_additional_services()['total'] for car in cars_sold])
|
||||
total_vat_from_additonals = sum([car.get_additional_services()['services_vat'] for car in cars_sold])
|
||||
total_vat_collected = total_vat_on_cars + total_vat_from_additonals
|
||||
total_revenue_collected = total_revenue_from_cars + total_revenue_from_additonals
|
||||
|
||||
total_discount = cars_sold.aggregate(total=Sum('discount_amount'))['total'] or 0
|
||||
|
||||
current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# Get distinct values for filter dropdowns
|
||||
# Get distinct makes for the initial dropdown, other dropdowns will be populated via AJAX
|
||||
base_sold_cars_queryset = models.Car.objects.filter(dealer=dealer, status='sold')
|
||||
makes =base_sold_cars_queryset.values_list('id_car_make__name', flat=True).distinct()
|
||||
models_qs =base_sold_cars_queryset.values_list('id_car_model__name', flat=True).distinct()
|
||||
|
||||
series =base_sold_cars_queryset.values_list('id_car_serie__name', flat=True).distinct()
|
||||
stock_types=base_sold_cars_queryset.values_list('stock_type', flat=True).distinct()
|
||||
years = base_sold_cars_queryset.values_list('year', flat=True).distinct().order_by('-year')
|
||||
makes = base_sold_cars_queryset.values_list('id_car_make__name', flat=True).distinct().order_by('id_car_make__name')
|
||||
|
||||
context = {
|
||||
'cars_sold': cars_sold,
|
||||
'total_cars_sold':total_cars_sold,
|
||||
'total_cars_sold': total_cars_sold,
|
||||
'current_time': current_time,
|
||||
'dealer': dealer,
|
||||
'total_revenue_from_cars': total_revenue_from_cars,
|
||||
'total_revenue_from_additonals':total_revenue_from_additonals,
|
||||
'total_revenue_from_additonals': total_revenue_from_additonals,
|
||||
'total_revenue_collected': total_revenue_collected,
|
||||
'total_vat_on_cars':total_vat_on_cars,
|
||||
'total_vat_from_additonals':total_vat_from_additonals,
|
||||
'total_vat_collected':total_vat_collected,
|
||||
'total_vat_on_cars': total_vat_on_cars,
|
||||
'total_vat_from_additonals': total_vat_from_additonals,
|
||||
'total_vat_collected': total_vat_collected,
|
||||
'total_discount': total_discount,
|
||||
'makes': makes,
|
||||
'models': models_qs,
|
||||
'series': series,
|
||||
'years': years,
|
||||
'stock_types':stock_types,
|
||||
'selected_make': selected_make,
|
||||
'selected_model': selected_model,
|
||||
'selected_serie': selected_serie,
|
||||
'selected_year': selected_year,
|
||||
'selected_stock_type':selected_stock_type,
|
||||
'selected_stock_type': selected_stock_type,
|
||||
'start_date': start_date_str,
|
||||
'end_date': end_date_str,
|
||||
}
|
||||
|
||||
return render(request, 'ledger/reports/car_sale_report.html', context)
|
||||
|
||||
|
||||
### 2. Updated `get_filtered_choices`
|
||||
|
||||
@login_required
|
||||
def get_filtered_choices(request, dealer_slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
|
||||
# Get all filter parameters from the request
|
||||
selected_make = request.GET.get('make')
|
||||
selected_model = request.GET.get('model')
|
||||
selected_serie = request.GET.get('serie')
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
# Start with the base queryset
|
||||
queryset = models.Car.objects.filter(dealer=dealer, status='sold')
|
||||
|
||||
# Apply filters based on what is selected
|
||||
if selected_make:
|
||||
queryset = queryset.filter(id_car_make__name=selected_make)
|
||||
|
||||
if selected_model:
|
||||
queryset = queryset.filter(id_car_model__name=selected_model)
|
||||
|
||||
if selected_serie:
|
||||
queryset = queryset.filter(id_car_serie__name=selected_serie)
|
||||
|
||||
# Corrected: Apply date filters to the AJAX queryset
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
queryset = queryset.filter(sold_date__gte=start_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
queryset = queryset.filter(sold_date__lte=end_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
data = {
|
||||
'models': list(queryset.values_list('id_car_model__name', flat=True).distinct().order_by('id_car_model__name')),
|
||||
'series': list(queryset.values_list('id_car_serie__name', flat=True).distinct().order_by('id_car_serie__name')),
|
||||
'years': list(queryset.values_list('year', flat=True).distinct().order_by('-year')),
|
||||
'stock_types': list(queryset.values_list('stock_type', flat=True).distinct().order_by('stock_type'))
|
||||
}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
### 3. Updated `car_sale_report_csv_export`
|
||||
|
||||
@login_required
|
||||
def car_sale_report_csv_export(request, dealer_slug):
|
||||
response = HttpResponse(content_type='text/csv')
|
||||
@ -11229,6 +11326,8 @@ def car_sale_report_csv_export(request, dealer_slug):
|
||||
selected_serie = request.GET.get('serie')
|
||||
selected_year = request.GET.get('year')
|
||||
selected_stock_type = request.GET.get('stock_type')
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
if selected_make:
|
||||
cars_sold = cars_sold.filter(id_car_make__name=selected_make)
|
||||
@ -11240,15 +11339,28 @@ def car_sale_report_csv_export(request, dealer_slug):
|
||||
cars_sold = cars_sold.filter(year=selected_year)
|
||||
if selected_stock_type:
|
||||
cars_sold = cars_sold.filter(stock_type=selected_stock_type)
|
||||
|
||||
# Corrected: Apply date filters for CSV export
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
cars_sold = cars_sold.filter(sold_date__gte=start_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
cars_sold = cars_sold.filter(sold_date__lte=end_date)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
# Write the data for the filtered cars
|
||||
for car in cars_sold:
|
||||
# Fetching data for the additional services
|
||||
additional_services = car.get_additional_services()
|
||||
services_total_price = additional_services['total']
|
||||
services_vat_amount = additional_services['services_vat']
|
||||
|
||||
# Checking for the invoice number to avoid errors on cars without one
|
||||
invoice_number = None
|
||||
sold_date = None
|
||||
if car.invoice:
|
||||
@ -11268,18 +11380,17 @@ def car_sale_report_csv_export(request, dealer_slug):
|
||||
sold_date.strftime("%Y-%m-%d %H:%M:%S") if sold_date else '',
|
||||
car.cost_price,
|
||||
car.marked_price,
|
||||
car.discount, # Ensure this property returns a number
|
||||
car.final_price, # Selling Price without VAT
|
||||
car.vat_amount, # VAT on the car
|
||||
services_total_price, # Total services without VAT
|
||||
services_vat_amount, # VAT on services
|
||||
car.discount_amount,
|
||||
car.final_price,
|
||||
car.vat_amount,
|
||||
services_total_price,
|
||||
services_vat_amount,
|
||||
car.final_price_plus_services_plus_vat,
|
||||
invoice_number,
|
||||
])
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@login_required
|
||||
# @permission_required('inventory.view_staff')
|
||||
def staff_password_reset_view(request, dealer_slug, user_pk):
|
||||
|
||||
Binary file not shown.
@ -13191,20 +13191,14 @@ msgid "Total cars"
|
||||
msgstr "إجمالي السيارات"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:113
|
||||
#, fuzzy
|
||||
#| msgid "Subscriptions"
|
||||
msgid "Plan & Subscription"
|
||||
msgstr "الاشتراكات"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:125
|
||||
#, fuzzy
|
||||
#| msgid "Car Details"
|
||||
msgid "Company Details"
|
||||
msgstr "تفاصيل السيارة"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:137
|
||||
#, fuzzy
|
||||
#| msgid "Car Transfer"
|
||||
msgid "Car Brands"
|
||||
msgstr "نقل السيارة"
|
||||
|
||||
@ -13252,8 +13246,6 @@ msgid "Upgrade Plan"
|
||||
msgstr "ترقية الخطة"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:212
|
||||
#, fuzzy
|
||||
#| msgid "Manage Groups & Permissions"
|
||||
msgid "Manage Users & Cars"
|
||||
msgstr "إدارة المجموعات والأذونات"
|
||||
|
||||
@ -13269,20 +13261,14 @@ msgid "Contact support to increase your limits"
|
||||
msgstr ""
|
||||
|
||||
#: templates/dealers/dealer_detail.html:258
|
||||
#, fuzzy
|
||||
#| msgid "Client Information"
|
||||
msgid "Contact Information"
|
||||
msgstr "معلومات العميل"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:286
|
||||
#, fuzzy
|
||||
#| msgid "User Information"
|
||||
msgid "VAT Information"
|
||||
msgstr "معلومات المستخدم"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:292
|
||||
#, fuzzy
|
||||
#| msgid "Updated At"
|
||||
msgid "Update VAT"
|
||||
msgstr "تم التحديث"
|
||||
|
||||
@ -13291,8 +13277,6 @@ msgid "Makes you are selling"
|
||||
msgstr "الماركات التي تبيعها"
|
||||
|
||||
#: templates/dealers/dealer_detail.html:321
|
||||
#, fuzzy
|
||||
#| msgid "No staff member selected."
|
||||
msgid "No car makes selected."
|
||||
msgstr "لم يتم اختيار أي عضو من الفريق."
|
||||
|
||||
|
||||
@ -122,7 +122,7 @@
|
||||
data: {{ monthly_cars_sold_json|safe }},
|
||||
backgroundColor: primaryColor,
|
||||
borderColor: primaryColor,
|
||||
borderWidth: 1
|
||||
borderWidth: 1,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
@ -193,7 +193,7 @@
|
||||
plugins: {
|
||||
legend: {
|
||||
display: true,
|
||||
labels: { color: '#495057', boxWidth: 20 }
|
||||
labels: { boxWidth: 20 }
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(33, 37, 41, 0.9)',
|
||||
@ -250,7 +250,7 @@
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'right',
|
||||
labels: { color: '#343a40', font: { size: 14 } }
|
||||
labels: { font: { size: 14 } }
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(33, 37, 41, 0.9)',
|
||||
@ -349,7 +349,7 @@
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'right',
|
||||
labels: { color: '#343a40', font: { size: 14 } }
|
||||
labels: { font: { size: 14 } }
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(33, 37, 41, 0.9)',
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{% load static %}
|
||||
{% load tenhal_tag %}
|
||||
{% block title %}
|
||||
{{ _("Car Sale Report") |capfirst }}
|
||||
{{ _("Car Sale Report")|capfirst }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<style>
|
||||
@ -15,7 +15,7 @@
|
||||
}
|
||||
.summary-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.summary-card .card-body {
|
||||
display: flex;
|
||||
@ -32,9 +32,7 @@
|
||||
.summary-card .card-text {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
<div class="container-fluid report-container">
|
||||
<header class="report-header text-center">
|
||||
@ -47,11 +45,19 @@
|
||||
<p class="text-muted">{% trans 'Report Date' %}: {{ current_time }}</p>
|
||||
</header>
|
||||
<main>
|
||||
<section id="filters" class="mb-5 p-4 rounded border border-primary">
|
||||
<section id="filters" class="mb-5 p-4 rounded border border-primary">
|
||||
<h2 class="section-heading mb-4">
|
||||
{% trans 'Filters' %} <i class="fas fa-sliders-h ms-2"></i>
|
||||
</h2>
|
||||
<form method="GET" class="row g-3 align-items-end">
|
||||
<form method="GET" class="row g-3 align-items-end" data-filter-url="{% url 'get_filtered_choices' dealer_slug=dealer.slug %}">
|
||||
<div class="col-md-6">
|
||||
<label for="start_date" class="form-label">{% trans 'Start Date' %}</label>
|
||||
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ start_date }}">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="end_date" class="form-label">{% trans 'End Date' %}</label>
|
||||
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ end_date }}">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="make-select" class="form-label">{% trans 'Make' %}</label>
|
||||
<select id="make-select" name="make" class="form-select">
|
||||
@ -65,44 +71,36 @@
|
||||
<label for="model-select" class="form-label">{% trans 'Model' %}</label>
|
||||
<select id="model-select" name="model" class="form-select">
|
||||
<option value="">{% trans 'All Models' %}</option>
|
||||
{% for model in models %}
|
||||
<option value="{{ model }}"
|
||||
{% if model == selected_model %}selected{% endif %}>{{ model }}</option>
|
||||
{% endfor %}
|
||||
{% if selected_model %}
|
||||
<option value="{{ selected_model }}" selected>{{ selected_model }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="serie-select" class="form-label">{% trans 'Serie' %}</label>
|
||||
<select id="serie-select" name="serie" class="form-select">
|
||||
<option value="">{% trans 'All Series' %}</option>
|
||||
{% for serie in series %}
|
||||
<option value="{{ serie }}"
|
||||
{% if serie == selected_serie %}selected{% endif %}>{{ serie }}</option>
|
||||
{% endfor %}
|
||||
{% if selected_serie %}
|
||||
<option value="{{ selected_serie }}" selected>{{ selected_serie }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="year-select" class="form-label">{% trans 'Year' %}</label>
|
||||
<select id="year-select" name="year" class="form-select">
|
||||
<option value="">{% trans 'All Years' %}</option>
|
||||
{% for year in years %}
|
||||
<option value="{{ year }}"
|
||||
{% if year|stringformat:"s" == selected_year %}selected{% endif %}>
|
||||
{{ year }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% if selected_year %}
|
||||
<option value="{{ selected_year }}" selected>{{ selected_year }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="stock_type-select" class="form-label">{% trans 'Stock Types' %}</label>
|
||||
<select id="stock_type-select" name="stock_type" class="form-select">
|
||||
<option value="">{% trans 'Stock Types' %}</option>
|
||||
{% for stock_type in stock_types %}
|
||||
<option value="{{ stock_type }}"
|
||||
{% if stock_type == selected_stock_type %}selected{% endif %}>
|
||||
{{ stock_type }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
<option value="">{% trans 'All Stock Types' %}</option>
|
||||
{% if selected_stock_type %}
|
||||
<option value="{{ selected_stock_type }}" selected>{{ selected_stock_type }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
@ -111,27 +109,8 @@
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<!---->
|
||||
{% comment %} 'cars_sold': cars_sold,
|
||||
'current_time': current_time,
|
||||
'dealer': dealer,
|
||||
'total_revenue_from_cars': total_revenue_from_cars,
|
||||
'total_revenue_from_additonals':total_revenue_from_additonals,
|
||||
'total_revenue_collected': total_revenue_collected,
|
||||
'total_vat_on_cars':total_vat_on_cars,
|
||||
'total_vat_from_additonals':total_vat_from_additonals,
|
||||
'total_vat_collected':total_vat_collected,
|
||||
'total_discount': total_discount,
|
||||
'makes': makes,
|
||||
'models': models_qs,
|
||||
'series': series,
|
||||
'years': years,
|
||||
'selected_make': selected_make,
|
||||
'selected_model': selected_model,
|
||||
'selected_serie': selected_serie,
|
||||
'selected_year': selected_year, {% endcomment %}
|
||||
<!---->
|
||||
</section>
|
||||
|
||||
<section id="summary" class="mb-5">
|
||||
<h2 class="section-heading mb-4 border-start border-5 border-primary p-2">{% trans 'Report Summary' %}</h2>
|
||||
<div class="row g-4">
|
||||
@ -166,7 +145,7 @@
|
||||
<span>{% trans 'Total Revenue' %}<span class="icon-saudi_riyal"></span></span>
|
||||
</h5>
|
||||
<p class="card-text">
|
||||
<span>{{ total_revenue_collected |floatformat:2 }} <span class="icon-saudi_riyal"></span></span>
|
||||
<span>{{ total_revenue_collected|floatformat:2 }} <span class="icon-saudi_riyal"></span></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -302,14 +281,82 @@
|
||||
<span>{{ car.final_price_plus_services_plus_vat|floatformat:2 }}<span class="icon-saudi_riyal"></span></span>
|
||||
</td>
|
||||
<td class="fs-9">
|
||||
<span>{{ car.invoice.invoice_number }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
{% endblock %}
|
||||
<span>{{ car.invoice.invoice_number }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const makeSelect = document.getElementById('make-select');
|
||||
const modelSelect = document.getElementById('model-select');
|
||||
const serieSelect = document.getElementById('serie-select');
|
||||
const yearSelect = document.getElementById('year-select');
|
||||
const stockTypeSelect = document.getElementById('stock_type-select');
|
||||
const startDateInput = document.getElementById('start_date');
|
||||
const endDateInput = document.getElementById('end_date');
|
||||
const form = document.querySelector('form');
|
||||
const baseUrl = form.dataset.filterUrl;
|
||||
|
||||
function updateOptions(selectElement, options, currentValue) {
|
||||
const name = selectElement.name.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
||||
selectElement.innerHTML = `<option value="">All ${name}s</option>`;
|
||||
options.forEach(option => {
|
||||
const newOption = document.createElement('option');
|
||||
newOption.value = option;
|
||||
newOption.textContent = option;
|
||||
if (String(option) === String(currentValue)) {
|
||||
newOption.selected = true;
|
||||
}
|
||||
selectElement.appendChild(newOption);
|
||||
});
|
||||
}
|
||||
|
||||
function fetchAndUpdateDropdowns() {
|
||||
const make = makeSelect.value;
|
||||
const model = modelSelect.value;
|
||||
const serie = serieSelect.value;
|
||||
const start_date = startDateInput.value;
|
||||
const end_date = endDateInput.value;
|
||||
|
||||
// Corrected: Include start_date and end_date in the AJAX URL
|
||||
const url = `${baseUrl}?make=${make}&model=${model}&serie=${serie}&start_date=${start_date}&end_date=${end_date}`;
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
updateOptions(modelSelect, data.models, model);
|
||||
updateOptions(serieSelect, data.series, serie);
|
||||
updateOptions(yearSelect, data.years, yearSelect.value);
|
||||
updateOptions(stockTypeSelect, data.stock_types, stockTypeSelect.value);
|
||||
})
|
||||
.catch(error => console.error('Error fetching filtered choices:', error));
|
||||
}
|
||||
|
||||
// Event listeners for all filter elements
|
||||
makeSelect.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
modelSelect.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
serieSelect.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
yearSelect.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
stockTypeSelect.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
startDateInput.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
endDateInput.addEventListener('change', fetchAndUpdateDropdowns);
|
||||
|
||||
// Initial call to populate other dropdowns on page load
|
||||
fetchAndUpdateDropdowns();
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% block title %}
|
||||
{{ _("Car Purchase Report") |capfirst }}
|
||||
{{ _("Car Purchase Report")|capfirst }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<style>
|
||||
@ -45,6 +45,26 @@
|
||||
</p>
|
||||
<p class="text-muted">{% trans "Report Date" %}: {{ current_time }}</p>
|
||||
</header>
|
||||
<section id="filters" class="mb-5 p-4 rounded border border-primary">
|
||||
<h2 class="section-heading mb-4">
|
||||
{% trans 'Filters' %} <i class="fas fa-sliders-h ms-2"></i>
|
||||
</h2>
|
||||
<form method="GET" class="row g-3 align-items-end">
|
||||
<div class="col-md-3">
|
||||
<label for="start_date" class="form-label">{% trans 'Start Date' %}</label>
|
||||
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ start_date|default_if_none:'' }}">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="end_date" class="form-label">{% trans 'End Date' %}</label>
|
||||
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ end_date|default_if_none:'' }}">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
<i class="fas fa-filter me-2"></i>{% trans 'Filter' %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<main>
|
||||
<section id="summary" class="mb-5">
|
||||
<h2 class="section-heading mb-4 border-start border-3 border-primary p-2">{% trans 'Report Summary' %}</h2>
|
||||
@ -84,7 +104,7 @@
|
||||
<section id="purchase-details" class="mb-3">
|
||||
<h2 class="section-heading border-start border-3 border-primary p-2">{% trans 'Detailed Purchase List' %}</h2>
|
||||
<div class="d-flex justify-content-end mb-3 d-print-none">
|
||||
<a href="{% url 'purchase-report-csv-export' request.dealer.slug %}"
|
||||
<a href="{% url 'purchase-report-csv-export' request.dealer.slug %}?start_date={{ start_date|default_if_none:'' }}&end_date={{ end_date|default_if_none:'' }}"
|
||||
class="btn btn-phoenix-primary">
|
||||
<i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %}
|
||||
</a>
|
||||
@ -126,4 +146,4 @@
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -122,7 +122,7 @@
|
||||
<div class="row d-flex justify-content-center align-items-center mt-5 mb-3 ms-6 ps-3">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{% if not items.car %}
|
||||
{% if not items %}
|
||||
{% url "car_add" request.dealer.slug as create_car_url %}
|
||||
{% include "message-illustration.html" with value1="Please add at least one car or complete the car info before creating a quotation." value2="Add car" message_image="images/logos/no-content-new.jpg" url=create_car_url %}
|
||||
{% endif %}
|
||||
|
||||
@ -128,7 +128,9 @@
|
||||
<h2 class="mb-7">{{ _("Pricing") }}</h2>
|
||||
<div class="row g-3 mb-7 mb-lg-11">
|
||||
{% for plan in plan_list %}
|
||||
<div class="col-lg-3">
|
||||
|
||||
<div class="col-lg-4" onclick="window.location='{% url "account_signup" %}';">
|
||||
|
||||
<input type="radio"
|
||||
class="btn-check"
|
||||
name="selected_plan"
|
||||
@ -156,7 +158,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user