Compare commits

...

7 Commits

27 changed files with 2098 additions and 864 deletions

5
.gitignore vendored
View File

@ -163,8 +163,11 @@ GitHub.sublime-settings
.history
static-copy
static
static/*
staticfiles
media
tmp
logs
logs
static/testdir

View File

@ -17,31 +17,17 @@ import django
django.setup()
from django.urls import path
from channels.routing import ProtocolTypeRouter, URLRouter
from whitenoise import WhiteNoise
from channels.auth import AuthMiddlewareStack
from api import routing
from inventory.notifications.sse import NotificationSSEApp
from django.urls import re_path
from django.core.asgi import get_asgi_application
from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler
from pathlib import Path
# application = ProtocolTypeRouter(
# {
# "http": get_asgi_application(),
# # "websocket": AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)),
# }
# )
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "car_inventory.settings")
django.setup()
BASE_DIR = Path(__file__).resolve().parent.parent
# BASE_DIR = Path(__file__).resolve().parent.parent
app = get_asgi_application()
# app = WhiteNoise(app, root=str(BASE_DIR / 'staticfiles'))
application = ProtocolTypeRouter(
{
"http": AuthMiddlewareStack(
@ -50,7 +36,7 @@ application = ProtocolTypeRouter(
path("sse/notifications/", NotificationSSEApp()),
re_path(
r"", app
), # All other routes go to Django
),
]
)
),
@ -58,5 +44,5 @@ application = ProtocolTypeRouter(
)
if django.conf.settings.DEBUG:
application = ASGIStaticFilesHandler(app)
# if django.conf.settings.DEBUG:
# application = ASGIStaticFilesHandler(app)

View File

@ -5,7 +5,7 @@ from django.urls import path, include
from schema_graph.views import Schema
from django.conf.urls.static import static
from django.conf.urls.i18n import i18n_patterns
from inventory.notifications.sse import NotificationSSEApp
# from inventory.notifications.sse import NotificationSSEApp
# import debug_toolbar
# from two_factor.urls import urlpatterns as tf_urls
@ -33,5 +33,7 @@ urlpatterns += i18n_patterns(
# path('', include(tf_urls)),
)
# if not settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root = settings.STATIC_ROOT)

View File

@ -1,82 +1,3 @@
# import json
# from django.contrib.auth.models import AnonymousUser
# from django.contrib.auth import get_user_model
# from django.db import close_old_connections
# from urllib.parse import parse_qs
# from channels.db import database_sync_to_async
# from inventory.models import Notification
# import asyncio
# @database_sync_to_async
# def get_notifications(user, last_id):
# return Notification.objects.filter(
# user=user, id__gt=last_id, is_read=False
# ).order_by("created")
# class NotificationSSEApp:
# async def __call__(self, scope, receive, send):
# if scope["type"] != "http":
# return
# query_string = parse_qs(scope["query_string"].decode())
# last_id = int(query_string.get("last_id", [0])[0])
# # Get user from scope if using AuthMiddlewareStack
# user = scope.get("user", AnonymousUser())
# if not user.is_authenticated:
# await send({
# "type": "http.response.start",
# "status": 403,
# "headers": [(b"content-type", b"text/plain")],
# })
# await send({
# "type": "http.response.body",
# "body": b"Unauthorized",
# })
# return
# await send({
# "type": "http.response.start",
# "status": 200,
# "headers": [
# (b"content-type", b"text/event-stream"),
# (b"cache-control", b"no-cache"),
# (b"x-accel-buffering", b"no"),
# ]
# })
# try:
# while True:
# close_old_connections()
# notifications = await get_notifications(user, last_id)
# for notification in notifications:
# data = {
# "id": notification.id,
# "message": notification.message,
# "created": notification.created.isoformat(),
# "is_read": notification.is_read,
# }
# event_str = (
# f"id: {notification.id}\n"
# f"event: notification\n"
# f"data: {json.dumps(data)}\n\n"
# )
# await send({
# "type": "http.response.body",
# "body": event_str.encode("utf-8"),
# "more_body": True
# })
# last_id = notification.id
# await asyncio.sleep(2)
# except asyncio.CancelledError:
# pass
import json
import time
from django.contrib.auth.models import AnonymousUser

View File

@ -1003,10 +1003,10 @@ def create_po_item_upload(sender, instance, created, **kwargs):
if instance.po_status == "fulfilled" or instance.po_status == 'approved':
for item in instance.get_itemtxs_data()[0]:
dealer = models.Dealer.objects.get(entity=instance.entity)
if item.bill_model.is_paid():
models.PoItemsUploaded.objects.get_or_create(
dealer=dealer, po=instance, item=item, status=instance.po_status
)
if item.bill_model and item.bill_model.is_paid():
models.PoItemsUploaded.objects.get_or_create(
dealer=dealer, po=instance, item=item, status=instance.po_status
)
# @receiver(post_save, sender=models.Staff)

View File

@ -342,6 +342,11 @@ urlpatterns = [
views.CarDetailView.as_view(),
name="car_detail",
),
path(
"<slug:dealer_slug>/cars/<slug:slug>/estimate/",
views.create_estimate_for_car,
name="create_estimate_for_car",
),
path("cars/<slug:slug>/history/", views.car_history, name="car_history"),
path(
"<slug:dealer_slug>/cars/<slug:slug>/update/",
@ -938,7 +943,7 @@ urlpatterns = [
views.ItemServiceUpdateView.as_view(),
name="item_service_update",
),
path(
"<slug:dealer_slug>/items/services/<int:pk>/detail/",
views.ItemServiceDetailView.as_view(),
@ -962,7 +967,7 @@ urlpatterns = [
),
path(
"<slug:dealer_slug>/items/expeneses/<uuid:pk>/detail/",
views.ItemExpenseDetailView.as_view(),
views.ItemExpenseDetailView.as_view(),
name="item_expense_detail",
),
# Bills

View File

@ -1329,7 +1329,9 @@ def get_finance_data(estimate, dealer):
additional_services = car.get_additional_services()
discounted_price = Decimal(car.marked_price) - discount
vat_amount = discounted_price * vat.rate
total_services_amount=additional_services.get("total")
total_services_vat = sum([x[1] for x in additional_services.get("services")])
total_services_amount_=additional_services.get("total_")
total_vat = vat_amount + total_services_vat
return {
"car": car,
@ -1340,9 +1342,16 @@ def get_finance_data(estimate, dealer):
"discount_amount": discount,
"additional_services": additional_services,
"final_price": discounted_price + vat_amount,
"total_services_vat": total_services_vat,
"total_services_amount":total_services_amount,
"total_services_amount_":total_services_amount_,
"total_vat": total_vat,
"grand_total": discounted_price + total_vat + additional_services.get("total"),
}
# totals = self.calculate_totals()

View File

@ -4656,7 +4656,7 @@ def sales_list_view(request, dealer_slug):
search_query = request.GET.get('q', None)
if search_query:
qs = qs.filter(
Q(order_number__icontains=search_query)|
Q(customer__phone_number__icontains=search_query)|
Q(customer__customer_name__icontains=search_query)
).distinct()
@ -5092,6 +5092,7 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
def get_context_data(self, **kwargs):
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
estimate = kwargs.get("object")
if estimate.get_itemtxs_data():
# calculator = CarFinanceCalculator(estimate)
# finance_data = calculator.get_finance_data()
@ -5099,6 +5100,8 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
invoice_obj = InvoiceModel.objects.all().filter(ce_model=estimate).first()
kwargs["data"] = finance_data
kwargs["customer_obj"]=estimate.customer.customer_set.first()
kwargs['dealer_info']=dealer
kwargs["invoice"] = invoice_obj
try:
@ -5119,29 +5122,33 @@ class EstimatePrintView(EstimateDetailView):
It reuses the data-fetching logic from EstimateDetailView but
uses a dedicated, stripped-down print template.
"""
template_name = "sales/estimates/estimate_preview.html"
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
# lang = request.GET.get('lang', 'ar')
template_path = "sales/estimates/estimate_preview.html"
if request.GET.get('lang')=='en':
template_path = "sales/estimates/estimate_preview_en.html"
else:
template_path = "sales/estimates/estimate_preview_ar.html"
html_string = render_to_string(template_path, context)
pdf_file = HTML(string=html_string).write_pdf()
base_url = request.build_absolute_uri('/')
pdf_file = HTML(string=html_string, base_url=base_url).write_pdf()
response = HttpResponse(pdf_file, content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="estimate_{self.object.estimate_number}.pdf"'
return response
@ -5522,7 +5529,7 @@ class InvoiceListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
entity = dealer.entity
staff = getattr(self.request.user, "staff", None)
qs = []
qs=None
try:
if any(
[
@ -5871,7 +5878,6 @@ class InvoicePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
model = InvoiceModel
context_object_name = "invoice"
template_name = "sales/invoices/invoice_preview.html"
permission_required = ["django_ledger.view_invoicemodel"]
def get_context_data(self, **kwargs):
@ -5881,8 +5887,37 @@ class InvoicePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
# calculator = CarFinanceCalculator(invoice)
finance_data = get_finance_data(invoice,dealer)
kwargs["data"] = finance_data
kwargs["dealer"] = dealer
kwargs["dealer_info"] = dealer
kwargs["customer_obj"]=invoice.customer.customer_set.first()
return super().get_context_data(**kwargs)
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
# lang = request.GET.get('lang', 'ar')
if request.GET.get('lang')=='en':
template_path = "sales/invoices/invoice_preview_en.html"
elif request.GET.get('lang')=='ar':
template_path = "sales/invoices/invoice_preview_ar.html"
else:
# just for preview not for download
return render(request,'sales/invoices/invoice_preview.html',context)
html_string = render_to_string(template_path, context)
base_url = request.build_absolute_uri('/')
pdf_file = HTML(string=html_string, base_url=base_url).write_pdf()
response = HttpResponse(pdf_file, content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="invoice_{self.object.invoice_number}.pdf"'
return response
# payments
@ -6221,10 +6256,10 @@ class LeadListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
| Q(last_name__icontains=query)
| Q(id_car_make__name__icontains=query)
| Q(id_car_model__name__icontains=query)
| Q(email__icontains=query)
| Q(phone_number__icontains=query)
| Q(next_action__icontains=query)
| Q(staff__name__icontains=query)
| Q(staff__first_name__icontains=query)
| Q(staff__last_name__icontains=query)
)
if self.request.is_dealer: # or self.request.is_manager:
@ -10238,7 +10273,8 @@ def payment_callback(request, dealer_slug):
# return render(request, "payment_failed.html", {"message": message})
@login_required
async def sse_stream(request): # 👈 Mark as async!
async def sse_stream(request):
import asyncio
def event_generator():
last_id = int(request.GET.get("last_id", 0))
@ -10878,19 +10914,23 @@ def InventoryItemCreateView(request, dealer_slug):
serie = request.POST.get("serie")
trim = request.POST.get("trim")
year = request.POST.get("year")
exterior = models.ExteriorColors.objects.get(
pk=request.POST.get("exterior")
)
interior = models.InteriorColors.objects.get(
pk=request.POST.get("interior")
)
exterior = request.POST.get("exterior")
interior = request.POST.get("interior")
make_name = models.CarMake.objects.get(pk=make)
model_name = models.CarModel.objects.get(pk=model)
serie_name = models.CarSerie.objects.get(pk=serie)
trim_name = models.CarTrim.objects.get(pk=trim)
exterior_name = models.ExteriorColors.objects.get(
pk=request.POST.get("exterior")
)
interior_name = models.InteriorColors.objects.get(
pk=request.POST.get("interior")
)
inventory_name = f"{make_name.name} || {model_name.name} || {serie_name.name} || {trim_name.name} || {year} || {exterior_name.name} || {interior_name.name}"
display_name = f"{make_name.name} {model_name.name} {serie_name.name} {trim_name.name} {year} {exterior_name.name}"
inventory_name = f"{make_name.name} || {model_name.name} || {serie_name.name} || {trim_name.name} || {year} || {exterior.name} || {interior.name}"
if (
inventory := entity.get_items_inventory()
.filter(name=inventory_name)
@ -10898,17 +10938,27 @@ def InventoryItemCreateView(request, dealer_slug):
):
messages.error(request, _("Inventory item already exists"))
return response
uom = entity.get_uom_all().filter(name="Unit").first()
if not uom:
uom = entity.create_uom(name="Unit", unit_abbr="unit")
entity.create_item_inventory(
name=inventory_name,
item = entity.create_item_inventory(
name=display_name,
uom_model=uom,
item_type=ItemModel.ITEM_TYPE_MATERIAL,
inventory_account=account,
coa_model=coa,
)
item.additional_info.update(
{
"make": make,
"model": model,
"serie": serie,
"trim": trim,
"year": year,
"exterior": exterior,
"interior": interior,
})
item.save()
messages.success(request, _("Inventory item created successfully"))
return response
@ -11005,6 +11055,9 @@ class PurchaseOrderDetailView(LoginRequiredMixin, PermissionRequiredMixin, Detai
for i in po_items_qs.values("po_total_amount", "po_item_status")
if i["po_item_status"] != "cancelled"
)
items = [{"total": x.total_amount, "q": x.quantity} for x in po_model.get_itemtxs_data()[0].all()]
po_quantity = sum(item["q"] for item in items)
context['po_quantity']=po_quantity
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
@ -11014,18 +11067,18 @@ class PurchaseOrderDetailView(LoginRequiredMixin, PermissionRequiredMixin, Detai
"item_model", "bill_model"
)
)
if self.object.po_status == 'fulfilled':
context['po_items_list']=po_items_qs
context['vendor']=po_items_qs.first().bill_model.vendor
context['dealer']=request.dealer
# Check if PDF format is requested
if request.GET.get('format') == 'pdf':
# Use a separate, print-friendly template for the PDF
if request.GET.get('lang')=='en':
html_string = render_to_string(
"purchase_orders/po_detail_en_pdf.html",
"purchase_orders/po_detail_en_pdf.html",
context
)
else:
@ -11035,9 +11088,8 @@ class PurchaseOrderDetailView(LoginRequiredMixin, PermissionRequiredMixin, Detai
)
# Use WeasyPrint to generate the PDF
pdf = HTML(string=html_string).write_pdf()
base_url = request.build_absolute_uri('/')
pdf = HTML(string=html_string, base_url=base_url).write_pdf()
response = HttpResponse(pdf, content_type="application/pdf")
response["Content-Disposition"] = f'attachment; filename="PO_{self.object.po_number}.pdf"'
@ -11223,18 +11275,14 @@ def upload_cars(request, dealer_slug, pk=None):
)
try:
if item:
data = [x.strip() for x in item.item_model.name.split("||")]
make = models.CarMake.objects.filter(is_sa_import=True).get(
name=data[0]
)
model = make.carmodel_set.get(name=data[1])
trim = models.CarTrim.objects.filter(
name=data[3], id_car_serie__id_car_model=model.id_car_model
).first()
serie = trim.id_car_serie
year = data[4]
exterior = models.ExteriorColors.objects.get(name=data[5])
interior = models.InteriorColors.objects.get(name=data[6])
# data = [x.strip() for x in item.item_model.name.split("||")]
make = models.CarMake.objects.get(pk=item.addition_info.get("make"))
model = models.CarModel.objects.get(pk=item.addition_info.get("model"))
trim = models.CarTrim.objects.get(pk=item.addition_info.get("trim"))
serie = models.CarSerie.objects.get(pk=item.addition_info.get("serie"))
year = item.addition_info.get("year")
exterior = models.ExteriorColors.objects.get(pk=item.addition_info.get("exterior"))
interior = models.InteriorColors.objects.get(pk=item.addition_info.get("interior"))
receiving_date = timezone.now()
vendor_model = item.bill_model.vendor
vendor = models.Vendor.objects.get(vendor_model=vendor_model)

View File

@ -35,7 +35,8 @@
<div class="row my-5">
<div class="card rounded ">
<div class="card-header ">
<p class="mb-0">{{ _("Group Details") }}</p>
<p class="mb-2">{{ _("Group Details") }}</p>
<a class="btn btn-phoenix-secondary " href="{% url 'group_list' request.dealer.slug %}">{% trans "Group List" %}</a>
</div>
<div class="card-body">
<div class="row">

View File

@ -87,9 +87,13 @@
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
} });
}
});
{% with last_notif=notifications_|last %}
let lastNotificationId = {{ last_notif.id|default:0 }};
{% endwith %}
let lastNotificationId = {{ notifications_.last.id|default:0 }};
let seenNotificationIds = new Set();
let counter = document.getElementById('notification-counter');
let notificationsContainer = document.getElementById('notifications-container');
@ -100,7 +104,6 @@
let initialUnreadCount = {{ notifications_.count|default:0 }};
updateCounter(initialUnreadCount);
fetchInitialNotifications();
function fetchInitialNotifications() {
@ -108,29 +111,22 @@
.then(response => response.json())
.then(data => {
if (data.notifications && data.notifications.length > 0) {
lastNotificationId = data.notifications[0].id;
seenNotificationIds = new Set();
let unreadCount = 0;
data.notifications.forEach(notification => {
seenNotificationIds.add(notification.id);
if (!notification.is_read) {
unreadCount++;
}
if (!notification.is_read) unreadCount++;
});
renderNotifications(data.notifications);
updateCounter(unreadCount);
setTimeout(() => {
connectSSE();
}, 5000);
}
// Always connect SSE after initial load
setTimeout(() => {
connectSSE();
}, 1000);
})
.catch(error => {
console.error('Error fetching initial notifications:', error);
@ -143,12 +139,12 @@
eventSource.close();
}
// ✅ FIXED URL HERE
eventSource = new EventSource("/sse/notifications/?last_id=" + lastNotificationId);
eventSource.addEventListener('notification', function(e) {
try {
const data = JSON.parse(e.data);
if (seenNotificationIds.has(data.id)) return;
seenNotificationIds.add(data.id);
@ -158,6 +154,11 @@
updateCounter('increment');
if (!notificationsContainer) {
console.warn("Notification container missing, can't render SSE event");
return;
}
const notificationElement = createNotificationElement(data);
notificationsContainer.insertAdjacentHTML('afterbegin', notificationElement);
@ -168,7 +169,7 @@
Toast.fire({
icon: 'info',
html:`${data.message}`
html: `${data.message}`
});
} catch (error) {
@ -220,7 +221,7 @@
</div>
</div>
</div>
`;
`;
}
function updateCounter(action) {
@ -231,12 +232,14 @@
if (notificationCountDiv) {
notificationCountDiv.innerHTML = `
<span class="badge bg-danger rounded-pill" id="notification-counter" style="position: absolute; top: 8px; right: 3px; font-size: 0.50rem;">0</span>
`;
`;
counter = document.getElementById('notification-counter');
}
}
}
if (!counter) return;
let currentCount = parseInt(counter.textContent) || 0;
if (action === 'increment') {
@ -294,11 +297,11 @@
notificationCard.closest('.notification-card').classList.add('fade-out');
setTimeout(() => {
notificationCard.closest('.notification-card').remove();
}, 200);
}, 1000);
}
}
});
}
});
});
</script>
</script>

View File

@ -125,7 +125,7 @@
</div>
</div>
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="name align-middle white-space-nowrap ps-0 px-1">
<td class="name align-middle white-space-nowrap px-1">
<div class="d-flex align-items-center">
<div>
<a class="fs-8 fw-bold"
@ -144,7 +144,7 @@
<td class="date align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 text-body-tertiary">
{{ org.created|date }}
</td>
<td class="align-middle white-space-nowrap text-end pe-0 ps-4">
<td class="align-middle white-space-nowrap text-end pe-2 ps-4">
{% if perms.inventory.change_organization or perms.inventory.delete_organization %}
<div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"

View File

@ -19,9 +19,9 @@
{% if po_model.po_status == 'fulfilled' %}
<div class="ms-2">
<a class="btn btn-phoenix-primary my-2 mx-2"
href="{{ request.path }}?format=pdf&lang=en"><i class="fa-solid fa-arrow-down me-1"></i>{% trans 'Download PO ENG' %}</a>
href="{{ request.path }}?format=pdf&lang=en"><i class="fa-solid fa-arrow-down me-1"></i>{% trans 'Download PO EN' %}</a>
<a class="btn btn-phoenix-primary my-2"
href="{{ request.path }}?format=pdf&lang=ar"><i class="fa-solid fa-arrow-down me-1"></i>{% trans 'Download PO ARB' %}</a>
href="{{ request.path }}?format=pdf&lang=ar"><i class="fa-solid fa-arrow-down me-1"></i>{% trans 'Download PO AR' %}</a>
</diV>
{% endif %}
</div>

View File

@ -1,6 +1,6 @@
{% load tenhal_tag %}
{% load custom_filters %}
{% load i18n static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
@ -109,50 +109,94 @@
/* Footer Styles */
.document-footer {
position: relative;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 10px;
color: #888;
border-top: 1px solid #ddd;
padding-top: 15px;
margin-top: 30px;
margin: 0 20mm;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.footer-logo {
text-align: center;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
}
.footer-powered p {
font-size: 11px;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
</style>
</head>
<body>
<div class="document-header">
<div>
<h1>{{ dealer.name }}</h1>
<address>
العنوان&nbsp;:&nbsp;{{ dealer.address }}<br>
البريد الإلكتروني&nbsp;:&nbsp;{{ dealer.user.email }}<br>
الهاتف&nbsp;:&nbsp;{{ dealer.phone_number }}<br>
رقم السجل التجاري&nbsp;:&nbsp;{{ dealer.crn }} &nbsp;|&nbsp; رقم ضريبة القيمة المضافة&nbsp;:&nbsp;{{ dealer.vrn }}
</address>
</div>
<div>
<div class="dealer-logo ">
{% if dealer.logo %}
<img class="rounded-soft"
style="max-width:100px;
max-height:100px"
src="{{dealer.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div>
<div>
<h1>أمر شراء</h1>
<h2 style="font-size: 18px;">{{ po_model.po_number }}</h2>
</div>
<div>
<h1>{{ dealer.name }}</h1>
<address>
العنوان: {{ dealer.address }}<br>
البريد الإلكتروني: {{ dealer.user.email }}<br>
الهاتف: {{ dealer.phone_number }}<br>
رقم السجل التجاري: {{ dealer.crn }} &nbsp;|&nbsp; رقم ضريبة القيمة المضافة: {{ dealer.vrn }}
</address>
</div>
</div>
<div class="document-details">
<div class="section">
<h2>التفاصيل:</h2>
<p><span class="label">رقم أمر الشراء:</span> {{ po_model.po_number }}</p>
<p><span class="label">تاريخ الإصدار:</span> {{ po_model.date_fulfilled|date:"Y/m/d" }}</p>
<p><span class="label">رقم أمر الشراء&nbsp;:&nbsp;</span> {{ po_model.po_number }}</p>
<p><span class="label">تاريخ الإصدار&nbsp;:&nbsp;</span> {{ po_model.date_fulfilled|date:"Y/m/d" }}</p>
</div>
<div class="section">
<h2>يُرسل إلى:</h2>
<p><span class="label">المورد:</span> {{ vendor.vendor_name }}</p>
<p><span class="label">البريد الإلكتروني:</span> {{ vendor.email }}</p>
<p><span class="label">الهاتف:</span> {{ vendor.phone }}</p>
<p><span class="label">العنوان:</span> {{ vendor.address_1 }}</p>
<p><span class="label">المورد&nbsp;:&nbsp;</span> {{ vendor.vendor_name }}</p>
<p><span class="label">البريد الإلكتروني&nbsp;:&nbsp;</span> {{ vendor.email }}</p>
<p><span class="label">الهاتف&nbsp;:&nbsp;</span> {{ vendor.phone }}</p>
<p><span class="label">العنوان&nbsp;:&nbsp;</span> {{ vendor.address_1 }}</p>
</div>
</div>
<div class="col-lg-12">
@ -170,13 +214,24 @@
<div class="document-details" style="margin-top: 10px; border-top: 1px solid #ddd; padding-top: 10px;">
<div class="section text-right" style="width: 100%;">
<p class="h4"><span class="label">المبلغ الإجمالي:</span> {{ po_total_amount|floatformat:'2g' }}<span class="icon-saudi_riyal"></span></p>
<p class="h4"><span class="label">المبلغ الإجمالي&nbsp;:&nbsp;</span> {{ po_total_amount|currency_format }}<span class="icon-saudi_riyal"></span></p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
<div class="document-footer footer-flex">
<p>&copy;&nbsp;<strong>هيكل</strong>&nbsp;{% now "Y" %}&nbsp;جميع الحقوق محفوظة.</p>
<p><strong>تنحل</strong>مدعوم من</p>
</div>
</body>
</html>

View File

@ -103,22 +103,49 @@
text-align: right;
}
/* Footer Styles */
/* Footer Styles */
.document-footer {
position: relative;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 10px;
color: #888;
border-top: 1px solid #ddd;
padding-top: 15px;
margin-top: 30px;
margin: 0 20mm;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.footer-logo {
text-align: center;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
}
.footer-powered p {
font-size: 11px;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
</style>
</head>
<body>
@ -126,12 +153,25 @@
<div>
<h1>{{ dealer.name }}</h1>
<address>
Address: {{ dealer.address}}<br>
Email: {{ dealer.user.email }}<br>
Phone: {{dealer.phone_number }}<br>
CRN: {{dealer.crn}}&nbsp;&nbsp;|&nbsp;VRN: {{dealer.vrn}}
Address&nbsp;:&nbsp;{{ dealer.address}}<br>
Email&nbsp;:&nbsp;{{ dealer.user.email }}<br>
Phone&nbsp;:&nbsp;{{dealer.phone_number }}<br>
CRN&nbsp;:&nbsp;{{dealer.crn}}&nbsp;&nbsp;|&nbsp;VRN&nbsp;:&nbsp;{{dealer.vrn}}
</address>
</div>
<div>
<div class="dealer-logo ">
{% if dealer.logo %}
<img class="rounded-soft"
style="max-width:100px;
max-height:100px"
src="{{dealer.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div>
<div>
<h1>PURCHASE ORDER</h1>
<h2 style="font-size: 18px;">{{ po_model.po_number }}</h2>
@ -141,15 +181,15 @@
<div class="document-details">
<div class="section">
<h2>BILL TO:</h2>
<p><span class="label">Vendor: {{vendor.vendor_name}}</span> </p>
<p><span class="label">Email: {{vendor.email}}</span> </p>
<p><span class="label">Phone: {{vendor.phone}}</span> </p>
<p><span class="label">Address: {{vendor.address_1}}</span> </p>
<p><span class="label">Vendor&nbsp;:&nbsp;{{vendor.vendor_name}}</span> </p>
<p><span class="label">Email&nbsp;:&nbsp;{{vendor.email}}</span> </p>
<p><span class="label">Phone&nbsp;:&nbsp;{{vendor.phone}}</span> </p>
<p><span class="label">Address&nbsp;:&nbsp;{{vendor.address_1}}</span> </p>
</div>
<div class="section">
<h2>DETAILS:</h2>
<p><span class="label">PO Number:</span> {{ po_model.po_number }}</p>
<p><span class="label">Issue Date:</span> {{ po_model.date_fulfilled|date:"F j, Y" }}</p>
<p><span class="label">PO Number&nbsp;:&nbsp;</span> {{ po_model.po_number }}</p>
<p><span class="label">Issue Date&nbsp;:&nbsp;</span> {{ po_model.date_fulfilled|date:"F j, Y" }}</p>
</div>
</div>
<div class="col-lg-12">
@ -161,14 +201,25 @@
<div class="document-details" style="margin-top: 30px;">
<div class="section text-right">
<p class="h4"><span class="label">Total Amount:</span> {{ po_total_amount|floatformat:'2g' }}<span class="icon-saudi_riyal"></span></p>
<p class="h4"><span class="label">Total Amount&nbsp;:&nbsp;</span> {{ po_total_amount|currency_format }}<span class="icon-saudi_riyal"></span></p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer footer-flex">
<p>&copy;&nbsp;{% now "Y" %}&nbsp;All rights reserved&nbsp;<strong>Haikal</strong>&nbsp;</p>
<p>Powered By&nbsp;<strong>Tenhal</strong></p>
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
</body>
</html>

View File

@ -6,7 +6,7 @@
<tr class="has-text-centered bg-body-highlight">
<th>البند</th>
<th>سعر الوحدة</th>
<th>كمية أمر الشراء</th>
<th>الكمية</th>
<th>المبلغ</th>
</tr>
</thead>
@ -14,7 +14,7 @@
{% for item in po_items_list %}
<tr>
<td>{{ item.item_model }}</td>
<td class="has-text-centered">{{ item.po_unit_cost }}</td>
<td class="has-text-centered">{{ item.po_unit_cost|currency_format }}</td>
<td class="has-text-centered">{{ item.po_quantity }}</td>
<td class="has-text-centered">
<span class="icon-saudi_riyal"></span>{{ item.po_total_amount | currency_format }}
@ -26,12 +26,12 @@
<tfoot>
<tr>
<td>إجمالي مبلغ أمر الشراء</td>
<td></td>
<td class="has-text-left">إجمالي مبلغ أمر الشراء</td>
<td class="has-text-left">{{po_quantity}}</td>
<td class="has-text-weight-bold has-text-centered">
<span class="icon-saudi_riyal"></span>{{ po_model.po_amount | currency_format }}
</td>
<td></td>
</tr>
</tfoot>

View File

@ -14,7 +14,7 @@
{% for item in po_items_list %}
<tr>
<td>{{ item.item_model }}</td>
<td class="has-text-centered">{{ item.po_unit_cost }}</td>
<td class="has-text-centered">{{ item.po_unit_cost|currency_format}}</td>
<td class="has-text-centered">{{ item.po_quantity }}</td>
<td class="has-text-centered">
<span class="icon-saudi_riyal"></span>{{ item.po_total_amount | currency_format }}
@ -26,13 +26,15 @@
<tfoot>
<tr>
<td></td>
<td class="has-text-right">Total PO Amount</td>
<td>Total PO Amount</td>
<td class="has-text-right"></td>
<td>{{po_quantity}}</td>
<td class="has-text-weight-bold has-text-centered">
<span class="icon-saudi_riyal"></span>{{ po_model.po_amount | currency_format }}
</td>
<td></td>
</tr>
</tfoot>
</table>

View File

@ -134,11 +134,17 @@
{% if perms.django_ledger.change_estimatemodel %}
<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-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 %}"
<a href="{% url 'estimate_print' request.dealer.slug estimate.pk %}?lang=en"
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>
<span class="d-none d-sm-inline-block"><i class="fas fa-print me-2"></i>{% trans 'Print EN' %}</span>
</a>
<a href="{% url 'estimate_print' request.dealer.slug estimate.pk %}?lang=ar"
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 AR' %}</span>
</a>
{% endif %}
{% if estimate.sale_orders.first %}
<!--if sale order exist-->

View File

@ -1,264 +0,0 @@
{% load i18n static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>{% trans "Quotation" %}</title>
<style>
/* General Body and Font Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 12px;
color: #333;
margin: 0;
padding: 0;
}
/* Page Layout and Margins for PDF */
@page {
size: A4;
margin: 20mm;
@top-left {
content: "صفحة " counter(page) " من " counter(pages);
font-size: 10px;
color: #555;
}
}
/* Header Styles */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.document-header .logo {
max-width: 150px;
height: auto;
}
.document-header h1 {
font-size: 24px;
margin: 0;
color: #0056b3; /* A professional blue */
}
.document-header address {
text-align: right;
font-style: normal;
font-size: 10px;
}
/* Document Details Section */
.document-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 1.6;
}
.document-details .section {
width: 48%;
}
.document-details h2 {
font-size: 14px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
margin-bottom: 10px;
color: #555;
}
.document-details p {
margin: 0;
font-size: 12px;
}
.document-details .label {
font-weight: bold;
color: #555;
}
/* Table Styles */
.table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.table th {
background-color: #f2f2f2;
font-weight: bold;
}
.table tfoot td {
border-top: 2px solid #333;
font-weight: bold;
}
.text-right {
text-align: left;
}
.text-left {
text-align: right;
}
.text-center {
text-align: center;
}
/* Footer Styles */
.document-footer {
text-align: center;
font-size: 10px;
color: #888;
border-top: 1px solid #ddd;
padding-top: 15px;
margin-top: 30px;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
</style>
</head>
<body>
<div class="document-header">
<div>
<h1>{{ request.dealer.name }}</h1>
<address>
العنوان: {{ request.dealer.address }}<br>
البريد الإلكتروني: {{ request.dealer.user.email }}<br>
الهاتف: {{ request.dealer.phone_number }}<br>
رقم السجل التجاري: {{ request.dealer.crn }}&nbsp;&nbsp;|&nbsp;الرقم الضريبي: {{ request.dealer.vrn }}
</address>
</div>
<div>
<h1>عرض سعر</h1>
<h2 style="font-size: 18px;">{{ estimate.estimate_number }}</h2>
</div>
</div>
<div class="document-details">
<div class="section">
<h2>{{ estimate.customer.customer_name }}: إلى</h2>
<p><span class="label">العميل: {{ estimate.customer.customer_name }}</span></p>
<p><span class="label">البريد الإلكتروني: {{ estimate.customer.email |default:"N/A"}}</span></p>
<p><span class="label">الهاتف: {{ estimate.customer.phone_number|default:"N/A" }}</span></p>
<p><span class="label">العنوان: {{ estimate.customer.address_1|default:"N/A" }}</span></p>
</div>
<div class="section text-left">
<h2>التفاصيل:</h2>
<p><span class="label">رقم عرض السعر:</span> {{ estimate.estimate_number }}</p>
<p><span class="label">تاريخ الإصدار:</span> {{ estimate.date_approved|date:"Y/m/d" }}</p>
<p><span class="label">طريقة الدفع:</span> {{ estimate.get_terms_display }}</p>
</div>
</div>
<div class="col-lg-12">
<div class="table-responsive">
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">تفاصيل السيارة</span>
</div>
<table class="table table-sm table-bordered m-1">
<thead>
<tr>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الصانع</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الموديل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">السلسلة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الفئة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">السنة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">رقم الهيكل</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الكمية</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">سعر الوحدة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الخصم</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الضريبة</span>
</th>
<th class="text-wrap text-center align-content-center">
<span class="fs-10">الإجمالي</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_make.name }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_model.name }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_serie.name }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_trim.name }}</td>
<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>
</table>
</div>
</div>
{% if data.additional_services %}
<div class="col-lg-12">
<div class="table-responsive">
<div class="d-flex justify-content-between">
<span class="fs-9 fw-thin">الخدمات الإضافية</span>
</div>
<table class="table table-sm table-bordered m-1">
<thead>
<tr>
<th class="text-center fs-10 align-content-center">النوع</th>
<th class="text-center fs-10 align-content-center">القيمة</th>
<th class="text-center fs-10 align-content-center">ضريبة الخدمة</th>
<th class="text-center fs-10 align-content-center">الإجمالي</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.0.name }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price|floatformat:2 }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.1|floatformat:2 }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price_|floatformat:2 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<div class="document-details" style="margin-top: 30px;">
<div class="section text-left">
<p><span class="label">إجمالي ضريبة القيمة المضافة:</span> {{ data.total_vat|floatformat:'2g' }}</p>
<p><span class="label">الإجمالي الكلي:</span> {{ data.grand_total|floatformat:'2g' }}</p>
<p><span class="label">كتابةً:</span> {{ data.grand_total|num_to_words }}</p>
</div>
</div>
<div class="document-footer footer-flex">
<p>&copy;&nbsp;{% now "Y" %}&nbsp;جميع الحقوق محفوظة&nbsp;<strong>هيكل</strong></p>
<p>بواسطة&nbsp;<strong>تنحل</strong></p>
</div>
</body>
</html>

