fix the invoice and estimate calculation

This commit is contained in:
gitea 2025-01-07 14:35:36 +00:00
parent 0cb378d25f
commit e1b2fb9c83
5 changed files with 128 additions and 74 deletions

View File

@ -321,42 +321,34 @@ class CarFinance(models.Model):
selling_price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Selling Price")) selling_price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Selling Price"))
discount_amount = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Discount Amount"), discount_amount = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Discount Amount"),
default=Decimal('0.00')) default=Decimal('0.00'))
# profit_margin = models.DecimalField(max_digits=14,
# decimal_places=2,
# verbose_name=_("Profit Margin"),
# editable=False)
# vat_amount = models.DecimalField(max_digits=14,
# decimal_places=2,
# verbose_name=_("Vat Amount"),
# editable=False,default=Decimal('0.00'))
# registration_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Registration Fee"),
# default=Decimal('0.00'))
# administration_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Administration Fee"),
# default=Decimal('0.00'))
# transportation_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Transportation Fee"),
# default=Decimal('0.00'))
# custom_card_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Custom Card Fee"),
# default=Decimal('0.00'))
@property @property
def total(self): def total(self):
total = 0 total = self.selling_price
if self.additional_services.count() != 0: if self.additional_services.count() != 0:
total_additional_services = sum(x.default_amount for x in self.additional_services.all()) total_additional_services = sum(x.default_amount for x in self.additional_services.all())
total = self.selling_price + total_additional_services total += total_additional_services
else:
total = self.selling_price
if self.discount_amount != 0:
total = total - self.discount_amount
return total return total
@property
def total_discount(self):
if self.discount_amount != 0:
total = self.total - self.discount_amount
return total
return self.total
@property
def total_vat(self):
return self.total_discount + self.vat_amount
@property @property
def vat_amount(self): def vat_amount(self):
vat = VatRate.objects.filter(is_active=True).first() vat = VatRate.objects.filter(is_active=True).first()
return (self.total * vat.vat_rate).quantize(Decimal('0.01')) if vat:
return (self.total_discount * Decimal(vat.vat_rate)).quantize(Decimal('0.01'))
@property return Decimal('0.00')
def total_vat(self):
return self.total + self.vat_amount

View File

@ -1,3 +1,4 @@
from decimal import Decimal
from django.shortcuts import redirect from django.shortcuts import redirect
from django.contrib import messages from django.contrib import messages
from django.utils import timezone from django.utils import timezone
@ -91,3 +92,10 @@ def reserve_car(car,request):
messages.error(request, f"Error reserving car: {e}") messages.error(request, f"Error reserving car: {e}")
return redirect("car_detail", pk=car.pk) return redirect("car_detail", pk=car.pk)
def calculate_vat_amount(amount):
vat = models.VatRate.objects.filter(is_active=True).first()
if vat:
return ((amount * Decimal(vat.vat_rate)).quantize(Decimal('0.01')),vat.vat_rate)
return amount

View File

