some changes in invoice

This commit is contained in:
gitea 2025-01-06 15:51:19 +00:00
parent da1b53c775
commit a03bb8ccf1
6 changed files with 139 additions and 280 deletions

View File

@ -801,6 +801,7 @@ class Customer(models.Model):
middle = f" {self.middle_name}" if self.middle_name else "" middle = f" {self.middle_name}" if self.middle_name else ""
return f"{self.first_name}{middle} {self.last_name}" return f"{self.first_name}{middle} {self.last_name}"
@property @property
def get_full_name(self): def get_full_name(self):
return f"{self.first_name} {self.middle_name} {self.last_name}" return f"{self.first_name} {self.middle_name} {self.last_name}"

View File

@ -218,7 +218,7 @@ def create_ledger_entity(sender, instance, created, **kwargs):
active=True, active=True,
) )
#Create Deferred Revenue Account #Create Deferred Revenue Account
entity.create_account( deferred_revenue = entity.create_account(
coa_model=coa, coa_model=coa,
code="2060", code="2060",
role=roles.LIABILITY_CL_DEFERRED_REVENUE, role=roles.LIABILITY_CL_DEFERRED_REVENUE,
@ -226,6 +226,9 @@ def create_ledger_entity(sender, instance, created, **kwargs):
balance_type="credit", balance_type="credit",
active=True, active=True,
) )
deferred_revenue.role_default = True
deferred_revenue.save()
# Create Vendor # Create Vendor
@receiver(post_save, sender=models.Vendor) @receiver(post_save, sender=models.Vendor)

View File

