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") }}
{% 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 @@
| {{ _("Note") }} |
{{ _("Date") }} |
-
- {% for note in customer_notes %}
+
+ {% for note in notes %}
| {{ note.note }} |
{{ note.created }} |
@@ -221,30 +220,86 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {%trans 'INFO'%}
+
+
+
+ {% 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 @@
-