This commit is contained in:
gitea 2025-01-28 12:28:05 +00:00
parent 7142975004
commit a3cb3c5f55
13 changed files with 424 additions and 113 deletions

208
Pipfile Normal file
View File

@ -0,0 +1,208 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
aiohappyeyeballs = "==2.4.4"
aiohttp = "==3.11.11"
aiohttp-retry = "==2.8.3"
aiosignal = "==1.3.2"
alabaster = "==1.0.0"
albucore = "==0.0.23"
albumentations = "==2.0.0"
annotated-types = "==0.7.0"
anyio = "==4.8.0"
arabic-reshaper = "==3.0.0"
asgiref = "==3.8.1"
astor = "==0.8.1"
astroid = "==3.3.8"
attrs = "==23.2.0"
autopep8 = "==2.3.2"
babel = "==2.15.0"
beautifulsoup4 = "==4.12.3"
bleach = "==6.2.0"
blinker = "==1.9.0"
brotli = "==1.1.0"
certifi = "==2024.12.14"
cffi = "==1.17.1"
chardet = "==5.2.0"
charset-normalizer = "==3.4.1"
click = "==8.1.8"
colorama = "==0.4.6"
commonmark = "==0.9.1"
contourpy = "==1.3.1"
crispy-bootstrap5 = "==2024.10"
cryptography = "==44.0.0"
cssselect2 = "==0.7.0"
ctranslate2 = "==4.5.0"
cycler = "==0.12.1"
cython = "==3.0.11"
decorator = "==5.1.1"
desert = "==2020.11.18"
dill = "==0.3.9"
distro = "==1.9.0"
dj-rest-auth = "==7.0.1"
dj-shop-cart = "==7.1.1"
django = "==5.1.5"
django-allauth = "==65.3.1"
django-appointment = "==3.7.4"
django-autoslug = "==1.9.9"
django-bootstrap5 = "==24.3"
django-classy-tags = "==4.1.0"
django-cors-headers = "==4.6.0"
django-countries = "==7.6.1"
django-crispy-forms = "==2.3"
django-debug-toolbar = "==5.0.1"
django-extensions = "==3.2.3"
django-filter = "==24.3"
django-formtools = "==2.5.1"
django-ledger = "==0.7.3"
django-money = "==3.5.3"
django-nine = "==0.2.7"
django-nonefield = "==0.4"
django-phonenumber-field = "==8.0.0"
django-picklefield = "==3.2"
django-prometheus = "==2.3.1"
django-q2 = "==1.7.6"
django-sekizai = "==4.1.0"
django-silk = "==5.3.2"
django-sms = "==0.7.0"
django-sslserver = "==0.22"
django-tables2 = "==2.7.5"
django-treebeard = "==4.7.1"
django-view-breadcrumbs = "==2.5.1"
djangocms-admin-style = "==3.3.1"
djangorestframework = "==3.15.2"
djangorestframework-simplejwt = "==5.4.0"
djangoviz = "==0.1.1"
docutils = "==0.21.2"
easy-thumbnails = "==2.10"
et-xmlfile = "==2.0.0"
faker = "==33.3.1"
filelock = "==3.16.1"
fire = "==0.7.0"
flask = "==3.1.0"
fonttools = "==4.55.3"
frozenlist = "==1.5.0"
fsspec = "==2024.12.0"
gprof2dot = "==2024.6.6"
graphqlclient = "==0.2.4"
greenlet = "==3.1.1"
h11 = "==0.14.0"
h2 = "==4.1.0"
hpack = "==4.0.0"
hstspreload = "==2025.1.1"
httpcore = "==1.0.7"
httpx = "==0.28.1"
hyperframe = "==6.0.1"
idna = "==3.10"
imageio = "==2.37.0"
imagesize = "==1.4.1"
imgaug = "==0.4.0"
iso4217 = "==1.12.20240625"
isodate = "==0.7.2"
isort = "==5.13.2"
itsdangerous = "==2.2.0"
jinja2 = "==3.1.5"
jiter = "==0.8.2"
joblib = "==1.4.2"
kiwisolver = "==1.4.8"
lazy-loader = "==0.4"
ledger = "==1.0.1"
libretranslatepy = "==2.1.4"
lmdb = "==1.6.2"
lxml = "==5.3.0"
markdown = "==3.7"
markdown-it-py = "==3.0.0"
markupsafe = "==3.0.2"
marshmallow = "==3.25.1"
matplotlib = "==3.10.0"
mccabe = "==0.7.0"
mdurl = "==0.1.2"
mouseinfo = "==0.1.3"
mpmath = "==1.3.0"
multidict = "==6.1.0"
mypy-extensions = "==1.0.0"
networkx = "==3.4.2"
newrelic = "==10.4.0"
nltk = "==3.9.1"
libquadmath = "==2.2.2"
oauthlib = "==3.2.2"
ofxtools = "==0.9.5"
openai = "==1.59.8"
opencv-contrib-python = "==4.11.0.86"
opencv-python = "==4.11.0.86"
opencv-python-headless = "==4.11.0.86"
openpyxl = "==3.1.5"
opt-einsum = "==3.4.0"
outcome = "==1.3.0.post0"
packaging = "==24.2"
pandas = "==2.2.3"
pango = "==0.0.1"
pdfkit = "==1.0.0"
phonenumbers = "==8.13.53"
pillow = "==11.1.0"
platformdirs = "==4.3.6"
prometheus-client = "==0.21.1"
propcache = "==0.2.1"
protobuf = "==5.29.3"
psycopg = "==3.2.4"
psycopg-binary = "==3.2.4"
psycopg-c = "==3.2.4"
py-moneyed = "==3.0"
pyautogui = "==0.9.54"
pyclipper = "==1.3.0.post6"
pycodestyle = "==2.12.1"
pycparser = "==2.22"
pydantic = "==2.10.5"
pydantic-core = "==2.27.2"
pydotplus = "==2.0.2"
pydyf = "==0.11.0"
pygetwindow = "==0.0.9"
pygments = "==2.19.1"
pyjwt = "==2.10.1"
pylint = "==3.3.3"
pymsgbox = "==1.0.9"
pymysql = "==1.1.1"
pyobjc-core = "==11.0"
pyobjc-framework-cocoa = "==11.0"
pyobjc-framework-quartz = "==11.0"
pyparsing = "==3.2.1"
pyperclip = "==1.9.0"
pyphen = "==0.17.0"
pypng = "==0.20220715.0"
pyrect = "==0.2.0"
pyscreeze = "==1.0.1"
pyserial = "==3.5"
pysocks = "==1.7.1"
python-bidi = "==0.6.3"
python-dateutil = "==2.9.0.post0"
python-docx = "==1.1.2"
python-openid = "==2.2.5"
python3-saml = "==1.16.0"
pytweening = "==1.2.0"
pytz = "==2024.2"
pyvin = "==0.0.2"
pywa = "==2.7.0"
pywhat = "==5.1.0"
pywhatkit = "==5.4"
pyyaml = "==6.0.2"
pyzbar = "==0.1.9"
qrcode = "==8.0"
rapidfuzz = "==3.11.0"
regex = "==2024.11.6"
reportlab = "==4.2.5"
requests = "==2.32.3"
requests-oauthlib = "==2.0.0"
rfc3986 = "==2.0.0"
rich = "==13.9.4"
rubicon-objc = "==0.5.0"
sacremoses = "==0.1.1"
scikit-image = "==0.25.0"
scikit-learn = "*"
[dev-packages]
[requires]
python_version = "3.12"

