diff --git a/inventory/views.py b/inventory/views.py index 39cc68fc..160e08f8 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -2266,6 +2266,49 @@ class CustomerListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): return context +# class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# """ +# CustomerDetailView handles retrieving and presenting detailed information about +# a specific customer. It ensures that the user is authenticated and has the +# necessary permissions before accessing the customer's details. This view +# provides context data including estimates and invoices related to the customer. + +# :ivar model: The model associated with the view. +# :type model: CustomerModel +# :ivar template_name: The path to the template used for rendering the view. +# :type template_name: str +# :ivar context_object_name: The name of the variable in the template context +# for the object being viewed. +# :type context_object_name: str +# :ivar permission_required: The list of permissions required to access this view. +# :type permission_required: list[str] +# """ + +# model = models.Customer +# template_name = "customers/view_customer.html" +# context_object_name = "customer" +# permission_required = ["inventory.view_customer"] + +# def get_context_data(self, **kwargs): +# dealer = get_user_type(self.request) +# entity = dealer.entity +# context = super().get_context_data(**kwargs) + +# context["notes"] = models.Notes.objects.filter( +# dealer=dealer, +# content_type__model="customer", object_id=self.object.id +# ) +# estimates = entity.get_estimates().filter(customer=self.object.customer_model) +# invoices = entity.get_invoices().filter(customer=self.object.customer_model) + +# total = estimates.count() + invoices.count() + +# context["estimates"] = estimates +# context["invoices"] = invoices +# context["total"] = total +# context["note_form"] = forms.NoteForm() +# return context + class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): """ CustomerDetailView handles retrieving and presenting detailed information about @@ -2293,17 +2336,22 @@ class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView dealer = get_user_type(self.request) entity = dealer.entity context = super().get_context_data(**kwargs) - context["customer_notes"] = models.Notes.objects.filter( - object_id=self.object.pk + + context["notes"] = models.Notes.objects.filter( + dealer=dealer, + content_type__model="customer", object_id=self.object.id ) estimates = entity.get_estimates().filter(customer=self.object.customer_model) invoices = entity.get_invoices().filter(customer=self.object.customer_model) + context['leads']=self.object.customer_leads.all() + total = estimates.count() + invoices.count() context["estimates"] = estimates context["invoices"] = invoices context["total"] = total + context["note_form"] = forms.NoteForm() return context @@ -4337,15 +4385,12 @@ def sales_list_view(request, dealer_slug): except Exception as e: print(e) - # query = request.GET.get('q') - # # if query: - # # qs = qs.filter( - # # Q(order_number__icontains=query) | - # # Q(customer__name__icontains=query) | - # # Q(item_details__icontains=query) - - # # ).distinct() - #r + search_query = request.GET.get('q', None) + if search_query: + qs = qs.filter( + Q(order_number__icontains=search_query)| + Q(customer__customer_name__icontains=search_query) + ).distinct() paginator = Paginator(qs, 30) page_number = request.GET.get("page") @@ -4445,23 +4490,32 @@ class EstimateListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): related_content_type=ContentType.objects.get_for_model(models.Staff), related_object_id=self.request.staff.pk, ) - context["staff_estimates"] = EstimateModel.objects.filter(pk__in=[x.content_object.pk for x in qs]) + qs = EstimateModel.objects.filter(pk__in=[x.content_object.pk for x in qs]) + search_query = self.request.GET.get('q', None) + if search_query: + qs = qs.filter( + Q(estimate_number__icontains=search_query)| + Q(customer__customer_name__icontains=search_query) + ).distinct() + context["staff_estimates"] = qs return context def get_queryset(self): dealer = get_user_type(self.request) entity = dealer.entity status = self.request.GET.get("status") + queryset = entity.get_estimates() if status: queryset = queryset.filter(status=status) search_query = self.request.GET.get('q', None) - + if search_query: queryset = queryset.filter( - Q(estimate_number__icontains=search_query) - + Q(estimate_number__icontains=search_query)| + Q(customer__customer_name__icontains=search_query) ).distinct() + return queryset diff --git a/static/js/main.js b/static/js/main.js index da998095..10093df8 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -249,3 +249,46 @@ const getDataTableInit = () => { }; + + +/* + // Register delete modal initializer +htmxInitializer.register(function initDeleteModals() { + const deleteModal = document.getElementById("deleteModal"); + const confirmDeleteBtn = document.getElementById("deleteModalConfirm"); + const deleteModalMessage = document.getElementById("deleteModalText"); + + // Clean up old listeners + document.querySelectorAll(".delete-btn").forEach(btn => { + btn.removeEventListener("click", handleDeleteClick); + }); + + // Add new listeners + document.querySelectorAll(".delete-btn").forEach(button => { + button.addEventListener("click", handleDeleteClick); + }); + + function handleDeleteClick() { + if (!deleteModal || !confirmDeleteBtn || !deleteModalMessage) return; + + const deleteUrl = this.getAttribute("data-url"); + const deleteMessage = this.getAttribute("data-message") || "Are you sure?"; + + confirmDeleteBtn.setAttribute("href", deleteUrl); + deleteModalMessage.textContent = deleteMessage; + + if (typeof htmx !== 'undefined') htmx.process(confirmDeleteBtn); + if (typeof bootstrap !== 'undefined') new bootstrap.Modal(deleteModal).show(); + } +}, "delete_modals"); + +// Register custom selects initializer +htmxInitializer.register(function initCustomSelects() { + // Your custom select initialization code +}, "custom_selects"); + +// Register form submission initializer +htmxInitializer.register(function initForms() { + // Your form handling code +}, "forms"); +*/ \ No newline at end of file diff --git a/templates/crm/notifications_history.html b/templates/crm/notifications_history.html index 61f4ec98..b2374191 100644 --- a/templates/crm/notifications_history.html +++ b/templates/crm/notifications_history.html @@ -3,7 +3,7 @@