View File

@ -0,0 +1,357 @@
{% load i18n static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>عرض سعر</title>
<style>
/* General Body and Font Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 12px;
color: #333;
margin: 0;
padding: 0;
position: relative;
}
/* Page Layout and Margins for PDF */
@page {
size: A4;
margin: 20mm;
@top-left {
content: "صفحة " counter(page) " من " counter(pages);
font-size: 10px;
color: #555;
}
}
/* Header Styles */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.document-header .logo {
max-width: 150px;
height: auto;
}
.document-header h1 {
font-size: 24px;
margin: 0;
color: #0056b3;
}
.document-header address {
text-align: right;
font-style: normal;
font-size: 10px;
}
/* Document Details Section */
.document-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 1.6;
}
.document-details .section {
width: 48%;
}
.document-details h2 {
font-size: 14px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
margin-bottom: 10px;
color: #555;
}
.document-details p {
margin: 0;
font-size: 12px;
}
.document-details .label {
font-weight: bold;
color: #555;
}
/* Table Styles */
.table {
width: 80%;
border-collapse: collapse;
margin: 20px auto; /* Centering the table */
}
.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.table th {
background-color: #f2f2f2;
font-weight: bold;
}
.table tfoot td {
border-top: 2px solid #333;
font-weight: bold;
}
.text-right {
text-align: left;
}
.text-left {
text-align: right;
}
.text-center {
text-align: center;2px solid #333;
}
/* Responsive and layout helpers */
.table-container {
width: 100%;
overflow-x: auto;
margin-bottom: 20px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.table-header span {
font-size: 9px;
font-weight: lighter;
}
/* Footer Styles */
.document-footer {
position: relative;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 10px;
color: #888;
padding-top: 15px;
margin: 0 20mm;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.footer-logo {
text-align: center;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
}
.footer-powered p {
font-size: 11px;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
</style>
</head>
<body>
<div class="document-header">
<div>
<h1>{{ dealer_info.name }}</h1>
<address>
العنوان&nbsp;:&nbsp;{{ dealer_info.address }}<br>
البريد الإلكتروني&nbsp;:&nbsp;{{ dealer_info.user.email }}<br>
الهاتف&nbsp;:&nbsp;{{ dealer_info.phone_number }}<br>
رقم السجل التجاري&nbsp;:&nbsp;{{dealer_info.crn }}<br>
الرقم الضريبي&nbsp;:&nbsp;{{ dealer_info.vrn }}
</address>
</div>
<div>
<div class="dealer-logo ">
{% if dealer_info.logo %}
<img class="rounded-soft"
style="max-width:100px;
max-height:100px"
src="{{dealer_info.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div>
<div>
<h1>عرض سعر</h1>
<h2 style="font-size: 18px;">{{ estimate.estimate_number }}</h2>
</div>
</div>
<div class="document-details">
<div class="section">
<h2>{{ customer_obj.full_name }}: إلى</h2>
<p><span class="label">العميل&nbsp;:&nbsp;{{ customer_obj.full_name }}</span></p>
<p><span class="label">البريد الإلكتروني&nbsp;:&nbsp;{{ customer_obj.email |default:"N/A"}}</span></p>
<p><span class="label">الهاتف&nbsp;:&nbsp;{{ customer_obj.phone_number|default:"N/A" }}</span></p>
<p><span class="label">العنوان&nbsp;:&nbsp;{{ customer_obj.address|default:"N/A" }}</span></p>
</div>
<div class="section text-left">
<h2>التفاصيل:</h2>
<p><span class="label">رقم عرض السعر&nbsp;:&nbsp;</span> {{estimate.estimate_number }}</p>
<p><span class="label">تاريخ الإصدار&nbsp;:&nbsp;</span> {{ estimate.date_approved|date:"Y/m/d" }}</p>
<p><span class="label">طريقة الدفع&nbsp;:&nbsp;</span> {{ estimate.get_terms_display }}</p>
</div>
</div>
<div class="table-container">
<div class="table-header">
<span>تفاصيل السيارة</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>الصانع</span>
</th>
<th class="text-center">
<span>الموديل</span>
</th>
<th class="text-center">
<span>السلسلة</span>
</th>
<th class="text-center">
<span>الفئة</span>
</th>
<th class="text-center">
<span>السنة</span>
</th>
<th class="text-center">
<span>رقم الهيكل</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">{{ data.car.id_car_make.name }}</td>
<td class="text-center">{{ data.car.id_car_model.name }}</td>
<td class="text-center">{{ data.car.id_car_serie.name }}</td>
<td class="text-center">{{ data.car.id_car_trim.name }}</td>
<td class="text-center">{{ data.car.year }}</td>
<td class="text-center">{{ data.car.vin }}</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container">
<div class="table-header">
<span>التفاصيل المالية</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>الكمية</span>
</th>
<th class="text-center">
<span>سعر الوحدة</span>
</th>
<th class="text-center">
<span>الخصم</span>
</th>
<th class="text-center">
<span>الضريبة</span>
</th>
<th class="text-center">
<span>الإجمالي</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">1</td>
<td class="text-center">{{ data.car.marked_price|currency_format}}</td>
<td class="text-center">{{ data.discount_amount|currency_format}}</td>
<td class="text-center">{{ data.vat_amount|currency_format }}</td>
<td class="text-center">{{ data.final_price|currency_format }}</td>
</tr>
</tbody>
</table>
</div>
{% if data.additional_services %}
<div class="table-container">
<div class="table-header">
<span>الخدمات الإضافية</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">النوع</th>
<th class="text-center">القيمة</th>
<th class="text-center">ضريبة الخدمة</th>
<th class="text-center">الإجمالي</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="text-center">{{ service.0.name }}</td>
<td class="text-center">{{ service.0.price|currency_format }}</td>
<td class="text-center">{{ service.1|currency_format}}</td>
<td class="text-center">{{ service.0.price_|currency_format}}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="text-center"></td>
<td class="text-center">{{ data.total_services_amount|currency_format}}</td>
<td class="text-center">{{ data.total_services_vat|currency_format}}</td>
<td class="text-center">{{ data.total_services_amount_|currency_format}}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<div class="document-details" style="margin-top: 30px; ">
<div class="section text-left">
<p><span class="label">إجمالي ضريبة القيمة المضافة&nbsp;:&nbsp;</span> {{ data.total_vat|currency_format }}</p>
<p><span class="label">الإجمالي الكلي&nbsp;:&nbsp;</span> {{ data.grand_total|currency_format}}</p>
<p><span class="label">كتابةً&nbsp;:&nbsp;</span> {{ data.grand_total|num_to_words }}</p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,357 @@
{% load static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Quotation</title>
<style>
/* General Body and Font Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 12px;
color: #333;
margin: 0;
padding: 0;
position: relative;
}
/* Page Layout and Margins for PDF */
@page {
size: A4;
margin: 20mm;
@top-left {
content: "صفحة " counter(page) " من " counter(pages);
font-size: 10px;
color: #555;
}
}
/* Header Styles */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.document-header .logo {
max-width: 150px;
height: auto;
}
.document-header h1 {
font-size: 24px;
margin: 0;
color: #0056b3;
}
.document-header address {
text-align: right;
font-style: normal;
font-size: 10px;
}
/* Document Details Section */
.document-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 1.6;
}
.document-details .section {
width: 48%;
}
.document-details h2 {
font-size: 14px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
margin-bottom: 10px;
color: #555;
}
.document-details p {
margin: 0;
font-size: 12px;
}
.document-details .label {
font-weight: bold;
color: #555;
}
/* Table Styles */
.table {
width: 80%;
border-collapse: collapse;
margin: 20px auto; /* Centering the table */
}
.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.table th {
background-color: #f2f2f2;
font-weight: bold;
}
.table tfoot td {
border-top: 2px solid #333;
font-weight: bold;
}
.text-right {
text-align: left;
}
.text-left {
text-align: right;
}
.text-center {
text-align: center;2px solid #333;
}
/* Responsive and layout helpers */
.table-container {
width: 100%;
overflow-x: auto;
margin-bottom: 20px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.table-header span {
font-size: 9px;
font-weight: lighter;
}
/* Footer Styles */
.document-footer {
position: relative;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 10px;
color: #888;
padding-top: 15px;
margin: 0 20mm;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.footer-logo {
text-align: center;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
}
.footer-powered p {
font-size: 11px;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
</style>
</head>
<body>
<div class="document-header">
<div>
<h1>{{ dealer_info.name }}</h1>
<address>
Address&nbsp;:&nbsp;{{ dealer_info.address }}<br>
Email&nbsp;:&nbsp;{{ dealer_info.user.email }}<br>
Phone&nbsp;:&nbsp;{{ dealer_info.phone_number }}<br>
Commercial Registration No.&nbsp;:&nbsp;{{dealer_info.crn }}<br>
VAT No.&nbsp;:&nbsp;{{ dealer_info.vrn }}
</address>
</div>
<div>
<div class="dealer-logo ">
{% if dealer_info.logo %}
<img class="rounded-soft"
style="max-width:100px;
max-height:100px"
src="{{dealer_info.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div>
<div>
<h1>Quotation</h1>
<h2 style="font-size: 18px;">{{ estimate.estimate_number }}</h2>
</div>
</div>
<div class="document-details">
<div class="section">
<h2>To: {{ customer_obj.full_name }}</h2>
<p><span class="label">Customer&nbsp;:&nbsp;{{ customer_obj.full_name }}</span></p>
<p><span class="label">Email&nbsp;:&nbsp;{{ customer_obj.email |default:"N/A"}}</span></p>
<p><span class="label">Phone&nbsp;:&nbsp;{{ customer_obj.phone_number|default:"N/A" }}</span></p>
<p><span class="label">Address&nbsp;:&nbsp;{{ customer_obj.address|default:"N/A" }}</span></p>
</div>
<div class="section text-right">
<h2>Details:</h2>
<p><span class="label">Quotation Number&nbsp;:&nbsp;</span> {{ estimate.estimate_number }}</p>
<p><span class="label">Issue Date&nbsp;:&nbsp;</span> {{ estimate.date_approved|date:"Y/m/d" }}</p>
<p><span class="label">Payment Method&nbsp;:&nbsp;</span> {{ estimate.get_terms_display }}</p>
</div>
</div>
<div class="table-container">
<div class="table-header">
<span>Car Details</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>Make</span>
</th>
<th class="text-center">
<span>Model</span>
</th>
<th class="text-center">
<span>Series</span>
</th>
<th class="text-center">
<span>Trim</span>
</th>
<th class="text-center">
<span>Year</span>
</th>
<th class="text-center">
<span>VIN</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">{{ data.car.id_car_make.name }}</td>
<td class="text-center">{{ data.car.id_car_model.name }}</td>
<td class="text-center">{{ data.car.id_car_serie.name }}</td>
<td class="text-center">{{ data.car.id_car_trim.name }}</td>
<td class="text-center">{{ data.car.year }}</td>
<td class="text-center">{{ data.car.vin }}</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container">
<div class="table-header">
<span>Financial Details</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>Quantity</span>
</th>
<th class="text-center">
<span>Unit Price</span>
</th>
<th class="text-center">
<span>Discount</span>
</th>
<th class="text-center">
<span>VAT</span>
</th>
<th class="text-center">
<span>Total</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">1</td>
<td class="text-center">{{ data.car.marked_price|currency_format}}</td>
<td class="text-center">{{ data.discount_amount|currency_format }}</td>
<td class="text-center">{{ data.vat_amount|currency_format}}</td>
<td class="text-center">{{ data.final_price|currency_format}}</td>
</tr>
</tbody>
</table>
</div>
{% if data.additional_services %}
<div class="table-container">
<div class="table-header">
<span>Additional Services</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">Type</th>
<th class="text-center">Value</th>
<th class="text-center">Service VAT</th>
<th class="text-center">Total</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="text-center">{{ service.0.name }}</td>
<td class="text-center">{{ service.0.price|currency_format }}</td>
<td class="text-center">{{ service.1|currency_format}}</td>
<td class="text-center">{{ service.0.price_|currency_format}}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="text-center"></td>
<td class="text-center">{{ data.total_services_amount|currency_format}}</td>
<td class="text-center">{{ data.total_services_vat|currency_format}}</td>
<td class="text-center">{{ data.total_services_amount_|currency_format }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<div class="document-details" style="margin-top: 30px; ">
<div class="section text-right">
<p><span class="label">Total VAT&nbsp;:&nbsp;</span> {{ data.total_vat|currency_format}}</p>
<p><span class="label">Grand Total&nbsp;:&nbsp;</span> {{ data.grand_total|currency_format }}</p>
<p><span class="label">In words&nbsp;:&nbsp;</span> {{ data.grand_total|num_to_words }}</p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
</body>
</html>

View File

@ -144,6 +144,16 @@
{% endif %}
<a href="{% url 'invoice_preview' request.dealer.slug invoice.pk %}"
class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
<a href="{% url 'invoice_preview' request.dealer.slug invoice.pk %}?lang=en"
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 EN' %}</span>
</a>
<a href="{% url 'invoice_preview' request.dealer.slug invoice.pk %}?lang=ar"
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 AR' %}</span>
</a>
</div>
</div>
{{ invoice.amount_owned }}

View File

@ -14,9 +14,9 @@
</h2>
</div>
</div>
<div class="col-auto">
{% comment %} <div class="col-auto">
<div class="d-flex">{% include 'partials/search_box.html' %}</div>
</div>
</div> {% endcomment %}
</div>
<div class="table-responsive px-1 scrollbar">
<table class="table align-items-center table-flush">

View File

@ -1,367 +1,333 @@
{% load i18n static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% trans "Invoice" %}</title>
<link href="{% static 'css/theme.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-default">
<link href="{% static 'css/user.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-default">
<link href="{% static 'css/custom.css' %}" type="text/css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet">
<style>
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
background-color: #f8f9fa;
}
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>{% trans "Invoice Preview" %}</title>
.invoice-container {
width: 210mm;
min-height: 297mm;
padding: 10mm;
margin: 10mm auto;
background: white;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
}
<style>
/* General Body and Font Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 14px;
color: #333;
background-color: #f7f7f7;
margin: 0;
padding: 20px;
}
.invoice-content {
flex-grow: 1;
}
/* Container for the document content */
.document-container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 40px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
.invoice-header {
text-align: center;
border-bottom: 2px solid #dee2e6;
padding-bottom: 10px;
margin-bottom: 20px;
}
/* Header Styles */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.document-header .logo {
max-width: 150px;
height: auto;
}
.document-header h1 {
font-size: 24px;
margin: 0;
color: #0056b3;
}
.document-header h2 {
font-size: 18px;
margin: 0;
}
.document-header address {
text-align: right;
font-style: normal;
font-size: 10px;
}
.qr-code {
text-align: center;
margin-top: 10px;
}
/* Document Details Section */
.document-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 1.6;
}
.document-details .section {
width: 48%;
}
.document-details h2 {
font-size: 14px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
margin-bottom: 10px;
color: #555;
}
.document-details p {
margin: 0;
font-size: 12px;
}
.document-details .label {
font-weight: bold;
color: #555;
}
.qr-code img {
width: 3cm;
height: 3cm;
border-radius: 0.3333333333rem;
}
/* Table Styles */
.table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
font-size: 12px;
}
.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.table th {
background-color: #f2f2f2;
font-weight: bold;
}
.table tfoot td {
border-top: 2px solid #333;
font-weight: bold;
}
.text-right {
text-align: left;
}
.text-left {
text-align: right;
}
.text-center {
text-align: center;
}
.invoice-details, .invoice-table {
font-size: 14px;
}
/* Responsive and layout helpers */
.table-container {
width: 100%;
overflow-x: auto;
margin-bottom: 20px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.table-header span {
font-size: 14px;
font-weight: normal;
}
.invoice-table th {
background-color: #f8f9fa;
font-weight: 600;
}
.invoice-total {
text-align: right;
font-size: 16px;
font-weight: 600;
margin-top: 10px;
}
.footer-note {
margin-top: auto;
padding-top: 10mm;
font-size: 13px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 2px solid #dee2e6; /* Add a top border to separate from content */
}
.logo-img img {
width: 10mm;
height: 10mm;
}
</style>
</head>
<body>
<div class="row p-2">
<div class="col-2">
<button class="btn btn-sm btn-phoenix-danger w-100"
onclick="window.history.back()">الرجوع&nbsp;/&nbsp;Back</button>
/* Footer Styles */
.document-footer {
text-align: center;
font-size: 10px;
color: #888;
border-top: 1px solid #ddd;
padding-top: 15px;
margin-top: 30px;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
margin: 5px 0 0;
}
.footer-powered p {
font-size: 11px;
margin: 0;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
</style>
</head>
<body>
<div class="document-container">
<div class="document-header">
<div>
<h1>{{ dealer_info.name }}</h1>
<address>
العنوان&nbsp;:&nbsp;{{ dealer_info.address }}<br>
البريد الإلكتروني&nbsp;:&nbsp;{{ dealer_info.user.email }}<br>
الهاتف&nbsp;:&nbsp;{{ dealer_info.phone_number }}<br>
رقم السجل التجاري&nbsp;:&nbsp;{{dealer_info.crn }}&nbsp;&nbsp;|&nbsp;الرقم الضريبي&nbsp;:&nbsp;{{ dealer_info.vrn }}
</address>
</div>
<div class="col-2">
<button class="btn btn-sm btn-phoenix-primary w-100" id="download-pdf">تحميل&nbsp;/&nbsp;Download</button>
<div>
<h1>عرض سعر</h1>
<h2>{{ estimate.estimate_number }}</h2>
</div>
<div class="col-8"></div>
</div>
<div class="invoice-container" id="invoice-content">
<div class="invoice-content">
<div class="invoice-header">
<h5 class="fs-5">
<span>Invoice</span>&nbsp;/&nbsp;<span>فاتورة</span>
</h5>
</div>
<div class="invoice-details p-1">
<div class="d-flex justify-content-around align-items-end">
<div class="d-flex justify-content-start align-items-center">
<div class="qr-code">
<img src="{% static 'qr_code/Marwan_qr.png' %}" alt="QR Code">
</div>
</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>
<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 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">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>
</tr>
</thead>
<tbody>
<tr>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_make.name }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_model.name }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_serie.name }}</td>
<td class="ps-1 fs-10 align-content-center">{{ data.car.id_car_trim.name }}</td>
<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>
</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.additional_services %}
<div class="invoice-table p-1">
<table class="table table-sm table-bordered m-1">
<thead>
<tr>
<th class="text-center fs-10 align-content-center">Type&nbsp;/&nbsp;النوع</th>
<th class="text-center fs-10 align-content-center">Price&nbsp;/&nbsp;السعر</th>
<th class="text-center fs-10 align-content-center">Service VAT&nbsp;/&nbsp;ضريبة الخدمة</th>
<th class="text-center fs-10 align-content-center">
<span class="fs-10">Total</span> / <span class="fs-10">الإجمالي</span>
</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="ps-1 text-start fs-10 align-content-center">{{ service.0.name }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price|floatformat }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.1|floatformat }}</td>
<td class="ps-1 text-center fs-10 align-content-center">{{ service.0.price_|floatformat }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<div class="invoice-total d-flex justify-content-end">
<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 class="document-details">
<div class="section">
<h2>{{ estimate.customer.customer_name }}: إلى</h2>
<p><span class="label">العميل&nbsp;:&nbsp;{{ customer_obj.full_name }}</span></p>
<p><span class="label">البريد الإلكتروني&nbsp;:&nbsp;{{ customer_obj.email |default:"N/A"}}</span></p>
<p><span class="label">الهاتف&nbsp;:&nbsp;{{ customer_obj.phone_number|default:"N/A" }}</span></p>
<p><span class="label">العنوان&nbsp;:&nbsp;{{ customer_obj.address|default:"N/A" }}</span></p>
</div>
<div class="footer-note">
<div class="logo-img text-center">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p class="fs-9 fw-bold">
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
<div class="section text-left">
<h2>التفاصيل:</h2>
<p><span class="label">رقم عرض السعر&nbsp;:&nbsp;</span> {{ estimate.estimate_number }}</p>
<p><span class="label">تاريخ الإصدار&nbsp;:&nbsp;</span> {{ estimate.date_approved|date:"Y/m/d" }}</p>
<p><span class="label">طريقة الدفع&nbsp;:&nbsp;</span> {{ estimate.get_terms_display }}</p>
</div>
</div>
<div class="table-container">
<div class="table-header">
<span>تفاصيل السيارة</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>الصانع</span>
</th>
<th class="text-center">
<span>الموديل</span>
</th>
<th class="text-center">
<span>السلسلة</span>
</th>
<th class="text-center">
<span>الفئة</span>
</th>
<th class="text-center">
<span>السنة</span>
</th>
<th class="text-center">
<span>رقم الهيكل</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">{{ data.car.id_car_make.name }}</td>
<td class="text-center">{{ data.car.id_car_model.name }}</td>
<td class="text-center">{{ data.car.id_car_serie.name }}</td>
<td class="text-center">{{ data.car.id_car_trim.name }}</td>
<td class="text-center">{{ data.car.year }}</td>
<td class="text-center">{{ data.car.vin }}</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container">
<div class="table-header">
<span>التفاصيل المالية</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>الكمية</span>
</th>
<th class="text-center">
<span>سعر الوحدة</span>
</th>
<th class="text-center">
<span>الخصم</span>
</th>
<th class="text-center">
<span>الضريبة</span>
</th>
<th class="text-center">
<span>الإجمالي</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">1</td>
<td class="text-center">{{ data.car.marked_price|floatformat:2 }}</td>
<td class="text-center">{{ data.discount_amount|floatformat:2 }}</td>
<td class="text-center">{{ data.vat_amount|floatformat:2 }}</td>
<td class="text-center">{{ data.final_price|floatformat:2 }}</td>
</tr>
</tbody>
</table>
</div>
{% if data.additional_services %}
<div class="table-container">
<div class="table-header">
<span>الخدمات الإضافية</span>
</div>
<p class="fs-11">
<span class="fw-thin">Powered&nbsp;by&nbsp;</span>
<a class="text-decoration-none fs-9"
href="https://tenhal.sa"
style="color: #112e40"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
<table class="table">
<thead>
<tr>
<th class="text-center">النوع</th>
<th class="text-center">القيمة</th>
<th class="text-center">ضريبة الخدمة</th>
<th class="text-center">الإجمالي</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="text-center">{{ service.0.name }}</td>
<td class="text-center">{{ service.0.price|floatformat:2 }}</td>
<td class="text-center">{{ service.1|floatformat:2 }}</td>
<td class="text-center">{{ service.0.price_|floatformat:2 }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="text-center"></td>
<td class="text-center">{{ data.total_services_amount|floatformat:'2g'}}</td>
<td class="text-center">{{ data.total_services_vat|floatformat:'2g'}}</td>
<td class="text-center">{{ data.total_services_amount_|floatformat:'2g' }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<div class="document-details" style="margin-top: 30px; ">
<div class="section text-left">
<p><span class="label">إجمالي ضريبة القيمة المضافة&nbsp;:&nbsp;</span> {{ data.total_vat|floatformat:'2g' }}</p>
<p><span class="label">الإجمالي الكلي&nbsp;:&nbsp;</span> {{ data.grand_total|floatformat:'2g' }}</p>
<p><span class="label">كتابةً&nbsp;:&nbsp;</span> {{ data.grand_total|num_to_words }}</p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
<script src="{% static 'js/html2pdf.bundle.min.js' %}"></script>
<script>
document.getElementById('download-pdf').addEventListener('click', function () {
html2pdf().from(document.getElementById('invoice-content')).set({
margin: 0,
filename: "{{ invoice.invoice_number }}_{{ invoice.customer.customer_name  }}_{{invoice.date_approved|date:'Y-m-d' }}.pdf",
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 3 },
jsPDF: { unit: 'mm', format: 'a3', orientation: 'portrait' }
}).save();
});
</script>
</body>
</html>
</div>
</body>
</html>

View File

@ -0,0 +1,359 @@
{% load static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>فاتورة</title>
<style>
/* General Body and Font Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 12px;
color: #333;
margin: 0;
padding: 0;
position: relative;
}
/* Page Layout and Margins for PDF */
@page {
size: A4;
margin: 20mm;
@top-left {
content: "صفحة " counter(page) " من " counter(pages);
font-size: 10px;
color: #555;
}
}
/* Header Styles */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.document-header .logo {
max-width: 150px;
height: auto;
}
.document-header h1 {
font-size: 24px;
margin: 0;
color: #0056b3;
}
.document-header address {
text-align: right;
font-style: normal;
font-size: 10px;
}
/* Document Details Section */
.document-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 1.6;
}
.document-details .section {
width: 48%;
}
.document-details h2 {
font-size: 14px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
margin-bottom: 10px;
color: #555;
}
.document-details p {
margin: 0;
font-size: 12px;
}
.document-details .label {
font-weight: bold;
color: #555;
}
/* Table Styles */
.table {
width: 80%;
border-collapse: collapse;
margin: 20px auto; /* Centering the table */
}
.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.table th {
background-color: #f2f2f2;
font-weight: bold;
}
.table tfoot td {
border-top: 2px solid #333;
font-weight: bold;
}
.text-right {
text-align: left;
}
.text-left {
text-align: right;
}
.text-center {
text-align: center;2px solid #333;
}
/* Responsive and layout helpers */
.table-container {
width: 100%;
overflow-x: auto;
margin-bottom: 20px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.table-header span {
font-size: 9px;
font-weight: lighter;
}
/* Footer Styles */
.document-footer {
position: relative;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 10px;
color: #888;
padding-top: 15px;
margin: 0 20mm;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.footer-logo {
text-align: center;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
}
.footer-powered p {
font-size: 11px;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
</style>
</head>
<body>
<div class="document-header">
<div>
<h1>{{ dealer_info.name }}</h1>
<address>
العنوان&nbsp;:&nbsp;{{ dealer_info.address }}<br>
البريد الإلكتروني&nbsp;:&nbsp;{{ dealer_info.user.email }}<br>
الهاتف&nbsp;:&nbsp;{{ dealer_info.phone_number }}<br>
رقم السجل التجاري&nbsp;:&nbsp;{{dealer_info.crn }}<br>
الرقم الضريبي&nbsp;:&nbsp;{{ dealer_info.vrn }}
</address>
</div>
<div>
<div class="dealer-logo ">
{% if dealer_info.logo %}
<img class="rounded-soft"
style="max-width:100px;
max-height:100px"
src="{{dealer_info.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div>
<div>
<h1>فاتورة</h1>
<h2 style="font-size: 18px;">{{ invoice.invoice_number }}</h2>
</div>
</div>
<div class="document-details">
<div class="section">
<h2>{{ customer_obj.full_name }}: إلى</h2>
<p><span class="label">العميل&nbsp;:&nbsp;{{ customer_obj.full_name }}</span></p>
<p><span class="label">البريد الإلكتروني&nbsp;:&nbsp;{{ customer_obj.email |default:"N/A"}}</span></p>
<p><span class="label">الهاتف&nbsp;:&nbsp;{{ customer_obj.phone_number|default:"N/A" }}</span></p>
<p><span class="label">العنوان&nbsp;:&nbsp;{{ customer_obj.address|default:"N/A" }}</span></p>
</div>
<div class="section text-left">
<h2>التفاصيل:</h2>
<p><span class="label">رقم عرض السعر&nbsp;:&nbsp;</span> {{ invoice.invoice_number }}</p>
<p><span class="label">تاريخ الإصدار&nbsp;:&nbsp;</span> {{ invoice.date_approved|date:"Y/m/d" }}</p>
<p><span class="label">طريقة الدفع&nbsp;:&nbsp;</span> {{ invoice.get_terms_display }}</p>
</div>
</div>
<div class="table-container">
<div class="table-header">
<span>تفاصيل السيارة</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>الصانع</span>
</th>
<th class="text-center">
<span>الموديل</span>
</th>
<th class="text-center">
<span>السلسلة</span>
</th>
<th class="text-center">
<span>الفئة</span>
</th>
<th class="text-center">
<span>السنة</span>
</th>
<th class="text-center">
<span>رقم الهيكل</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">{{ data.car.id_car_make.name }}</td>
<td class="text-center">{{ data.car.id_car_model.name }}</td>
<td class="text-center">{{ data.car.id_car_serie.name }}</td>
<td class="text-center">{{ data.car.id_car_trim.name }}</td>
<td class="text-center">{{ data.car.year }}</td>
<td class="text-center">{{ data.car.vin }}</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container">
<div class="table-header">
<span>التفاصيل المالية</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>الكمية</span>
</th>
<th class="text-center">
<span>سعر الوحدة</span>
</th>
<th class="text-center">
<span>الخصم</span>
</th>
<th class="text-center">
<span>الضريبة</span>
</th>
<th class="text-center">
<span>الإجمالي</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">1</td>
<td class="text-center">{{ data.car.marked_price|currency_format }}</td>
<td class="text-center">{{ data.discount_amount|currency_format}}</td>
<td class="text-center">{{ data.vat_amount|currency_format}}</td>
<td class="text-center">{{ data.final_price|currency_format }}</td>
</tr>
</tbody>
</table>
</div>
{% if data.additional_services %}
<div class="table-container">
<div class="table-header">
<span>الخدمات الإضافية</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">النوع</th>
<th class="text-center">القيمة</th>
<th class="text-center">ضريبة الخدمة</th>
<th class="text-center">الإجمالي</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="text-center">{{ service.0.name }}</td>
<td class="text-center">{{ service.0.price|currency_format}}</td>
<td class="text-center">{{ service.1|currency_format }}</td>
<td class="text-center">{{ service.0.price_|currency_format}}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="text-center"></td>
<td class="text-center">{{ data.total_services_amount|currency_format}}</td>
<td class="text-center">{{ data.total_services_vat|currency_format}}</td>
<td class="text-center">{{ data.total_services_amount_|currency_format }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<div class="document-details" style="margin-top: 30px; ">
<div class="section text-left">
<p><span class="label">إجمالي ضريبة القيمة المضافة&nbsp;:&nbsp;</span> {{ data.total_vat|currency_format }}</p>
<p><span class="label">الإجمالي الكلي&nbsp;:&nbsp;</span> {{ data.grand_total|currency_format}}</p>
<p><span class="label">كتابةً&nbsp;:&nbsp;</span> {{ data.grand_total|num_to_words }}</p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,357 @@
{% load static custom_filters num2words_tags %}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Invoice</title>
<style>
/* General Body and Font Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 12px;
color: #333;
margin: 0;
padding: 0;
position: relative;
}
/* Page Layout and Margins for PDF */
@page {
size: A4;
margin: 20mm;
@top-left {
content: "صفحة " counter(page) " من " counter(pages);
font-size: 10px;
color: #555;
}
}
/* Header Styles */
.document-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.document-header .logo {
max-width: 150px;
height: auto;
}
.document-header h1 {
font-size: 24px;
margin: 0;
color: #0056b3;
}
.document-header address {
text-align: right;
font-style: normal;
font-size: 10px;
}
/* Document Details Section */
.document-details {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
line-height: 1.6;
}
.document-details .section {
width: 48%;
}
.document-details h2 {
font-size: 14px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
margin-bottom: 10px;
color: #555;
}
.document-details p {
margin: 0;
font-size: 12px;
}
.document-details .label {
font-weight: bold;
color: #555;
}
/* Table Styles */
.table {
width: 80%;
border-collapse: collapse;
margin: 20px auto; /* Centering the table */
}
.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.table th {
background-color: #f2f2f2;
font-weight: bold;
}
.table tfoot td {
border-top: 2px solid #333;
font-weight: bold;
}
.text-right {
text-align: left;
}
.text-left {
text-align: right;
}
.text-center {
text-align: center;2px solid #333;
}
/* Responsive and layout helpers */
.table-container {
width: 100%;
overflow-x: auto;
margin-bottom: 20px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.table-header span {
font-size: 9px;
font-weight: lighter;
}
/* Footer Styles */
.document-footer {
position: relative;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 10px;
color: #888;
padding-top: 15px;
margin: 0 20mm;
}
.footer-flex {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.footer-logo {
text-align: center;
}
.footer-logo img {
height: 20px;
width: 20px;
}
.footer-logo p {
font-size: 9px;
font-weight: bold;
}
.footer-powered p {
font-size: 11px;
}
.footer-powered span {
font-weight: lighter;
}
.footer-powered a {
color: #112e40;
text-decoration: none;
font-size: 9px;
}
</style>
</head>
<body>
<div class="document-header">
<div>
<h1>{{ dealer_info.name }}</h1>
<address>
Address&nbsp;:&nbsp;{{ dealer_info.address }}<br>
Email&nbsp;:&nbsp;{{ dealer_info.user.email }}<br>
Phone&nbsp;:&nbsp;{{ dealer_info.phone_number }}<br>
Commercial Registration No.&nbsp;:&nbsp;{{dealer_info.crn }}<br>
VAT No.&nbsp;:&nbsp;{{ dealer_info.vrn }}
</address>
</div>
<div>
<div class="dealer-logo ">
{% if dealer_info.logo %}
<img class="rounded-soft"
style="max-width:100px;
max-height:100px"
src="{{dealer_info.logo.url|default:'' }}"
alt="Dealer Logo" />
{% endif %}
</div>
</div>
<div>
<h1>Invoice</h1>
<h2 style="font-size: 18px;">{{ invoice.invoice_number }}</h2>
</div>
</div>
<div class="document-details">
<div class="section">
<h2>To: {{ customer_obj.full_name }}</h2>
<p><span class="label">Customer&nbsp;:&nbsp;{{ customer_obj.full_name }}</span></p>
<p><span class="label">Email&nbsp;:&nbsp;{{ customer_obj.email |default:"N/A"}}</span></p>
<p><span class="label">Phone&nbsp;:&nbsp;{{ customer_obj.phone_number|default:"N/A" }}</span></p>
<p><span class="label">Address&nbsp;:&nbsp;{{ customer_obj.address|default:"N/A" }}</span></p>
</div>
<div class="section text-right">
<h2>Details:</h2>
<p><span class="label">Quotation Number&nbsp;:&nbsp;</span> {{ invoice.invoice_number }}</p>
<p><span class="label">Issue Date&nbsp;:&nbsp;</span> {{ invoice.date_approved|date:"Y/m/d" }}</p>
<p><span class="label">Payment Method&nbsp;:&nbsp;</span> {{ invoiceget_terms_display }}</p>
</div>
</div>
<div class="table-container">
<div class="table-header">
<span>Car Details</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>Make</span>
</th>
<th class="text-center">
<span>Model</span>
</th>
<th class="text-center">
<span>Series</span>
</th>
<th class="text-center">
<span>Trim</span>
</th>
<th class="text-center">
<span>Year</span>
</th>
<th class="text-center">
<span>VIN</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">{{ data.car.id_car_make.name }}</td>
<td class="text-center">{{ data.car.id_car_model.name }}</td>
<td class="text-center">{{ data.car.id_car_serie.name }}</td>
<td class="text-center">{{ data.car.id_car_trim.name }}</td>
<td class="text-center">{{ data.car.year }}</td>
<td class="text-center">{{ data.car.vin }}</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container">
<div class="table-header">
<span>Financial Details</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">
<span>Quantity</span>
</th>
<th class="text-center">
<span>Unit Price</span>
</th>
<th class="text-center">
<span>Discount</span>
</th>
<th class="text-center">
<span>VAT</span>
</th>
<th class="text-center">
<span>Total</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">1</td>
<td class="text-center">{{ data.car.marked_price|currency_format}}</td>
<td class="text-center">{{ data.discount_amount|currency_format }}</td>
<td class="text-center">{{ data.vat_amount|currency_format}}</td>
<td class="text-center">{{ data.final_price|currency_format }}</td>
</tr>
</tbody>
</table>
</div>
{% if data.additional_services %}
<div class="table-container">
<div class="table-header">
<span>Additional Services</span>
</div>
<table class="table">
<thead>
<tr>
<th class="text-center">Type</th>
<th class="text-center">Value</th>
<th class="text-center">Service VAT</th>
<th class="text-center">Total</th>
</tr>
</thead>
<tbody>
{% for service in data.additional_services.services %}
<tr>
<td class="text-center">{{ service.0.name }}</td>
<td class="text-center">{{ service.0.price|currency_format }}</td>
<td class="text-center">{{ service.1|currency_format}}</td>
<td class="text-center">{{ service.0.price_|currency_format}}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="text-center"></td>
<td class="text-center">{{ data.total_services_amount|currency_format}}</td>
<td class="text-center">{{ data.total_services_vat|currency_format}}</td>
<td class="text-center">{{ data.total_services_amount_|currency_format }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<div class="document-details" style="margin-top: 30px; ">
<div class="section text-right">
<p><span class="label">Total VAT&nbsp;:&nbsp;</span> {{ data.total_vat|currency_format}}</p>
<p><span class="label">Grand Total&nbsp;:&nbsp;</span> {{ data.grand_total|currency_format}}</p>
<p><span class="label">In words&nbsp;:&nbsp;</span> {{ data.grand_total|num_to_words }}</p>
</div>
</div>
<hr style="border-bottom:1px solid #ccc; ">
<div class="document-footer">
<div class="footer-logo">
<img src="{% static 'images/logos/logo-d-pdf.png' %}" alt="Logo" />
<p>
<span>Haikal</span>&nbsp;|&nbsp;<span>هيكل</span>
</p>
</div>
<div class="footer-powered">
<p>
<span>Powered&nbsp;by&nbsp;</span>
<a href="https://tenhal.sa"><span>TENHAL</span>&nbsp;|&nbsp;<span>تنحل</span></a>
</p>
</div>
</div>
</body>
</html>

View File

@ -15,9 +15,9 @@
</h2>
</div>
</div>
<div class="col-auto">
{% comment %} <div class="col-auto">
<div class="d-flex">{% include 'partials/search_box.html' %}</div>
</div>
</div> {% endcomment %}
</div>
<div class="table-responsive scrollbar mx-n1 px-1">
<table class="table align-items-center table-flush">

View File

@ -101,7 +101,7 @@
<a class="fs-8 fw-bold"
href="{% url 'vendor_detail' request.dealer.slug vendor.slug %}">{{ vendor.arabic_name }}</a>
<div class="d-flex align-items-center">
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2">{{ vendor.name }}</p>
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2">{{ vendor.name|title }}</p>
<!--<span class="badge badge-phoenix badge-phoenix-primary">{{ vendor.vendor_model.uuid }}</span>-->
</div>
</div>