Binary file not shown.

View File

@ -9,6 +9,8 @@ from phonenumber_field.phonenumber import PhoneNumber
from .mixins import AddClassMixin
from django.forms.models import inlineformset_factory
from django_ledger.forms.invoice import InvoiceModelCreateForm as InvoiceModelCreateFormBase
from django_ledger.forms.estimate import EstimateModelCreateForm as EstimateModelCreateFormBase
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
from django_ledger.forms.vendor import VendorModelForm
from .models import (
@ -675,7 +677,10 @@ class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
self.fields['prepaid_account'].widget = forms.HiddenInput()
self.fields['unearned_account'].widget = forms.HiddenInput()
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
def get_customer_queryset(self):
if 'customer' in self.fields:
self.fields['customer'].queryset = self.USER_MODEL.dealer.entity.get_customers()
class BillModelCreateForm(BillModelCreateFormBase):
def __init__(self, *args, **kwargs):
@ -692,4 +697,15 @@ class SaleOrderForm(forms.ModelForm):
fields = ['estimate','payment_method', 'comments']
widgets = {
'comments': forms.Textarea(attrs={'rows': 3}),
}
}
class EstimateModelCreateForm(EstimateModelCreateFormBase):
def __init__(self, *args, entity_slug, user_model, **kwargs):
super(EstimateModelCreateForm, self).__init__(*args, entity_slug=entity_slug, user_model=user_model, **kwargs)
self.ENTITY_SLUG = entity_slug
self.USER_MODEL = user_model
self.fields['customer'].queryset = self.get_customer_queryset()
def get_customer_queryset(self):
return self.USER_MODEL.dealer.entity.get_customers()