{{ _("Notifications") }}

- {{ _("Mark all as read") }} + {{ _("Mark all as read") }}
{% if notifications %}
diff --git a/templates/customers/view_customer.html b/templates/customers/view_customer.html index 08d29783..16cabea7 100644 --- a/templates/customers/view_customer.html +++ b/templates/customers/view_customer.html @@ -88,16 +88,15 @@
{% if perms.inventory.change_customer %}
- "> - - {% trans 'Add Note' %} - + {% if perms.inventory.change_lead %} + + {% endif %}
{% endif %} @@ -105,8 +104,8 @@ - - {% for note in customer_notes %} + + {% for note in notes %} @@ -221,30 +220,86 @@ - - -
{{ _("Note") }} {{ _("Date") }}
{{ note.note }} {{ note.created }}
+ + + + + + + + + + + {% for lead in leads %} + + + + + + + + + + + + + {% endfor %} + + + +
{% trans 'Leads'|upper %}{% trans 'Opportunities'|upper %}{% trans 'Estimates'|upper %}{% trans 'Sale orders'|upper %}{% trans 'Invoices'|upper %}
{{lead}} ({{ forloop.counter }}){{lead.opportunity}} ({{ forloop.counter }}) + + {% for estimate in lead.customer.customer_model.estimatemodel_set.all %} +
{{estimate}}
+
+ {% endfor %} +
+ {% for estimate in lead.customer.customer_model.estimatemodel_set.all %} +
{{estimate.sale_orders.first}}
+
+ {% endfor %} +
+ {% for invoice in lead.customer.customer_model.invoicemodel_set.all %} + + {% if invoice.is_paid %} + +
{{invoice}}
+
+ {%else%} + +
{{invoice}}
+
+ {% endif %} + +
+ {% endfor %} +
+
+ {% include 'partials/pagination.html' %} +
+ + + + {% include "components/note_modal.html" with content_type="customer" slug=customer.slug %} + {% endblock %} diff --git a/templates/partials/search_box.html b/templates/partials/search_box.html index fabad3c6..ee61669b 100644 --- a/templates/partials/search_box.html +++ b/templates/partials/search_box.html @@ -1,35 +1,16 @@ -