From a4cb25cfbd0d219d36dab69b7cac142700fa3bde Mon Sep 17 00:00:00 2001 From: Faheedkhan Date: Wed, 9 Jul 2025 12:04:01 +0300 Subject: [PATCH 1/5] bill detail ui change --- templates/bill/bill_detail.html | 418 +++++++++++++++++--------------- templates/bill/bill_update.html | 15 ++ 2 files changed, 235 insertions(+), 198 deletions(-) diff --git a/templates/bill/bill_detail.html b/templates/bill/bill_detail.html index 5de0d08e..e69548e8 100644 --- a/templates/bill/bill_detail.html +++ b/templates/bill/bill_detail.html @@ -36,210 +36,232 @@ {% endblock %} {% block content %} -
-
- -
-
-
- {% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %} - - -
-
-
+
- -
- {% if bill.is_configured %} -
-
-
-
-
-
- {% trans 'Cash Account' %}: - - {{ bill.cash_account.code }} - -
-

- {% currency_symbol %}{{ bill.get_amount_cash | absolute | currency_format }} -

-
-
- {% if bill.accrue %} -
-
-
- {% trans 'Prepaid Account' %}: - - {{ bill.prepaid_account.code }} - -
-

- {% currency_symbol %}{{ bill.get_amount_prepaid | currency_format }} -

-
-
-
-
-
- {% trans 'Accounts Payable' %}: - - {{ bill.unearned_account.code }} - -
-

- {% currency_symbol %}{{ bill.get_amount_unearned | currency_format }} -

-
-
-
-
-
- {% trans 'Accrued' %} {{ bill.get_progress | percentage }} -
-

- {% currency_symbol %}{{ bill.get_amount_earned | currency_format }} -

-
-
- {% else %} -
-
-
- {% trans 'You Still Owe' %} -
-

- {% currency_symbol %}{{ bill.get_amount_open | currency_format }} -

-
-
- {% endif %} -
-
-
- {% endif %} +
+
+
+
+
+ {% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %} - -
-
-
- -
{% trans 'Bill Items' %}
-
-
-
-
- - - - - - - - - - - - - {% for bill_item in itemtxs_qs %} - - - - - - - - - {% endfor %} - - - - - - - - - -
{% trans 'Item' %}{% trans 'Entity Unit' %}{% trans 'Unit Cost' %}{% trans 'Quantity' %}{% trans 'Total' %}{% trans 'PO' %}
-
-
-
{{ bill_item.item_model }}
-
+ -
- - {% if bill_item.entity_unit %} - {{ bill_item.entity_unit }} - {% endif %} - - - - {{ bill_item.unit_cost | currency_format }} - - - {{ bill_item.quantity }} - - - {{ bill_item.total_amount | currency_format }} - - - {% if bill_item.po_model_id %} - {% if perms.django_ledger.view_purchaseordermodel%} - - {% trans 'View PO' %} - - {% endif %} - {% endif %} -
{% trans 'Total' %} - - {% currency_symbol %}{{ total_amount__sum | currency_format }} - -
+
+
+
+ +
+
+ +
+
+
+ +
{% trans 'Bill Notes' %}
+
+
+ {% if perms.django_ledger.change_billmodel%} +
+ {% include 'bill/includes/card_markdown.html' with style='card_1' title='' notes_html=bill.notes_html %} +
+ {% endif %}
-
- -
-
-
- -
{% trans 'Bill Transactions' %}
-
-
-
- {% transactions_table bill %} -
-
- - -
-
-
- -
{% trans 'Bill Notes' %}
-
-
- {% if perms.django_ledger.change_billmodel%} -
- {% include 'bill/includes/card_markdown.html' with style='card_1' title='' notes_html=bill.notes_html %} -
- {% endif %} -
-
-
+ + +
+
+
+ {% if bill.is_configured %} +
+
+
+
+
+
+ {% trans 'Cash Account' %}: + + {{ bill.cash_account.code }} + +
+

+ {% currency_symbol %}{{ bill.get_amount_cash | absolute | currency_format }} +