@ -69,7 +69,13 @@ from . import models, forms
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from .utils import get_calculations, reserve_car, send_email, get_user_type from .utils import (
calculate_vat_amount,
get_calculations,
reserve_car,
send_email,
get_user_type,
)
from django.contrib.auth.models import User from django.contrib.auth.models import User
from allauth.account import views from allauth.account import views
from django.db.models import Count, F, Value from django.db.models import Count, F, Value
@ -753,9 +759,12 @@ class CustomerDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
name = f"{context['customer'].first_name} {context['customer'].middle_name} {context['customer'].last_name}" name = f"{context['customer'].first_name} {context['customer'].middle_name} {context['customer'].last_name}"
context["estimates"] = self.request.entity.get_estimates().filter(customer__customer_name=name) context["estimates"] = self.request.entity.get_estimates().filter(
customer__customer_name=name
)
return context return context
class CustomerCreateView( class CustomerCreateView(
LoginRequiredMixin, LoginRequiredMixin,
SuccessMessageMixin, SuccessMessageMixin,
@ -1425,6 +1434,7 @@ def download_quotation_pdf(request, quotation_id):
# return redirect("quotation_detail", pk=pk) # return redirect("quotation_detail", pk=pk)
def payment_create(request, pk): def payment_create(request, pk):
quotation = get_object_or_404(models.SaleQuotation, pk=pk) quotation = get_object_or_404(models.SaleQuotation, pk=pk)
dealer = get_user_type(request) dealer = get_user_type(request)
@ -1573,6 +1583,7 @@ def bank_account_delete(request, pk):
# Accounts # Accounts
class AccountListView(LoginRequiredMixin, ListView): class AccountListView(LoginRequiredMixin, ListView):
model = AccountModel model = AccountModel
template_name = "ledger/coa_accounts/account_list.html" template_name = "ledger/coa_accounts/account_list.html"
@ -1707,8 +1718,8 @@ def create_estimate(request):
"item_number": item_instance.item_number, "item_number": item_instance.item_number,
"quantity": float(item.get("quantity")), "quantity": float(item.get("quantity")),
"unit_cost": car_instance.finances.cost_price, "unit_cost": car_instance.finances.cost_price,
"unit_revenue": car_instance.finances.total_vat, "unit_revenue": car_instance.finances.selling_price,
"total_amount": car_instance.finances.total_vat "total_amount": (car_instance.finances.total_vat)
* int(item.get("quantity")), * int(item.get("quantity")),
} }
) )
@ -1730,7 +1741,8 @@ def create_estimate(request):
"unit_cost": instance.finances.cost_price, "unit_cost": instance.finances.cost_price,
"unit_revenue": instance.finances.selling_price, "unit_revenue": instance.finances.selling_price,
"quantity": float(quantities), "quantity": float(quantities),
"total_amount": instance.finances.total * int(quantities), "total_amount": instance.finances.total_vat
* int(quantities),
} }
} }
@ -1788,19 +1800,27 @@ class EstimateDetailView(LoginRequiredMixin, DetailView):
estimate = kwargs.get("object") estimate = kwargs.get("object")
if estimate.get_itemtxs_data(): if estimate.get_itemtxs_data():
total = sum( total = sum(
( float(
models.Car.objects.get(vin=x.item_model.name).finances.total_vat models.Car.objects.get(
vin=x.item_model.name
).finances.total
) )
* float(x.ce_quantity)
for x in estimate.get_itemtxs_data()[0].all() for x in estimate.get_itemtxs_data()[0].all()
) )
discount_amount = sum(
models.CarFinance.objects.get(
car__vin=i.item_model.name
).discount_amount
for i in estimate.get_itemtxs_data()[0].all()
)
vat = models.VatRate.objects.filter(is_active=True).first() vat = models.VatRate.objects.filter(is_active=True).first()
grand_total = float(total) - float(discount_amount)
vat_amount = round(float(grand_total) * float(vat.vat_rate), 2)
vat_amount = round(total * vat.vat_rate, 2)
# grand_total = round(
# (total * vat.vat_rate) + total, 2
# )
kwargs["vat_amount"] = vat_amount kwargs["vat_amount"] = vat_amount
kwargs["total"] = total kwargs["total"] = grand_total + vat_amount
kwargs["discount_amount"] = discount_amount
kwargs["vat"] = vat.rate kwargs["vat"] = vat.rate
kwargs["invoice"] = ( kwargs["invoice"] = (
InvoiceModel.objects.all().filter(ce_model=estimate).first() InvoiceModel.objects.all().filter(ce_model=estimate).first()
@ -1891,15 +1911,27 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
invoice = kwargs.get("object") invoice = kwargs.get("object")
vat = models.VatRate.objects.filter(is_active=True).first()
if invoice.get_itemtxs_data(): if invoice.get_itemtxs_data():
total = sum( total = sum(
x.unit_cost * x.quantity for x in invoice.get_itemtxs_data()[0].all() float(x.ce_revenue_estimate) * float(x.ce_quantity)
for x in invoice.ce_model.get_itemtxs_data()[0].all()
) )
total = int(total) discount_amount = sum(
vat = models.VatRate.objects.filter(is_active=True).first() models.CarFinance.objects.get(
kwargs["vat_amount"] = total * vat.vat_rate car__vin=i.item_model.name
kwargs["total"] = (total * vat.vat_rate) + total ).discount_amount
for i in invoice.get_itemtxs_data()[0].all()
)
grand_total = float(total) - float(discount_amount)
vat_amount = round(float(grand_total) * float(vat.vat_rate), 2)
kwargs["vat_amount"] = vat_amount
kwargs["total"] = grand_total + vat_amount
kwargs["discount_amount"] = discount_amount
kwargs["vat"] = vat.rate kwargs["vat"] = vat.rate
kwargs["amount_left"] = invoice.amount_due - invoice.amount_paid kwargs["amount_left"] = invoice.amount_due - invoice.amount_paid
kwargs["payments"] = JournalEntryModel.objects.filter( kwargs["payments"] = JournalEntryModel.objects.filter(
@ -1962,16 +1994,26 @@ def invoice_create(request, pk):
unit_items = estimate.get_itemtxs_data()[0] unit_items = estimate.get_itemtxs_data()[0]
# for item in unit_items: itemtxs = []
# car = models.Car.objects.get(vin=item.item_model.name) for item in unit_items:
car = models.Car.objects.get(vin=item.item_model.name)
itemtxs.append(
{
"item_number": item.item_model.item_number,
"unit_cost": car.finances.total_vat,
"unit_revenue": car.finances.total_vat,
"quantity": item.ce_quantity,
"total_amount": float(car.finances.total_vat)
* float(item.ce_quantity),
}
)
invoice_itemtxs = { invoice_itemtxs = {
i.item_model.item_number: { i.get("item_number"): {
"unit_cost": i.ce_unit_revenue_estimate, "unit_cost": i.get("unit_cost"),
"quantity": i.ce_quantity, "quantity": i.get("quantity"),
"total_amount": i.ce_revenue_estimate, "total_amount": i.get("total_amount"),
} }
for i in unit_items for i in itemtxs
} }
invoice_itemtxs = invoice_model.migrate_itemtxs( invoice_itemtxs = invoice_model.migrate_itemtxs(
@ -2117,7 +2159,6 @@ class UserActivityLogListView(ListView):
return queryset return queryset
# CRM RELATED VIEWS # CRM RELATED VIEWS
def create_lead(request, pk): def create_lead(request, pk):
customer = get_object_or_404(models.Customer, pk=pk) customer = get_object_or_404(models.Customer, pk=pk)
@ -2344,6 +2385,7 @@ def send_email_view(request, pk):
{"estimate": estimate, "message": msg}, {"estimate": estimate, "message": msg},
) )
# errors # errors
def custom_page_not_found_view(request, exception): def custom_page_not_found_view(request, exception):
return render(request, "errors/404.html", {}) return render(request, "errors/404.html", {})

View File

@ -141,6 +141,12 @@
<span id="grand-total">{{vat_amount}}</span> <span id="grand-total">{{vat_amount}}</span>
</td> </td>
</tr> </tr>
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-bold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
<td class="align-middle text-start fw-bold">
<span id="grand-total">{{discount_amount}}</span>
</td>
</tr>
<tr class="bg-body-secondary total-sum"> <tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-bold text-body-highlight" colspan="4">{% trans "Grand Total" %}</td> <td class="align-middle ps-4 fw-bold text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
<td class="align-middle text-start fw-bold"> <td class="align-middle text-start fw-bold">

View File

@ -145,13 +145,13 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for item in invoice.get_itemtxs_data.0 %} {% for item in invoice.ce_model.get_itemtxs_data.0 %}
<tr> <tr>
<td class="">{{forloop.counter}}</td> <td class="">{{forloop.counter}}</td>
<td class="">{{item.item_model.name}}</td> <td class="">{{item.item_model.name}}</td>
<td class="align-middle">{{item.quantity}}</td> <td class="align-middle">{{item.ce_quantity}}</td>
<td class="align-middle ps-5">{{item.unit_cost}}</td> <td class="align-middle ps-5">{{item.ce_unit_revenue_estimate}}</td>
<td class="align-middle text-body-tertiary fw-semibold">{{item.total_amount}}</td> <td class="align-middle text-body-tertiary fw-semibold">{{item.ce_revenue_estimate}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="bg-body-secondary total-sum"> <tr class="bg-body-secondary total-sum">
@ -160,6 +160,12 @@
<span id="grand-total">{{vat_amount}}</span> <span id="grand-total">{{vat_amount}}</span>
</td> </td>
</tr> </tr>
<tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-bold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
<td class="align-middle text-start fw-bold">
<span id="grand-total">{{discount_amount}}</span>
</td>
</tr>
<tr class="bg-body-secondary total-sum"> <tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-bold text-body-highlight" colspan="4">{% trans "Grand Total" %}</td> <td class="align-middle ps-4 fw-bold text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
<td class="align-middle text-start fw-bold"> <td class="align-middle text-start fw-bold">