@ -91,7 +91,7 @@ urlpatterns = [
path('generate_invoice/<int:pk>/', views.generate_invoice, name='generate_invoice'), path('generate_invoice/<int:pk>/', views.generate_invoice, name='generate_invoice'),
path('sales/quotations/<int:pk>/mark_quotation/', views.mark_quotation, name='mark_quotation'), path('sales/quotations/<int:pk>/mark_quotation/', views.mark_quotation, name='mark_quotation'),
path('sales/quotations/<int:pk>/post_quotation/', views.post_quotation, name='post_quotation'), path('sales/quotations/<int:pk>/post_quotation/', views.post_quotation, name='post_quotation'),
path('sales/quotations/<int:pk>/invoice_detail/', views.invoice_detail, name='invoice_detail'), # path('sales/quotations/<int:pk>/invoice_detail/', views.invoice_detail, name='invoice_detail'),
path('subscriptions', views.SubscriptionPlans.as_view(), name='subscriptions'), path('subscriptions', views.SubscriptionPlans.as_view(), name='subscriptions'),
#Payment URLs #Payment URLs
# path('sales/quotations/<int:pk>/payment/', views.PaymentCreateView.as_view(), name='payment_create'), # path('sales/quotations/<int:pk>/payment/', views.PaymentCreateView.as_view(), name='payment_create'),
@ -140,6 +140,7 @@ urlpatterns = [
path('sales/estimates/<uuid:pk>/send_email', views.send_email_view, name='send_email'), path('sales/estimates/<uuid:pk>/send_email', views.send_email_view, name='send_email'),
# Invoice # Invoice
path('sales/invoices/', views.InvoiceListView.as_view(), name='invoice_list'), path('sales/invoices/', views.InvoiceListView.as_view(), name='invoice_list'),
path('sales/invoices/create/', views.invoice_create, name='invoice_create'),
path('sales/invoices/<uuid:pk>/create/', views.invoice_create, name='invoice_create'), path('sales/invoices/<uuid:pk>/create/', views.invoice_create, name='invoice_create'),
path('sales/invoices/<uuid:pk>/', views.InvoiceDetailView.as_view(), name='invoice_detail'), path('sales/invoices/<uuid:pk>/', views.InvoiceDetailView.as_view(), name='invoice_detail'),
path('sales/invoices/<uuid:pk>/preview/', views.InvoicePreviewView.as_view(), name='invoice_preview'), path('sales/invoices/<uuid:pk>/preview/', views.InvoicePreviewView.as_view(), name='invoice_preview'),

View File

@ -749,7 +749,12 @@ class CustomerDetailView(LoginRequiredMixin, DetailView):
model = models.Customer model = models.Customer
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,
@ -1274,23 +1279,6 @@ def UserDeleteview(request, pk):
return redirect("user_list") return redirect("user_list")
# 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", {})
class OrganizationListView(LoginRequiredMixin, ListView): class OrganizationListView(LoginRequiredMixin, ListView):
model = models.Organization model = models.Organization
template_name = "organizations/organization_list.html" template_name = "organizations/organization_list.html"
@ -1378,31 +1366,6 @@ class RepresentativeDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteVi
success_message = "Representative deleted successfully." success_message = "Representative deleted successfully."
# def quotation_pdf_view(request, pk):
# # Get the quotation object
# quotation = models.SaleQuotation.objects.get(pk=pk)
#
# # Render the HTML template for the quotation page
# context = {
# "quotation": quotation,
# }
# context_result = get_calculations(quotation)
# context = context.update(context_result)
#
# html_content = render_to_string("sales/quotation_pdf.html", context)
#
# # Create a PDF file
#
# pdf_file = HTML(string=html_content).render()
#
# # Save the PDF file to a file
# with open("quotation.pdf", "wb") as f:
# f.write(pdf_file.write_pdf())
#
# # Return the PDF file as a response
# return HttpResponse(pdf_file, content_type="application/pdf")
@login_required @login_required
def download_quotation_pdf(request, quotation_id): def download_quotation_pdf(request, quotation_id):
try: try:
@ -1427,59 +1390,40 @@ def download_quotation_pdf(request, quotation_id):
return HttpResponse("Quotation not found", status=404) return HttpResponse("Quotation not found", status=404)
@login_required # @login_required
def invoice_detail(request, pk): # def invoice_detail(request, pk):
quotation = get_object_or_404(models.SaleQuotation, pk=pk) # quotation = get_object_or_404(models.SaleQuotation, pk=pk)
dealer = request.user.dealer # dealer = request.user.dealer
entity = dealer.entity # entity = dealer.entity
customer = ( # customer = (
entity.get_customers() # entity.get_customers()
.filter(customer_name=quotation.customer.get_full_name) # .filter(customer_name=quotation.customer.get_full_name)
.first() # .first()
) # )
invoice_model = entity.get_invoices() # invoice_model = entity.get_invoices()
invoice = invoice_model.filter( # invoice = invoice_model.filter(
customer=customer, date_draft=quotation.date_draft # customer=customer, date_draft=quotation.date_draft
).first() # ).first()
return redirect("quotation_detail", pk=pk) # return redirect("quotation_detail", pk=pk)
@login_required # @login_required
def payment_invoice(request, pk): # def payment_invoice(request, pk):
quotation = get_object_or_404(models.SaleQuotation, pk=pk) # quotation = get_object_or_404(models.SaleQuotation, pk=pk)
dealer = request.user.dealer # dealer = request.user.dealer
entity = dealer.entity # entity = dealer.entity
customer = ( # customer = (
entity.get_customers() # entity.get_customers()
.filter(customer_name=quotation.customer.get_full_name) # .filter(customer_name=quotation.customer.get_full_name)
.first() # .first()
) # )
invoice_model = entity.get_invoices() # invoice_model = entity.get_invoices()
invoice = invoice_model.filter( # invoice = invoice_model.filter(
customer=customer, date_draft=quotation.date_draft # customer=customer, date_draft=quotation.date_draft
).first() # ).first()
return redirect("quotation_detail", pk=pk)
# class PaymentCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
# model = models.Payment
# form_class = forms.PaymentForm
# template_name = "sales/payments/payment_form.html"
# success_url = reverse_lazy("quotation_list")
# success_message = "Payment created successfully."
# def form_valid(self, form):
# quotation = get_object_or_404(models.SaleQuotation, pk=self.kwargs["pk"])
# form.instance.quotation = quotation
# form.save()
# return super().form_valid(form)
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# context["quotation"] = get_object_or_404(models.SaleQuotation, pk=self.kwargs["pk"])
# return context
# 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)
@ -1629,7 +1573,6 @@ 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"
@ -1705,36 +1648,6 @@ class EstimateListView(LoginRequiredMixin, ListView):
return entity.get_estimates() return entity.get_estimates()
# class EstimateCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
# model = EstimateModel
# form_class = EstimateModelCreateForm
# template_name = "sales/estimates/estimate_form.html"
# success_url = reverse_lazy("estimate_list")
# success_message = "Estimate created successfully."
# def get_form_kwargs(self):
# """
# Override this method to pass additional keyword arguments to the form.
# """
# entity = self.request.user.dealer.entity
# kwargs = super().get_form_kwargs()
# kwargs['entity_slug'] = entity.slug
# kwargs['user_model'] = entity.admin
# return kwargs
# def get_context_data(self, **kwargs):
# entity = self.request.user.dealer.entity
# kwargs['items'] = entity.get_items_all()
# return super().get_context_data(**kwargs)
# def get_customer_queryset(self):
# entity = self.request.user.dealer.entity
# return entity.get_customer_queryset()
# def form_valid(self, form):
# form.instance.entity = self.request.user.dealer.entity
# return super().form_valid(form)
# @csrf_exempt # @csrf_exempt
@login_required @login_required
def create_estimate(request): def create_estimate(request):
@ -1831,12 +1744,12 @@ 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)
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)
url = reverse("estimate_detail", kwargs={"pk": estimate.pk}) url = reverse("estimate_detail", kwargs={"pk": estimate.pk})
return JsonResponse( return JsonResponse(
@ -1846,16 +1759,7 @@ def create_estimate(request):
"url": f"{url}", "url": f"{url}",
} }
) )
# 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
@ -1894,13 +1798,10 @@ class EstimateDetailView(LoginRequiredMixin, DetailView):
) )
vat = models.VatRate.objects.filter(is_active=True).first() vat = models.VatRate.objects.filter(is_active=True).first()
# Calculate VAT and total with 2 decimal places vat_amount = round(total * vat.vat_rate, 2)
vat_amount = round(total * vat.vat_rate, 2) # Round to 2 decimal places
grand_total = round( grand_total = round(
(total * vat.vat_rate) + total, 2 (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
kwargs["vat"] = vat.rate kwargs["vat"] = vat.rate
@ -1945,7 +1846,6 @@ class EstimatePreviewView(LoginRequiredMixin, DetailView):
@login_required @login_required
def estimate_mark_as(request, pk): def estimate_mark_as(request, pk):
estimate = get_object_or_404(EstimateModel, pk=pk) estimate = get_object_or_404(EstimateModel, pk=pk)
entity = estimate.entity
mark = request.GET.get("mark") mark = request.GET.get("mark")
if mark: if mark:
if mark == "review": if mark == "review":
@ -1953,13 +1853,11 @@ def estimate_mark_as(request, pk):
messages.error(request, "Estimate is not ready for review") messages.error(request, "Estimate is not ready for review")
return redirect("estimate_detail", pk=estimate.pk) return redirect("estimate_detail", pk=estimate.pk)
estimate.mark_as_review() estimate.mark_as_review()
elif mark == "approved": elif mark == "approved":
if not estimate.can_approve(): if not estimate.can_approve():
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():
@ -1967,36 +1865,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())
@ -2032,6 +1904,7 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
kwargs["vat_amount"] = total * vat.vat_rate kwargs["vat_amount"] = total * vat.vat_rate
kwargs["total"] = (total * vat.vat_rate) + total kwargs["total"] = (total * vat.vat_rate) + total
kwargs["vat"] = vat.rate kwargs["vat"] = vat.rate
kwargs["amount_left"] = invoice.amount_due - invoice.amount_paid
kwargs["payments"] = JournalEntryModel.objects.filter( kwargs["payments"] = JournalEntryModel.objects.filter(
ledger=invoice.ledger ledger=invoice.ledger
).all() ).all()
@ -2067,7 +1940,7 @@ def invoice_mark_as(request, pk):
def invoice_create(request, pk): def invoice_create(request, pk):
estimate = get_object_or_404(EstimateModel, pk=pk) estimate = get_object_or_404(EstimateModel, pk=pk)
entity = request.user.dealer.entity entity = request.entity
form = InvoiceModelCreateForm(entity_slug=entity.slug, user_model=entity.admin) form = InvoiceModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
if request.method == "POST": if request.method == "POST":
@ -2081,6 +1954,7 @@ def invoice_create(request, pk):
terms=invoice.terms, terms=invoice.terms,
cash_account=invoice.cash_account, cash_account=invoice.cash_account,
prepaid_account=invoice.prepaid_account, prepaid_account=invoice.prepaid_account,
payable_account=invoice.unearned_account,
coa_model=entity.get_default_coa(), coa_model=entity.get_default_coa(),
) )
ledger = entity.create_ledger(name=f"Invoice {str(invoice_model.pk)}") ledger = entity.create_ledger(name=f"Invoice {str(invoice_model.pk)}")
@ -2242,58 +2116,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):
@ -2467,3 +2289,72 @@ 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", {})

