dashboards and sale report

This commit is contained in:
Faheedkhan 2025-08-17 13:56:56 +03:00
parent 5ff9b4c573
commit d997a0ae50
12 changed files with 1052 additions and 691 deletions

View File

@ -583,6 +583,7 @@ class AdditionalServices(models.Model, LocalizedNameMixin):
"price_": str(self.price_), "price_": str(self.price_),
"taxable": self.taxable, "taxable": self.taxable,
"uom": self.uom, "uom": self.uom,
"service_tax":str(self.service_tax)
} }
@property @property
@ -593,6 +594,13 @@ class AdditionalServices(models.Model, LocalizedNameMixin):
if self.taxable if self.taxable
else self.price else self.price
) )
@property
def service_tax(self):
vat = VatRate.objects.filter(dealer=self.dealer, is_active=True).first()
return (
Decimal(self.price * vat.rate)
)
class Meta: class Meta:
verbose_name = _("Additional Services") verbose_name = _("Additional Services")
@ -865,19 +873,64 @@ class Car(Base):
# #
@property @property
def get_additional_services_amount(self): def get_additional_services_amount(self):
return sum([Decimal(x.price) for x in self.additional_services.all()])
@property
def get_additional_services_amount_(self):
return sum([Decimal(x.price_) for x in self.additional_services.all()]) return sum([Decimal(x.price_) for x in self.additional_services.all()])
@property
def get_additional_services_vat(self):
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
return sum([Decimal((x.price)*(vat.rate)) for x in self.additional_services.all()])
def get_additional_services(self): def get_additional_services(self):
return {"services": [x for x in self.additional_services.all()],"total":self.get_additional_services_amount} vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
return {"services": [[x,(x.price)*(vat.rate)] for x in self.additional_services.all()],
"total_":self.get_additional_services_amount_,
"total":self.get_additional_services_amount,
"services_vat":self.get_additional_services_vat}
@property @property
def final_price(self):
return Decimal(self.marked_price -self.discount)
@property
def vat_amount(self): def vat_amount(self):
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first() vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
return Decimal(self.marked_price) * (vat.rate / 100) return Decimal(self.final_price) * (vat.rate)
@property @property
def total_vat(self): def total_services_and_car_vat(self):
return Decimal(self.marked_price) + Decimal(self.vat_amount) return self.vat_amount+self.get_additional_services()['services_vat']
@property
def final_price_plus_vat(self):
return Decimal(self.final_price) + Decimal(self.vat_amount)
@property
def final_price_plus_services_plus_vat(self):
return Decimal(self.final_price_plus_vat) + Decimal(self.get_additional_services()['total_']) #total services with vat and car_sell price with vat
# to be used after invoice is created
@property
def invoice(self):
return self.item_model.invoicemodel_set.first() or None
@property
def estimate(self):
return getattr(self.invoice,'ce_model',None)
@property
def discount(self):
if not self.estimate:
return 0
try:
instance = ExtraInfo.objects.get(
dealer=self.dealer,
content_type=ContentType.objects.get_for_model(EstimateModel),
object_id=self.estimate.pk,
)
return Decimal(instance.data.get('discount',0))
except ExtraInfo.DoesNotExist:
return Decimal(0)
# def get_discount_amount(self,estimate,user): # def get_discount_amount(self,estimate,user):
# try: # try:
# instance = models.ExtraInfo.objects.get( # instance = models.ExtraInfo.objects.get(

View File

@ -43,7 +43,7 @@ urlpatterns = [
#dashboards #dashboards
path("dashboards/dealer/", views.DealerDashboard.as_view(),name="dealer_dashboard"), path("dashboards/dealer/", views.DealerDashboard,name="dealer_dashboard"),
path( "dashboards/manager/", views.ManagerDashboard.as_view(),name="manager_dashboard"), path( "dashboards/manager/", views.ManagerDashboard.as_view(),name="manager_dashboard"),
path("dashboards/sales/", views.SalesDashboard.as_view(), name="sales_dashboard"), path("dashboards/sales/", views.SalesDashboard.as_view(), name="sales_dashboard"),
path("dashboards/accountant/", views.AccountantDashboard.as_view(), name="accountant_dashboard"), path("dashboards/accountant/", views.AccountantDashboard.as_view(), name="accountant_dashboard"),
@ -775,6 +775,7 @@ urlpatterns = [
views.EstimateDetailView.as_view(), views.EstimateDetailView.as_view(),
name="estimate_detail", name="estimate_detail",
), ),
path('<slug:dealer_slug>/sales/estimates/print/<uuid:pk>/', views.EstimatePrintView.as_view(), name='estimate_print'),
path( path(
"<slug:dealer_slug>/sales/estimates/create/", "<slug:dealer_slug>/sales/estimates/create/",
views.create_estimate, views.create_estimate,

View File

@ -1288,18 +1288,24 @@ def get_finance_data(estimate,dealer):
) )
discount = extra_info.data.get("discount", 0) discount = extra_info.data.get("discount", 0)
discount = Decimal(discount) discount = Decimal(discount)
vat_amount = car.marked_price * vat.rate
additional_services = car.get_additional_services() additional_services = car.get_additional_services()
discounted_price=(Decimal(car.marked_price) - discount)
vat_amount = discounted_price * vat.rate
total_services_vat=sum([ x[1] for x in additional_services.get("services")])
total_vat=vat_amount+total_services_vat
return { return {
"car": car, "car": car,
"discounted_price": (Decimal(car.marked_price) - discount) or 0, "discounted_price": discounted_price or 0,
"price_before_discount": car.marked_price, "price_before_discount": car.marked_price,
"vat_amount": vat_amount, "vat_amount": vat_amount,
"vat_rate": vat.rate, "vat_rate": vat.rate,
"discount_amount": discount, "discount_amount": discount,
"additional_services": additional_services, "additional_services": additional_services,
"grand_total": (car.marked_price - discount) + vat_amount + additional_services.get("total") "final_price": discounted_price+ vat_amount,
"total_services_vat":total_services_vat,
"total_vat":total_vat,
"grand_total": discounted_price + vat_amount + additional_services.get("total")
} }

View File

