From a930acfae53393c9ec8bae9326308ee301ea5f05 Mon Sep 17 00:00:00 2001 From: ismail Date: Wed, 25 Jun 2025 14:29:38 +0300 Subject: [PATCH] update and formatting --- .gitignore | 1 + inventory/context_processors.py | 2 +- inventory/middleware.py | 8 +- .../migrations/0011_dealer_business_name.py | 19 - .../0012_remove_dealer_business_name.py | 17 - inventory/mixins.py | 10 +- inventory/models.py | 16 +- inventory/templatetags/custom_filters.py | 15 +- inventory/urls.py | 119 ++++-- inventory/views.py | 306 +++++++++----- templates/base.html | 2 +- .../bill/transactions/tags/txs_table.html | 2 +- templates/crm/leads/lead_list.html | 38 +- .../crm/opportunities/opportunity_list.html | 20 +- templates/customers/customer_list.html | 20 +- templates/groups/group_list.html | 14 +- templates/header.html | 6 +- templates/inventory/car_detail.html | 6 +- templates/inventory/car_list_view.html | 374 +++++++++--------- templates/inventory/inventory_stats.html | 16 +- templates/inventory/tags/inventory_table.html | 8 +- templates/items/expenses/expenses_list.html | 18 +- templates/items/service/service_list.html | 18 +- .../bank_accounts/bank_account_list.html | 16 +- templates/ledger/bills/bill_list.html | 14 +- .../journal_entry/journal_entry_list.html | 20 +- .../journal_entry_transactions.html | 16 +- templates/ledger/ledger/ledger_list.html | 16 +- .../organizations/organization_list.html | 26 +- templates/partials/pagination.html | 156 ++++---- .../plans/billing_info_create_or_update.html | 4 +- templates/purchase_orders/po_detail.html | 24 +- templates/purchase_orders/po_list.html | 14 +- templates/purchase_orders/po_upload_cars.html | 18 +- .../sales/estimates/estimate_detail.html | 66 ++-- templates/sales/estimates/estimate_list.html | 12 +- templates/sales/invoices/invoice_detail.html | 68 ++-- templates/sales/invoices/invoice_list.html | 12 +- templates/sales/journals/journal_list.html | 10 +- templates/sales/orders/order_list.html | 10 +- templates/sales/payments/payment_list.html | 10 +- templates/sales/saleorder_detail.html | 2 +- templates/sales/sales_list.html | 2 +- 43 files changed, 859 insertions(+), 712 deletions(-) delete mode 100644 inventory/migrations/0011_dealer_business_name.py delete mode 100644 inventory/migrations/0012_remove_dealer_business_name.py diff --git a/.gitignore b/.gitignore index e5884ed1..8e0bbe6f 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ Makefile .idea/**/dynamic.xml .idea/**/uiDesigner.xml .idea/**/dbnavigator.xml +**/migrations/ # Gradle .idea/**/gradle.xml diff --git a/inventory/context_processors.py b/inventory/context_processors.py index 89af5dbd..8b35b790 100644 --- a/inventory/context_processors.py +++ b/inventory/context_processors.py @@ -42,4 +42,4 @@ def breadcrumbs(request): for i in range(len(path)): url = "/" + "/".join(path[: i + 1]) + "/" breadcrumbs.append({"name": path[i].capitalize(), "url": url}) - return {"breadcrumbs": breadcrumbs} \ No newline at end of file + return {"breadcrumbs": breadcrumbs} diff --git a/inventory/middleware.py b/inventory/middleware.py index 14010720..a68653ce 100644 --- a/inventory/middleware.py +++ b/inventory/middleware.py @@ -124,10 +124,8 @@ class DealerSlugMiddleware: def process_view(self, request, view_func, view_args, view_kwargs): if request.user.is_authenticated: dealer = get_user_type(request) - if 'dealer_slug' not in view_kwargs: - return redirect('home', - dealer_slug=dealer.slug, - **view_kwargs) - elif view_kwargs['dealer_slug'] != dealer.slug: + if "dealer_slug" not in view_kwargs: + return redirect("home", dealer_slug=dealer.slug, **view_kwargs) + elif view_kwargs["dealer_slug"] != dealer.slug: raise Http404("Dealer slug mismatch") return None diff --git a/inventory/migrations/0011_dealer_business_name.py b/inventory/migrations/0011_dealer_business_name.py deleted file mode 100644 index e7dd6751..00000000 --- a/inventory/migrations/0011_dealer_business_name.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.1 on 2025-06-23 12:21 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0010_alter_saleorder_created_by_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='dealer', - name='business_name', - field=models.CharField(default='poiiiioioioi', max_length=255, verbose_name='Buiseness Name'), - preserve_default=False, - ), - ] diff --git a/inventory/migrations/0012_remove_dealer_business_name.py b/inventory/migrations/0012_remove_dealer_business_name.py deleted file mode 100644 index c8e9444f..00000000 --- a/inventory/migrations/0012_remove_dealer_business_name.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 5.2.1 on 2025-06-24 12:55 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0011_dealer_business_name'), - ] - - operations = [ - migrations.RemoveField( - model_name='dealer', - name='business_name', - ), - ] diff --git a/inventory/mixins.py b/inventory/mixins.py index b730dbb5..e3e8fe81 100644 --- a/inventory/mixins.py +++ b/inventory/mixins.py @@ -69,10 +69,8 @@ class LocalizedNameMixin: class DealerSlugMixin: def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated: - if 'dealer_slug' not in kwargs: - return redirect('home', - dealer_slug=request.dealer.slug, - **kwargs) - elif kwargs['dealer_slug'] != request.dealer.slug: + if "dealer_slug" not in kwargs: + return redirect("home", dealer_slug=request.dealer.slug, **kwargs) + elif kwargs["dealer_slug"] != request.dealer.slug: raise Http404("Dealer slug mismatch") - return super().dispatch(request, *args, **kwargs) \ No newline at end of file + return super().dispatch(request, *args, **kwargs) diff --git a/inventory/models.py b/inventory/models.py index a9484260..f043ee29 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -2482,16 +2482,22 @@ class SaleOrder(models.Model): item_data = self.invoice.get_itemtxs_data() if item_data: return item_data - return [] # Return an empty list if no invoice or no item data - + return [] # Return an empty list if no invoice or no item data + @property def cars(self): # Check if self.items is not empty before trying to iterate - if self.items.exists() if hasattr(self.items, 'exists') else self.items: # Handle both QuerySet and list + if ( + self.items.exists() if hasattr(self.items, "exists") else self.items + ): # Handle both QuerySet and list # Ensure x is an *instance* of ItemTransactionModel # item_model should be a ForeignKey to your CarModel within ItemTransactionModel - return [x.item_model.car for x in self.items if hasattr(x, 'item_model') and hasattr(x.item_model, 'car')] - return [] # Return an empty list if no items or no associated cars + return [ + x.item_model.car + for x in self.items + if hasattr(x, "item_model") and hasattr(x.item_model, "car") + ] + return [] # Return an empty list if no items or no associated cars class CustomGroup(models.Model): diff --git a/inventory/templatetags/custom_filters.py b/inventory/templatetags/custom_filters.py index 474bca31..031f26de 100644 --- a/inventory/templatetags/custom_filters.py +++ b/inventory/templatetags/custom_filters.py @@ -1,4 +1,3 @@ - from typing import Union from random import randint from django import template @@ -493,15 +492,15 @@ def transactions_table( qs = object_type.get_transaction_queryset(annotated=True) transaction_model_qs = qs.annotate( debit_credit_sort_order=Case( - When(tx_type='debit', then=Value(0)), # Debits will get sort order 0 - When(tx_type='credit', then=Value(1)), # Credits will get sort order 1 - default=Value(2), # Fallback for any other tx_type, if applicable - output_field=IntegerField() + When(tx_type="debit", then=Value(0)), # Debits will get sort order 0 + When(tx_type="credit", then=Value(1)), # Credits will get sort order 1 + default=Value(2), # Fallback for any other tx_type, if applicable + output_field=IntegerField(), ) ).order_by( - '-timestamp', # Primary sort: chronological (oldest first) - '-debit_credit_sort_order', # Secondary sort: Debits (0) before Credits (1) - 'pk' # Optional: Tie-breaker for consistent order + "-timestamp", # Primary sort: chronological (oldest first) + "-debit_credit_sort_order", # Secondary sort: Debits (0) before Credits (1) + "pk", # Optional: Tie-breaker for consistent order ) elif isinstance(object_type, InvoiceModel): transaction_model_qs = object_type.get_transaction_queryset( diff --git a/inventory/urls.py b/inventory/urls.py index 475b6cdf..5b6f9adb 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -280,20 +280,48 @@ urlpatterns = [ ), # Car URLs path("/cars/upload_cars/", views.upload_cars, name="upload_cars"), - path("/cars//upload_cars/", views.upload_cars, name="upload_cars"), + path( + "/cars//upload_cars/", + views.upload_cars, + name="upload_cars", + ), path("/cars/add/", views.CarCreateView.as_view(), name="car_add"), - path("/cars/inventory/", views.CarInventory.as_view(), name="car_inventory_all"), + path( + "/cars/inventory/", + views.CarInventory.as_view(), + name="car_inventory_all", + ), path( "/cars/inventory////", views.CarInventory.as_view(), name="car_inventory", ), - path("/cars/inventory/stats", views.inventory_stats_view, name="inventory_stats"), - path("/cars/inventory/list", views.CarListView.as_view(), name="car_list"), - path("/cars//", views.CarDetailView.as_view(), name="car_detail"), + path( + "/cars/inventory/stats", + views.inventory_stats_view, + name="inventory_stats", + ), + path( + "/cars/inventory/list", + views.CarListView.as_view(), + name="car_list", + ), + path( + "/cars//", + views.CarDetailView.as_view(), + name="car_detail", + ), path("cars//history/", views.car_history, name="car_history"), - path("/cars//update/", views.CarUpdateView.as_view(), name="car_update"), - path("/cars//delete/", views.CarDeleteView.as_view(), name="car_delete"), + path( + "/cars//update/", + views.CarUpdateView.as_view(), + name="car_update", + ), + path( + "/cars//delete/", + views.CarDeleteView.as_view(), + name="car_delete", + ), path( "/cars//finance/create/", views.CarFinanceCreateView.as_view(), @@ -309,9 +337,13 @@ urlpatterns = [ views.bulk_update_car_price, name="bulk_update_car_price", ), - path("/ajax/", views.AjaxHandlerView.as_view(), name="ajax_handler"), path( - "/cars//add-color/", views.CarColorCreate.as_view(), name="add_color" + "/ajax/", views.AjaxHandlerView.as_view(), name="ajax_handler" + ), + path( + "/cars//add-color/", + views.CarColorCreate.as_view(), + name="add_color", ), path( "/car/colors//update/", @@ -355,7 +387,11 @@ urlpatterns = [ ), path("cars/inventory/search/", views.SearchCodeView.as_view(), name="car_search"), # path('cars//colors//update/',views.CarColorUpdateView.as_view(),name='color_update'), - path("/cars/reserve//", views.reserve_car_view, name="reserve_car"), + path( + "/cars/reserve//", + views.reserve_car_view, + name="reserve_car", + ), path( "/reservations//", views.manage_reservation, @@ -373,17 +409,17 @@ urlpatterns = [ ), # sales list path( - "sales/list/", + "/sales/list/", views.sales_list_view, name="sales_list", ), path( - "sale_orders//", + "/sale_orders//", views.SaleOrderDetailView.as_view(), name="order_detail", ), path( - "inventory//list/", + "/inventory//list/", views.InventoryListView.as_view(), name="inventort_list", ), @@ -614,7 +650,9 @@ urlpatterns = [ ), # Bank Account path( - "/bank_accounts/", views.BankAccountListView.as_view(), name="bank_account_list" + "/bank_accounts/", + views.BankAccountListView.as_view(), + name="bank_account_list", ), path( "/bank_accounts//", @@ -637,31 +675,49 @@ urlpatterns = [ name="bank_account_delete", ), # Account - path("/coa_accounts/", views.AccountListView.as_view(), name="account_list"), + path( + "/coa_accounts/", + views.AccountListView.as_view(), + name="account_list", + ), path( "/coa_accounts//", views.AccountDetailView.as_view(), name="account_detail", ), path( - "/coa_accounts/create/", views.AccountCreateView.as_view(), name="account_create" + "/coa_accounts/create/", + views.AccountCreateView.as_view(), + name="account_create", ), path( "/coa_accounts//update/", views.AccountUpdateView.as_view(), name="account_update", ), - path("/coa_accounts//delete/", views.account_delete, name="account_delete"), + path( + "/coa_accounts//delete/", + views.account_delete, + name="account_delete", + ), ################################################# # Estimate ################################################# - path("/sales/estimates/", views.EstimateListView.as_view(), name="estimate_list"), + path( + "/sales/estimates/", + views.EstimateListView.as_view(), + name="estimate_list", + ), path( "/sales/estimates//", views.EstimateDetailView.as_view(), name="estimate_detail", ), - path("/sales/estimates/create/", views.create_estimate, name="estimate_create"), + path( + "/sales/estimates/create/", + views.create_estimate, + name="estimate_create", + ), path( "/sales/estimates/create//", views.create_estimate, @@ -683,7 +739,9 @@ urlpatterns = [ name="payment_request", ), path( - "/sales/estimates//send_email", views.send_email_view, name="send_email" + "/sales/estimates//send_email", + views.send_email_view, + name="send_email", ), path( "/sales/estimates//sale_order/", @@ -703,9 +761,15 @@ urlpatterns = [ ############################################### # Invoice ############################################### - path("/sales/invoices/", views.InvoiceListView.as_view(), name="invoice_list"), path( - "/sales/invoices//create/", views.invoice_create, name="invoice_create" + "/sales/invoices/", + views.InvoiceListView.as_view(), + name="invoice_list", + ), + path( + "/sales/invoices//create/", + views.invoice_create, + name="invoice_create", ), path( "/sales/invoices//", @@ -740,7 +804,9 @@ urlpatterns = [ # path('sales/estimates//preview/', views.EstimatePreviewView.as_view(), name='estimate_preview'), # path('send_email/', views.send_email, name='send_email'), # Payment - path("/sales/payments/", views.PaymentListView, name="payment_list"), + path( + "/sales/payments/", views.PaymentListView, name="payment_list" + ), path( "/sales/payments//create/", views.PaymentCreateView, @@ -793,7 +859,11 @@ urlpatterns = [ name="item_expense_update", ), # Bills - path("/items/bills/", views.BillListView.as_view(), name="bill_list"), + path( + "/items/bills/", + views.BillListView.as_view(), + name="bill_list", + ), # path("items/bills/create/", views.BillModelCreateViewView.as_view(), name="bill_create"), path( "/items/bills//create/", @@ -1121,7 +1191,6 @@ urlpatterns = [ views.PurchaseOrderMarkAsVoidView.as_view(), name="po-action-mark-as-void", ), - ] handler404 = "inventory.views.custom_page_not_found_view" diff --git a/inventory/views.py b/inventory/views.py index 6af0e212..fe8643e4 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -349,7 +349,7 @@ class HomeView(LoginRequiredMixin, TemplateView): template_name = "index.html" - def dispatch(self, request,*args, **kwargs): + def dispatch(self, request, *args, **kwargs): # Redirect unauthenticated users to the welcome page if not request.user.is_authenticated: return redirect("welcome") @@ -620,8 +620,12 @@ class CarCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): def get_success_url(self): """Determine the redirect URL based on user choice.""" if self.request.POST.get("add_another"): - return reverse("car_add", kwargs={"dealer_slug": self.kwargs["dealer_slug"]}) - return reverse("inventory_stats", kwargs={"dealer_slug": self.kwargs["dealer_slug"]}) + return reverse( + "car_add", kwargs={"dealer_slug": self.kwargs["dealer_slug"]} + ) + return reverse( + "inventory_stats", kwargs={"dealer_slug": self.kwargs["dealer_slug"]} + ) def form_valid(self, form): dealer = get_user_type(self.request) @@ -675,7 +679,7 @@ class AjaxHandlerView(LoginRequiredMixin, View): :ivar request: Django request object containing HTTP request details. """ - def get(self, request,dealer_slug, *args, **kwargs): + def get(self, request, dealer_slug, *args, **kwargs): action = request.GET.get("action") handlers = { "decode_vin": self.decode_vin, @@ -988,7 +992,13 @@ class CarColorCreate(LoginRequiredMixin, PermissionRequiredMixin, CreateView): return super().form_valid(form) def get_success_url(self): - return reverse_lazy("car_detail", kwargs={"dealer_slug":self.request.dealer.slug,"slug": self.kwargs["slug"]}) + return reverse_lazy( + "car_detail", + kwargs={ + "dealer_slug": self.request.dealer.slug, + "slug": self.kwargs["slug"], + }, + ) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -1027,7 +1037,13 @@ class CarColorsUpdateView( """ # self.object refers to the CarColors instance that was just updated. # self.object.car then refers to the associated Car instance. - return reverse("car_detail", kwargs={"dealer_slug":self.request.dealer.slug,"slug": self.object.car.slug}) + return reverse( + "car_detail", + kwargs={ + "dealer_slug": self.request.dealer.slug, + "slug": self.object.car.slug, + }, + ) def get_context_data(self, **kwargs): """ @@ -1140,7 +1156,7 @@ class CarListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): @login_required -def inventory_stats_view(request,dealer_slug): +def inventory_stats_view(request, dealer_slug): """ Handle the inventory stats view for a dealer, displaying detailed information about the cars, including counts grouped by make, model, and trim. @@ -1245,7 +1261,6 @@ def inventory_stats_view(request,dealer_slug): return render(request, "inventory/inventory_stats.html", {"inventory": result}) - # @login_required # def inventory_stats_view(request): # """ @@ -1362,7 +1377,6 @@ def inventory_stats_view(request,dealer_slug): # return render(request, "inventory/inventory_stats.html", context) - class CarDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): """ Provides a detailed view of a single car instance. @@ -1427,7 +1441,10 @@ class CarFinanceCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateVi return super().form_valid(form) def get_success_url(self): - return reverse("car_detail", kwargs={"dealer_slug":self.request.dealer.slug,"slug": self.car.slug}) + return reverse( + "car_detail", + kwargs={"dealer_slug": self.request.dealer.slug, "slug": self.car.slug}, + ) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -1474,7 +1491,13 @@ class CarFinanceUpdateView( permission_required = ["inventory.change_carfinance"] def get_success_url(self): - return reverse("car_detail", kwargs={"dealer_slug":self.request.dealer.slug,"slug": self.object.car.slug}) + return reverse( + "car_detail", + kwargs={ + "dealer_slug": self.request.dealer.slug, + "slug": self.object.car.slug, + }, + ) def get_form_kwargs(self): kwargs = super().get_form_kwargs() @@ -1871,7 +1894,13 @@ class CustomCardCreateView(LoginRequiredMixin, CreateView): def get_success_url(self): messages.success(self.request, _("Custom Card added successfully")) - return reverse_lazy("car_detail", kwargs={"dealer_slug":self.request.dealer.slug,"slug": self.kwargs["slug"]}) + return reverse_lazy( + "car_detail", + kwargs={ + "dealer_slug": self.request.dealer.slug, + "slug": self.kwargs["slug"], + }, + ) class CarRegistrationCreateView(LoginRequiredMixin, CreateView): @@ -1913,11 +1942,17 @@ class CarRegistrationCreateView(LoginRequiredMixin, CreateView): def get_success_url(self): messages.success(self.request, _("Registration added successfully")) - return reverse_lazy("car_detail", kwargs={"dealer_slug":self.request.dealer.slug,"slug": self.kwargs["slug"]}) + return reverse_lazy( + "car_detail", + kwargs={ + "dealer_slug": self.request.dealer.slug, + "slug": self.kwargs["slug"], + }, + ) @login_required() -def reserve_car_view(request, dealer_slug,slug): +def reserve_car_view(request, dealer_slug, slug): """ Handles car reservation requests. This view requires the user to be logged in and processes only POST requests. When invoked, it checks if the specified car @@ -1945,7 +1980,7 @@ def reserve_car_view(request, dealer_slug,slug): @login_required -def manage_reservation(request,dealer_slug, reservation_id): +def manage_reservation(request, dealer_slug, reservation_id): """ Handles the management of a car reservation, providing options to renew or cancel an existing reservation associated with the logged-in user. @@ -1974,7 +2009,9 @@ def manage_reservation(request,dealer_slug, reservation_id): reservation.reserved_until = timezone.now() + timezone.timedelta(hours=24) reservation.save() messages.success(request, _("Reservation renewed successfully")) - return redirect("car_detail",dealer_slug=request.dealer.slug, slug=reservation.car.slug) + return redirect( + "car_detail", dealer_slug=request.dealer.slug, slug=reservation.car.slug + ) elif action == "cancel": car = reservation.car @@ -1982,7 +2019,9 @@ def manage_reservation(request,dealer_slug, reservation_id): car.status = models.CarStatusChoices.AVAILABLE car.save() messages.success(request, _("Reservation canceled successfully")) - return redirect("car_detail",dealer_slug=request.dealer.slug, slug=reservation.car.slug) + return redirect( + "car_detail", dealer_slug=request.dealer.slug, slug=reservation.car.slug + ) else: return JsonResponse( @@ -3454,10 +3493,16 @@ class BankAccountUpdateView( kwargs["entity_slug"] = entity.slug # Get entity_slug from URL kwargs["user_model"] = entity.admin # Get user_model from the request return kwargs + def get_success_url(self): - return reverse_lazy("bank_account_detail", kwargs={"dealer_slug": self.kwargs["dealer_slug"], "pk": self.object.pk}) + return reverse_lazy( + "bank_account_detail", + kwargs={"dealer_slug": self.kwargs["dealer_slug"], "pk": self.object.pk}, + ) + + @login_required -def bank_account_delete(request,dealer_slug, pk): +def bank_account_delete(request, dealer_slug, pk): """ Delete a bank account entry from the database. @@ -3590,8 +3635,11 @@ class AccountCreateView( entity = get_user_type(self.request).entity form.initial["coa_model"] = entity.get_default_coa() return form + def get_success_url(self): - return reverse("account_list", kwargs={"dealer_slug":self.kwargs["dealer_slug"]}) + return reverse( + "account_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]} + ) class AccountDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): @@ -3691,12 +3739,16 @@ class AccountUpdateView( form.fields["_ref_node_id"].widget = HiddenInput() form.fields["_position"].widget = HiddenInput() return form + def get_success_url(self): - return reverse_lazy("account_list", kwargs={"dealer_slug":self.kwargs["dealer_slug"]}) + return reverse_lazy( + "account_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]} + ) + @login_required @permission_required("inventory.view_carfinance") -def account_delete(request, dealer_slug,pk): +def account_delete(request, dealer_slug, pk): """ Handles the deletion of an account object identified by its primary key (pk). Ensures that the user has the necessary permissions to perform the deletion. Successfully @@ -3715,13 +3767,13 @@ def account_delete(request, dealer_slug,pk): account.delete() messages.success(request, _("Account deleted successfully")) - return redirect("account_list",dealer_slug=dealer_slug) + return redirect("account_list", dealer_slug=dealer_slug) # Sales list @login_required @permission_required("inventory.view_lead", raise_exception=True) -def sales_list_view(request): +def sales_list_view(request, dealer_slug): """ Handles the retrieval and presentation of a paginated list of item transactions for sales, specific to the logged-in user's entity. Requires the user to have appropriate @@ -3735,7 +3787,7 @@ def sales_list_view(request): item transactions specific to the user's entity. :rtype: HttpResponse """ - dealer = get_user_type(request) + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) entity = dealer.entity sale_orders = models.SaleOrder.objects.filter( @@ -3812,7 +3864,7 @@ class EstimateListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): # @csrf_exempt @login_required @permission_required("django_ledger.add_estimatemodel", raise_exception=True) -def create_estimate(request, dealer_slug,slug=None): +def create_estimate(request, dealer_slug, slug=None): """ Creates a new estimate based on the provided data and saves it. This function processes a POST request and expects a JSON payload containing details of the estimate such as @@ -4005,7 +4057,9 @@ def create_estimate(request, dealer_slug,slug=None): opportunity.estimate = estimate opportunity.save() - url = reverse("estimate_detail", kwargs={"dealer_slug": dealer.slug,"pk": estimate.pk}) + url = reverse( + "estimate_detail", kwargs={"dealer_slug": dealer.slug, "pk": estimate.pk} + ) return JsonResponse( { "status": "success", @@ -4111,7 +4165,7 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView @login_required @permission_required("inventory.add_saleorder", raise_exception=True) -def create_sale_order(request,dealer_slug, pk): +def create_sale_order(request, dealer_slug, pk): """ Creates a sale order for a given estimate and updates associated item and car data. @@ -4204,7 +4258,7 @@ class SaleOrderDetail(DetailView): @login_required -def preview_sale_order(request, dealer_slug,pk): +def preview_sale_order(request, dealer_slug, pk): """ Handles rendering of the sale order preview page for a specific estimate. @@ -4304,7 +4358,7 @@ class EstimatePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailVie @login_required @permission_required("django_ledger.change_estimatemodel", raise_exception=True) -def estimate_mark_as(request,dealer_slug, pk): +def estimate_mark_as(request, dealer_slug, pk): """ Marks an estimate with a specified status based on the requested action and permissions. The marking possibilities include review, approval, rejection, @@ -4327,29 +4381,39 @@ def estimate_mark_as(request,dealer_slug, pk): if mark == "review": if not estimate.can_review(): messages.error(request, _("Quotation is not ready for review")) - return redirect("estimate_detail",dealer_slug=dealer.slug, pk=estimate.pk) + return redirect( + "estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk + ) estimate.mark_as_review() elif mark == "approved": if not estimate.can_approve(): messages.error(request, _("Quotation is not ready for approval")) - return redirect("estimate_detail",dealer_slug=dealer.slug, pk=estimate.pk) + return redirect( + "estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk + ) estimate.mark_as_approved() messages.success(request, _("Quotation approved successfully")) elif mark == "rejected": if not estimate.can_cancel(): messages.error(request, _("Quotation is not ready for rejection")) - return redirect("estimate_detail",dealer_slug=dealer.slug, pk=estimate.pk) + return redirect( + "estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk + ) estimate.mark_as_canceled() messages.success(request, _("Quotation canceled successfully")) elif mark == "completed": if not estimate.can_complete(): messages.error(request, _("Quotation is not ready for completion")) - return redirect("estimate_detail",dealer_slug=dealer.slug, pk=estimate.pk) + return redirect( + "estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk + ) elif mark == "canceled": if not estimate.can_cancel(): messages.error(request, _("Quotation is not ready for cancellation")) - return redirect("estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk) + return redirect( + "estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk + ) estimate.mark_as_canceled() try: car = models.Car.objects.get( @@ -4526,7 +4590,10 @@ class ApprovedInvoiceModelUpdateFormView( return kwargs def get_success_url(self): - return reverse_lazy("invoice_detail", kwargs={"dealer_slug":self.kwargs["dealer_slug"],"pk": self.object.pk}) + return reverse_lazy( + "invoice_detail", + kwargs={"dealer_slug": self.kwargs["dealer_slug"], "pk": self.object.pk}, + ) class PaidInvoiceModelUpdateFormView( @@ -4571,7 +4638,10 @@ class PaidInvoiceModelUpdateFormView( return kwargs def get_success_url(self): - return reverse_lazy("invoice_detail", kwargs={"dealer_slug":self.kwargs["dealer_slug"],"pk": self.object.pk}) + return reverse_lazy( + "invoice_detail", + kwargs={"dealer_slug": self.kwargs["dealer_slug"], "pk": self.object.pk}, + ) def form_valid(self, form): invoice = form.save() @@ -4587,7 +4657,7 @@ class PaidInvoiceModelUpdateFormView( @login_required @permission_required("django_ledger.change_invoicemodel", raise_exception=True) -def invoice_mark_as(request,dealer_slug, pk): +def invoice_mark_as(request, dealer_slug, pk): """ Marks an invoice as approved if it meets the required conditions. @@ -4610,17 +4680,17 @@ def invoice_mark_as(request,dealer_slug, pk): if mark and mark == "accept": if not invoice.can_approve(): messages.error(request, "invoice is not ready for approval") - return redirect("invoice_detail",dealer_slug=dealer_slug, pk=invoice.pk) + return redirect("invoice_detail", dealer_slug=dealer_slug, pk=invoice.pk) invoice.mark_as_approved( entity_slug=dealer.entity.slug, user_model=dealer.entity.admin ) invoice.save() - return redirect("invoice_detail",dealer_slug=dealer_slug, pk=invoice.pk) + return redirect("invoice_detail", dealer_slug=dealer_slug, pk=invoice.pk) @login_required @permission_required("django_ledger.add_invoicemodel", raise_exception=True) -def invoice_create(request,dealer_slug, pk): +def invoice_create(request, dealer_slug, pk): """ Handles the creation of a new invoice associated with a given estimate. It validates the submitted data through a form, processes the invoice, updates related models, and @@ -4636,7 +4706,7 @@ def invoice_create(request,dealer_slug, pk): creation or renders the invoice creation form template otherwise. :rtype: HttpResponse """ - dealer = get_object_or_404(models.Dealer,slug=dealer_slug) + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) estimate = get_object_or_404(EstimateModel, pk=pk) entity = dealer.entity @@ -4678,7 +4748,7 @@ def invoice_create(request,dealer_slug, pk): estimate.save() invoice.save() messages.success(request, "Invoice created successfully") - return redirect("invoice_detail", dealer_slug=dealer.slug,pk=invoice.pk) + return redirect("invoice_detail", dealer_slug=dealer.slug, pk=invoice.pk) else: print(form.errors) form = forms.InvoiceModelCreateForm( @@ -4726,7 +4796,7 @@ class InvoicePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailView permission_required = ["django_ledger.view_invoicemodel"] def get_context_data(self, **kwargs): - dealer = get_object_or_404(models.Dealer,slug=self.kwargs["dealer_slug"]) + dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) invoice = kwargs.get("object") if invoice.get_itemtxs_data(): calculator = CarFinanceCalculator(invoice) @@ -4741,7 +4811,7 @@ class InvoicePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailView @login_required @permission_required("django_ledger.add_journalentrymodel", raise_exception=True) -def PaymentCreateView(request,dealer_slug, pk): +def PaymentCreateView(request, dealer_slug, pk): """ Handles the creation of a payment entry associated with an invoice or bill. Validates the payment data against the model's current state and reflects the changes in @@ -4764,7 +4834,7 @@ def PaymentCreateView(request,dealer_slug, pk): redirect to the detail view of the processed invoice or bill, re-render the payment form with error messages or indicate success in payment creation. """ - dealer = get_object_or_404(models.Dealer,slug=dealer_slug) + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) invoice = InvoiceModel.objects.filter(pk=pk).first() bill = BillModel.objects.filter(pk=pk).first() model = invoice if invoice else bill @@ -4784,7 +4854,7 @@ def PaymentCreateView(request,dealer_slug, pk): model.mark_as_approved(user_model=entity.admin) if model.amount_paid == model.amount_due: messages.error(request, _("fully paid")) - return redirect(redirect_url, dealer_slug=dealer.slug,pk=model.pk) + return redirect(redirect_url, dealer_slug=dealer.slug, pk=model.pk) if model.amount_paid + amount > model.amount_due: messages.error(request, _("Amount exceeds due amount")) return redirect(redirect_url, dealer_slug=dealer.slug, pk=model.pk) @@ -4816,7 +4886,7 @@ def PaymentCreateView(request,dealer_slug, pk): @login_required @permission_required("django_ledger.view_journalentrymodel", raise_exception=True) -def PaymentListView(request,dealer_slug): +def PaymentListView(request, dealer_slug): """ Handles the view for listing payment information associated with the journals of a specific entity. This view is protected to ensure only authenticated and authorized users can @@ -4832,7 +4902,7 @@ def PaymentListView(request,dealer_slug): :return: The rendered HTML response displaying the list of payments. :rtype: HttpResponse """ - dealer = get_object_or_404(models.Dealer,slug=dealer_slug) + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) entity = dealer.entity journals = JournalEntryModel.objects.filter(ledger__entity=entity).all() @@ -4846,7 +4916,7 @@ def PaymentListView(request,dealer_slug): @login_required @permission_required("django_ledger.view_journalentrymodel", raise_exception=True) -def PaymentDetailView(request,dealer_slug, pk): +def PaymentDetailView(request, dealer_slug, pk): """ This function handles the detail view for a payment by fetching a journal entry and its associated transactions. It ensures that the request is authenticated @@ -4860,7 +4930,7 @@ def PaymentDetailView(request,dealer_slug, pk): entry and its associated transactions. :rtype: HttpResponse """ - dealer = get_object_or_404(models.Dealer,slug=dealer_slug) + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) journal = JournalEntryModel.objects.filter(pk=pk).first() transactions = ( TransactionModel.objects.filter(journal_entry=journal) @@ -4876,7 +4946,7 @@ def PaymentDetailView(request,dealer_slug, pk): @login_required @permission_required("django_ledger.change_journalentrymodel", raise_exception=True) -def payment_mark_as_paid(request, dealer_slug,pk): +def payment_mark_as_paid(request, dealer_slug, pk): """ Marks an invoice as paid if it meets the conditions of being fully paid and eligible for payment. Also ensures that related ledger journal entries are locked and posted @@ -4895,7 +4965,7 @@ def payment_mark_as_paid(request, dealer_slug,pk): :raises: In case of an exception during the process, an error message is displayed to the user through Django's messaging framework. """ - dealer = get_object_or_404(models.Dealer,slug=dealer_slug) + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) invoice = get_object_or_404(InvoiceModel, pk=pk) if request.method == "POST": try: @@ -4920,7 +4990,7 @@ def payment_mark_as_paid(request, dealer_slug,pk): ) except Exception as e: messages.error(request, f"Error: {str(e)}") - return redirect("invoice_detail",dealer_slug=dealer_slug, pk=invoice.pk) + return redirect("invoice_detail", dealer_slug=dealer_slug, pk=invoice.pk) # activity log @@ -6651,8 +6721,8 @@ class BillModelCreateView(CreateView): for_purchase_order = False for_estimate = False - def get(self, request, dealer_slug,**kwargs): - dealer = get_object_or_404(models.Dealer,slug=dealer_slug) + def get(self, request, dealer_slug, **kwargs): + dealer = get_object_or_404(models.Dealer, slug=dealer_slug) if not request.user.is_authenticated: return HttpResponseForbidden() @@ -6665,7 +6735,7 @@ class BillModelCreateView(CreateView): ) if not estimate_model.can_bind(): return HttpResponseNotFound("404 Not Found") - return super(BillModelCreateView, self).get(request,dealer_slug, **kwargs) + return super(BillModelCreateView, self).get(request, dealer_slug, **kwargs) def get_context_data(self, **kwargs): context = super(BillModelCreateView, self).get_context_data(**kwargs) @@ -6797,17 +6867,29 @@ class BillModelCreateView(CreateView): po_pk = self.kwargs["po_pk"] return reverse( "purchase_order_update", - kwargs={"dealer_slug": self.kwargs["dealer_slug"],"entity_slug": entity_slug, "po_pk": po_pk}, + kwargs={ + "dealer_slug": self.kwargs["dealer_slug"], + "entity_slug": entity_slug, + "po_pk": po_pk, + }, ) elif self.for_estimate: return reverse( "customer-estimate-detail", - kwargs={"dealer_slug": self.kwargs["dealer_slug"],"entity_slug": entity_slug, "ce_pk": self.kwargs["ce_pk"]}, + kwargs={ + "dealer_slug": self.kwargs["dealer_slug"], + "entity_slug": entity_slug, + "ce_pk": self.kwargs["ce_pk"], + }, ) bill_model: BillModel = self.object return reverse( "bill-detail", - kwargs={"dealer_slug": self.kwargs["dealer_slug"],"entity_slug": entity_slug, "bill_pk": bill_model.uuid}, + kwargs={ + "dealer_slug": self.kwargs["dealer_slug"], + "entity_slug": entity_slug, + "bill_pk": bill_model.uuid, + }, ) @@ -6823,7 +6905,7 @@ class BillModelDetailViewView(BillModelDetailView): class BillModelUpdateViewView(BillModelUpdateView): template_name = "bill/bill_update.html" - def post(self, request, dealer_slug,entity_slug,bill_pk, *args, **kwargs): + def post(self, request, dealer_slug, entity_slug, bill_pk, *args, **kwargs): if self.action_update_items: if not request.user.is_authenticated: return HttpResponseForbidden() @@ -6888,7 +6970,9 @@ class BillModelUpdateViewView(BillModelUpdateView): ) context = self.get_context_data(itemtxs_formset=itemtxs_formset) return self.render_to_response(context=context) - return super(BillModelUpdateViewView, self).post(request,dealer_slug,entity_slug,bill_pk, **kwargs) + return super(BillModelUpdateViewView, self).post( + request, dealer_slug, entity_slug, bill_pk, **kwargs + ) def get_success_url(self): return reverse( @@ -7091,7 +7175,7 @@ class OrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): # email @login_required @permission_required("django_ledger.view_estimatemodel", raise_exception=True) -def send_email_view(request,dealer_slug, pk): +def send_email_view(request, dealer_slug, pk): """ View function to send an email for an estimate. This function allows authenticated and authorized users to send an email containing the estimate details to the customer. @@ -7112,10 +7196,12 @@ def send_email_view(request,dealer_slug, pk): if not estimate.get_itemtxs_data()[0]: messages.error(request, _("Quotation has no items")) - return redirect("estimate_detail", dealer_slug=dealer_slug,pk=estimate.pk) + return redirect("estimate_detail", dealer_slug=dealer_slug, pk=estimate.pk) link = request.build_absolute_uri( - reverse_lazy("estimate_preview", kwargs={"dealer_slug":dealer_slug,"pk": estimate.pk}) + reverse_lazy( + "estimate_preview", kwargs={"dealer_slug": dealer_slug, "pk": estimate.pk} + ) ) msg = f""" @@ -7152,7 +7238,7 @@ def send_email_view(request,dealer_slug, pk): estimate.mark_as_review() messages.success(request, _("Email sent successfully")) - return redirect("estimate_detail", dealer_slug=dealer.slug,pk=estimate.pk) + return redirect("estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk) # errors @@ -8342,7 +8428,7 @@ class JournalEntryListView(LoginRequiredMixin, ListView): model = JournalEntryModel context_object_name = "journal_entries" template_name = "ledger/journal_entry/journal_entry_list.html" - ordering=['-timestamp'] + ordering = ["-timestamp"] def get_queryset(self): qs = super().get_queryset() @@ -8454,12 +8540,14 @@ def JournalEntryTransactionsView(request, pk): # .order_by("account__code") # .all() # ) - qs=TransactionModel.objects.filter(journal_entry=journal).all() - transactions=qs.annotate( - debit_credit_sort_order=Case(When(tx_type='debit',then=Value(0)), - When(tx_type='credit',then=Value(1)), - output_field=IntegerField()) - ).order_by('debit_credit_sort_order') + qs = TransactionModel.objects.filter(journal_entry=journal).all() + transactions = qs.annotate( + debit_credit_sort_order=Case( + When(tx_type="debit", then=Value(0)), + When(tx_type="credit", then=Value(1)), + output_field=IntegerField(), + ) + ).order_by("debit_credit_sort_order") return render( request, "ledger/journal_entry/journal_entry_transactions.html", @@ -9074,7 +9162,7 @@ def PurchaseOrderCreateView(request, dealer_slug): return render(request, "purchase_orders/po_form.html", {"form": form}) -def InventoryItemCreateView(request,dealer_slug): +def InventoryItemCreateView(request, dealer_slug): dealer = get_object_or_404(models.Dealer, slug=dealer_slug) for_po = request.GET.get("for_po") entity = dealer.entity @@ -9115,7 +9203,10 @@ def InventoryItemCreateView(request,dealer_slug): .first() ): messages.error(request, _("Inventory item already exists")) - return redirect(f"{reverse('inventory_item_create')}?for_po={for_po}", dealer_slug=dealer.slug) + return redirect( + f"{reverse('inventory_item_create')}?for_po={for_po}", + dealer_slug=dealer.slug, + ) uom = entity.get_uom_all().get(name="Unit") entity.create_item_inventory( name=inventory_name, @@ -9147,7 +9238,7 @@ def InventoryItemCreateView(request,dealer_slug): ) -def inventory_items_filter(request,dealer_slug): +def inventory_items_filter(request, dealer_slug): dealer = get_object_or_404(models.Dealer, slug=dealer_slug) make = request.GET.get("make") model = request.GET.get("model") @@ -9253,7 +9344,11 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase): return HttpResponseRedirect( redirect_to=reverse( "purchase_order_update", - kwargs={"dealer_slug": dealer_slug,"entity_slug": entity_slug, "po_pk": po_pk}, + kwargs={ + "dealer_slug": dealer_slug, + "entity_slug": entity_slug, + "po_pk": po_pk, + }, ) ) return super(PurchaseOrderUpdateView, self).get( @@ -9318,7 +9413,7 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase): context=self.get_context_data(itemtxs_formset=itemtxs_formset) ) return super(PurchaseOrderUpdateView, self).post( - request,dealer_slug, entity_slug, *args, **kwargs + request, dealer_slug, entity_slug, *args, **kwargs ) def get_form(self, form_class=None): @@ -9349,19 +9444,24 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase): class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase): - def get_redirect_url(self,dealer_slug, entity_slug, po_pk, *args, **kwargs): + def get_redirect_url(self, dealer_slug, entity_slug, po_pk, *args, **kwargs): return reverse( - "purchase_order_update", kwargs={"dealer_slug":dealer_slug,"entity_slug": entity_slug, "po_pk": po_pk} + "purchase_order_update", + kwargs={ + "dealer_slug": dealer_slug, + "entity_slug": entity_slug, + "po_pk": po_pk, + }, ) - def get(self, request,dealer_slug, entity_slug, po_pk, *args, **kwargs): + def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs): # kwargs["user_model"] = self.request.user dealer = get_object_or_404(models.Dealer, slug=dealer_slug) kwargs["user_model"] = dealer.entity.admin if not self.action_name: raise ImproperlyConfigured("View attribute action_name is required.") response = super(BasePurchaseOrderActionActionView, self).get( - request,dealer_slug,entity_slug,po_pk, *args, **kwargs + request, dealer_slug, entity_slug, po_pk, *args, **kwargs ) po_model: PurchaseOrderModel = self.get_object() @@ -9386,7 +9486,9 @@ class PurchaseOrderModelDeleteView(PurchaseOrderModelDeleteViewBase): message="PO deleted successfully.", level=messages.SUCCESS, ) - return reverse("purchase_order_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]}) + return reverse( + "purchase_order_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]} + ) class PurchaseOrderMarkAsDraftView(BasePurchaseOrderActionActionView): @@ -9415,9 +9517,14 @@ class PurchaseOrderMarkAsVoidView(BasePurchaseOrderActionActionView): ##############################bil class BaseBillActionView(BaseBillActionViewBase): - def get_redirect_url(self,dealer_slug, entity_slug, bill_pk, *args, **kwargs): + def get_redirect_url(self, dealer_slug, entity_slug, bill_pk, *args, **kwargs): return reverse( - "bill-update", kwargs={"dealer_slug": self.kwargs["dealer_slug"],"entity_slug": entity_slug, "bill_pk": bill_pk} + "bill-update", + kwargs={ + "dealer_slug": self.kwargs["dealer_slug"], + "entity_slug": entity_slug, + "bill_pk": bill_pk, + }, ) @@ -9465,14 +9572,14 @@ class BillModelActionForceMigrateView(BaseBillActionView): ############################################################### -def view_items_inventory(request,dealer_slug, entity_slug, po_pk): +def view_items_inventory(request, dealer_slug, entity_slug, po_pk): dealer = get_object_or_404(models.Dealer, slug=dealer_slug) po = PurchaseOrderModel.objects.get(pk=po_pk) items = po.get_itemtxs_data()[0] - items_per_page = 30 + items_per_page = 30 paginator = Paginator(items, items_per_page) - page_number = request.GET.get('page') + page_number = request.GET.get("page") try: page_obj = paginator.get_page(page_number) except PageNotAnInteger: @@ -9482,21 +9589,26 @@ def view_items_inventory(request,dealer_slug, entity_slug, po_pk): # If page is out of range (e.g. 9999), deliver last page of results. page_obj = paginator.get_page(paginator.num_pages) return render( - request, "purchase_orders/po_upload_cars.html", {"po": po, "items": items,"page_obj":page_obj} + request, + "purchase_orders/po_upload_cars.html", + {"po": po, "items": items, "page_obj": page_obj}, ) -def upload_cars(request,dealer_slug, pk=None): +def upload_cars(request, dealer_slug, pk=None): item = None dealer = get_object_or_404(models.Dealer, slug=dealer_slug) - response = redirect("upload_cars",dealer_slug=dealer_slug) + response = redirect("upload_cars", dealer_slug=dealer_slug) if pk: item = get_object_or_404(ItemTransactionModel, pk=pk) - response = redirect("upload_cars", dealer_slug=dealer_slug,pk=pk) + response = redirect("upload_cars", dealer_slug=dealer_slug, pk=pk) if item.item_model.additional_info.get("uploaded"): messages.add_message(request, messages.ERROR, "Item already uploaded.") return redirect( - "view_items_inventory",dealer_slug=dealer_slug, entity_slug=dealer.entity.slug, po_pk=item.po_model.pk + "view_items_inventory", + dealer_slug=dealer_slug, + entity_slug=dealer.entity.slug, + po_pk=item.po_model.pk, ) if request.method == "POST": @@ -9506,7 +9618,9 @@ def upload_cars(request,dealer_slug, pk=None): if item: item = ItemTransactionModel.objects.get(pk=pk) data = [x.strip() for x in item.item_model.name.split("||")] - make = models.CarMake.objects.filter(is_sa_import=True).get(name=data[0]) + make = models.CarMake.objects.filter(is_sa_import=True).get( + name=data[0] + ) model = make.carmodel_set.get(name=data[1]) trim = models.CarTrim.objects.filter( name=data[3], id_car_serie__id_car_model=model.id_car_model @@ -9541,7 +9655,7 @@ def upload_cars(request,dealer_slug, pk=None): if not csv_file.name.endswith(".csv"): messages.error(request, "Please upload a CSV file") - return redirect("upload_cars",dealer_slug=dealer_slug) + return redirect("upload_cars", dealer_slug=dealer_slug) try: # Read the file content file_content = csv_file.read().decode("utf-8") @@ -9644,5 +9758,3 @@ class InventoryListView(InventoryListViewBase): entity_slug=dealer.entity.slug, ) return super().get_queryset() - - diff --git a/templates/base.html b/templates/base.html index 76641d01..e8ead5bb 100644 --- a/templates/base.html +++ b/templates/base.html @@ -63,7 +63,7 @@ {% include 'header.html' %}
- + {% include "plans/expiration_messages.html" %} {% block period_navigation %} diff --git a/templates/bill/transactions/tags/txs_table.html b/templates/bill/transactions/tags/txs_table.html index 115bfbff..09f87b38 100644 --- a/templates/bill/transactions/tags/txs_table.html +++ b/templates/bill/transactions/tags/txs_table.html @@ -17,7 +17,7 @@ - + {% for transaction_model in transaction_model_qs %} diff --git a/templates/crm/leads/lead_list.html b/templates/crm/leads/lead_list.html index b0dd8c0d..cd45009c 100644 --- a/templates/crm/leads/lead_list.html +++ b/templates/crm/leads/lead_list.html @@ -231,27 +231,27 @@ {% endfor %} - - + + +
+ {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %} + {% else %} + + {% trans "No Lead Yet" %} + + {% endif %} + - {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} - {% else %} - - {% trans "No Lead Yet" %} - - {% endif %} - - {% endblock %} diff --git a/templates/crm/opportunities/opportunity_list.html b/templates/crm/opportunities/opportunity_list.html index bcdfb32a..13b82df5 100644 --- a/templates/crm/opportunities/opportunity_list.html +++ b/templates/crm/opportunities/opportunity_list.html @@ -90,14 +90,14 @@
{% include 'crm/opportunities/partials/opportunity_grid.html' %}
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %} {% endblock %} \ No newline at end of file diff --git a/templates/customers/customer_list.html b/templates/customers/customer_list.html index a913ca67..cbf6a168 100644 --- a/templates/customers/customer_list.html +++ b/templates/customers/customer_list.html @@ -109,15 +109,15 @@ {% endif %} - {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %} {% include 'modal/delete_modal.html' %} {% endblock %} \ No newline at end of file diff --git a/templates/groups/group_list.html b/templates/groups/group_list.html index 0ec7a11d..f50937a9 100644 --- a/templates/groups/group_list.html +++ b/templates/groups/group_list.html @@ -46,13 +46,13 @@ {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- + +
+ +
+ {% include 'partials/pagination.html'%} +
+
{% endif %}
diff --git a/templates/header.html b/templates/header.html index ab136a22..95fcb815 100644 --- a/templates/header.html +++ b/templates/header.html @@ -98,7 +98,7 @@ {% endif %} - + {% if perms.django_ledger.view_invoicemodel %} {% endif %} - {% endif %} + {% endif %} diff --git a/templates/inventory/car_detail.html b/templates/inventory/car_detail.html index 67294700..8aeb3428 100644 --- a/templates/inventory/car_detail.html +++ b/templates/inventory/car_detail.html @@ -163,14 +163,14 @@ {% trans "Custom Card" %} - + >{% trans 'Add' %} {% endif %} @@ -196,7 +196,7 @@ hx-get="{% url 'add_registration' request.dealer.slug car.slug %}" hx-target=".main-modal-body" hx-swap="innerHTML" - >{% trans 'Add' %} + >{% trans 'Add' %} diff --git a/templates/inventory/car_list_view.html b/templates/inventory/car_list_view.html index d12e6662..8b566764 100644 --- a/templates/inventory/car_list_view.html +++ b/templates/inventory/car_list_view.html @@ -25,83 +25,83 @@ {% endblock customCSS %} {% block content %} -
+
-
-

{{ _("Inventory") }}

-
+
+

{{ _("Inventory") }}

+
- -
-
- {% csrf_token %} -
- - -
+ +
+ + {% csrf_token %} +
+ + +
+ +
+
+
+
+ Loading... +
+ -
-
-
- Loading... -
-
+
@@ -165,147 +165,147 @@ {{ _("Search") }}
-
-
-
-
-
- {{ _("Select All") }} -
- {% for car in cars %} -
-
-
-
-
- -
+
+
+
+
+
+ {{ _("Select All") }} +
+ {% for car in cars %} +
+
+
+
+
+
+
-
-
- {{ car.vin }} -
+
+
+ {{ car.vin }}
+
-
-
+
+
-
-
{{ car.year }}
-

- - {{ car.id_car_make.get_local_name }} - - {{ car.id_car_model.get_local_name }} -

- - {{ car.id_car_trim }} - -
+
+
{{ car.year }}
+

+ + {{ car.id_car_make.get_local_name }} + + {{ car.id_car_model.get_local_name }} +

+ + {{ car.id_car_trim }} + +
-
-

- {{ car.colors.exterior.get_local_name }} -

- - {{ car.receiving_date|naturalday|capfirst }} - -
+
+

+ {{ car.colors.exterior.get_local_name }} +

+ + {{ car.receiving_date|naturalday|capfirst }} + +
-
- {% if car.status == "available" %} - {{ _("Available") }} - {% elif car.status == "reserved" %} - {{ _("Reserved") }} - {% elif car.status == "sold" %} - {{ _("Sold") }} - {% elif car.status == "transfer" %} - {{ _("Transfer") }} - {% endif %} -
+
+ {% if car.status == "available" %} + {{ _("Available") }} + {% elif car.status == "reserved" %} + {{ _("Reserved") }} + {% elif car.status == "sold" %} + {{ _("Sold") }} + {% elif car.status == "transfer" %} + {{ _("Transfer") }} + {% endif %} +
-
-
- {{ _("Inventory Ready") }} - {% if car.ready %} - - Ready - - {{ _("Yes") }} - {% else %} - - Not Ready - - {{ _("No") }} - {% endif %} -
+
+
+ {{ _("Inventory Ready") }} + {% if car.ready %} + + Ready + + {{ _("Yes") }} + {% else %} + + Not Ready + + {{ _("No") }} + {% endif %}
+
- - {% empty %} -
-
- -

{{ _("No vehicles found") }}

-

{{ _("Try adjusting your search criteria or filters") }}

-
+
+ {% empty %} +
+
+ +

{{ _("No vehicles found") }}

+

{{ _("Try adjusting your search criteria or filters") }}

- {% endfor %} -
-
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} +
+ {% endfor %}
+ {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %} +
-
+
+
{% endblock %} {% block customJS %} diff --git a/templates/inventory/inventory_stats.html b/templates/inventory/inventory_stats.html index 16c50ce4..c59f22f8 100644 --- a/templates/inventory/inventory_stats.html +++ b/templates/inventory/inventory_stats.html @@ -86,15 +86,15 @@ {% endfor %}
{% if is_paginated %} - -
- -
- {% include 'partials/pagination.html'%} -
- + +
+ +
+ {% include 'partials/pagination.html'%} +
+
- {% endif %} + {% endif %}
{% endblock %} diff --git a/templates/inventory/tags/inventory_table.html b/templates/inventory/tags/inventory_table.html index 8fc14eb3..9ff9e909 100644 --- a/templates/inventory/tags/inventory_table.html +++ b/templates/inventory/tags/inventory_table.html @@ -13,12 +13,12 @@ - + {% for i in inventory_list %} - + - - {{ i.item_model__name }} + + {{ i.item_model__name }} {{ i.item_model__name }} {{ i.item_model__uom__name }} {{ i.total_quantity | floatformat:3 }} diff --git a/templates/items/expenses/expenses_list.html b/templates/items/expenses/expenses_list.html index 4f1c69d3..630aad73 100644 --- a/templates/items/expenses/expenses_list.html +++ b/templates/items/expenses/expenses_list.html @@ -61,16 +61,16 @@
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+
- {% endif %} + {% endif %} {% endif %}
{% endblock %} \ No newline at end of file diff --git a/templates/items/service/service_list.html b/templates/items/service/service_list.html index 031c5249..e45368af 100644 --- a/templates/items/service/service_list.html +++ b/templates/items/service/service_list.html @@ -62,16 +62,16 @@
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+
- {% endif %} + {% endif %} {% endif %}
{% endblock %} \ No newline at end of file diff --git a/templates/ledger/bank_accounts/bank_account_list.html b/templates/ledger/bank_accounts/bank_account_list.html index 331ed4f3..9c8187e1 100644 --- a/templates/ledger/bank_accounts/bank_account_list.html +++ b/templates/ledger/bank_accounts/bank_account_list.html @@ -52,14 +52,14 @@
- {% if page_obj.paginator.num_pages > 1 %} -
- -
- {% include 'partials/pagination.html'%} -
- -
+ {% if page_obj.paginator.num_pages > 1 %} +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
{% endif %} {% endif %} diff --git a/templates/ledger/bills/bill_list.html b/templates/ledger/bills/bill_list.html index 53dfaf28..49b27b57 100644 --- a/templates/ledger/bills/bill_list.html +++ b/templates/ledger/bills/bill_list.html @@ -96,16 +96,16 @@
- {% if page_obj.paginator.num_pages > 1 %} + {% if page_obj.paginator.num_pages > 1 %} -
+
-
- {% include 'partials/pagination.html'%} -
+
+ {% include 'partials/pagination.html'%} +
-
- {% endif %} +
+ {% endif %}
{% endblock %} diff --git a/templates/ledger/journal_entry/journal_entry_list.html b/templates/ledger/journal_entry/journal_entry_list.html index 4dfb790c..85bc6f04 100644 --- a/templates/ledger/journal_entry/journal_entry_list.html +++ b/templates/ledger/journal_entry/journal_entry_list.html @@ -113,16 +113,16 @@
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %}
diff --git a/templates/ledger/journal_entry/journal_entry_transactions.html b/templates/ledger/journal_entry/journal_entry_transactions.html index fcf5a989..1e1fae34 100644 --- a/templates/ledger/journal_entry/journal_entry_transactions.html +++ b/templates/ledger/journal_entry/journal_entry_transactions.html @@ -42,14 +42,14 @@
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+
{% endif %}
diff --git a/templates/ledger/ledger/ledger_list.html b/templates/ledger/ledger/ledger_list.html index 82ce253b..e08ed35f 100644 --- a/templates/ledger/ledger/ledger_list.html +++ b/templates/ledger/ledger/ledger_list.html @@ -121,15 +121,15 @@
- {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%}
+ +
{% endif %}
{% endblock %} \ No newline at end of file diff --git a/templates/organizations/organization_list.html b/templates/organizations/organization_list.html index 497e6e3a..03589420 100644 --- a/templates/organizations/organization_list.html +++ b/templates/organizations/organization_list.html @@ -24,9 +24,9 @@
-
- {% include 'partials/search_box.html' %} -
+
+ {% include 'partials/search_box.html' %} +
@@ -123,16 +123,16 @@ - {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} + {% if page_obj.paginator.num_pages > 1 %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %} {% endblock %} diff --git a/templates/partials/pagination.html b/templates/partials/pagination.html index 66bec0ef..a3b89dbc 100644 --- a/templates/partials/pagination.html +++ b/templates/partials/pagination.html @@ -1,90 +1,90 @@ {% load i18n static %}
-
- {{ _("Showing") }} {{ page_obj.start_index }} {{ _("to") }} {{ page_obj.end_index }} - {{ _("of") }} {{ page_obj.paginator.count }} {{ _("results") }} -
-
\ No newline at end of file diff --git a/templates/plans/billing_info_create_or_update.html b/templates/plans/billing_info_create_or_update.html index e2d07dab..a0b01280 100644 --- a/templates/plans/billing_info_create_or_update.html +++ b/templates/plans/billing_info_create_or_update.html @@ -11,11 +11,11 @@