View File

@ -27,7 +27,7 @@
</button> </button>
<a type="button" <a type="button"
class="btn btn-sm btn-danger" class="btn btn-sm btn-danger"
href="{% url 'customer_delete' customer.id %}"> href="{% url 'customer_delete' customer.pk %}">
{% trans 'Yes' %} {% trans 'Yes' %}
</a> </a>
</div> </div>
@ -37,8 +37,7 @@
<!-- Delete Modal --> <!-- Delete Modal -->
<div class="container"> <div class="container">
<div class="mb-9">
<div class="mb-9">
<div class="row align-items-center justify-content-between g-3 mb-4"> <div class="row align-items-center justify-content-between g-3 mb-4">
<div class="col-auto"> <div class="col-auto">
<h3 class="mb-0">{% trans 'Customer details' %}</h3> <h3 class="mb-0">{% trans 'Customer details' %}</h3>
@ -119,7 +118,7 @@
</div> </div>
<div class="col-12 col-xxl-8"> <div class="col-12 col-xxl-8">
<div class="mb-6"> <div class="mb-6">
<h3 class="mb-4">{{ _("Cars") }} <span class="text-body-tertiary fw-normal">(4)</span></h3> <h3 class="mb-4">{{ _("Cars") }} <span class="text-body-tertiary fw-normal">({{ estimates.count }})</span></h3>
<div class="border-top border-bottom border-translucent" id="customerOrdersTable" data-list='{"valueNames":["order","total","payment_status","fulfilment_status","delivery_type","date"],"page":6,"pagination":true}'> <div class="border-top border-bottom border-translucent" id="customerOrdersTable" data-list='{"valueNames":["order","total","payment_status","fulfilment_status","delivery_type","date"],"page":6,"pagination":true}'>
<div class="table-responsive scrollbar"> <div class="table-responsive scrollbar">
<table class="table table-sm fs-9 mb-0"> <table class="table table-sm fs-9 mb-0">
@ -135,10 +134,21 @@
</tr> </tr>
</thead> </thead>
<tbody class="list" id="customer-order-table-body"> <tbody class="list" id="customer-order-table-body">
{% for estimate in estimates %}
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="order align-middle white-space-nowrap ps-0"><a class="fw-semibold" href="#!">#2453</a></td> <td class="order align-middle white-space-nowrap ps-0"><a class="fw-semibold" href="{% url 'estimate_detail' estimate.pk %}">#{{ estimate.estimate_number }}</a></td>
<td class="total align-middle text-end fw-semibold pe-7 text-body-highlight">$87</td> <td class="total align-middle text-end fw-semibold pe-7 text-body-highlight">$87</td>
<td class="payment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-success"><span class="badge-label">Paid</span><span class="ms-1" data-feather="check" style="height:12.8px;width:12.8px;"></span></span></td> <td class="payment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary">
{% if estimate.is_draft %}
<span class="badge badge-phoenix badge-phoenix-warning text-uppercase">{% trans 'Draft' %}</span>
{% elif estimate.is_review %}
<span class="badge badge-phoenix badge-phoenix-info text-uppercase">{% trans 'Review' %}</span>
{% elif estimate.is_approved %}
<span class="badge badge-phoenix badge-phoenix-success text-uppercase">{% trans 'Approved' %}</span>
{% else %}
<span class="badge badge-phoenix badge-phoenix-success text-uppercase">{% trans 'Paid' %}</span>
{% endif %}
</td>
<td class="fulfilment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-success"><span class="badge-label">Order Fulfilled</span><span class="ms-1" data-feather="check" style="height:12.8px;width:12.8px;"></span></span></td> <td class="fulfilment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-success"><span class="badge-label">Order Fulfilled</span><span class="ms-1" data-feather="check" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="delivery_type align-middle white-space-nowrap text-body fs-9 text-start">Cash on delivery</td> <td class="delivery_type align-middle white-space-nowrap text-body fs-9 text-start">Cash on delivery</td>
<td class="date align-middle white-space-nowrap text-body-tertiary fs-9 ps-4 text-end">Dec 12, 12:56 PM</td> <td class="date align-middle white-space-nowrap text-body-tertiary fs-9 ps-4 text-end">Dec 12, 12:56 PM</td>
@ -151,55 +161,7 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> {% endfor %}
<td class="order align-middle white-space-nowrap ps-0"><a class="fw-semibold" href="#!">#2452</a></td>
<td class="total align-middle text-end fw-semibold pe-7 text-body-highlight">$7264</td>
<td class="payment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-secondary"><span class="badge-label">Cancelled</span><span class="ms-1" data-feather="x" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="fulfilment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-info"><span class="badge-label">Ready to pickup</span><span class="ms-1" data-feather="info" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="delivery_type align-middle white-space-nowrap text-body fs-9 text-start">Free shipping</td>
<td class="date align-middle white-space-nowrap text-body-tertiary fs-9 ps-4 text-end">Dec 9, 2:28PM</td>
<td class="align-middle white-space-nowrap text-end pe-0 ps-5">
<div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2"><a class="dropdown-item" href="#!">View</a><a class="dropdown-item" href="#!">Export</a>
<div class="dropdown-divider"></div><a class="dropdown-item text-danger" href="#!">Remove</a>
</div>
</div>
</td>
</tr>
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="order align-middle white-space-nowrap ps-0"><a class="fw-semibold" href="#!">#2451</a></td>
<td class="total align-middle text-end fw-semibold pe-7 text-body-highlight">$375</td>
<td class="payment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-warning"><span class="badge-label">Pending</span><span class="ms-1" data-feather="alert-octagon" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="fulfilment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-warning"><span class="badge-label">Partial FulfiLled</span><span class="ms-1" data-feather="alert-octagon" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="delivery_type align-middle white-space-nowrap text-body fs-9 text-start">Local pickup</td>
<td class="date align-middle white-space-nowrap text-body-tertiary fs-9 ps-4 text-end">Dec 4, 12:56 PM</td>
<td class="align-middle white-space-nowrap text-end pe-0 ps-5">
<div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2"><a class="dropdown-item" href="#!">View</a><a class="dropdown-item" href="#!">Export</a>
<div class="dropdown-divider"></div><a class="dropdown-item text-danger" href="#!">Remove</a>
</div>
</div>
</td>
</tr>
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="order align-middle white-space-nowrap ps-0"><a class="fw-semibold" href="#!">#2450</a></td>
<td class="total align-middle text-end fw-semibold pe-7 text-body-highlight">$657</td>
<td class="payment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-secondary"><span class="badge-label">Cancelled</span><span class="ms-1" data-feather="x" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="fulfilment_status align-middle white-space-nowrap text-start fw-bold text-body-tertiary"><span class="badge badge-phoenix fs-10 badge-phoenix-secondary"><span class="badge-label">Order CancelLed</span><span class="ms-1" data-feather="x" style="height:12.8px;width:12.8px;"></span></span></td>
<td class="delivery_type align-middle white-space-nowrap text-body fs-9 text-start">Standard shipping</td>
<td class="date align-middle white-space-nowrap text-body-tertiary fs-9 ps-4 text-end">Dec 1, 4:07 AM</td>
<td class="align-middle white-space-nowrap text-end pe-0 ps-5">
<div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2"><a class="dropdown-item" href="#!">View</a><a class="dropdown-item" href="#!">Export</a>
<div class="dropdown-divider"></div><a class="dropdown-item text-danger" href="#!">Remove</a>
</div>
</div>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -55,6 +55,7 @@
<div> <div>
<p class="fw-bold mb-1">{% trans 'Paid Amount' %}</p> <p class="fw-bold mb-1">{% trans 'Paid Amount' %}</p>
<h4 class="fw-bolder text-nowrap">${{invoice.amount_paid}}</h4> <h4 class="fw-bolder text-nowrap">${{invoice.amount_paid}}</h4>
<h6 class="fw-normal text-nowrap text-success">${{amount_left}} Left</h6>
</div> </div>
</div> </div>
</div> </div>