+
+
+ {% if bill.accrue %} +
+
+
+ {% trans 'Prepaid Account' %}: + + {{ bill.prepaid_account.code }} + +
+

+ {% currency_symbol %}{{ bill.get_amount_prepaid | currency_format }} +

+
+
+
+
+
+ {% trans 'Accounts Payable' %}: + + {{ bill.unearned_account.code }} + +
+

+ {% currency_symbol %}{{ bill.get_amount_unearned | currency_format }} +

+
+
+
+
+
+ {% trans 'Accrued' %} {{ bill.get_progress | percentage }} +
+

+ {% currency_symbol %}{{ bill.get_amount_earned | currency_format }} +

+
+
+ {% else %} +
+
+
+ {% trans 'You Still Owe' %} +
+

+ {% currency_symbol %}{{ bill.get_amount_open | currency_format }} +

+
+
+ {% endif %} +
+
+
+ {% endif %} + + +
+ +
+ +
+
+
+ +
{% trans 'Bill Items' %}
+
+
+
+
+ + + + + + + + + + + + + {% for bill_item in itemtxs_qs %} + + + + + + + + + {% endfor %} + + + + + + + + + +
{% trans 'Item' %}{% trans 'Entity Unit' %}{% trans 'Unit Cost' %}{% trans 'Quantity' %}{% trans 'Total' %}{% trans 'PO' %}
+
+
+
{{ bill_item.item_model }}
+
+
+
+ + {% if bill_item.entity_unit %} + {{ bill_item.entity_unit }} + {% endif %} + + + + {{ bill_item.unit_cost | currency_format }} + + + {{ bill_item.quantity }} + + + {{ bill_item.total_amount | currency_format }} + + + {% if bill_item.po_model_id %} + {% if perms.django_ledger.view_purchaseordermodel%} + + {% trans 'View PO' %} + + {% endif %} + {% endif %} +
{% trans 'Total' %} + + {% currency_symbol %}{{ total_amount__sum | currency_format }} + +
+
+
+
+ + +
+ +
+ +
+
+
+ +
{% trans 'Bill Transactions' %}
+
+
+
+ {% transactions_table bill %} +
+
+ + +
+ +
+ +
+ + +
{% include "bill/includes/mark_as.html" %} {% endblock %} \ No newline at end of file diff --git a/templates/bill/bill_update.html b/templates/bill/bill_update.html index 0fb4e1a7..f9c2a90d 100644 --- a/templates/bill/bill_update.html +++ b/templates/bill/bill_update.html @@ -22,6 +22,21 @@ class="btn btn-phoenix-secondary w-100 mb-2"> {% trans 'Back to Bill Detail' %} + +
+ {% csrf_token %} + +
+ {{ form|crispy }} +
+ + + + + +
From fed9c20bb4559a34f8c3a78cb1e8f13c9184d3dc Mon Sep 17 00:00:00 2001 From: Faheedkhan Date: Wed, 9 Jul 2025 13:22:39 +0300 Subject: [PATCH 2/5] comma missing in the allowed_models of manager --- inventory/models.py | 2 +- inventory/views.py | 2 +- templates/sales/sales_list.html | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/inventory/models.py b/inventory/models.py index 4f20430a..b04c193a 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -2606,7 +2606,7 @@ class CustomGroup(models.Model): "activity", "opportunity", "vendor", - "customer" + "customer", "notes", "tasks", "activity", diff --git a/inventory/views.py b/inventory/views.py index f697bdb6..de68403a 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -9922,7 +9922,7 @@ class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListVie return self.model.objects.filter(entity=dealer.entity) # def get_queryset(self): - # dealer = get_user_type(self.request) + # dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) # entity = dealer.entity # queryset = self.model.objects.filter(entity=entity) diff --git a/templates/sales/sales_list.html b/templates/sales/sales_list.html index 91d891d0..1f3c978a 100644 --- a/templates/sales/sales_list.html +++ b/templates/sales/sales_list.html @@ -129,7 +129,7 @@