{% trans "Provide billing data"|upper %}

{% csrf_token %} {{ form|crispy }} - + - {% if object %} + {% if object %} {{ _("Delete") }} {% endif %} diff --git a/templates/purchase_orders/po_detail.html b/templates/purchase_orders/po_detail.html index f9194caa..79465d8b 100644 --- a/templates/purchase_orders/po_detail.html +++ b/templates/purchase_orders/po_detail.html @@ -50,29 +50,29 @@ - +
-
-
-

{{ po_model.po_title }}

+
+
+

{{ po_model.po_title }}

-
- {% po_item_table1 po_items %} -
+
+ {% po_item_table1 po_items %}
- - - {% trans 'PO List' %} -
+ + + {% trans 'PO List' %} +
+
{% include "purchase_orders/includes/mark_as.html" %} {% endblock %} diff --git a/templates/purchase_orders/po_list.html b/templates/purchase_orders/po_list.html index c51e2cbe..0240eabf 100644 --- a/templates/purchase_orders/po_list.html +++ b/templates/purchase_orders/po_list.html @@ -82,16 +82,16 @@ - {% if page_obj.paginator.num_pages > 1 %} + {% if page_obj.paginator.num_pages > 1 %} -
- -
- {% include 'partials/pagination.html'%} -
+
+
+ {% include 'partials/pagination.html'%}
- {% endif %} + +
+ {% endif %}
{% include 'modal/delete_modal.html' %} {% endblock %} \ No newline at end of file diff --git a/templates/purchase_orders/po_upload_cars.html b/templates/purchase_orders/po_upload_cars.html index b9a34597..4fddd7cc 100644 --- a/templates/purchase_orders/po_upload_cars.html +++ b/templates/purchase_orders/po_upload_cars.html @@ -57,14 +57,14 @@ {% if page_obj.paginator.num_pages > 1 %} - -
- -
- {% include 'partials/pagination.html'%} -
- -
- {% endif %} + +
+ +
+ {% include 'partials/pagination.html'%} +
+ +
+ {% endif %}
{% endblock content %} \ No newline at end of file diff --git a/templates/sales/estimates/estimate_detail.html b/templates/sales/estimates/estimate_detail.html index f9c7bb78..cf2ca8b9 100644 --- a/templates/sales/estimates/estimate_detail.html +++ b/templates/sales/estimates/estimate_detail.html @@ -105,40 +105,40 @@
-
-
-
{% trans 'Quotation Number' %}:
-