View File

@ -87,13 +87,13 @@ def create_ledger_entity(sender, instance, created, **kwargs):
use_accrual_method=False,
fy_start_month=1,
)
if entity:
if entity:
instance.entity = entity
instance.save()
coa = entity.create_chart_of_accounts(
assign_as_default=True, commit=True, coa_name=_(f"{entity_name}-COA")
)
)
if coa:
# Create unit of measures
entity.create_uom(name="Unit", unit_abbr="unit")
@ -688,9 +688,10 @@ def create_item_model(sender, instance, created, **kwargs):
name=instance.vin,
item_type=ItemModel.ITEM_TYPE_MATERIAL,
uom_model=uom,
coa_model=coa,
additional_info={}
coa_model=coa,
)
product.additional_info = {}
product.save()
product = entity.get_items_all().filter(name=instance.vin).first()
product.additional_info.update({'car_info': instance.to_dict()})
@ -702,6 +703,7 @@ def update_item_model_cost(sender, instance, created, **kwargs):
entity = instance.car.dealer.entity
product = entity.get_items_all().filter(name=instance.car.vin).first()
product.default_amount = instance.selling_price
product.additional_info = {}
product.additional_info.update({"car_finance":instance.to_dict()})

View File

@ -1,3 +1,4 @@
from django.core.exceptions import ObjectDoesNotExist
import json
import random
import datetime
@ -577,3 +578,98 @@ def to_dict(obj):
else:
obj_dict[key] = str(value)
return obj_dict
class CarFinanceCalculator:
VAT_OBJ_NAME = 'vat_rate'
CAR_FINANCE_KEY = 'car_finance'
CAR_INFO_KEY = 'car_info'
ADDITIONAL_SERVICES_KEY = 'additional_services'
def __init__(self, model):
self.model = model
self.vat_rate = self._get_vat_rate()
self.item_transactions = self._get_item_transactions()
self.additional_services = self._get_additional_services()
def _get_vat_rate(self):
vat = models.VatRate.objects.filter(is_active=True).first()
if not vat:
raise ObjectDoesNotExist("No active VAT rate found")
return vat.rate
def _get_item_transactions(self):
return self.model.get_itemtxs_data()[0].all()
@staticmethod
def _get_quantity(item):
return item.ce_quantity or item.quantity
def _get_nested_value(self, item, *keys):
current = item.item_model.additional_info
for key in keys:
current = current.get(key, {})
return current
def _get_car_data(self, item):
quantity = self._get_quantity(item)
car_finance = self._get_nested_value(item, self.CAR_FINANCE_KEY)
car_info = self._get_nested_value(item, self.CAR_INFO_KEY)
unit_price = Decimal(car_finance.get('selling_price', 0))
return {
"item_number": item.item_model.item_number,
"vin": car_info.get('vin'),
"make": car_info.get('make'),
"model": car_info.get('model'),
"year": car_info.get('year'),
"trim": car_info.get('mileage'), # Verify if this should actually be mileage
"cost_price": car_finance.get('cost_price'),
"selling_price": car_finance.get('selling_price'),
"discount": car_finance.get('discount_amount'),
"quantity": quantity,
"unit_price": unit_price,
"total": unit_price * Decimal(quantity),
"total_vat": car_finance.get('total_vat'),
"additional_services": self._get_nested_value(item, self.ADDITIONAL_SERVICES_KEY),
}
def _get_additional_services(self):
return [
{"name": service.name, "price": service.price}
for item in self.item_transactions
for service in self._get_nested_value(item, self.ADDITIONAL_SERVICES_KEY) or []
]
def calculate_totals(self):
total_price = sum(
Decimal(self._get_nested_value(item, self.CAR_FINANCE_KEY, 'selling_price')) *
Decimal(self._get_quantity(item))
for item in self.item_transactions
)
total_vat_amount = total_price * self.vat_rate
total_discount = sum(
Decimal(self._get_nested_value(item, self.CAR_FINANCE_KEY, 'discount_amount'))
for item in self.item_transactions
)
return {
"total_price": total_price,
"total_vat_amount": total_vat_amount,
"total_discount": total_discount,
"grand_total": (total_price + total_vat_amount) - total_discount,
}
def get_finance_data(self):
totals = self.calculate_totals()
return {
"cars": [self._get_car_data(item) for item in self.item_transactions],
"quantity": sum(self._get_quantity(item) for item in self.item_transactions),
"total_price": totals['total_price'],
"total_vat": totals['total_vat_amount'] + totals['total_price'],
"total_discount": totals['total_discount'],
"grand_total": totals['grand_total'],
"additionals": self.additional_services,
"vat": self.vat_rate,
}

