From 490723c3f46ead21e2c0db7dd4aed6fee07919bd Mon Sep 17 00:00:00 2001 From: Faheed Date: Sun, 14 Sep 2025 19:03:59 +0300 Subject: [PATCH] added the implemetation for the detail of expense and service and opportunity list search fix --- inventory/urls.py | 12 ++- inventory/views.py | 36 +++++++ .../crm/opportunities/opportunity_detail.html | 3 +- .../crm/opportunities/opportunity_list.html | 45 +++++---- .../partials/opportunity_grid.html | 2 +- templates/customers/view_customer.html | 2 +- templates/items/expenses/expense_detail.html | 97 +++++++++++++++++++ templates/items/expenses/expenses_list.html | 5 +- templates/items/service/service_detail.html | 66 +++++++++++++ templates/items/service/service_list.html | 6 +- templates/ledger/reports/car_sale_report.html | 2 +- .../sales/estimates/estimate_detail.html | 4 +- templates/sales/invoices/invoice_detail.html | 4 +- templates/users/user_list.html | 2 +- 14 files changed, 252 insertions(+), 34 deletions(-) create mode 100644 templates/items/expenses/expense_detail.html create mode 100644 templates/items/service/service_detail.html diff --git a/inventory/urls.py b/inventory/urls.py index d3b39132..4073cdae 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -938,7 +938,12 @@ urlpatterns = [ views.ItemServiceUpdateView.as_view(), name="item_service_update", ), - + + path( + "/items/services//detail/", + views.ItemServiceDetailView.as_view(), + name="item_service_detail", + ), # Expanese path( "/items/expeneses/", @@ -955,6 +960,11 @@ urlpatterns = [ views.ItemExpenseUpdateView.as_view(), name="item_expense_update", ), + path( + "/items/expeneses//detail/", + views.ItemExpenseDetailView.as_view(), + name="item_expense_detail", + ), # Bills path( "/items/bills/", diff --git a/inventory/views.py b/inventory/views.py index 49d54ba6..2387d62d 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -7762,7 +7762,17 @@ class ItemServiceListView(LoginRequiredMixin, PermissionRequiredMixin, ListView) ) return qs +class ItemServiceDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): + model = models.AdditionalServices + template_name = "items/service/service_detail.html" + context_object_name = "service" + permission_required = ["inventory.view_additionalservices"] + def get_context_data(self, **kwargs): + context=super().get_context_data(**kwargs) + sold_cars=models.Car.objects.filter(status='sold',) + context['total_services_price']=self.object.price*self.object.additionals.filter(status='sold').count() + return context class ItemExpenseCreateView(LoginRequiredMixin, PermissionRequiredMixin,SuccessMessageMixin, CreateView): @@ -7896,6 +7906,32 @@ class ItemExpenseListView(LoginRequiredMixin, PermissionRequiredMixin, ListView) return qs +class ItemExpenseDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): + queryset=ItemModel.objects.filter(item_role='expense') + template_name = "items/expenses/expense_detail.html" + context_object_name = "expense" + permission_required = ["django_ledger.view_itemmodel"] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + # Get the related bills queryset + bills_list = self.object.billmodel_set.all().order_by('-created') + + # Paginate the bills + paginator = Paginator(bills_list, 10) # Show 10 bills per page + page_number = self.request.GET.get('page') + page_obj = paginator.get_page(page_number) + + # Add the paginated bills to the context + context['page_obj'] = page_obj + context["entity"] = get_user_type(self.request).entity + return context + + + + + + class BillListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): """ Provides a view for listing bills. diff --git a/templates/crm/opportunities/opportunity_detail.html b/templates/crm/opportunities/opportunity_detail.html index 3a53ee6f..5198269b 100644 --- a/templates/crm/opportunities/opportunity_detail.html +++ b/templates/crm/opportunities/opportunity_detail.html @@ -72,6 +72,7 @@ {% endif %}
{% if opportunity.car.marked_price %} + {% trans "Marked Price: " %}
{{ opportunity.car.marked_price }}
@@ -370,7 +371,7 @@ {% if request.user.email == opportunity.staff.email %}
{% trans "You" %}
{% else %} -
{{ opportunity.staff.get_local_name }}
+
{{ opportunity.staff.fullname }}
{% endif %} diff --git a/templates/crm/opportunities/opportunity_list.html b/templates/crm/opportunities/opportunity_list.html index 97533751..7579dce6 100644 --- a/templates/crm/opportunities/opportunity_list.html +++ b/templates/crm/opportunities/opportunity_list.html @@ -29,17 +29,22 @@
-
- + id="filter-container" + hx-get="{% url 'opportunity_list' request.dealer.slug %}" + hx-target="#opportunities-grid" + hx-select="#opportunities-grid" + hx-swap="outerHTML"> -
- -
+ hx-include="#search-form input, select[name='stage']">
{% if page_obj.paginator.num_pages > 1 %} -
-
{% include 'partials/pagination.html' %}
+
+
+ {% include 'partials/pagination.html' %} +
{% endif %} {% else %} @@ -125,17 +128,19 @@ document.addEventListener("DOMContentLoaded", function() { const searchInput = document.getElementById("search-input"); const clearButton = document.getElementById("clear-search"); - const searchForm = document.getElementById("search-form"); - + if (clearButton) { clearButton.addEventListener("click", function() { + // Clear the input field searchInput.value = ""; - // This clears the search and triggers the htmx search - // by submitting the form with an empty query. - searchForm.submit(); + + // Trigger HTMX search with a 'search' event + // This uses the hx-trigger="search" on the form + // and prevents a full page reload. + searchInput.dispatchEvent(new Event('search', { bubbles: true })); }); } }); {% endblock %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/crm/opportunities/partials/opportunity_grid.html b/templates/crm/opportunities/partials/opportunity_grid.html index ebe06229..448fcfa2 100644 --- a/templates/crm/opportunities/partials/opportunity_grid.html +++ b/templates/crm/opportunities/partials/opportunity_grid.html @@ -67,7 +67,7 @@ {% else %} {{ opportunity.staff.fullname }}

- {% endif %} + {% endif %}
diff --git a/templates/customers/view_customer.html b/templates/customers/view_customer.html index 53da72fe..f369aa62 100644 --- a/templates/customers/view_customer.html +++ b/templates/customers/view_customer.html @@ -11,7 +11,7 @@

- {% trans 'Customer details' %} + {% trans 'Customer details' %}

diff --git a/templates/items/expenses/expense_detail.html b/templates/items/expenses/expense_detail.html new file mode 100644 index 00000000..d13b58ac --- /dev/null +++ b/templates/items/expenses/expense_detail.html @@ -0,0 +1,97 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} +{% load tenhal_tag %} + +{% block title %}{% trans "Expense Detail" %}{% endblock %} + +{% block content %} + +
+
+

{{ expense.name|title }}

+

{% trans "Comprehensive details for your expense." %}

+
+
+ +
+
+
+
+
+ +

{% trans "Expense Information" %} Back To List

+ +
+
+
SKU
+

{{ expense.sku|default:"N/A" }}

+
+
+
UPC
+

{{ expense.upc|default:"N/A" }}

+
+
+
{% trans "Default Amount" %}
+

{{ expense.default_amount }}

+
+
+
{% trans "Expense Account" %}
+

{{ expense.expense_account }}

+
+
+ +
+ +

{% trans "Associated Bills" %}

+ + + {% if page_obj %} +
+
+ + + + + + + + + + + {% for bill in page_obj%} + + + + + + + + + {% endfor %} + +
{% trans "Bill Number" %}{% trans "Status" %}{% trans "Vendor" %}{% trans "Terms" %}{% trans "Created On" %}
+ + {{ bill.bill_number }} + + + {{ bill.get_bill_status_display }} + {{ bill.vendor }}{{ bill.get_terms_display }}{{ bill.created|date:"M j, Y" }}
+ +
+ {% if page_obj.paginator.num_pages > 1 %} +
+
{% include 'partials/pagination.html' %}
+
+ {% endif %} + {% else %} +
+ {% trans "No bills are associated with this expense yet." %} +
+ {% endif %} +
+
+ + + +{% endblock %} diff --git a/templates/items/expenses/expenses_list.html b/templates/items/expenses/expenses_list.html index f4e60d44..627fdc2f 100644 --- a/templates/items/expenses/expenses_list.html +++ b/templates/items/expenses/expenses_list.html @@ -51,9 +51,12 @@ href="{% url 'item_expense_update' request.dealer.slug expense.pk %}"> {% trans "Update" %} - + {% trans "Create Expense Bill" %} + + {% trans "Expense Detail" %} + {% endif %} diff --git a/templates/items/service/service_detail.html b/templates/items/service/service_detail.html new file mode 100644 index 00000000..18f71962 --- /dev/null +++ b/templates/items/service/service_detail.html @@ -0,0 +1,66 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} +{% load tenhal_tag %} + +{% block title %}{{ service.name|title }} - {% trans "My Company" %}{% endblock %} + +{% block content %} + +
+
+

{{ service.name|title }}

+

{{ service.description|default:"No description provided." }}

+
+
+ +
+
+ +
+
+ +

{% trans "Service Details" %}

+ + + + +
+ +
+
{% trans 'Service Name' %}
+

{{ service.name|capfirst }}

+
+ +
+
{% trans 'Price' %}
+

{{ service.price }}

+
+ +
+
{% trans 'Unit of Measure' %}
+

{{ service.get_uom_display }}

+
+ +
+
{% trans 'Tax Status' %}
+

{% if service.taxable %}{% trans 'Taxable' %}{% else %}{% trans 'Non Taxable' %}{% endif %}

+
+ +
+ +
+
+ +
+

{% trans "Total Revenue from this service" %}

+

{{ total_services_price }}

+
+ +
+
+ +{% endblock %} diff --git a/templates/items/service/service_list.html b/templates/items/service/service_list.html index 00ce8e3a..fcf5543f 100644 --- a/templates/items/service/service_list.html +++ b/templates/items/service/service_list.html @@ -52,9 +52,9 @@ href="{% url 'item_service_update' request.dealer.slug service.pk %}"> {% trans "Update" %} - {% comment %} - {% trans "Delete" %} - {% endcomment %} + + {% trans "service detail" %} + {% endif %} diff --git a/templates/ledger/reports/car_sale_report.html b/templates/ledger/reports/car_sale_report.html index e17979b0..88db5f35 100644 --- a/templates/ledger/reports/car_sale_report.html +++ b/templates/ledger/reports/car_sale_report.html @@ -57,7 +57,7 @@
-
65000.00 +