{{estimate.estimate_number}}

-
-
-
{% trans 'Quotation Date' %}:
-

{{estimate.created}}

-
-
-
{% trans 'Customer' %}:
-

{{estimate.customer.customer_name}}

-
-
-
{% trans 'Email' %}:
-

{{estimate.customer.email}}

-
-
-
{% trans "Quotation Status" %}:
-
- {% if estimate.status == 'draft' %} - {% trans "Draft" %} - {% elif estimate.status == 'in_review' %} - {% trans "In Review" %} - {% elif estimate.status == 'approved' %} - {% trans "Approved" %} - {% elif estimate.status == 'completed' %} - {% trans "Completed" %} - {% elif estimate.status == 'canceled' %} - {% trans "Canceled" %} - {% endif %} -
-
+
+
+
{% trans 'Quotation Number' %}:
+

{{estimate.estimate_number}}

+
+
{% trans 'Quotation Date' %}:
+

{{estimate.created}}

+
+
+
{% trans 'Customer' %}:
+

{{estimate.customer.customer_name}}

+
+
+
{% trans 'Email' %}:
+

{{estimate.customer.email}}

+
+
+
{% trans "Quotation Status" %}:
+
+ {% if estimate.status == 'draft' %} + {% trans "Draft" %} + {% elif estimate.status == 'in_review' %} + {% trans "In Review" %} + {% elif estimate.status == 'approved' %} + {% trans "Approved" %} + {% elif estimate.status == 'completed' %} + {% trans "Completed" %} + {% elif estimate.status == 'canceled' %} + {% trans "Canceled" %} + {% endif %} +
+
+
diff --git a/templates/sales/estimates/estimate_list.html b/templates/sales/estimates/estimate_list.html index c548f272..8255a8ea 100644 --- a/templates/sales/estimates/estimate_list.html +++ b/templates/sales/estimates/estimate_list.html @@ -60,11 +60,11 @@
{% if page_obj.paginator.num_pages > 1 %} -
-
- {% include 'partials/pagination.html'%} -
-
- {% endif %} +
+
+ {% include 'partials/pagination.html'%} +
+
+ {% endif %}
{% endblock %} \ No newline at end of file diff --git a/templates/sales/invoices/invoice_detail.html b/templates/sales/invoices/invoice_detail.html index 1f180cd0..a97dd8a9 100644 --- a/templates/sales/invoices/invoice_detail.html +++ b/templates/sales/invoices/invoice_detail.html @@ -172,41 +172,41 @@
-
-
-
{% trans "Invoice Number" %} :
-