View File

@ -1,3 +1,4 @@
from rich import print
from decimal import Decimal
from django.core.paginator import Paginator
from django.forms import DateField, DateInput, HiddenInput, TextInput
@ -34,7 +35,8 @@ from django_ledger.forms.invoice import (
PaidInvoiceModelUpdateForm,
)
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
from django_ledger.forms.estimate import EstimateModelCreateForm
# from django_ledger.forms.estimate import EstimateModelCreateForm
from django_ledger.forms.invoice import InvoiceModelCreateForm
from django_ledger.forms.item import (
ServiceCreateForm,
@ -82,6 +84,7 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth.models import Group
from .utils import (
CarFinanceCalculator,
calculate_vat_amount,
get_calculations,
get_car_finance_data,
@ -2349,7 +2352,7 @@ def create_estimate(request):
}
)
form = EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
form = forms.EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
form.fields["customer"].queryset = entity.get_customers().filter(active=True)
car_list = models.Car.objects.filter(
dealer=dealer, finances__selling_price__gt=0
@ -2378,14 +2381,17 @@ class EstimateDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs):
estimate = kwargs.get("object")
if estimate.get_itemtxs_data():
data = get_financial_values(estimate)
kwargs["vat_amount"] = data["vat_amount"]
kwargs["total"] = data["grand_total"]
kwargs["discount_amount"] = data["discount_amount"]
kwargs["vat"] = data["vat"]
kwargs["car_and_item_info"] = data["car_and_item_info"]
kwargs["additional_services"] = data["additional_services"]
# data = get_financial_values(estimate)
calculator = CarFinanceCalculator(estimate)
finance_data = calculator.get_finance_data()
# kwargs["vat_amount"] = data["vat_amount"]
# kwargs["total"] = data["grand_total"]
# kwargs["discount_amount"] = data["discount_amount"]
# kwargs["vat"] = data["vat"]
# kwargs["car_and_item_info"] = data["car_and_item_info"]
# kwargs["additional_services"] = data["additional_services"]
kwargs['data'] = finance_data
print(finance_data)
kwargs["invoice"] = (
InvoiceModel.objects.all().filter(ce_model=estimate).first()
)
@ -2400,8 +2406,8 @@ def create_sale_order(request, pk):
form = forms.SaleOrderForm(request.POST)
if form.is_valid():
form.save()
if not estimate.is_completed():
estimate.mark_as_completed()
if not estimate.is_approved():
estimate.mark_as_approved()
estimate.save()
messages.success(request, "Sale Order created successfully")
return redirect("estimate_detail", pk=pk)
@ -2409,11 +2415,13 @@ def create_sale_order(request, pk):
form = forms.SaleOrderForm()
form.fields["estimate"].queryset = EstimateModel.objects.filter(pk=pk)
form.initial['estimate'] = estimate
data = get_car_finance_data(estimate)
# data = get_car_finance_data(estimate)
calculator = CarFinanceCalculator(estimate)
finance_data = calculator.get_finance_data()
return render(
request,
"sales/estimates/sale_order_form.html",
{"form": form, "estimate": estimate, "items": items,"data": data},
{"form": form, "estimate": estimate, "items": items,"data": finance_data},
)
def preview_sale_order(request,pk):
@ -2510,14 +2518,16 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
invoice = kwargs.get("object")
if invoice.get_itemtxs_data():
data = get_financial_values(invoice)
kwargs["vat_amount"] = data["vat_amount"]
kwargs["total"] = data["grand_total"]
kwargs["discount_amount"] = data["discount_amount"]
kwargs["vat"] = data["vat"]
kwargs["car_and_item_info"] = data["car_and_item_info"]
kwargs["additional_services"] = data["additional_services"]
# data = get_financial_values(invoice)
calculator = CarFinanceCalculator(invoice)
finance_data = calculator.get_finance_data()
# kwargs["vat_amount"] = data["vat_amount"]
# kwargs["total"] = data["grand_total"]
# kwargs["discount_amount"] = data["discount_amount"]
# kwargs["vat"] = data["vat"]
# kwargs["car_and_item_info"] = data["car_and_item_info"]
# kwargs["additional_services"] = data["additional_services"]
kwargs["data"] = finance_data
kwargs["payments"] = JournalEntryModel.objects.filter(
ledger=invoice.ledger
).all()