{{tx.customer.phone_number}}

- {% if tx.estimate %} + {% if tx.estimate and perms.django_ledger.view_estimatemodel%}

{{ tx.estimate.estimate_number}} @@ -147,7 +147,7 @@ {% endif %} - {% if tx.invoice %} + {% if tx.invoice and perms.django_ledger.view_invoicemodel%}

{{tx.invoice.invoice_number}} From 8398dcd5decbdbfcf349c25bf02acb9a4706186d Mon Sep 17 00:00:00 2001 From: Faheedkhan Date: Wed, 9 Jul 2025 14:05:03 +0300 Subject: [PATCH 3/5] changes to the lead_list table --- templates/crm/leads/lead_list.html | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/templates/crm/leads/lead_list.html b/templates/crm/leads/lead_list.html index 8c7911ce..42792e05 100644 --- a/templates/crm/leads/lead_list.html +++ b/templates/crm/leads/lead_list.html @@ -50,18 +50,20 @@

{{ _("Phone Number") }}
- -
-
- {{ _("Schedule") }} -
- +
- {{ _("Action")|capfirst }} + {{ _("Next Action")|capfirst }}
+ +
+
+ {{ _("Scheduled at") }} +
+ +
@@ -69,15 +71,16 @@
- + {% comment %}
{{ _("Opportunity")|capfirst }}
- + {% endcomment %} {{ _("Action") }} + {% for lead in leads %} @@ -103,7 +106,7 @@
- +
{{lead.full_name|capfirst}}
@@ -128,9 +131,9 @@ {{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }} {{ lead.email }} - {{ lead.phone_number }} - - {{ lead.get_status|upper }} + {{ lead.phone_number }} + {{ lead.next_action|upper }} + {{ lead.next_action_date|upper }} {{ lead.staff|upper }} {% comment %} {% if lead.opportunity.stage == "prospect" %} @@ -145,13 +148,13 @@ {{ lead.opportunity.stage|upper }} {% endif %} {% endcomment %} - + {% comment %} {% if lead.opportunity %} Opportunity {{ lead.opportunity.lead}} {% endif %} - + {% endcomment %} {% if user == lead.staff.user or request.is_dealer %}
From 51b2833e5426c65cc29b149ab9f6b31f14879b05 Mon Sep 17 00:00:00 2001 From: Faheedkhan Date: Thu, 10 Jul 2025 13:17:15 +0300 Subject: [PATCH 4/5] added search --- inventory/views.py | 75 ++++++++++++++++--- .../crm/opportunities/opportunity_list.html | 53 ++++++++----- templates/customers/customer_list.html | 4 +- templates/ledger/bills/bill_list.html | 23 +----- 4 files changed, 104 insertions(+), 51 deletions(-) diff --git a/inventory/views.py b/inventory/views.py index de68403a..a04ea1bf 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -3864,6 +3864,15 @@ class BankAccountDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailV template_name = "ledger/bank_accounts/bank_account_detail.html" context_object_name = "bank_account" permission_required = ["django_ledger.view_bankaccountmodel"] + + def get_queryset(self): + dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) + query=self.request.GET.get('q') + qs=self.model.objects.filter(entity=dealer.entity) + if query: + qs=apply_search_filters(qs,query) + return qs + return qs class BankAccountUpdateView( @@ -5584,14 +5593,23 @@ class LeadListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): query = self.request.GET.get("q") qs = models.Lead.objects.filter(dealer=dealer).exclude(status="converted") if query: - qs = apply_search_filters(qs, query) + qs = qs.filter(Q(first_name__icontains=query) + | Q(last_name__icontains=query) + | Q(id_car_make__name__icontains=query) + | Q(id_car_model__name__icontains=query) + | Q(email__icontains=query) + | Q(phone_number__icontains=query) + | Q(next_action__icontains=query) + | Q(staff__name__icontains=query)) + if self.request.is_dealer: return qs staffmember = getattr(self.request.user, "staffmember", None) if staff := getattr(staffmember, "staff", None): return qs.filter(staff=staff) return models.Lead.objects.none() - + + class LeadDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): """ @@ -6654,12 +6672,15 @@ class OpportunityListView(LoginRequiredMixin,PermissionRequiredMixin, ListView): queryset = models.Opportunity.objects.filter(dealer=dealer, lead__staff=staff) # Search filter - search = self.request.GET.get("search") + search = self.request.GET.get("q") if search: queryset = queryset.filter( - Q(customer__customer_name__icontains=search) + Q(customer__first_name__icontains=search) + | Q(customer__last_name__icontains=search) | Q(customer__email__icontains=search) - ) + + ) + # Stage filter stage = self.request.GET.get("stage") @@ -6947,10 +6968,17 @@ class ItemServiceListView(LoginRequiredMixin, PermissionRequiredMixin, ListView) paginate_by = 30 permission_required = ["inventory.view_additionalservices"] - def get_queryset(self): dealer = get_user_type(self.request) - return models.AdditionalServices.objects.filter(dealer=dealer).all() + query=self.request.GET.get('q') + qs= models.AdditionalServices.objects.filter(dealer=dealer).all() + if query: + qs=apply_search_filters(qs,query) + return qs + + # def get_queryset(self): + # dealer = get_user_type(self.request) + # return models.AdditionalServices.objects.filter(dealer=dealer).all() class ItemExpenseCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): @@ -7068,9 +7096,18 @@ class ItemExpenseListView(LoginRequiredMixin, PermissionRequiredMixin, ListView) paginate_by = 30 permission_required = ["django_ledger.view_itemmodel"] + # def get_queryset(self): + # dealer = get_user_type(self.request) + # return dealer.entity.get_items_expenses() + def get_queryset(self): dealer = get_user_type(self.request) - return dealer.entity.get_items_expenses() + query=self.request.GET.get('q') + qs= dealer.entity.get_items_expenses() + if query: + qs=apply_search_filters(qs,query) + return qs + class BillListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): @@ -7100,6 +7137,9 @@ class BillListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): def get_queryset(self): dealer = get_user_type(self.request) qs = dealer.entity.get_bills() + query=self.request.GET.get('q') + if query: + qs=qs.filter(vendor__vendor_name__icontains=query) return qs def get_context_data(self, **kwargs): @@ -9917,12 +9957,23 @@ class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListVie template_name = "purchase_orders/po_list.html" permission_required = ["django_ledger.view_purchaseordermodel"] - def get_queryset(self): - dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) - return self.model.objects.filter(entity=dealer.entity) - # def get_queryset(self): # dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) + # return self.model.objects.filter(entity=dealer.entity) + def get_queryset(self): + dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) + query=self.request.GET.get("q") + qs=self.model.objects.filter(entity=dealer.entity) + if query: + qs=apply_search_filters(qs,query) + if self.request.is_dealer: + return qs + staffmember= staffmember = getattr(self.request.user, "staffmember", None) + if staff := getattr(staffmember, "staff", None): + return qs.filter(staff=staff) + return self.model.objects.none() + # def get_queryset(self): + # dealer = get_user_type(self.request) # entity = dealer.entity # queryset = self.model.objects.filter(entity=entity) diff --git a/templates/crm/opportunities/opportunity_list.html b/templates/crm/opportunities/opportunity_list.html index 5e9a9e69..2412faa1 100644 --- a/templates/crm/opportunities/opportunity_list.html +++ b/templates/crm/opportunities/opportunity_list.html @@ -12,25 +12,22 @@
-
- - -
+ + + -
+
- {% if request.GET.q %} - - - - {% endif %} -
- +
+
+ {% include 'partials/search_box.html' %} +
From d7ba36b7733ed269cd36e96b0bf84268fadfff5f Mon Sep 17 00:00:00 2001 From: Faheedkhan Date: Thu, 10 Jul 2025 19:04:10 +0300 Subject: [PATCH 5/5] bug fixes for search --- haikalbot/migrations/0001_initial.py | 2 +- haikalbot/migrations/0002_initial.py | 2 +- inventory/migrations/0001_initial.py | 4 ++-- inventory/models.py | 6 +++++- inventory/views.py | 14 ++++++-------- templates/purchase_orders/includes/card_po.html | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/haikalbot/migrations/0001_initial.py b/haikalbot/migrations/0001_initial.py index 4d92b23a..6d70604b 100644 --- a/haikalbot/migrations/0001_initial.py +++ b/haikalbot/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.4 on 2025-07-09 13:00 +# Generated by Django 5.1.7 on 2025-07-10 12:55 import django.db.models.deletion import django.utils.timezone diff --git a/haikalbot/migrations/0002_initial.py b/haikalbot/migrations/0002_initial.py index 1b740d02..dd38a5d5 100644 --- a/haikalbot/migrations/0002_initial.py +++ b/haikalbot/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.4 on 2025-07-09 13:00 +# Generated by Django 5.1.7 on 2025-07-10 12:55 import django.db.models.deletion from django.db import migrations, models diff --git a/inventory/migrations/0001_initial.py b/inventory/migrations/0001_initial.py index 8e326055..cf9ffd02 100644 --- a/inventory/migrations/0001_initial.py +++ b/inventory/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.4 on 2025-07-09 13:00 +# Generated by Django 5.1.7 on 2025-07-10 12:55 import datetime import django.core.serializers.json @@ -22,7 +22,7 @@ class Migration(migrations.Migration): ('appointment', '0001_initial'), ('auth', '0012_alter_user_first_name_max_length'), ('contenttypes', '0002_remove_content_type_name'), - ('django_ledger', '0023_merge_20250708_1825'), + ('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] diff --git a/inventory/models.py b/inventory/models.py index 13af691d..0bf0e7d4 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -2707,7 +2707,8 @@ class CustomGroup(models.Model): "notes", "tasks", "activity", - "payment"], + "payment", + 'vendor'], other_perms=[ "view_car", "view_carlocation", @@ -2715,6 +2716,9 @@ class CustomGroup(models.Model): "view_carcolors", "view_cartransfer", "view_saleorder", + "view_leads", + "view_opportunity", + "view_customers", ], ) diff --git a/inventory/views.py b/inventory/views.py index b2f525b9..a20fd1a4 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -2496,7 +2496,7 @@ class VendorListView(LoginRequiredMixin,PermissionRequiredMixin, ListView): @login_required -@permission_required('django_ledger.view_vendormodel',raise_exception=True) +@permission_required('inventory.view_vendor',raise_exception=True) def vendorDetailView(request, dealer_slug,slug): """ Fetches and renders the detail view for a specific vendor. @@ -9970,12 +9970,10 @@ class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListVie qs=self.model.objects.filter(entity=dealer.entity) if query: qs=apply_search_filters(qs,query) - if self.request.is_dealer: - return qs - staffmember= staffmember = getattr(self.request.user, "staffmember", None) - if staff := getattr(staffmember, "staff", None): - return qs.filter(staff=staff) - return self.model.objects.none() + return qs + + + # def get_queryset(self): # dealer = get_user_type(self.request) # entity = dealer.entity @@ -10058,7 +10056,7 @@ class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase): class PurchaseOrderModelDeleteView(PurchaseOrderModelDeleteViewBase): template_name = "purchase_orders/po_delete.html" - permission_required = "django_ledger.delete_purchaseordermodel" + permission_required = "django_ledger.delete_purchaseordermodel" def get_success_url(self): messages.add_message( diff --git a/templates/purchase_orders/includes/card_po.html b/templates/purchase_orders/includes/card_po.html index f3688d96..5b5110d1 100644 --- a/templates/purchase_orders/includes/card_po.html +++ b/templates/purchase_orders/includes/card_po.html @@ -149,7 +149,7 @@ onclick="showPOModal('Fulfill PO', '{% url 'po-action-mark-as-fulfilled' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Fulfilled')"> {% trans 'Mark as Fulfilled' %} - + {% endif %}