{{invoice.invoice_number}}

-
-
-
{% trans "Invoice Date" %} :
-

{{invoice.created}}

-
-
-
{% trans "Customer Name" %} :
-

{{invoice.customer.customer_name}}

-
-
-
{% trans "Customer Email" %} :
-

{{invoice.customer.email}}

-
-
-
{% trans "Invoice Status" %} :
-
- {% if invoice.invoice_status == 'draft' %} - {% trans "Draft" %} - {% elif invoice.invoice_status == 'in_review' %} - {% trans "In Review" %} - {% elif invoice.invoice_status == 'approved' %} - {% trans "Approved" %} - {% elif invoice.invoice_status == 'declined' %} - {% trans "Declined" %} - {% elif invoice.invoice_status == 'paid' %} - {% trans "Paid" %} - {% endif %} -
- -
+
+
+
{% trans "Invoice Number" %} :
+

{{invoice.invoice_number}}

+
+
+
{% trans "Invoice Date" %} :
+

{{invoice.created}}

+
+
+
{% trans "Customer Name" %} :
+

{{invoice.customer.customer_name}}

+
+
+
{% trans "Customer Email" %} :
+

{{invoice.customer.email}}

+
+
+
{% trans "Invoice Status" %} :
+
+ {% if invoice.invoice_status == 'draft' %} + {% trans "Draft" %} + {% elif invoice.invoice_status == 'in_review' %} + {% trans "In Review" %} + {% elif invoice.invoice_status == 'approved' %} + {% trans "Approved" %} + {% elif invoice.invoice_status == 'declined' %} + {% trans "Declined" %} + {% elif invoice.invoice_status == 'paid' %} + {% trans "Paid" %} + {% endif %}
+ +
+
diff --git a/templates/sales/invoices/invoice_list.html b/templates/sales/invoices/invoice_list.html index c1213490..73e937a9 100644 --- a/templates/sales/invoices/invoice_list.html +++ b/templates/sales/invoices/invoice_list.html @@ -70,12 +70,12 @@
- {% if page_obj.paginator.num_pages > 1 %} -
-
- {% include 'partials/pagination.html'%} -
-
+ {% if page_obj.paginator.num_pages > 1 %} +
+
+ {% include 'partials/pagination.html'%} +
+
{% endif %}
{% endblock %} \ No newline at end of file diff --git a/templates/sales/journals/journal_list.html b/templates/sales/journals/journal_list.html index 30b211e1..c8e3bae1 100644 --- a/templates/sales/journals/journal_list.html +++ b/templates/sales/journals/journal_list.html @@ -44,11 +44,11 @@
{% if page_obj.paginator.num_pages > 1%} -
-
- {% include 'partials/pagination.html'%} -
-
+
+
+ {% include 'partials/pagination.html'%} +
+
{% endif %} {% endblock %} \ No newline at end of file diff --git a/templates/sales/orders/order_list.html b/templates/sales/orders/order_list.html index 8014aad8..e9c98181 100644 --- a/templates/sales/orders/order_list.html +++ b/templates/sales/orders/order_list.html @@ -53,11 +53,11 @@ {% if page_obj.paginator.num_pages > 1%} -
-
- {% include 'partials/pagination.html'%} -
-
+
+
+ {% include 'partials/pagination.html'%} +
+
{% endif %} diff --git a/templates/sales/payments/payment_list.html b/templates/sales/payments/payment_list.html index d2e1ece3..894411a4 100644 --- a/templates/sales/payments/payment_list.html +++ b/templates/sales/payments/payment_list.html @@ -54,11 +54,11 @@ {% if page_obj.paginator.num_pages > 1 %} -
-
- {% include 'partials/pagination.html'%} -
-
+
+
+ {% include 'partials/pagination.html'%} +
+
{% endif %} {% endblock %} \ No newline at end of file diff --git a/templates/sales/saleorder_detail.html b/templates/sales/saleorder_detail.html index bb2d50b1..bfd46022 100644 --- a/templates/sales/saleorder_detail.html +++ b/templates/sales/saleorder_detail.html @@ -247,7 +247,7 @@