Binary file not shown.

View File

@ -1,70 +1,45 @@
from decimal import Decimal
from django_ledger.models import EstimateModel
from django_ledger.models import EstimateModel,EntityModel
from rich import print
from datetime import date
from inventory.models import VatRate
from inventory.utils import CarFinanceCalculator
def run():
# estimate = EstimateModel.objects.first()
# calculator = CarFinanceCalculator(estimate)
# finance_data = calculator.get_finance_data()
# print(finance_data)
# entity = EntityModel.objects.get(name="ismail")
# bs_report = entity.get_balance_sheet_statement(
# to_date=date(2025, 1, 1),
# save_pdf=False,
# filepath='./'
# )
# ic_report = entity.get_income_statement(
# from_date=date(2022, 1, 1),
# to_date=date(2022, 12, 31),
# save_pdf=False,
# filepath='./'
# )
# # print(bs_report)
# print(ic_report.get_report_data())
estimate = EstimateModel.objects.first()
vat = VatRate.objects.filter(is_active=True).first()
data = estimate.get_itemtxs_data()[0].all()
total = sum(
[
Decimal(item.item_model.additional_info["car_finance"]["selling_price"])
* Decimal(item.ce_quantity or item.quantity)
for item in data
]
)
additional_services = []
for i in data:
if i.item_model.additional_info["additional_services"]:
additional_services.extend(
[
{"name": x.name, "price": x.price}
for x in i.item_model.additional_info["additional_services"]
]
)
cars_info = {
"cars": [
{
"vin": x.item_model.additional_info["car_info"]["vin"],
"make": x.item_model.additional_info["car_info"]["make"],
"model": x.item_model.additional_info["car_info"]["model"],
"year": x.item_model.additional_info["car_info"]["year"],
"trim": x.item_model.additional_info["car_info"]["mileage"],
"cost_price": x.item_model.additional_info["car_finance"]["cost_price"],
"selling_price": x.item_model.additional_info["car_finance"][
"selling_price"
],
"discount": x.item_model.additional_info["car_finance"][
"discount_amount"
],
"total": x.item_model.additional_info["car_finance"]["total"],
"additional_services": x.item_model.additional_info[
"additional_services"
],
}
for x in data
],
"quantity": data.count(),
"total_price": total,
"total__vat": (total * vat.rate) + total,
"total_discount": sum(
Decimal(x.item_model.additional_info["car_finance"]["discount_amount"])
for x in data
),
"grand_total": Decimal(total * vat.rate)
+ total
- Decimal(
sum(
Decimal(x.item_model.additional_info["car_finance"]["discount_amount"])
for x in data
)
),
"additionals": additional_services,
}
print(cars_info)
calculator = CarFinanceCalculator(estimate)
finance_data = calculator.get_finance_data()
invoice_itemtxs = {
i.get("item_number"): {
"unit_cost": i.get("total"),
"quantity": i.get("quantity"),
"total_amount": i.get("total_vat"),
}
for i in finance_data.get("cars")
}
print(invoice_itemtxs)

View File

@ -236,9 +236,13 @@
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'bills'|capfirst %}</span>
</div>
</a>
{% if request.user.is_authenticated %}
<a class="nav-link" href="{% url 'entity-bs' request.user.dealer.entity.slug %}">
{% else %}
<a class="nav-link" href="#">
{% endif %}
<div class="d-flex align-items-center">
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'bills'|capfirst %}</span>
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'Reports'|capfirst %}</span>
</div>
</a>
</li>

View File

@ -21,7 +21,7 @@
{% endblock %}
{% block content %}
{% block content %}
<div class="card shadow-sm border-0 p-6">
<div class="card-body">
<div class="text-center mb-5">
@ -44,6 +44,7 @@
</h2>
<p class="h5 fst-italic fw-light">As of {{ to_date | date:'m/d/Y' }}</p>
</div>
<!-- Balance Sheet Statement -->
<div class="table-responsive">

View File