@ -17,7 +17,7 @@ from random import randint
from decimal import Decimal from decimal import Decimal
from io import TextIOWrapper from io import TextIOWrapper
from django.apps import apps from django.apps import apps
from datetime import datetime, timedelta from datetime import datetime, timedelta,date
from calendar import month_name from calendar import month_name
from pyzbar.pyzbar import decode from pyzbar.pyzbar import decode
from urllib.parse import urlparse, urlunparse from urllib.parse import urlparse, urlunparse
@ -391,101 +391,164 @@ class TestView(TemplateView):
template_name = "inventory/cars_list_api.html" template_name = "inventory/cars_list_api.html"
class DealerDashboard(LoginRequiredMixin, TemplateView): # class DealerDashboard(LoginRequiredMixin, TemplateView):
""" # """
ManagerDashboard class is a view handling the dashboard for a manager. # ManagerDashboard class is a view handling the dashboard for a manager.
Provides functionality to manage and view various statistics and data specific # Provides functionality to manage and view various statistics and data specific
to the dealer associated with the authenticated manager. It uses a specific # to the dealer associated with the authenticated manager. It uses a specific
template and ensures authentication before granting access. The class # template and ensures authentication before granting access. The class
aggregates data about cars, leads, financial statistics, and other related # aggregates data about cars, leads, financial statistics, and other related
business information for display in the manager's dashboard. # business information for display in the manager's dashboard.
:ivar template_name: Path to the template used for rendering the manager's dashboard. # :ivar template_name: Path to the template used for rendering the manager's dashboard.
:type template_name: str # :type template_name: str
""" # """
template_name = "dashboards/dealer_dashbaord.html" # template_name = "dashboards/dealer_dashbaord.html"
# def dispatch(self, request, *args, **kwargs): # # def dispatch(self, request, *args, **kwargs):
# if not request.user.is_authenticated: # # if not request.user.is_authenticated:
# return redirect("welcome") # # return redirect("welcome")
# if not getattr(request.user, "dealer", False): # # if not getattr(request.user, "dealer", False):
# return HttpResponseForbidden( # # return HttpResponseForbidden(
# "You are not authorized to view this dashboard." # # "You are not authorized to view this dashboard."
# ) # # )
# return super().dispatch(request, *args, **kwargs) # # return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): # def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # context = super().get_context_data(**kwargs)
dealer = get_user_type(self.request) # dealer = get_user_type(self.request)
entity = dealer.entity # entity = dealer.entity
qs = models.Car.objects.filter(dealer=dealer) # qs = models.Car.objects.filter(dealer=dealer)
total_cars = qs.count() # total_cars = qs.count()
stats = models.CarFinance.objects.filter(car__dealer=dealer).aggregate( # # stats = models.CarFinance.objects.filter(car__dealer=dealer).aggregate(
total_cost_price=Sum("cost_price"), # # total_cost_price=Sum("cost_price"),
total_selling_price=Sum("selling_price"), # # total_selling_price=Sum("selling_price"),
) # # )
total_cost_price = stats["total_cost_price"] or 0 # # total_cost_price = stats["total_cost_price"] or 0
total_selling_price = stats["total_selling_price"] or 0 # # total_selling_price = stats["total_selling_price"] or 0
total_profit = total_selling_price - total_cost_price # # total_profit = total_selling_price - total_cost_price
new_leads = models.Lead.objects.filter( # # new_leads = models.Lead.objects.filter(
dealer=dealer, status=models.Status.NEW # # dealer=dealer, status=models.Status.NEW
).count() # # ).count()
pending_leads = models.Lead.objects.filter( # # pending_leads = models.Lead.objects.filter(
dealer=dealer, status=models.Status.CONTACTED # # dealer=dealer, status=models.Status.CONTACTED
).count() # # ).count()
canceled_leads = models.Lead.objects.filter( # # canceled_leads = models.Lead.objects.filter(
dealer=dealer, status=models.Status.UNQUALIFIED # # dealer=dealer, status=models.Status.UNQUALIFIED
).count() # # ).count()
car_status_qs = qs.values("status").annotate(count=Count("status")) # # car_status_qs = qs.values("status").annotate(count=Count("status"))
car_status = {status: count for status, count in car_status_qs} # # car_status = {status: count for status, count in car_status_qs}
car_by_make_qs = qs.values("id_car_make__name").annotate(count=Count("id")) # # car_by_make_qs = qs.values("id_car_make__name").annotate(count=Count("id"))
car_by_make = list(car_by_make_qs) # # car_by_make = list(car_by_make_qs)
context["dealer"] = dealer # # context["dealer"] = dealer
context["total_activity"] = models.UserActivityLog.objects.filter( # # context["total_activity"] = models.UserActivityLog.objects.filter(
user=dealer.user # # user=dealer.user
).count() # # ).count()
context["total_cars"] = total_cars # # context["total_cars"] = total_cars
context["total_reservations"] = models.CarReservation.objects.filter( # # context["total_reservations"] = models.CarReservation.objects.filter(
reserved_until__gte=timezone.now() # # reserved_until__gte=timezone.now()
).count() # # ).count()
context["total_cost_price"] = total_cost_price # # context["total_cost_price"] = total_cost_price
context["total_selling_price"] = total_selling_price # # context["total_selling_price"] = total_selling_price
context["total_profit"] = total_profit # # context["total_profit"] = total_profit
context["new_leads"] = new_leads # # context["new_leads"] = new_leads
context["pending_leads"] = pending_leads # # context["pending_leads"] = pending_leads
context["canceled_leads"] = canceled_leads # # context["canceled_leads"] = canceled_leads
context["car"] = json.dumps(car_by_make) # # context["car"] = json.dumps(car_by_make)
context["available_cars"] =qs.filter(status='available').count() # # context["available_cars"] =qs.filter(status='available').count()
context["sold_cars"] = qs.filter(status='sold').count() # # context["sold_cars"] = qs.filter(status='sold').count()
context["reserved_cars"] = qs.filter(status='reserved').count() # # context["reserved_cars"] = qs.filter(status='reserved').count()
context["hold_cars"] =qs.filter(status='hold').count() # # context["hold_cars"] =qs.filter(status='hold').count()
context["damaged_cars"] = qs.filter(status='damaged').count() # # context["damaged_cars"] = qs.filter(status='damaged').count()
context["transfer_cars"] = qs.filter(status='transfer').count() # # context["transfer_cars"] = qs.filter(status='transfer').count()
context["present_inventory_count"]=total_cars-context["sold_cars"]-context["damaged_cars"] # # context["present_inventory_count"]=total_cars-context["sold_cars"]-context["damaged_cars"]
cars_sold=qs.filter(status='sold') # # cars_sold=qs.filter(status='sold')
# cars_sold.aggregate(total_inventory_value=sum()) # # cars_sold.aggregate(total_inventory_value=sum())
context["customers"] = entity.get_customers().count() # context["customers"] = entity.get_customers().count()
context["staff"] = models.Staff.objects.filter(dealer=dealer).count() # context["staff"] = models.Staff.objects.filter(dealer=dealer).count()
context["total_leads"] = models.Lead.objects.filter(dealer=dealer).count() # context["total_leads"] = models.Lead.objects.filter(dealer=dealer).count()
context["invoices"] = entity.get_invoices().count() # context["invoices"] = entity.get_invoices().count()
context["estimates"] = entity.get_estimates().count() # context["estimates"] = entity.get_estimates().count()
context["purchase_orders"] = entity.get_purchase_orders().count() # context["purchase_orders"] = entity.get_purchase_orders().count()
return context # return context
def DealerDashboard(request):
dealer = request.dealer
cars_sold = models.Car.objects.filter(dealer=dealer, status='sold')
today_local = timezone.localdate()
start_date_str = request.GET.get('start_date')
end_date_str = request.GET.get('end_date')
if not start_date_str:
start_date = today_local - timedelta(days=30)
else:
start_date = timezone.datetime.strptime(start_date_str, '%Y-%m-%d').date()
if not end_date_str:
end_date = today_local
else:
end_date = timezone.datetime.strptime(end_date_str, '%Y-%m-%d').date()
# The database query will automatically be handled in a timezone-aware manner
cars_sold_filtered = cars_sold.filter(
sold_date__date__gte=start_date,
sold_date__date__lte=end_date
)
print(cars_sold_filtered)
# # Calculate summary data for the filtered results
total_cars_sold=cars_sold_filtered.count()
print(total_cars_sold)
total_revenue_from_cars = sum([ car.final_price for car in cars_sold_filtered])
total_cost_of_cars_sold=sum([car.cost_price for car in cars_sold_filtered])
net_profit_from_cars=total_revenue_from_cars-total_cost_of_cars_sold
total_vat_collected_from_cars=sum([car.vat_amount for car in cars_sold_filtered])
total_revenue_from_services=sum([car.get_additional_services()['total'] for car in cars_sold_filtered])
total_vat_collected_from_services=sum([car.get_additional_services()['services_vat'] for car in cars_sold_filtered])
total_vat_collected = total_vat_collected_from_cars+total_vat_collected_from_services
total_revenue_generated=total_revenue_from_cars+total_revenue_from_services
total_discount = sum([car.discount for car in cars_sold_filtered])
context = {
'start_date': start_date,
'end_date': end_date,
'cars_sold': cars_sold_filtered,
'total_cars_sold':total_cars_sold,
'total_cost_of_cars_sold':total_cost_of_cars_sold,
'total_revenue_from_cars':total_revenue_from_cars,
'net_profit_from_cars':net_profit_from_cars,
'total_vat_collected_from_cars': total_vat_collected_from_cars,
'total_discount_on_cars':total_discount,
'total_revenue_from_services':total_revenue_from_services,
'total_vat_collected_from_services': total_vat_collected_from_services,
'total_revenue_generated': total_revenue_generated,
'total_vat_collected':total_vat_collected,
}
return render(request, 'dashboards/dealer_dashboard.html', context)
class ManagerDashboard(LoginRequiredMixin, TemplateView): class ManagerDashboard(LoginRequiredMixin, TemplateView):
""" """
@ -4815,7 +4878,7 @@ def create_estimate(request, dealer_slug, slug=None):
"quantity": 1, "quantity": 1,
"unit_cost": round(float(i.marked_price)), "unit_cost": round(float(i.marked_price)),
"unit_revenue": round(float(i.marked_price)), "unit_revenue": round(float(i.marked_price)),
"total_amount": round(float(i.total_vat)),# TODO : check later "total_amount": round(float(i.final_price_plus_vat)),# TODO : check later
} }
) )
@ -4836,7 +4899,7 @@ def create_estimate(request, dealer_slug, slug=None):
# "unit_cost": instance.cost_price, # "unit_cost": instance.cost_price,
# "unit_revenue": instance.marked_price, # "unit_revenue": instance.marked_price,
# "quantity": Decimal(quantities), # "quantity": Decimal(quantities),
# "total_amount": instance.total_vat * int(quantities),# TODO : check later # "total_amount": instance.final_price_plus_vat * int(quantities),# TODO : check later
# } # }
# } # }
@ -4994,6 +5057,7 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
# calculator = CarFinanceCalculator(estimate) # calculator = CarFinanceCalculator(estimate)
# finance_data = calculator.get_finance_data() # finance_data = calculator.get_finance_data()
finance_data = get_finance_data(estimate,dealer) finance_data = get_finance_data(estimate,dealer)
invoice_obj = InvoiceModel.objects.all().filter(ce_model=estimate).first() invoice_obj = InvoiceModel.objects.all().filter(ce_model=estimate).first()
kwargs["data"] = finance_data kwargs["data"] = finance_data
@ -5002,7 +5066,7 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
car = estimate.get_itemtxs_data()[0].first().item_model.car car = estimate.get_itemtxs_data()[0].first().item_model.car
selected_items = car.additional_services.filter(dealer=dealer) selected_items = car.additional_services.filter(dealer=dealer)
form = forms.AdditionalFinancesForm() form = forms.AdditionalFinancesForm()
form.fields["additional_finances"].queryset = form.fields["additional_finances"].queryset.filter(dealer=dealer) # TODO : check later form.fields["additional_finances"].queryset = form.fields["additional_finances"].queryset.filter(dealer=dealer) #
form.initial["additional_finances"] = selected_items form.initial["additional_finances"] = selected_items
kwargs["additionals_form"] = form kwargs["additionals_form"] = form
except Exception as e: except Exception as e:
@ -5010,6 +5074,16 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class EstimatePrintView(EstimateDetailView):
"""
A view to render a printer-friendly version of the estimate.
It reuses the data-fetching logic from EstimateDetailView but
uses a dedicated, stripped-down print template.
"""
template_name = "sales/estimates/estimate_preview.html"
@login_required @login_required
@permission_required("inventory.add_saleorder", raise_exception=True) @permission_required("inventory.add_saleorder", raise_exception=True)
def create_sale_order(request, dealer_slug, pk): def create_sale_order(request, dealer_slug, pk):
@ -5061,7 +5135,8 @@ def create_sale_order(request, dealer_slug, pk):
f"KeyError: 'car_info' or 'status' key missing when attempting to update status to 'sold' for item.item_model PK: {getattr(item.item_model, 'pk', 'N/A')}." f"KeyError: 'car_info' or 'status' key missing when attempting to update status to 'sold' for item.item_model PK: {getattr(item.item_model, 'pk', 'N/A')}."
) )
pass pass
item.item_model.car.sold_date=timezone.now() # to be checked added by faheed
item.item_model.car.save()# to be checked added byfaheed
item.item_model.car.mark_as_sold() item.item_model.car.mark_as_sold()
messages.success(request, "Sale Order created successfully") messages.success(request, "Sale Order created successfully")
@ -11027,12 +11102,14 @@ def purchase_report_csv_export(request,dealer_slug):
def car_sale_report_view(request, dealer_slug): def car_sale_report_view(request, dealer_slug):
dealer = get_object_or_404(models.Dealer, slug=dealer_slug) dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
cars_sold = models.Car.objects.filter(dealer=dealer, status='sold') cars_sold = models.Car.objects.filter(dealer=dealer, status='sold')
# Get filter parameters from the request # Get filter parameters from the request
selected_make = request.GET.get('make') selected_make = request.GET.get('make')
selected_model = request.GET.get('model') selected_model = request.GET.get('model')
selected_serie = request.GET.get('serie') selected_serie = request.GET.get('serie')
selected_year = request.GET.get('year') selected_year = request.GET.get('year')
selected_stock_type=request.GET.get('stock_type')
# Apply filters to the queryset # Apply filters to the queryset
if selected_make: if selected_make:
@ -11043,78 +11120,115 @@ def car_sale_report_view(request, dealer_slug):
cars_sold = cars_sold.filter(id_car_serie__name=selected_serie) cars_sold = cars_sold.filter(id_car_serie__name=selected_serie)
if selected_year: if selected_year:
cars_sold = cars_sold.filter(year=selected_year) cars_sold = cars_sold.filter(year=selected_year)
if selected_stock_type:
cars_sold = cars_sold.filter(stock_type=selected_stock_type)
# Get distinct values for filter dropdowns # Get distinct values for filter dropdowns
makes = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_make__name', flat=True).distinct() makes = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_make__name', flat=True).distinct()
models_qs = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_model__name', flat=True).distinct() models_qs = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_model__name', flat=True).distinct()
series = models.Car.objects.filter(dealer=dealer, status='sold').values_list(
'id_car_serie__name', flat=True).distinct() series = models.Car.objects.filter(dealer=dealer, status='sold').values_list('id_car_serie__name', flat=True).distinct()
stock_types=models.Car.objects.filter(dealer=dealer, status='sold').values_list('stock_type', flat=True).distinct()
years = models.Car.objects.filter(dealer=dealer, status='sold').values_list('year', flat=True).distinct().order_by('-year') years = models.Car.objects.filter(dealer=dealer, status='sold').values_list('year', flat=True).distinct().order_by('-year')
# # Calculate summary data for the filtered results # # Calculate summary data for the filtered results
total_cars_sold=cars_sold.count()
total_revenue_from_cars = sum([ car.final_price for car in cars_sold])
total_vat_on_cars=sum([car.vat_amount for car in cars_sold])
total_revenue = cars_sold.aggregate(total_revenue=Sum('finances__marked_price'))['total_revenue'] or 0 total_revenue_from_additonals=sum([car.get_additional_services()['total'] for car in cars_sold])
# total_vat = cars_sold.aggregate(total_vat=Sum('finances__vat_amount'))['total_vat'] or 0 total_vat_from_additonals=sum([car.get_additional_services()['services_vat'] for car in cars_sold])
total_discount = cars_sold.aggregate(total_discount=Sum('finances__discount_amount'))['total_discount'] or 0 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])
current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S") current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
context = { context = {
'cars_sold': cars_sold, 'cars_sold': cars_sold,
'total_cars_sold':total_cars_sold,
'current_time': current_time, 'current_time': current_time,
'dealer': dealer, 'dealer': dealer,
'total_revenue': total_revenue, 'total_revenue_from_cars': total_revenue_from_cars,
# 'total_vat': total_vat, '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, 'total_discount': total_discount,
'makes': makes, 'makes': makes,
'models': models_qs, 'models': models_qs,
'series': series, 'series': series,
'years': years, 'years': years,
'stock_types':stock_types,
'selected_make': selected_make, 'selected_make': selected_make,
'selected_model': selected_model, 'selected_model': selected_model,
'selected_serie': selected_serie, 'selected_serie': selected_serie,
'selected_year': selected_year, 'selected_year': selected_year,
'selected_stock_type':selected_stock_type,
} }
return render(request, 'ledger/reports/car_sale_report.html', context) return render(request, 'ledger/reports/car_sale_report.html', context)
def car_sale_report_csv_export(request,dealer_slug): @login_required
def car_sale_report_csv_export(request, dealer_slug):
response = HttpResponse(content_type='text/csv') response = HttpResponse(content_type='text/csv')
current_time = timezone.now().strftime("%Y-%m-%d_%H-%M-%S")
current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
filename = f"sales_report_{dealer_slug}_{current_time}.csv" filename = f"sales_report_{dealer_slug}_{current_time}.csv"
response['Content-Disposition'] = f'attachment; filename="{filename}"' response['Content-Disposition'] = f'attachment; filename="{filename}"'
writer = csv.writer(response) writer = csv.writer(response)
header=[ # Define the CSV header based on your HTML table headers
'Make', header = [
'VIN', 'VIN', 'Make', 'Model', 'Year', 'Serie', 'Trim', 'Mileage',
'Model', 'Stock Type', 'Created Date', 'Sold Date', 'Cost Price',
'Year', 'Marked Price', 'Discount Amount', 'Selling Price',
'Serie', 'VAT on Car', 'Services Price', 'VAT on Services', 'Final Total',
'Trim', 'Invoice Number'
'Mileage',
'Stock Type',
'Created Date',
'Sold Date',
'Cost Price',
'Marked Price',
'Discount Amount',
'Selling Price',
'Tax Amount',
'Invoice Number',
] ]
writer.writerow(header) writer.writerow(header)
dealer=get_object_or_404(models.Dealer,slug=dealer_slug) dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
cars_sold=models.Car.objects.filter(dealer=dealer,status='sold') cars_sold = models.Car.objects.filter(dealer=dealer, status='sold')
# Apply filters from the request, just like in your HTML view
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')
if selected_make:
cars_sold = cars_sold.filter(id_car_make__name=selected_make)
if selected_model:
cars_sold = cars_sold.filter(id_car_model__name=selected_model)
if selected_serie:
cars_sold = cars_sold.filter(id_car_serie__name=selected_serie)
if selected_year:
cars_sold = cars_sold.filter(year=selected_year)
if selected_stock_type:
cars_sold = cars_sold.filter(stock_type=selected_stock_type)
# Write the data for the filtered cars
for car in cars_sold: for car in cars_sold:
writer.writerow([ # 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:
invoice_number = car.invoice.invoice_number
sold_date = car.invoice.date_paid
writer.writerow([
car.vin, car.vin,
car.id_car_make.name, car.id_car_make.name,
car.id_car_model.name, car.id_car_model.name,
@ -11124,13 +11238,16 @@ def car_sale_report_csv_export(request,dealer_slug):
car.mileage if car.mileage else '0', car.mileage if car.mileage else '0',
car.stock_type, car.stock_type,
car.created_at.strftime("%Y-%m-%d %H:%M:%S") if car.created_at else '', car.created_at.strftime("%Y-%m-%d %H:%M:%S") if car.created_at else '',
car.sold_date.strftime("%Y-%m-%d %H:%M:%S") if car.sold_date else '', sold_date.strftime("%Y-%m-%d %H:%M:%S") if sold_date else '',
car.cost_price, car.cost_price,
car.marked_price, car.marked_price,
car.discount_amount, car.discount, # Ensure this property returns a number
car.selling_price, car.final_price, # Selling Price without VAT
car.vat_amount, # TODO : check later car.vat_amount, # VAT on the car
car.item_model.invoicemodel_set.first().invoice_number services_total_price, # Total services without VAT
services_vat_amount, # VAT on services
car.final_price_plus_services_plus_vat,
invoice_number,
]) ])
return response return response

