update
This commit is contained in:
commit
7fe829b362
@ -369,42 +369,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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
@ -59,7 +59,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
|
||||||
@ -740,6 +746,14 @@ class CustomerDetailView(LoginRequiredMixin, DetailView):
|
|||||||
template_name = "customers/view_customer.html"
|
template_name = "customers/view_customer.html"
|
||||||
context_object_name = "customer"
|
context_object_name = "customer"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
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
|
||||||
|
)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class CustomerCreateView(
|
class CustomerCreateView(
|
||||||
LoginRequiredMixin,
|
LoginRequiredMixin,
|
||||||
@ -1620,6 +1634,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"
|
||||||
@ -1785,7 +1800,7 @@ def create_estimate(request):
|
|||||||
"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.selling_price,
|
"unit_revenue": car_instance.finances.selling_price,
|
||||||
"total_amount": car_instance.finances.cost_price
|
"total_amount": (car_instance.finances.total_vat)
|
||||||
* int(item.get("quantity")),
|
* int(item.get("quantity")),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1807,7 +1822,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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1821,7 +1837,7 @@ def create_estimate(request):
|
|||||||
for item in items:
|
for item in items:
|
||||||
item_instance = ItemModel.objects.get(pk=item)
|
item_instance = ItemModel.objects.get(pk=item)
|
||||||
instance = models.Car.objects.get(vin=item_instance.name)
|
instance = models.Car.objects.get(vin=item_instance.name)
|
||||||
response = reserve_car(instance, request)
|
reserve_car(instance, request)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
item_instance = ItemModel.objects.get(pk=items)
|
item_instance = ItemModel.objects.get(pk=items)
|
||||||
@ -1837,15 +1853,6 @@ def create_estimate(request):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# except Exception as e:
|
|
||||||
# return JsonResponse(
|
|
||||||
# {
|
|
||||||
# "status": "error",
|
|
||||||
# "message": f"An error occurred while processing the request: {str(e)}",
|
|
||||||
# },
|
|
||||||
# status=400,
|
|
||||||
# )
|
|
||||||
|
|
||||||
form = EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
|
form = EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
|
||||||
car_list = models.Car.objects.filter(
|
car_list = models.Car.objects.filter(
|
||||||
dealer=dealer, finances__selling_price__gt=0
|
dealer=dealer, finances__selling_price__gt=0
|
||||||
@ -1874,25 +1881,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(
|
||||||
x.ce_revenue_estimate
|
models.Car.objects.get(
|
||||||
- models.Car.objects.get(
|
|
||||||
vin=x.item_model.name
|
vin=x.item_model.name
|
||||||
).finances.discount_amount
|
).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)
|
||||||
|
|
||||||
# Calculate VAT and total with 2 decimal places
|
|
||||||
vat_amount = round(total * vat.vat_rate, 2) # Round to 2 decimal places
|
|
||||||
grand_total = round(
|
|
||||||
(total * vat.vat_rate) + total, 2
|
|
||||||
) # Round to 2 decimal places
|
|
||||||
|
|
||||||
# Add values to the context
|
|
||||||
kwargs["vat_amount"] = vat_amount
|
kwargs["vat_amount"] = vat_amount
|
||||||
kwargs["total"] = grand_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()
|
||||||
@ -1949,7 +1958,6 @@ def estimate_mark_as(request, pk):
|
|||||||
messages.error(request, "Estimate is not ready for approval")
|
messages.error(request, "Estimate is not ready for approval")
|
||||||
return redirect("estimate_detail", pk=estimate.pk)
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
estimate.mark_as_approved()
|
estimate.mark_as_approved()
|
||||||
|
|
||||||
messages.success(request, "Estimate approved successfully.")
|
messages.success(request, "Estimate approved successfully.")
|
||||||
elif mark == "rejected":
|
elif mark == "rejected":
|
||||||
if not estimate.can_cancel():
|
if not estimate.can_cancel():
|
||||||
@ -1957,36 +1965,10 @@ def estimate_mark_as(request, pk):
|
|||||||
return redirect("estimate_detail", pk=estimate.pk)
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
estimate.mark_as_canceled()
|
estimate.mark_as_canceled()
|
||||||
messages.success(request, "Estimate canceled successfully.")
|
messages.success(request, "Estimate canceled successfully.")
|
||||||
|
|
||||||
elif mark == "completed":
|
elif mark == "completed":
|
||||||
if not estimate.can_complete():
|
if not estimate.can_complete():
|
||||||
messages.error(request, "Estimate is not ready for completion")
|
messages.error(request, "Estimate is not ready for completion")
|
||||||
return redirect("estimate_detail", pk=estimate.pk)
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
|
|
||||||
# invoice = entity.create_invoice(customer_model=estimate.customer,
|
|
||||||
# terms=estimate.terms,
|
|
||||||
# cash_account=entity.get_default_coa_accounts().get(name="Cash"),
|
|
||||||
# prepaid_account=entity.get_default_coa_accounts().get(name="Accounts Receivable"),
|
|
||||||
# coa_model=entity.get_default_coa()
|
|
||||||
# )
|
|
||||||
|
|
||||||
# unit_items = estimate.get_itemtxs_data()[0]
|
|
||||||
# invoice_itemtxs = {
|
|
||||||
# i.item_model.item_number: {
|
|
||||||
# 'unit_cost': i.ce_unit_cost_estimate,
|
|
||||||
# 'quantity': i.ce_quantity,
|
|
||||||
# 'total_amount': i.ce_cost_estimate
|
|
||||||
# } for i in unit_items
|
|
||||||
# }
|
|
||||||
|
|
||||||
# invoice_itemtxs = invoice.migrate_itemtxs(itemtxs=invoice_itemtxs,
|
|
||||||
# commit=True,
|
|
||||||
# operation=InvoiceModel.ITEMIZE_APPEND)
|
|
||||||
# invoice.bind_estimate(estimate)
|
|
||||||
# invoice.mark_as_review()
|
|
||||||
# estimate.mark_as_completed()
|
|
||||||
# estimate.save()
|
|
||||||
# invoice.save()
|
|
||||||
estimate.save()
|
estimate.save()
|
||||||
messages.success(request, "Estimate marked as " + mark.upper())
|
messages.success(request, "Estimate marked as " + mark.upper())
|
||||||
|
|
||||||
@ -2012,15 +1994,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["payments"] = JournalEntryModel.objects.filter(
|
kwargs["payments"] = JournalEntryModel.objects.filter(
|
||||||
ledger=invoice.ledger
|
ledger=invoice.ledger
|
||||||
@ -2080,13 +2074,27 @@ def invoice_create(request, pk):
|
|||||||
invoice_model.save()
|
invoice_model.save()
|
||||||
|
|
||||||
unit_items = estimate.get_itemtxs_data()[0]
|
unit_items = estimate.get_itemtxs_data()[0]
|
||||||
|
|
||||||
|
itemtxs = []
|
||||||
|
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_cost_estimate,
|
"unit_cost": i.get("unit_cost"),
|
||||||
"quantity": i.ce_quantity,
|
"quantity": i.get("quantity"),
|
||||||
"total_amount": i.ce_cost_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(
|
||||||
@ -2232,59 +2240,6 @@ class UserActivityLogListView(ListView):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
# email
|
|
||||||
def send_email_view(request, pk):
|
|
||||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
|
||||||
if request.method == "POST":
|
|
||||||
# if not estimate.can_review():
|
|
||||||
# messages.error(request, "Estimate is not ready for review")
|
|
||||||
# return redirect("estimate_detail", pk=estimate.pk)
|
|
||||||
if not estimate.get_itemtxs_data()[0]:
|
|
||||||
messages.error(request, "Estimate has no items")
|
|
||||||
return redirect("estimate_detail", pk=estimate.pk)
|
|
||||||
|
|
||||||
send_email(
|
|
||||||
"manager@tenhal.com",
|
|
||||||
request.POST.get("to"),
|
|
||||||
request.POST.get("subject"),
|
|
||||||
request.POST.get("message"),
|
|
||||||
)
|
|
||||||
# estimate.mark_as_review()
|
|
||||||
messages.success(request, "Email sent successfully!")
|
|
||||||
return redirect("estimate_detail", pk=estimate.pk)
|
|
||||||
link = reverse_lazy("estimate_preview", kwargs={"pk": estimate.pk})
|
|
||||||
msg = f"""
|
|
||||||
السلام عليكم
|
|
||||||
Dear {estimate.customer.customer_name},
|
|
||||||
|
|
||||||
أود أن أشارككم تقدير المشروع الذي ناقشناه. يرجى العثور على الوثيقة التفصيلية للمقترح المرفقة.
|
|
||||||
|
|
||||||
I hope this email finds you well. I wanted to share with you the estimate for the project we discussed. Please find the detailed estimate document attached.
|
|
||||||
|
|
||||||
يرجى مراجعة المقترح وإعلامي إذا كانت لديك أي أسئلة أو مخاوف. إذا كانت كل شيء يبدو جيدًا، يمكننا المضي قدمًا في المشروع.
|
|
||||||
|
|
||||||
Please review the estimate and let me know if you have any questions or concerns. If everything looks good, we can proceed with the project.
|
|
||||||
|
|
||||||
Estimate Link:
|
|
||||||
{link}
|
|
||||||
|
|
||||||
شكراً لاهتمامكم بهذا الأمر.
|
|
||||||
Thank you for your attention to this matter.
|
|
||||||
|
|
||||||
تحياتي,
|
|
||||||
Best regards,
|
|
||||||
[Your Name]
|
|
||||||
[Your Position]
|
|
||||||
[Your Company]
|
|
||||||
[Your Contact Information]
|
|
||||||
"""
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"sales/estimates/estimate_send.html",
|
|
||||||
{"estimate": estimate, "message": msg},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# 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)
|
||||||
@ -2459,3 +2414,73 @@ class SubscriptionPlans(ListView):
|
|||||||
model = models.SubscriptionPlan
|
model = models.SubscriptionPlan
|
||||||
template_name = "subscriptions/subscription_plan.html"
|
template_name = "subscriptions/subscription_plan.html"
|
||||||
context_object_name = "plans"
|
context_object_name = "plans"
|
||||||
|
|
||||||
|
|
||||||
|
# email
|
||||||
|
def send_email_view(request, pk):
|
||||||
|
estimate = get_object_or_404(EstimateModel, pk=pk)
|
||||||
|
if request.method == "POST":
|
||||||
|
# if not estimate.can_review():
|
||||||
|
# messages.error(request, "Estimate is not ready for review")
|
||||||
|
# return redirect("estimate_detail", pk=estimate.pk)
|
||||||
|
if not estimate.get_itemtxs_data()[0]:
|
||||||
|
messages.error(request, "Estimate has no items")
|
||||||
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
|
|
||||||
|
send_email(
|
||||||
|
"manager@tenhal.com",
|
||||||
|
request.POST.get("to"),
|
||||||
|
request.POST.get("subject"),
|
||||||
|
request.POST.get("message"),
|
||||||
|
)
|
||||||
|
estimate.mark_as_review()
|
||||||
|
messages.success(request, "Email sent successfully!")
|
||||||
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
|
link = reverse_lazy("estimate_preview", kwargs={"pk": estimate.pk})
|
||||||
|
msg = f"""
|
||||||
|
السلام عليكم
|
||||||
|
Dear {estimate.customer.customer_name},
|
||||||
|
|
||||||
|
أود أن أشارككم تقدير المشروع الذي ناقشناه. يرجى العثور على الوثيقة التفصيلية للمقترح المرفقة.
|
||||||
|
|
||||||
|
I hope this email finds you well. I wanted to share with you the estimate for the project we discussed. Please find the detailed estimate document attached.
|
||||||
|
|
||||||
|
يرجى مراجعة المقترح وإعلامي إذا كانت لديك أي أسئلة أو مخاوف. إذا كانت كل شيء يبدو جيدًا، يمكننا المضي قدمًا في المشروع.
|
||||||
|
|
||||||
|
Please review the estimate and let me know if you have any questions or concerns. If everything looks good, we can proceed with the project.
|
||||||
|
|
||||||
|
Estimate Link:
|
||||||
|
{link}
|
||||||
|
|
||||||
|
شكراً لاهتمامكم بهذا الأمر.
|
||||||
|
Thank you for your attention to this matter.
|
||||||
|
|
||||||
|
تحياتي,
|
||||||
|
Best regards,
|
||||||
|
[Your Name]
|
||||||
|
[Your Position]
|
||||||
|
[Your Company]
|
||||||
|
[Your Contact Information]
|
||||||
|
"""
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"sales/estimates/estimate_send.html",
|
||||||
|
{"estimate": estimate, "message": msg},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# errors
|
||||||
|
def custom_page_not_found_view(request, exception):
|
||||||
|
return render(request, "errors/404.html", {})
|
||||||
|
|
||||||
|
|
||||||
|
def custom_error_view(request, exception=None):
|
||||||
|
return render(request, "errors/500.html", {})
|
||||||
|
|
||||||
|
|
||||||
|
def custom_permission_denied_view(request, exception=None):
|
||||||
|
return render(request, "errors/403.html", {})
|
||||||
|
|
||||||
|
|
||||||
|
def custom_bad_request_view(request, exception=None):
|
||||||
|
return render(request, "errors/400.html", {})
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -144,13 +144,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">
|
||||||
@ -159,6 +159,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">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user