@ -58,14 +58,14 @@
<span class="icon is-small">{% icon 'bi:arrow-down' 24 %}</span>
</button>
</div>
{% comment %} <div class="dropdown-menu" id="dropdown-menu-{{ acc.uuid }}" role="menu">
<div class="dropdown-menu" id="dropdown-menu-{{ acc.uuid }}" role="menu">
<div class="dropdown-content">
<a href="{% url 'django_ledger:account-detail' entity_slug=entity_slug coa_slug=acc.coa_slug account_pk=acc.account_uuid %}"
class="dropdown-item has-text-success">{% trans 'Detail' %}</a>
<a href="{% url 'django_ledger:account-update' entity_slug=entity_slug coa_slug=acc.coa_slug account_pk=acc.account_uuid %}"
class="dropdown-item has-text-warning">{% trans 'Update' %}</a>
</div>
</div> {% endcomment %}
</div>
</div>
</td>
</tr>

View File

@ -45,8 +45,7 @@
{% elif estimate.status == 'in_review' %}
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block">{% trans 'Mark As Accept' %}</span></button>
{% elif estimate.status == 'approved' %}
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Sale Order' %}</span></a>
{% elif estimate.status == 'completed' %}
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Sale Order' %}</span></a>
<a href="{% url 'invoice_create' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Invoice' %}</span></a>
<a href="{% url 'preview_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview Sale Order' %}</span></a>
{% elif estimate.status == 'in_review' %}
@ -128,31 +127,31 @@
</tr>
</thead>
<tbody>
{% for item in car_and_item_info %}
{% for item in data.cars %}
<tr>
<td class="">{{forloop.counter}}</td>
<td class="">{{item.info.make}}</td>
<td class="">{{item.make}}</td>
<td class="align-middle">{{item.quantity}}</td>
<td class="align-middle ps-5">{{item.finances.selling_price}}</td>
<td class="align-middle ps-5">{{item.unit_price}}</td>
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
</tr>
{% endfor %}
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
<td class="align-middle text-start fw-semibold">
<span id="grand-total">- {{discount_amount}}</span>
<span id="grand-total">- {{data.total_discount}}</span>
</td>
</tr>
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Vat" %} ({{vat}}%)</td>
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Vat" %} ({{data.vat}}%)</td>
<td class="align-middle text-start fw-semibold">
<span id="grand-total">+ {{vat_amount}}</span>
<span id="grand-total"></span>
</td>
</tr>
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Additional Services" %}</td>
<td class="align-middle text-start fw-semibold">
{% for service in additional_services %}
{% for service in data.additional_services %}
<small><span class="fw-semibold">+ {{service.name}} - {{service.price}}</span></small><br>
{% endfor %}
</td>
@ -160,7 +159,7 @@
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-bolder text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
<td class="align-middle text-start fw-bolder">
<span id="grand-total">{{total}}</span>
<span id="grand-total">{{data.grand_total}}</span>
</td>
</tr>
</tbody>

View File

@ -219,23 +219,23 @@
</tr>
</thead>
<tbody>
{% for item in car_and_item_info %}
{% for item in data.cars %}
<tr>
<td class="">{{forloop.counter}}</td>
<td class="">{{item.info.make}}</td>
<td class="">{{item.make}}</td>
<td class="align-middle">{{item.quantity}}</td>
<td class="align-middle ps-5">{{item.finances.selling_price}}</td>
<td class="align-middle ps-5">{{item.selling_price}}</td>
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
</tr>
{% endfor %}
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
<td class="align-middle text-start fw-semibold">
<span id="grand-total">- {{discount_amount}}</span>
<span id="grand-total">- {{data.total_discount}}</span>
</td>
</tr>
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "VAT" %} ({{vat}}%)</td>
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "VAT" %} ({{data.vat}}%)</td>
<td class="align-middle text-start fw-semibold">
<span id="grand-total">+ {{vat_amount}}</span>
</td>
@ -243,7 +243,7 @@
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Additional Services" %}</td>
<td class="align-middle text-start fw-bold">
{% for service in additional_services %}
{% for service in data.additional_services %}
<small><span class="fw-bold">+ {{service.name}} - {{service.price}}</span></small><br>
{% endfor %}
</td>
@ -251,7 +251,7 @@
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-bolder text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
<td class="align-middle text-start fw-bolder">
<span id="grand-total">{{total}}</span>
<span id="grand-total">{{data.grand_total}}</span>
</td>
</tr>
</tbody>