View File

@ -1,28 +1,39 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% load i18n %}
{% load tenhal_tag %}
{% block title %}
{{ _("Dealership Dashboard") |capfirst }}
{% endblock title %}
{% block content%}
<div class="main-content flex-grow-1 container-fluid mt-4 mb-3"> <div class="main-content flex-grow-1 container-fluid mt-4 mb-3">
<div class="d-flex justify-content-between align-items-center mb-5 pb-3 border-bottom"> <div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-5 pb-3 border-bottom">
<h2 class="h3 fw-bold text-dark mb-0">Business Health Dashboard <i class="fas fa-chart-area text-primary ms-2"></i></h2> <h2 class="h3 fw-bold text-dark mb-3 mb-md-0">Business Health Dashboard <i class="fas fa-chart-area text-primary ms-2"></i></h2>
<div class="dropdown"> <form method="GET" class="date-filter-form">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> <div class="row g-3">
Last 30 Days <div class="col-12 col-md-4">
</button> <label for="start-date" class="form-label">Start Date</label>
<ul class="dropdown-menu dropdown-menu-end shadow"> <input type="date" class="form-control" id="start-date" name="start_date"
<li><a class="dropdown-item" href="#">Today</a></li> value="{{ start_date|date:'Y-m-d' }}" required>
<li><a class="dropdown-item" href="#">Last 7 Days</a></li> </div>
<li><a class="dropdown-item" href="#">Last 90 Days</a></li> <div class="col-12 col-md-4">
</ul> <label for="end-date" class="form-label">End Date</label>
</div> <input type="date" class="form-control" id="end-date" name="end_date"
</div> value="{{ end_date|date:'Y-m-d' }}" required>
</div>
<div class="col-12 col-md-4 d-flex align-items-end">
<button type="submit" class="btn btn-primary w-100">Apply Filter</button>
</div>
</div>
</form>
</div>
<div class="row g-4 mb-5"> <div class="row g-4 mb-5">
<div class="col-sm-6 col-md-4 col-lg-3"> <div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0"> <div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4"> <div class="card-body d-flex flex-column justify-content-between p-4">
<div> <div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total Revenue</p> <p class="text-uppercase text-muted fw-bold small mb-1">Total Cost of Cars Sold</p>
<h4 class="fw-bolder text-primary mb-3">$1.25M</h4> <h4 class="fw-bolder text-secondary mb-3">{{total_cost_of_cars_sold|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div> </div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start"> <span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month +8% from last month
@ -34,8 +45,8 @@
<div class="card h-100 shadow-sm border-0"> <div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4"> <div class="card-body d-flex flex-column justify-content-between p-4">
<div> <div>
<p class="text-uppercase text-muted fw-bold small mb-1">Net Profit</p> <p class="text-uppercase text-muted fw-bold small mb-1">Total Revenue from cars</p>
<h4 class="fw-bolder text-success mb-3">$1.25M</h4> <h4 class="fw-bolder text-primary mb-3">{{total_revenue_from_cars|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div> </div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start"> <span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month +8% from last month
@ -47,8 +58,8 @@
<div class="card h-100 shadow-sm border-0"> <div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4"> <div class="card-body d-flex flex-column justify-content-between p-4">
<div> <div>
<p class="text-uppercase text-muted fw-bold small mb-1">Gross Profit</p> <p class="text-uppercase text-muted fw-bold small mb-1">Net Profit From Cars</p>
<h4 class="fw-bolder text-info mb-3">$1.25M</h4> <h4 class="fw-bolder text-success mb-3">{{net_profit_from_cars|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div> </div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start"> <span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month +8% from last month
@ -56,6 +67,87 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total Discount on cars</p>
<h4 class="fw-bolder text-primary mb-3">{{total_discount_on_cars|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total VAT collected from cars</p>
<h4 class="fw-bolder text-primary mb-3">{{total_vat_collected_from_cars|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total Revenue from Services</p>
<h4 class="fw-bolder text-primary mb-3">{{total_revenue_from_services|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total VAT collected from Services</p>
<h4 class="fw-bolder text-primary mb-3">{{total_vat_collected_from_services|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">{% trans "Total Revenue Generated" %}</p>
<h4 class="fw-bolder text-primary mb-3">{{total_revenue_generated|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">{% trans "Total VAT Collected" %}</p>
<h4 class="fw-bolder text-primary mb-3">{{total_vat_collected|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3"> <div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0"> <div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4"> <div class="card-body d-flex flex-column justify-content-between p-4">
@ -69,12 +161,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4">
<div>
<p class="text-uppercase text-muted fw-bold small mb-1">Gross Profit</p>
<h4 class="fw-bolder text-info mb-3">$1.25M</h4>
</div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month
</span>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-3"> <div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 shadow-sm border-0"> <div class="card h-100 shadow-sm border-0">
<div class="card-body d-flex flex-column justify-content-between p-4"> <div class="card-body d-flex flex-column justify-content-between p-4">
<div> <div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total VAT Collected</p> <p class="text-uppercase text-muted fw-bold small mb-1">Total VAT Collected</p>
<h4 class="fw-bolder text-primary mb-3">$1.25M</h4> <h4 class="fw-bolder text-primary mb-3">{{total_vat_collected|floatformat:2}}<span class="icon-saudi_riyal"></span></h4>
</div> </div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start"> <span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+8% from last month +8% from last month
@ -87,7 +193,7 @@
<div class="card-body d-flex flex-column justify-content-between p-4"> <div class="card-body d-flex flex-column justify-content-between p-4">
<div> <div>
<p class="text-uppercase text-muted fw-bold small mb-1">Total Cars Sold</p> <p class="text-uppercase text-muted fw-bold small mb-1">Total Cars Sold</p>
<h4 class="fw-bolder text-success mb-3">{{ sold_cars }}</h4> <h4 class="fw-bolder text-success mb-3">{{ total_cars_sold }}</h4>
</div> </div>
<span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start"> <span class="badge bg-success-subtle text-success fw-bold p-2 rounded-pill d-inline-flex align-self-start">
+5 units from last month +5 units from last month

View File

@ -123,8 +123,8 @@
<h5 class="fw-bold mb-0 text-dark">Car Models by Make in Inventory</h5> <h5 class="fw-bold mb-0 text-dark">Car Models by Make in Inventory</h5>
</div> </div>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6 mb-4"> <div class="col-md-6 mb-4 mt-3">
<label for="carMakeSelect" class="form-label fs-7">Select a Car Make:</label> <label for="carMakeSelect" class="form-label fs-8 mb-2">Select a Car Make:</label>
<select id="carMakeSelect" class="form-select"> <select id="carMakeSelect" class="form-select">
<option value="" disabled selected>-- Choose a make --</option> <option value="" disabled selected>-- Choose a make --</option>
</select> </select>

View File

@ -51,7 +51,7 @@
<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> <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">
<div class="col-md-3"> <div class="col-md-2">
<label for="make-select" class="form-label">{% trans 'Make' %}</label> <label for="make-select" class="form-label">{% trans 'Make' %}</label>
<select id="make-select" name="make" class="form-select"> <select id="make-select" name="make" class="form-select">
<option value="">{% trans 'All Makes' %}</option> <option value="">{% trans 'All Makes' %}</option>
@ -60,7 +60,7 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="col-md-3"> <div class="col-md-2">
<label for="model-select" class="form-label">{% trans 'Model' %}</label> <label for="model-select" class="form-label">{% trans 'Model' %}</label>
<select id="model-select" name="model" class="form-select"> <select id="model-select" name="model" class="form-select">
<option value="">{% trans 'All Models' %}</option> <option value="">{% trans 'All Models' %}</option>
@ -69,7 +69,7 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="col-md-3"> <div class="col-md-2">
<label for="serie-select" class="form-label">{% trans 'Serie' %}</label> <label for="serie-select" class="form-label">{% trans 'Serie' %}</label>
<select id="serie-select" name="serie" class="form-select"> <select id="serie-select" name="serie" class="form-select">
<option value="">{% trans 'All Series' %}</option> <option value="">{% trans 'All Series' %}</option>
@ -87,36 +87,98 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="col-md-1"> <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 %}
</select>
</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> <button type="submit" class="btn btn-primary w-100"><i class="fas fa-filter me-2"></i>{% trans 'Filter' %}</button>
</div> </div>
</form> </form>
</section> </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 id="summary" class="mb-5"> <section id="summary" class="mb-5">
<h2 class="section-heading mb-4 border-start border-5 border-primary p-2">{% trans 'Report Summary' %}</h2> <h2 class="section-heading mb-4 border-start border-5 border-primary p-2">{% trans 'Report Summary' %}</h2>
<div class="row g-4"> <div class="row g-4">
<div class="col-md-6 col-lg-3"> <div class="col-md-6 col-lg-3">
<div class="card summary-card"> <div class="card summary-card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{% trans 'Total Revenue' %}<span class="icon-saudi_riyal"></span></h5> <h5 class="card-title"><span>{% trans 'Total Revenue from Cars' %}<span class="icon-saudi_riyal"></span></span></h5>
<p class="card-text">{{ total_revenue|floatformat:2 }} <span class="icon-saudi_riyal"></span></p> <p class="card-text"><span>{{ total_revenue_from_cars|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></p>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6 col-lg-3"> <div class="col-md-6 col-lg-3">
<div class="card summary-card"> <div class="card summary-card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{% trans 'Total VAT Amount' %}<i class="fas fa-percent ms-2"></i></h5> <h5 class="card-title"><span>{% trans 'Total Revenue from Services' %}<span class="icon-saudi_riyal"></span></span></h5>
<p class="card-text">{{ 10000|floatformat:2 }} <span class="icon-saudi_riyal"></span></p> <p class="card-text"><span>{{ total_revenue_from_additonals|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></p>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6 col-lg-3">
<div class="card summary-card">
<div class="card-body">
<h5 class="card-title"><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></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="card summary-card">
<div class="card-body">
<h5 class="card-title">{% trans 'Total VAT from Cars' %}<i class="fas fa-percent ms-2"></i></h5>
<p class="card-text"><span>{{ total_vat_on_cars|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="card summary-card">
<div class="card-body">
<h5 class="card-title">{% trans 'Total VAT from Services' %}<i class="fas fa-percent ms-2"></i></h5>
<p class="card-text"><span>{{ total_vat_from_additonals|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="card summary-card">
<div class="card-body">
<h5 class="card-title">{% trans 'Total VAT' %}<i class="fas fa-percent ms-2"></i></h5>
<p class="card-text"><span>{{ total_vat_collected|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3"> <div class="col-md-6 col-lg-3">
<div class="card summary-card"> <div class="card summary-card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{% trans 'Total Discount Amount' %}<i class="fas fa-tag ms-2"></i></h5> <h5 class="card-title">{% trans 'Total Discount Amount' %}<i class="fas fa-tag ms-2"></i></h5>
<p class="card-text">{{ total_discount|floatformat:2 }} <span class="icon-saudi_riyal"></span></p> <p class="card-text"><span>{{ total_discount|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></p>
</div> </div>
</div> </div>
</div> </div>
@ -124,13 +186,10 @@
<div class="card summary-card"> <div class="card summary-card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{% trans 'Total Cars Sold' %}<i class="fas fa-car ms-2"></i></h5> <h5 class="card-title">{% trans 'Total Cars Sold' %}<i class="fas fa-car ms-2"></i></h5>
<p class="card-text">{{ cars_sold|length }}</p> <p class="card-text">{{ total_cars_sold }}</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
@ -142,7 +201,7 @@
<i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %} <i class="bi bi-download me-2"></i>{% trans 'Download as CSV' %}
</a> </a>
</div> </div>
<div class="table-responsive"> <div class="table-responsive table-container">
<table class="table table-striped table-hover table-bordered table-sm"> <table class="table table-striped table-hover table-bordered table-sm">
<thead> <thead>
<tr> <tr>
@ -160,7 +219,10 @@
<th class="fs-9">{% trans 'Marked Price' %}</th> <th class="fs-9">{% trans 'Marked Price' %}</th>
<th class="fs-9">{% trans 'Discount Amount' %}</th> <th class="fs-9">{% trans 'Discount Amount' %}</th>
<th class="fs-9">{% trans 'Selling Price' %}</th> <th class="fs-9">{% trans 'Selling Price' %}</th>
<th class="fs-9">{% trans 'Tax Amount' %}</th> <th class="fs-9">{% trans 'VAT on Car' %}</th>
<th class="fs-9">{% trans 'Services Price' %}</th>
<th class="fs-9">{% trans 'VAT on Services' %}</th>
<th class="fs-9">{% trans 'Final Total' %}</th>
<th class="fs-9">{% trans 'Invoice Number' %}</th> <th class="fs-9">{% trans 'Invoice Number' %}</th>
</tr> </tr>
</thead> </thead>
@ -178,12 +240,15 @@
<td class="fs-9">{{ car.stock_type|capfirst }}</td> <td class="fs-9">{{ car.stock_type|capfirst }}</td>
<td class="fs-9">{{ car.created_at|date }}</td> <td class="fs-9">{{ car.created_at|date }}</td>
<td class="fs-9">{{ car.invoice.date_paid|date|default_if_none:"-" }}</td> <td class="fs-9">{{ car.invoice.date_paid|date|default_if_none:"-" }}</td>
<td class="fs-9">{{ car.cost_price }} <span class="icon-saudi_riyal"></span></td> <td class="fs-9"><span>{{ car.cost_price }}<span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9">{{ car.marked_price }} <span class="icon-saudi_riyal"></span></td> <td class="fs-9"><span>{{ car.marked_price }} <span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9">{{ car.total_discount }} <span class="icon-saudi_riyal"></span></td># TODO : check later <td class="fs-9"><span>{{ car.discount}} <span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9">{{ car.selling_price }} <span class="icon-saudi_riyal"></span></td> <td class="fs-9"><span>{{ car.final_price}} <span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9">{{ car.vat_amount }} <span class="icon-saudi_riyal"></span></td># TODO : check later <td class="fs-9"><span>{{ car.vat_amount|floatformat:2 }} <span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9">{{ car.invoice.invoice_number }}</td> <td class="fs-9"><span>{{ car.get_additional_services.total|floatformat:2}} <span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9"><span>{{ car.get_additional_services.services_vat|floatformat:2}}<span class="icon-saudi_riyal"></span></span></td>
<td class="fs-9"><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> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -17,8 +17,7 @@
<table class="table table-hover table-bordered"> <table class="table table-hover table-bordered">
<thead class=""> <thead class="">
<tr> <tr>
<th style="min-width: 600px" <th class="d-flex justify-content-between align-items-center">
class="d-flex justify-content-between align-items-center">
{% trans 'Item' %} {% trans 'Item' %}
{% if po_model.is_draft %} {% if po_model.is_draft %}
<button type="button" <button type="button"

View File

@ -112,7 +112,7 @@
onclick="setFormAction('review')" onclick="setFormAction('review')"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#confirmModal"> data-bs-target="#confirmModal">
<i class="fa-solid fa-check-double me-1"></i><span class="d-none d-sm-inline-block"> {% trans 'Mark As Review' %}</span> <span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Review' %}</span>
</button> </button>
{% endif %} {% endif %}
{% elif estimate.status == 'in_review' %} {% elif estimate.status == 'in_review' %}
@ -122,46 +122,49 @@
class="btn btn-phoenix-secondary" class="btn btn-phoenix-secondary"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#confirmModal"> data-bs-target="#confirmModal">
<i class="fa-solid fa-check-double me-1"></i> <span class="d-none d-sm-inline-block">{% trans 'Mark As Approved' %}</span> <span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Approved' %}</span>
</button> </button>
{% endif %} {% endif %}
{% if estimate.can_approve and not request.is_manager %} {% if estimate.can_approve and not request.is_manager %}
<button class="btn btn-phoenix-warning" disabled> <button class="btn btn-phoenix-warning" disabled>
<i class="fas fa-hourglass-start me-1"></i><span class="text-warning d-none d-sm-inline-block ">{% trans 'Waiting for Manager Approval' %}</span> <i class="fas fa-hourglass-start me-2"></i><span class="text-warning">{% trans 'Waiting for Manager Approval' %}</span>
</button> </button>
{% endif %} {% endif %}
{% elif estimate.status == 'approved' %} {% elif estimate.status == 'approved' %}
{% if perms.django_ledger.change_estimatemodel %} {% if perms.django_ledger.change_estimatemodel %}
<a href="{% url 'send_email' request.dealer.slug estimate.pk %}" <a href="{% url 'send_email' request.dealer.slug estimate.pk %}"
class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-1"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a> class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-sm-2"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a>
<a href="{% url 'estimate_print' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-secondary" target="_blank">
<span class="d-none d-sm-inline-block"><i class="fas fa-print me-2"></i>{% trans 'Print' %}</span>
</a>
{% endif %} {% endif %}
{% if estimate.sale_orders.first %} {% if estimate.sale_orders.first %}
<!--if sale order exist--> <!--if sale order exist-->
{% if perms.django_ledger.add_invoicemodel %} {% if perms.django_ledger.add_invoicemodel %}
<a href="{% url 'invoice_create' request.dealer.slug estimate.pk %}" <a href="{% url 'invoice_create' request.dealer.slug estimate.pk %}"
class="btn btn-phoenix-primary"><i class="fa-solid fa-receipt me-1"></i><span class="d-none d-sm-inline-block me-1"> {% trans 'Create Invoice' %}</span></a> class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'Create Invoice' %}</span></a>
{% endif %} {% endif %}
{% if perms.inventory.view_saleorder %} {% if perms.inventory.view_saleorder %}
<a href="{% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk %}" <a href="{% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk %}"
class="btn btn-phoenix-primary"><i class="fas fa-shopping-cart me-1"></i><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a> class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a>
{% endif %} {% endif %}
{% else %} {% else %}
{% if perms.inventory.add_saleorder %} {% if perms.inventory.add_saleorder %}
<a href="{% url 'create_sale_order' request.dealer.slug estimate.pk %}" <a href="{% url 'create_sale_order' request.dealer.slug estimate.pk %}"
class="btn btn-phoenix-primary"><i class="fa-solid fa-file-import me-1"></i><span class="d-none d-sm-inline-block"> {% trans 'Create Sale Order' %}</span></a> class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-file-import"></i> {% trans 'Create Sale Order' %}</span></a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% elif estimate.status == 'completed' %} {% elif estimate.status == 'completed' %}
{% if perms.inventory.view_saleorder %} {% if perms.inventory.view_saleorder %}
<a href="{% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk %}" <a href="{% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk %}"
class="btn btn-phoenix-primary"><i class="fas fa-shopping-cart me-1"></i><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a> class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a>
{% endif %} {% endif %}
{% if perms.django_ledger.view_invoicemodel %} {% if perms.django_ledger.view_invoicemodel %}
<a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug estimate.invoicemodel_set.first.pk %}" <a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug estimate.invoicemodel_set.first.pk %}"
class="btn btn-phoenix-primary btn-sm" class="btn btn-phoenix-primary btn-sm"
type="button"><i class="fa-solid fa-receipt me-1"></i> type="button"><i class="fa-solid fa-receipt"></i>
<span class="d-none d-sm-inline-block">{{ _("View Invoice") }}</span> {{ _("View Invoice") }}</a>
</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if estimate.can_cancel %} {% if estimate.can_cancel %}
@ -169,7 +172,7 @@
<button class="btn btn-phoenix-danger" <button class="btn btn-phoenix-danger"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#CancelModal"> data-bs-target="#CancelModal">
<i class="fa-solid fa-ban me-1"></i> <span class="d-none d-sm-inline-block">{% trans "Cancel" %}</span> <i class="fa-solid fa-ban"></i> {% trans "Cancel" %}
</button> </button>
{% endif %} {% endif %}
{% endif %} {% endif %}
@ -179,31 +182,31 @@
<div class="row"> <div class="row">
<div class="col mb-2"> <div class="col mb-2">
<h6> <h6>
<i class="fa-solid fa-hashtag me-1"></i> {% trans 'Quotation Number' %}: <i class="fa-solid fa-hashtag"></i> {% trans 'Quotation Number' %}:
</h6> </h6>
<p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.estimate_number }}</p> <p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.estimate_number }}</p>
</div> </div>
<div class="col mb-2"> <div class="col mb-2">
<h6> <h6>
<i class="fa-solid fa-calendar-days me-1"></i> {% trans 'Quotation Date' %}: <i class="fa-solid fa-calendar-days"></i> {% trans 'Quotation Date' %}:
</h6> </h6>
<p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.created }}</p> <p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.created }}</p>
</div> </div>
<div class="col mb-2"> <div class="col mb-2">
<h6> <h6>
<i class="fa-solid fa-user me-1"></i> {% trans 'Customer' %}: <i class="fa-solid fa-user"></i> {% trans 'Customer' %}:
</h6> </h6>
<p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.customer.customer_name }}</p> <p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.customer.customer_name }}</p>
</div> </div>
<div class="col mb-2"> <div class="col mb-2">
<h6> <h6>
<i class="fa-solid fa-envelope me-1"></i> {% trans 'Email' %}: <i class="fa-solid fa-envelope"></i> {% trans 'Email' %}:
</h6> </h6>
<p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.customer.email }}</p> <p class="fs-9 text-body-secondary fw-semibold mb-0">{{ estimate.customer.email }}</p>
</div> </div>
<div class="col"> <div class="col">
<h6> <h6>
<i class="fa-solid fa-list me-1"></i> {% trans "Quotation Status" %}: <i class="fa-solid fa-list"></i> {% trans "Quotation Status" %}:
</h6> </h6>
<div class="fs-9 text-body-secondary fw-semibold mb-0"> <div class="fs-9 text-body-secondary fw-semibold mb-0">
{% if estimate.status == 'draft' %} {% if estimate.status == 'draft' %}
@ -284,7 +287,7 @@
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Additional Services" %}</td> <td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Additional Services" %}</td>
<td class="align-middle text-start fw-semibold"> <td class="align-middle text-start fw-semibold">
{% for service in data.additional_services.services %} {% for service in data.additional_services.services %}
<small><span class="fw-semibold">+ {{ service.name }} - {{ service.price_|floatformat }}<span class="icon-saudi_riyal"></span></span></small> <small><span class="fw-semibold">+ {{ service.0.name }} - {{ service.0.price_|floatformat }}<span class="icon-saudi_riyal"></span></span></small>
<br> <br>
{% endfor %} {% endfor %}
{% if estimate.is_draft %} {% if estimate.is_draft %}

View File

@ -1,11 +1,10 @@
{% load i18n static custom_filters num2words_tags %} {% load i18n static custom_filters num2words_tags %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ar"> <html lang="ar" dir="rtl">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Invoice</title> <title>Quotation</title>
<!-- CSS -->
<link href="{% static 'css/theme.min.css' %}" <link href="{% static 'css/theme.min.css' %}"
type="text/css" type="text/css"
rel="stylesheet" rel="stylesheet"
@ -15,70 +14,80 @@
rel="stylesheet" rel="stylesheet"
id="user-style-default"> id="user-style-default">
<link href="{% static 'css/custom.css' %}" type="text/css" rel="stylesheet"> <link href="{% static 'css/custom.css' %}" type="text/css" rel="stylesheet">
<!-- Google Fonts - Roboto -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"> rel="stylesheet">
<!-- Custom CSS -->
<style> <style>
body { body {
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
margin: 0; margin: 0;
padding: 10mm; padding: 0;
background-color: #f8f9fa; background-color: #f8f9fa;
} }
.invoice-container { .invoice-container {
width: 210mm; width: 210mm;
min-height: 297mm; min-height: 297mm;
padding: 10mm; padding: 10mm;
margin: auto; margin: 10mm auto;
background: white; background: white;
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
position: relative; display: flex;
flex-direction: column;
} }
.invoice-content {
flex-grow: 1;
}
.invoice-header { .invoice-header {
text-align: center; text-align: center;
border-bottom: 2px solid #dee2e6; border-bottom: 2px solid #dee2e6;
padding-bottom: 10px; padding-bottom: 10px;
margin-bottom: 20px; margin-bottom: 20px;
} }
.qr-code { .qr-code {
text-align: center; text-align: center;
margin-top: 10px; margin-top: 10px;
} }
.qr-code img { .qr-code img {
width: 3cm; width: 3cm;
height: 3cm; height: 3cm;
border-radius: 0.3333333333rem; border-radius: 0.3333333333rem;
} }
.invoice-details, .invoice-table { .invoice-details, .invoice-table {
font-size: 12px; font-size: 14px;
} }
.invoice-table th { .invoice-table th {
background-color: #f8f9fa; background-color: #f8f9fa;
font-weight: 600; font-weight: 600;
} }
.invoice-total { .invoice-total {
text-align: right; text-align: right;
font-size: 13px; font-size: 16px;
font-weight: 600; font-weight: 600;
margin-top: 10px; margin-top: 10px;
} }
.footer-note { .footer-note {
position: absolute; margin-top: auto;
bottom: 10mm; padding-top: 10mm;
left: 10mm; font-size: 13px;
right: 10mm;
font-size: 10px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-top: 2px solid #dee2e6;
} }
.logo-img img { .logo-img img {
width: 10mm; width: 10mm;
height: 10mm; height: 10mm;
} }
</style> </style>
</head> </head>
<body> <body>
@ -92,267 +101,262 @@
</div> </div>
<div class="col-8"></div> <div class="col-8"></div>
</div> </div>
<div class="invoice-container" id="invoice-content">
<div class="invoice-header"> <div class="invoice-container" id="estimate-content">
<h5 class="fs-5"> <div class="invoice-content">
<span>Quotation</span>&nbsp;/&nbsp;<span>عرض سعر</span> <div class="invoice-header">
</h5> <h5 class="fs-5">
</div> <span>Quotation</span>&nbsp;/&nbsp;<span>عرض سعر</span>
<div class="invoice-details p-1"> </h5>
<table class="table table-sm table-responsive border-gray-50"> </div>
<tr> <div class="invoice-details p-1">
<td></td> <div class="d-flex justify-content-end align-items-end">
<td></td> <div class="dealer-logo ">
<td> {% if request.dealer.logo %}
<div class="qr-code"> <img class="rounded-soft" style="max-width:200px; max-height:200px;"
{% if dealer.logo %} src="{{ request.dealer.logo.url|default:'' }}"
<img class="rounded-soft" alt="Dealer Logo" />
src="{{ dealer.logo.url|default:'' }}" {% endif %}
alt="Dealer Logo" /> </div>
{% endif %} </div>
</div>
</td> <table class="table table-sm table-responsive border-gray-50">
</tr>
<tr>
<td class="ps-1">
<strong>Customer Name</strong>
</td>
<td class="text-center">
{{ dealer.arabic_name }}
<br>
{{ dealer.name }}
</td>
<td class="text-end">
<strong>{{ dealer.arabic_name }}</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Address</strong>
</td>
<td class="text-center">{{ dealer.address }}</td>
<td class="text-end">
<strong>العنوان</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Phone</strong>
</td>
<td class="text-center">{{ dealer.phone_number }}</td>
<td class="text-end">
<strong>جوال</strong>
</td>
</tr>
<tr>
<td>
<strong>VAT Number</strong>
</td>
<td>{{ dealer.vrn }}</td>
<td class="text-end">
<strong>الرقم الضريبي</strong>
</td>
</tr>
</table>
<table class="table table-sm table-bordered border-gray-50">
<tr>
<td class="ps-1">
<strong>Quotation&nbsp;Number</strong>
</td>
<td class="text-center">{{ estimate.estimate_number }}</td>
<td class="text-end p-1">
<strong>رقم عرض السعر</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Date</strong>
</td>
<td class="text-center">{{ estimate.date_approved| date:"Y/m/d" }}</td>
<td class="text-end p-1">
<strong>التاريخ</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Customer</strong>
</td>
<td class="text-center">{{ estimate.customer.customer_name }}</td>
<td class="text-end p-1">
<strong>العميل</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>VAT&nbsp;ID</strong>
</td>
<td class="text-center">{{ estimate.customer.vrn|default:"-" }}</td>
<td class="text-end p-1">
<strong>الرقم الضريبي</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Email</strong>
</td>
<td class="text-center">{{ estimate.customer.email |default:"N/A" }}</td>
<td class="text-end p-1">
<strong>البريد الإلكتروني</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Terms</strong>
</td>
<td class="text-center">{{ estimate.get_terms_display }}</td>
<td class="text-end p-1">
<strong>طريقة&nbsp;الدفع</strong>
</td>
</tr>
</table>
</div>
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">Car Details</span>
<span class="fs-9 fw-thin">تفاصيل السيارة</span>
</div>
<div class="invoice-table p-1">
<table class="table table-sm table-bordered m-1">
<thead>
<tr> <tr>
<th class="text-wrap text-center align-content-center"> <td class="ps-1">
<span class="fs-10">Make</span> / <span class="fs-10">الصانع</span> <strong>Dealership Name</strong>
</th> </td>
<th class="text-wrap text-center align-content-center"> <td class="text-center">
<span class="fs-10">Model</span> / <span class="fs-10">الموديل</span> {{ request.dealer.name }}
</th> </td>
<th class="text-wrap text-center align-content-center"> <td class="text-end">
<span class="fs-10">Trim</span> / <span class="fs-10">الفئة</span> <strong>اسم الوكالة</strong>
</th> </td>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Year</span> / <span class="fs-10">السنة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">VIN</span> / <span class="fs-10">الهيكل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Quantity</span> / <span class="fs-10">الكمية</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Unit Price</span> / <span class="fs-10">سعر الوحدة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Including VAT</span> / <span class="fs-10">شامل الضريبة</span>
</th>
</tr> </tr>
</thead>
<tbody>
{% for item in data.cars %}
<tr>
<td class="ps-1 fs-10 align-content-center" colspan="3">{{ item.make }} - {{ item.model }} - {{ item.trim }}</td>
<td class="text-center fs-10 align-content-center">{{ item.year }}</td>
<td class="ps-1 fs-10 align-content-center">{{ item.vin }}</td>
<td class="text-center fs-10 align-content-center">{{ item.quantity|floatformat:-1 }}</td>
<td class="text-center fs-10 align-content-center">{{ item.unit_price|floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{ item.total_vat|floatformat:2 }}</td>
</tr>
{% endfor %}
<tr> <tr>
<td class="ps-1 fs-10 align-content-center" colspan="5"></td> <td class="ps-1">
<td class="text-center fs-10 align-content-center">{{ data.quantity|floatformat:-1 }}</td> <strong>Dealership Address</strong>
<td class="text-center fs-10 align-content-center">{{ data.total_price_before_discount|floatformat:2 }}</td> </td>
<td class="text-center fs-10 align-content-center">{{ data.grand_total|floatformat:2 }}</td> <td class="text-center">{{ request.dealer.address }}</td>
<td class="text-end">
<strong>العنوان</strong>
</td>
</tr> </tr>
</tbody> <tr>
</table> <td class="ps-1">
</div> <strong>Phone</strong>
<div class="d-flex justify-content-between"> </td>
<span class="fs-9 fw-thin">Additional&nbsp;Services</span> <td class="text-center">{{ request.dealer.phone_number }}</td>
<span class="fs-9 fw-thin">الخدمات&nbsp;الإضافية</span> <td class="text-end">
</div> <strong>جوال</strong>
{% if data.additionals %} </td>
</tr>
<tr>
<td>
<strong>VAT Number</strong>
</td>
<td class="text-center">{{ request.dealer.vrn }}</td>
<td class="text-end">
<strong>الرقم الضريبي</strong>
</td>
</tr>
</table>
<table class="table table-sm table-bordered border-gray-50 ">
<tr>
<td class="ps-1">
<strong>Quotation&nbsp;Number</strong>
</td>
<td class="text-center">{{ estimate.estimate_number }}</td>
<td class="text-end p-1">
<strong>رقم عرض السعر</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Date</strong>
</td>
<td class="text-center">{{ estimate.date_approved| date:"Y/m/d" }}</td>
<td class="text-end p-1">
<strong>التاريخ</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Customer Name</strong>
</td>
<td class="text-center">{{ estimate.customer.customer_name }}</td>
<td class="text-end p-1">
<strong>العميل</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Email</strong>
</td>
<td class="text-center">{{ estimate.customer.email |default:"N/A" }}</td>
<td class="text-end p-1">
<strong>البريد الإلكتروني</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Terms</strong>
</td>
<td class="text-center">{{ estimate.get_terms_display }}</td>
<td class="text-end p-1">
<strong>طريقة&nbsp;الدفع</strong>
</td>
</tr>
</table>
</div>
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">Car Details</span>
<span class="fs-9 fw-thin">تفاصيل السيارة</span>
</div>
<div class="invoice-table p-1"> <div class="invoice-table p-1">
<table class="table table-sm table-bordered m-1"> <table class="table table-sm table-bordered m-1">
<thead> <thead>
<tr> <tr>
<th class="text-center fs-10 align-content-center">Type&nbsp;/&nbsp;النوع</th> <th class="text-wrap text-center align-content-center">
<th class="text-center fs-10 align-content-center">Price&nbsp;/&nbsp;القيمة</th> <span class="fs-10">Make</span> / <span class="fs-10">الصانع</span>
<th class="text-center fs-10 align-content-center"> </th>
<span class="fs-10">Including VAT</span> / <span class="fs-10">شامل الضريبة</span> <th class="text-wrap text-center align-content-center">
<span class="fs-10">Model</span> / <span class="fs-10">الموديل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Series</span> / <span class="fs-10">السلسلة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Trim</span> / <span class="fs-10">الفئة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Year</span> / <span class="fs-10">السنة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">VIN</span> / <span class="fs-10">رقم الهيكل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Quantity</span> / <span class="fs-10">الكمية</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Unit Price</span> / <span class="fs-10">سعر الوحدة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Discount</span> / <span class="fs-10">الخصم</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">VAT</span> / <span class="fs-10">الضريبة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Total</span> / <span class="fs-10">الإجمالي</span>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for item in data.additionals %} <tr>
<tr> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_make.name }}</td>
<td class="ps-1 text-start fs-10 align-content-center">{{ item.name }}</td> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_model.name }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ item.price|floatformat }}</td> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_serie.name }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ item.price_|floatformat }}</td> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_trim.name }}</td>
</tr> <td class="text-center fs-10 align-content-center">{{ data.car.year }}</td>
{% endfor %} <td class="ps-1 fs-10 align-content-center">{{ data.car.vin }}</td>
<td class="text-center fs-10 align-content-center">1</td>
<td class="text-center fs-10 align-content-center">{{ data.car.marked_price |floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{  data.discount_amount |floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{ data.vat_amount|floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{ data.final_price|floatformat:2 }}</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
{% endif %} <div class="d-flex justify-content-between">
<div class="invoice-total d-flex justify-content-end"> <span class="fs-9 fw-thin">Additional&nbsp;Services</span>
<div class="table-responsive"> <span class="fs-9 fw-thin">الخدمات&nbsp;الإضافية</span>
<table class="table table-sm table-responsive"> </div>
<tr> {% if data.additional_services %}
<td class="text-start ps-1"> <div class="invoice-table p-1">
<strong class="fs-9">VAT</strong> <table class="table table-sm table-bordered m-1">
</td> <thead>
<td class="text-center"> <tr>
<span class="fs-9">{{ data.total_vat_amount|floatformat }} <span class="icon-saudi_riyal"></span></span> <th class="text-center fs-10 align-content-center">Type&nbsp;/&nbsp;النوع</th>
</td> <th class="text-center fs-10 align-content-center">Price&nbsp;/&nbsp;القيمة</th>
<td class="text-end"> <th class="text-center fs-10 align-content-center">VAT&nbsp;/&nbsp;ضريبة الخدمة</th>
<strong class="fs-9">ضريبة&nbsp;القيمة&nbsp;المضافة</strong> <th class="text-center fs-10 align-content-center">
</td> <span class="fs-10">Total</span> / <span class="fs-10">الإجمالي</span>
</tr> </th>
<tr> </tr>
<td class="text-start ps-1"> </thead>
<strong class="fs-9">Total</strong> <tbody>
</td> {% for service in data.additional_services.services %}
<td class="text-center"> <tr>
<span class="fs-9">{{ data.grand_total|floatformat }}&nbsp;<span class="icon-saudi_riyal"></span></span> <td class="ps-1 text-start fs-10 align-content-center">{{ service.0.name }}</td>
</td> <td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price|floatformat }}</td>
<td class="text-end"> <td class="ps-1 text-center fs-10 align-content-center">{{ service.1|floatformat }}</td>
<strong class="fs-9">الإجمالي</strong> <td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price_|floatformat }}</td>
</td> </tr>
</tr> {% endfor %}
<tr> </tbody>
<td class="text-end" colspan="3"> </table>
<span class="fs-9 fw-bold">كتابةً:&nbsp;</span><span class="fs-9">{{ data.grand_total|num_to_words }}&nbsp;<span class="icon-saudi_riyal"></span></span> </div>
</td> {% endif %}
</tr> <div class="invoice-total d-flex justify-content-end">
</table> <div class="table-responsive">
<table class="table table-sm table-responsive">
<tr>
<td class="text-start ps-1">
<strong class="fs-9">Total VAT</strong>
</td>
<td class="text-center">
<span class="fs-9">{{ data.total_vat|floatformat }} <span class="icon-saudi_riyal"></span></span>
</td>
<td class="text-end">
<strong class="fs-9">إجمالي&nbsp;ضريبة&nbsp;القيمة&nbsp;المضافة</strong>
</td>
</tr>
<tr>
<td class="text-start ps-1">
<strong class="fs-9">Grand Total</strong>
</td>
<td class="text-center">
<span class="fs-9">{{ data.grand_total|floatformat }}&nbsp;<span class="icon-saudi_riyal"></span></span>
</td>
<td class="text-end">
<strong class="fs-9">الإجمالي</strong>
</td>
</tr>
<tr>
<td class="text-end" colspan="3">
<span class="fs-9 fw-bold">كتابةً:&nbsp;</span><span class="fs-9">{{ data.grand_total|num_to_words }}&nbsp;<span class="icon-saudi_riyal"></span></span>
</td>
</tr>
</table>
</div>
</div> </div>
</div> </div>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="footer-note"> <div class="footer-note">
<div class="logo-img text-center"> <div class="logo-img text-center">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" /> <img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p class="fs-11 fw-bold"> <p class="fs-9 fw-bold">
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span> <span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p> </p>
</div> </div>
<p class="fs-11"> <p class="fs-11">
<span class="fw-thin">Powered&nbsp;by&nbsp;</span><a class="text-decoration-none" <span class="fw-thin">Powered&nbsp;by&nbsp;</span>
href="https://tenhal.sa" <a class="text-decoration-none fs-9"
style="color: #112e40"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a> href="https://tenhal.sa"
style="color: #112e40;"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p> </p>
</div> </div>
</div> </div>
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script> <script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
<script src="{% static 'js/html2pdf.bundle.min.js' %}"></script> <script src="{% static 'js/html2pdf.bundle.min.js' %}"></script>
<script> <script>
document.getElementById('download-pdf').addEventListener('click', function () { document.getElementById('download-pdf').addEventListener('click', function () {
html2pdf().from(document.getElementById('invoice-content')).set({ html2pdf().from(document.getElementById('estimate-content')).set({
margin: 0, margin: 0,
filename: "{{ invoice.invoice_number }}_{{ invoice.customer.customer_name }}_{{ invoice.date_in_review|date:'Y-m-d' }}.pdf", filename: "{{ estimate.estimate_number }}_{{ estimate.customer.customer_name  }}_{{estimate.date_approved|date:'Y-m-d' }}.pdf",
image: { type: 'jpeg', quality: 0.98 }, image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 3 }, html2canvas: { scale: 3 },
jsPDF: { unit: 'mm', format: 'a3', orientation: 'portrait' } jsPDF: { unit: 'mm', format: 'a3', orientation: 'portrait' }
@ -360,4 +364,4 @@
}); });
</script> </script>
</body> </body>
</html> </html>

View File

@ -358,7 +358,7 @@
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Additional Services" %}</td> <td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Additional Services" %}</td>
<td class="align-middle text-start fw-bold"> <td class="align-middle text-start fw-bold">
{% for service in data.additional_services.services %} {% for service in data.additional_services.services %}
<small><span class="fw-bold">+ {{ service.name }} - {{ service.price_|floatformat }}<span class="icon-saudi_riyal"></span></span></small> <small><span class="fw-bold">+ {{ service.0.name }} - {{ service.0.price_|floatformat }}<span class="icon-saudi_riyal"></span></span></small>
<br> <br>
{% endfor %} {% endfor %}
</td> </td>

View File

@ -1,11 +1,10 @@
{% load i18n static custom_filters num2words_tags %} {% load i18n static custom_filters num2words_tags %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ar"> <html lang="ar" dir="rtl">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Invoice</title> <title>Invoice</title>
<!-- CSS -->
<link href="{% static 'css/theme.min.css' %}" <link href="{% static 'css/theme.min.css' %}"
type="text/css" type="text/css"
rel="stylesheet" rel="stylesheet"
@ -15,75 +14,80 @@
rel="stylesheet" rel="stylesheet"
id="user-style-default"> id="user-style-default">
<link href="{% static 'css/custom.css' %}" type="text/css" rel="stylesheet"> <link href="{% static 'css/custom.css' %}" type="text/css" rel="stylesheet">
<!-- Google Fonts - Roboto -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"> rel="stylesheet">
<!-- Custom CSS -->
<style> <style>
body { body {
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
margin: 0; margin: 0;
padding: 10mm; padding: 0;
background-color: #f8f9fa; background-color: #f8f9fa;
} }
.invoice-container { .invoice-container {
width: 210mm; width: 210mm;
min-height: 297mm; min-height: 297mm;
padding: 10mm; padding: 10mm;
margin: auto; margin: 10mm auto;
background: white; background: white;
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
position: relative; display: flex;
flex-direction: column;
} }
.invoice-content {
flex-grow: 1;
}
.invoice-header { .invoice-header {
text-align: center; text-align: center;
border-bottom: 2px solid #dee2e6; border-bottom: 2px solid #dee2e6;
padding-bottom: 10px; padding-bottom: 10px;
margin-bottom: 20px; margin-bottom: 20px;
} }
.qr-code { .qr-code {
text-align: center; text-align: center;
margin-top: 10px; margin-top: 10px;
} }
.qr-code img { .qr-code img {
width: 3cm; width: 3cm;
height: 3cm; height: 3cm;
border-radius: 0.3333333333rem; border-radius: 0.3333333333rem;
} }
.dealer-logo img {
width: 3cm;
height: 1cm;
position: relative;
}
.invoice-details, .invoice-table { .invoice-details, .invoice-table {
font-size: 12px; font-size: 14px;
} }
.invoice-table th { .invoice-table th {
background-color: #f8f9fa; background-color: #f8f9fa;
font-weight: 600; font-weight: 600;
} }
.invoice-total { .invoice-total {
text-align: right; text-align: right;
font-size: 13px; font-size: 16px;
font-weight: 600; font-weight: 600;
margin-top: 10px; margin-top: 10px;
} }
.footer-note { .footer-note {
position: absolute; margin-top: auto;
bottom: 10mm; padding-top: 10mm;
left: 10mm; font-size: 13px;
right: 10mm;
font-size: 10px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-top: 2px solid #dee2e6; /* Add a top border to separate from content */
} }
.logo-img img { .logo-img img {
width: 10mm; width: 10mm;
height: 10mm; height: 10mm;
} }
</style> </style>
</head> </head>
<body> <body>
@ -97,271 +101,274 @@
</div> </div>
<div class="col-8"></div> <div class="col-8"></div>
</div> </div>
<div class="invoice-container" id="invoice-content"> <div class="invoice-container" id="invoice-content">
<div class="invoice-header"> <div class="invoice-content">
<h5 class="fs-5">Tax&nbsp;Invoice&nbsp;&nbsp;/&nbsp;&nbsp;فاتورة&nbsp;ضريبية</h5> <div class="invoice-header">
</div> <h5 class="fs-5">
<div class="invoice-details p-1"> <span>Invoice</span>&nbsp;/&nbsp;<span>فاتورة</span>
<div class="d-flex justify-content-center align-items-center"> </h5>
<div class="qr-code">
<img src="{% static 'qr_code/Marwan_qr.png' %}" alt="QR Code">
</div>
</div> </div>
<div class="d-flex justify-content-end align-items-end"> <div class="invoice-details p-1">
<div class="dealer-logo "> <div class="d-flex justify-content-around align-items-end">
{% if dealer.logo %} <div class="d-flex justify-content-start align-items-center">
<img class="rounded-soft" <div class="qr-code">
src="{{ dealer.logo.url|default:'' }}" <img src="{% static 'qr_code/Marwan_qr.png' %}" alt="QR Code">
alt="Dealer Logo" /> </div>
{% endif %} </div>
<div class="dealer-logo ">
{% if request.dealer.logo %}
<img class="rounded-soft" style="max-width:150px; max-height:150px;"
src="{{ request.dealer.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div> </div>
<table class="table table-sm table-responsive border-gray-50">
<tr>
<td class="ps-1">
<strong>Dealership Name</strong>
</td>
<td class="text-center">
{{ request.dealer.name }}
</td>
<td class="text-end">
<strong>اسم الوكالة</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Dealership Address</strong>
</td>
<td class="text-center">{{ request.dealer.address }}</td>
<td class="text-end">
<strong>عنوان الوكالة</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Phone</strong>
</td>
<td class="text-center">{{ request.dealer.phone_number }}</td>
<td class="text-end">
<strong>جوال</strong>
</td>
</tr>
<tr>
<td>
<strong>VAT Number</strong>
</td>
<td class="text-center">{{ request.dealer.vrn }}</td>
<td class="text-end">
<strong>الرقم الضريبي</strong>
</td>
</tr>
</table>
<table class="table table-sm table-bordered border-gray-50 ">
<tr>
<td class="ps-1">
<strong>Invoice&nbsp;Number</strong>
</td>
<td class="text-center">{{ invoice.invoice_number }}</td>
<td class="text-end p-1">
<strong>رقم الفاتورة</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Date</strong>
</td>
<td class="text-center">{{ invoice.date_approved| date:"Y/m/d" }}</td>
<td class="text-end p-1">
<strong>التاريخ</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Customer Name</strong>
</td>
<td class="text-center">{{ invoice.customer.customer_name }}</td>
<td class="text-end p-1">
<strong>اسم العميل</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Email</strong>
</td>
<td class="text-center">{{ invoice.customer.email |default:"N/A" }}</td>
<td class="text-end p-1">
<strong>البريد الإلكتروني</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Terms</strong>
</td>
<td class="text-center">{{ invoice.get_terms_display }}</td>
<td class="text-end p-1">
<strong>شروط الدفع</strong>
</td>
</tr>
</table>
</div>
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">Car Details</span>
<span class="fs-9 fw-thin">تفاصيل السيارة</span>
</div> </div>
<table class="table table-sm table-bordered border-gray-50">
<tr>
<td class="ps-1">
<strong>Customer Name</strong>
</td>
<td class="text-center">
{{ dealer.arabic_name }}
<br>
{{ dealer.name }}
</td>
<td class="text-end">
<strong>اسم&nbsp;العميل</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Address</strong>
</td>
<td class="text-center">{{ dealer.address }}</td>
<td class="text-end">
<strong>العنوان</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Phone</strong>
</td>
<td class="text-center">{{ dealer.phone_number }}</td>
<td class="text-end">
<strong>جوال</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>VAT Number</strong>
</td>
<td class="text-center">{{ dealer.vrn }}</td>
<td class="text-end p-1">
<strong>الرقم الضريبي</strong>
</td>
</tr>
</table>
<table class="table table-sm table-bordered border-gray-50">
<tr>
<td class="ps-1">
<strong>Invoice&nbsp;Number</strong>
</td>
<td class="text-center">{{ invoice.invoice_number }}</td>
<td class="text-end p-1">
<strong>رقم&nbsp;الفاتورة</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Date</strong>
</td>
<td class="text-center">{{ invoice.date_in_review| date:"Y/m/d" }}</td>
<td class="text-end p-1">
<strong>التاريخ</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Customer</strong>
</td>
<td class="text-center">{{ invoice.customer.customer_name }}</td>
<td class="text-end p-1">
<strong>العميل</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>VAT&nbsp;ID</strong>
</td>
<td class="text-center">{{ invoice.customer.vrn|default:"-" }}</td>
<td class="text-end p-1">
<strong>الرقم&nbsp;الضريبي</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Email</strong>
</td>
<td class="text-center">{{ invoice.customer.email|default:"N/A" }}</td>
<td class="text-end p-1">
<strong>البريد&nbsp;الالكتروني</strong>
</td>
</tr>
<tr>
<td class="ps-1">
<strong>Terms</strong>
</td>
<td class="text-center">{{ invoice.get_terms_display }}</td>
<td class="text-end p-1">
<strong>طريقة&nbsp;الدفع</strong>
</td>
</tr>
</table>
</div>
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">Car&nbsp;Details</span>
<span class="fs-9 fw-thin">تفاصيل&nbsp;السيارة</span>
</div>
<div class="invoice-table p-1">
<table class="table table-sm table-bordered m-1">
<thead>
<tr>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Make</span> / <span class="fs-10">الصانع</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Model</span> / <span class="fs-10">الموديل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Trim</span> / <span class="fs-10">الفئة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Year</span> / <span class="fs-10">السنة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">VIN</span> / <span class="fs-10">الهيكل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Quantity</span> / <span class="fs-10">الكمية</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Unit Price</span> / <span class="fs-10">سعر الوحدة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Including VAT</span> / <span class="fs-10">شامل الضريبة</span>
</th>
</tr>
</thead>
<tbody>
{% for item in data.cars %}
<tr>
<td class="ps-1 fs-10 align-content-center" colspan="3">{{ item.make }} - {{ item.model }} - {{ item.trim }}</td>
<td class="text-center fs-10 align-content-center">{{ item.year }}</td>
<td class="ps-1 fs-10 align-content-center">{{ item.vin }}</td>
<td class="text-center fs-10 align-content-center">{{ item.quantity|floatformat }}</td>
<td class="text-center fs-10 align-content-center">{{ item.unit_price|floatformat }}</td>
<td class="text-center fs-10 align-content-center">{{ item.total_vat|floatformat }}</td>
</tr>
{% endfor %}
<tr>
<td class="ps-1 fs-10 align-content-center" colspan="5"></td>
<td class="text-center fs-10 align-content-center">{{ data.quantity|floatformat }}</td>
<td class="text-center fs-10 align-content-center">{{ data.total_price_before_discount|floatformat }}</td>
<td class="text-center fs-10 align-content-center">{{ data.grand_total|floatformat }}</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">Additional&nbsp;Services</span>
<span class="fs-9 fw-thin">الخدمات&nbsp;الإضافية</span>
</div>
{% if data.additionals %}
<div class="invoice-table p-1"> <div class="invoice-table p-1">
<table class="table table-sm table-bordered m-1"> <table class="table table-sm table-bordered m-1">
<thead> <thead>
<tr> <tr>
<th class="text-center fs-10 align-content-center">Type&nbsp;/&nbsp;النوع</th> <th class="text-wrap text-center align-content-center">
<th class="text-center fs-10 align-content-center">Price&nbsp;/&nbsp;القيمة</th> <span class="fs-10">Make</span> / <span class="fs-10">الصانع</span>
<th class="text-center fs-10 align-content-center"> </th>
<span class="fs-10">Including VAT</span> / <span class="fs-10">شامل الضريبة</span> <th class="text-wrap text-center align-content-center">
<span class="fs-10">Model</span> / <span class="fs-10">الموديل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Series</span> / <span class="fs-10">السلسلة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Trim</span> / <span class="fs-10">الفئة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Year</span> / <span class="fs-10">السنة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">VIN</span> / <span class="fs-10">رقم الهيكل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Quantity</span> / <span class="fs-10">الكمية</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Unit Price</span> / <span class="fs-10">سعر الوحدة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Discount</span> / <span class="fs-10">الخصم</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">VAT</span> / <span class="fs-10">الضريبة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">Total</span> / <span class="fs-10">الإجمالي</span>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for item in data.additionals %}
<tr> <tr>
<td class="ps-1 text-start fs-10 align-content-center">{{ item.name }}</td> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_make.name }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ item.price|floatformat }}</td> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_model.name }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ item.price_|floatformat }}</td> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_serie.name }}</td>
</tr> <td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_trim.name }}</td>
{% endfor %} <td class="text-center fs-10 align-content-center">{{ data.car.year }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.vin }}</td>
<td class="text-center fs-10 align-content-center">1</td>
<td class="text-center fs-10 align-content-center">{{ data.car.marked_price |floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{ data.discount_amount |floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{ data.vat_amount|floatformat:2 }}</td>
<td class="text-center fs-10 align-content-center">{{ data.final_price|floatformat:2 }}</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
{% endif %} <div class="d-flex justify-content-between">
<div class="invoice-total d-flex justify-content-end"> <span class="fs-9 fw-thin">Additional&nbsp;Services</span>
<div class="table-responsive"> <span class="fs-9 fw-thin">الخدمات&nbsp;الإضافية</span>
<table class="table table-sm table-responsive"> </div>
<tr> {% if data.additional_services %}
<td class="text-start ps-1"> <div class="invoice-table p-1">
<strong class="fs-9">VAT</strong> <table class="table table-sm table-bordered m-1">
</td> <thead>
<td class="text-center"> <tr>
<span class="fs-9">{{ data.total_vat_amount|floatformat }} <span class="icon-saudi_riyal"></span></span> <th class="text-center fs-10 align-content-center">Type&nbsp;/&nbsp;النوع</th>
</td> <th class="text-center fs-10 align-content-center">Price&nbsp;/&nbsp;السعر</th>
<td class="text-end"> <th class="text-center fs-10 align-content-center">Service VAT&nbsp;/&nbsp;ضريبة الخدمة</th>
<strong class="fs-9">ضريبة&nbsp;القيمة&nbsp;المضافة</strong> <th class="text-center fs-10 align-content-center">
</td> <span class="fs-10">Total</span> / <span class="fs-10">الإجمالي</span>
</tr> </th>
<tr> </tr>
<td class="text-start ps-1"> </thead>
<strong class="fs-9">Total</strong> <tbody>
</td> {% for service in data.additional_services.services %}
<td class="text-center"> <tr>
<span class="fs-9">{{ data.grand_total|floatformat }}&nbsp;<span class="icon-saudi_riyal"></span></span> <td class="ps-1 text-start fs-10 align-content-center">{{ service.0.name }}</td>
</td> <td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price|floatformat }}</td>
<td class="text-end"> <td class="ps-1 text-center fs-10 align-content-center">{{ service.1|floatformat }}</td>
<strong class="fs-9">الإجمالي</strong> <td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price_|floatformat }}</td>
</td> </tr>
</tr> {% endfor %}
<tr> </tbody>
<td class="text-end" colspan="3"> </table>
<span class="fs-9 fw-bold">كتابةً:&nbsp;</span><span class="fs-9">{{ data.grand_total|num_to_words }}&nbsp;<span class="icon-saudi_riyal"></span></span> </div>
</td> {% endif %}
</tr> <div class="invoice-total d-flex justify-content-end">
</table> <div class="table-responsive">
<table class="table table-sm table-responsive">
<tr>
<td class="text-start ps-1">
<strong class="fs-9">Total VAT</strong>
</td>
<td class="text-center">
<span class="fs-9">{{ data.total_vat|floatformat }} <span class="icon-saudi_riyal"></span></span>
</td>
<td class="text-end">
<strong class="fs-9">إجمالي&nbsp;ضريبة&nbsp;القيمة&nbsp;المضافة</strong>
</td>
</tr>
<tr>
<td class="text-start ps-1">
<strong class="fs-9">Grand Total</strong>
</td>
<td class="text-center">
<span class="fs-9">{{ data.grand_total|floatformat }}&nbsp;<span class="icon-saudi_riyal"></span></span>
</td>
<td class="text-end">
<strong class="fs-9">الإجمالي&nbsp;الكلي</strong>
</td>
</tr>
<tr>
<td class="text-end" colspan="3">
<span class="fs-9 fw-bold">كتابةً:&nbsp;</span><span class="fs-9">{{ data.grand_total|num_to_words }}&nbsp;<span class="icon-saudi_riyal"></span></span>
</td>
</tr>
</table>
</div>
</div> </div>
</div> </div>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="footer-note"> <div class="footer-note">
<div class="logo-img text-center"> <div class="logo-img text-center">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" /> <img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p class="fs-11 fw-bold"> <p class="fs-9 fw-bold">
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span> <span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p> </p>
</div> </div>
<p class="fs-11"> <p class="fs-11">
<span class="fw-thin">Powered&nbsp;by&nbsp;</span><a class="text-decoration-none" <span class="fw-thin">Powered&nbsp;by&nbsp;</span>
href="https://tenhal.sa" <a class="text-decoration-none fs-9"
style="color: #112e40"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a> href="https://tenhal.sa"
style="color: #112e40;"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p> </p>
</div> </div>
</div> </div>
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script> <script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
<script src="{% static 'js/html2pdf.bundle.min.js' %}"></script> <script src="{% static 'js/html2pdf.bundle.min.js' %}"></script>
<script> <script>
document.getElementById('download-pdf').addEventListener('click', function () { document.getElementById('download-pdf').addEventListener('click', function () {
html2pdf().from(document.getElementById('invoice-content')).set({ html2pdf().from(document.getElementById('invoice-content')).set({
margin: 0, margin: 0,
filename: "{{ invoice.invoice_number }}_{{ invoice.customer.customer_name }}_{{ invoice.date_in_review|date:'Y-m-d' }}.pdf", filename: "{{ invoice.invoice_number }}_{{ invoice.customer.customer_name  }}_{{invoice.date_approved|date:'Y-m-d' }}.pdf",
image: { type: 'jpeg', quality: 0.98 }, image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 3 }, html2canvas: { scale: 3 },
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } jsPDF: { unit: 'mm', format: 'a3', orientation: 'portrait' }
}).save(); }).save();
}); });
</script> </script>
</body> </body>
</html> </html>