implement the dealer slug for inventory and sales
This commit is contained in:
parent
55d6e56233
commit
3ce318317e
@ -1,5 +1,7 @@
|
||||
from django.conf import settings
|
||||
|
||||
from inventory.utils import get_user_type
|
||||
|
||||
|
||||
def currency_context(request):
|
||||
"""
|
||||
@ -40,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}
|
||||
return {"breadcrumbs": breadcrumbs}
|
||||
@ -1,6 +1,6 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from inventory.services import get_model, decodevin
|
||||
from inventory.services import get_make, get_model, decodevin
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
import requests
|
||||
@ -24,35 +24,36 @@ class Command(BaseCommand):
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(f"Generated VIN: {vin}"))
|
||||
self.stdout.write(self.style.SUCCESS(f"Description: {description}"))
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
"####################################################################################################"
|
||||
)
|
||||
)
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
"####################################################################################################"
|
||||
)
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(f"Decoded VIN: {result}"))
|
||||
make, model, year_model = result.values()
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"VIN: {vin} - Make {make} - Model {model} - Model Year {year_model}"
|
||||
)
|
||||
)
|
||||
m = get_model(model)
|
||||
self.stdout.write(self.style.SUCCESS(f"Make: {m.id_car_make} - Model: {m}"))
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
"####################################################################################################"
|
||||
)
|
||||
)
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
"####################################################################################################"
|
||||
)
|
||||
)
|
||||
# self.stdout.write(
|
||||
# self.style.SUCCESS(
|
||||
# "####################################################################################################"
|
||||
# )
|
||||
# )
|
||||
# self.stdout.write(
|
||||
# self.style.SUCCESS(
|
||||
# "####################################################################################################"
|
||||
# )
|
||||
# )
|
||||
# self.stdout.write(self.style.SUCCESS(f"Decoded VIN: {result}"))
|
||||
# make, model, year_model = result.values()
|
||||
# self.stdout.write(
|
||||
# self.style.SUCCESS(
|
||||
# f"VIN: {vin} - Make {make} - Model {model} - Model Year {year_model}"
|
||||
# )
|
||||
# )
|
||||
# make = get_make(make)
|
||||
# m = get_model(model,make)
|
||||
# self.stdout.write(self.style.SUCCESS(f"Make: {m.id_car_make} - Model: {m}"))
|
||||
# self.stdout.write(
|
||||
# self.style.SUCCESS(
|
||||
# "####################################################################################################"
|
||||
# )
|
||||
# )
|
||||
# self.stdout.write(
|
||||
# self.style.SUCCESS(
|
||||
# "####################################################################################################"
|
||||
# )
|
||||
# )
|
||||
|
||||
def generate_vin(self):
|
||||
# url = "https://www.vindecoder.org/vin-decoder"
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import logging
|
||||
|
||||
from django.http import Http404, HttpResponseForbidden
|
||||
from django.shortcuts import redirect
|
||||
from inventory import models
|
||||
from django.utils import timezone
|
||||
|
||||
@ -59,8 +62,11 @@ class InjectParamsMiddleware:
|
||||
|
||||
def __call__(self, request):
|
||||
try:
|
||||
# request.entity = request.user.dealer.entity
|
||||
request.dealer = get_user_type(request)
|
||||
if request.user.is_authenticated:
|
||||
request.dealer = get_user_type(request)
|
||||
request.entity = request.dealer.entity
|
||||
else:
|
||||
request.dealer = None
|
||||
except Exception:
|
||||
pass
|
||||
response = self.get_response(request)
|
||||
@ -107,3 +113,21 @@ class InjectDealerMiddleware:
|
||||
# if request.user.is_authenticated and not request.session.get('otp_verified', False):
|
||||
# return redirect(reverse('verify_otp'))
|
||||
# return self.get_response(request)
|
||||
class DealerSlugMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
response = self.get_response(request)
|
||||
return response
|
||||
|
||||
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:
|
||||
raise Http404("Dealer slug mismatch")
|
||||
return None
|
||||
|
||||
19
inventory/migrations/0011_dealer_business_name.py
Normal file
19
inventory/migrations/0011_dealer_business_name.py
Normal file
@ -0,0 +1,19 @@
|
||||
# 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,
|
||||
),
|
||||
]
|
||||
17
inventory/migrations/0012_remove_dealer_business_name.py
Normal file
17
inventory/migrations/0012_remove_dealer_business_name.py
Normal file
@ -0,0 +1,17 @@
|
||||
# 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',
|
||||
),
|
||||
]
|
||||
@ -1,5 +1,9 @@
|
||||
from django.http import Http404
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import get_language
|
||||
|
||||
from inventory.utils import get_user_type
|
||||
|
||||
|
||||
class AddClassMixin:
|
||||
"""
|
||||
@ -60,3 +64,15 @@ class LocalizedNameMixin:
|
||||
# return super().form_valid(form)
|
||||
# else:
|
||||
# return form.errors
|
||||
|
||||
|
||||
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:
|
||||
raise Http404("Dealer slug mismatch")
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
@ -442,6 +442,7 @@ def filter_by_role(accounts, role_prefix):
|
||||
@register.inclusion_tag("purchase_orders/tags/po_item_table.html", takes_context=True)
|
||||
def po_item_table1(context, queryset):
|
||||
return {
|
||||
"dealer_slug": context["view"].kwargs["dealer_slug"],
|
||||
"entity_slug": context["entity_slug"],
|
||||
"po_model": context["po_model"],
|
||||
"po_item_list": queryset,
|
||||
@ -459,6 +460,7 @@ def po_item_formset_table(context, po_model, itemtxs_formset):
|
||||
item_role="inventory"
|
||||
)
|
||||
return {
|
||||
"dealer_slug": context["view"].kwargs["dealer_slug"],
|
||||
"entity_slug": context["view"].kwargs["entity_slug"],
|
||||
"po_model": po_model,
|
||||
"itemtxs_formset": itemtxs_formset,
|
||||
@ -468,6 +470,7 @@ def po_item_formset_table(context, po_model, itemtxs_formset):
|
||||
@register.inclusion_tag("bill/tags/bill_item_formset.html", takes_context=True)
|
||||
def bill_item_formset_table(context, item_formset):
|
||||
return {
|
||||
"dealer_slug": context["view"].kwargs["dealer_slug"],
|
||||
"entity_slug": context["view"].kwargs["entity_slug"],
|
||||
"bill_pk": context["view"].kwargs["bill_pk"],
|
||||
"total_amount__sum": context["total_amount__sum"],
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
from django.conf.urls import handler403, handler400, handler404, handler500
|
||||
from django.urls import path
|
||||
from django_tables2.export.export import TableExport
|
||||
|
||||
from inventory.utils import get_user_type
|
||||
from . import views
|
||||
|
||||
from django.urls import path
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import RedirectView
|
||||
from django_tables2.export.export import TableExport
|
||||
from django.conf.urls import handler403, handler400, handler404, handler500
|
||||
|
||||
urlpatterns = [
|
||||
# main URLs
|
||||
path("", views.HomeView.as_view(), name="home"),
|
||||
path("<slug:dealer_slug>/", views.HomeView.as_view(), name="home"),
|
||||
path("welcome/", views.WelcomeView.as_view(), name="welcome"),
|
||||
# Accounts URLs
|
||||
# path("login/", allauth_views.LoginView.as_view(template_name="account/login.html"), name="account_login"),
|
||||
@ -277,28 +279,28 @@ urlpatterns = [
|
||||
name="vendor_delete",
|
||||
),
|
||||
# Car URLs
|
||||
path("cars/upload_cars/", views.upload_cars, name="upload_cars"),
|
||||
path("cars/<uuid:pk>/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("<slug:dealer_slug>/cars/upload_cars/", views.upload_cars, name="upload_cars"),
|
||||
path("<slug:dealer_slug>/cars/<uuid:pk>/upload_cars/", views.upload_cars, name="upload_cars"),
|
||||
path("<slug:dealer_slug>/cars/add/", views.CarCreateView.as_view(), name="car_add"),
|
||||
path("<slug:dealer_slug>/cars/inventory/", views.CarInventory.as_view(), name="car_inventory_all"),
|
||||
path(
|
||||
"cars/inventory/<slug:make_id>/<slug:model_id>/<slug:trim_id>/",
|
||||
"<slug:dealer_slug>/cars/inventory/<slug:make_id>/<slug:model_id>/<slug:trim_id>/",
|
||||
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/<slug:slug>/", views.CarDetailView.as_view(), name="car_detail"),
|
||||
path("<slug:dealer_slug>/cars/inventory/stats", views.inventory_stats_view, name="inventory_stats"),
|
||||
path("<slug:dealer_slug>/cars/inventory/list", views.CarListView.as_view(), name="car_list"),
|
||||
path("<slug:dealer_slug>/cars/<slug:slug>/", views.CarDetailView.as_view(), name="car_detail"),
|
||||
path("cars/<slug:slug>/history/", views.car_history, name="car_history"),
|
||||
path("cars/<slug:slug>/update/", views.CarUpdateView.as_view(), name="car_update"),
|
||||
path("cars/<slug:slug>/delete/", views.CarDeleteView.as_view(), name="car_delete"),
|
||||
path("<slug:dealer_slug>/cars/<slug:slug>/update/", views.CarUpdateView.as_view(), name="car_update"),
|
||||
path("<slug:dealer_slug>/cars/<slug:slug>/delete/", views.CarDeleteView.as_view(), name="car_delete"),
|
||||
path(
|
||||
"cars/<slug:slug>/finance/create/",
|
||||
"<slug:dealer_slug>/cars/<slug:slug>/finance/create/",
|
||||
views.CarFinanceCreateView.as_view(),
|
||||
name="car_finance_create",
|
||||
),
|
||||
path(
|
||||
"cars/finance/<int:pk>/update/",
|
||||
"<slug:dealer_slug>/cars/finance/<int:pk>/update/",
|
||||
views.CarFinanceUpdateView.as_view(),
|
||||
name="car_finance_update",
|
||||
),
|
||||
@ -307,12 +309,12 @@ urlpatterns = [
|
||||
views.bulk_update_car_price,
|
||||
name="bulk_update_car_price",
|
||||
),
|
||||
path("ajax/", views.AjaxHandlerView.as_view(), name="ajax_handler"),
|
||||
path("<slug:dealer_slug>/ajax/", views.AjaxHandlerView.as_view(), name="ajax_handler"),
|
||||
path(
|
||||
"cars/<slug:slug>/add-color/", views.CarColorCreate.as_view(), name="add_color"
|
||||
"<slug:dealer_slug>/cars/<slug:slug>/add-color/", views.CarColorCreate.as_view(), name="add_color"
|
||||
),
|
||||
path(
|
||||
"car/colors/<slug:slug>/update/",
|
||||
"<slug:dealer_slug>/car/colors/<slug:slug>/update/",
|
||||
views.CarColorsUpdateView.as_view(),
|
||||
name="car_colors_update",
|
||||
),
|
||||
@ -353,19 +355,19 @@ urlpatterns = [
|
||||
),
|
||||
path("cars/inventory/search/", views.SearchCodeView.as_view(), name="car_search"),
|
||||
# path('cars/<int:car_pk>/colors/<int:pk>/update/',views.CarColorUpdateView.as_view(),name='color_update'),
|
||||
path("cars/reserve/<slug:slug>/", views.reserve_car_view, name="reserve_car"),
|
||||
path("<slug:dealer_slug>/cars/reserve/<slug:slug>/", views.reserve_car_view, name="reserve_car"),
|
||||
path(
|
||||
"reservations/<int:reservation_id>/",
|
||||
"<slug:dealer_slug>/reservations/<int:reservation_id>/",
|
||||
views.manage_reservation,
|
||||
name="reservations",
|
||||
),
|
||||
path(
|
||||
"cars/<slug:slug>/add-custom-card/",
|
||||
"<slug:dealer_slug>/cars/<slug:slug>/add-custom-card/",
|
||||
views.CustomCardCreateView.as_view(),
|
||||
name="add_custom_card",
|
||||
),
|
||||
path(
|
||||
"cars/<slug:slug>/add-registration/",
|
||||
"<slug:dealer_slug>/cars/<slug:slug>/add-registration/",
|
||||
views.CarRegistrationCreateView.as_view(),
|
||||
name="add_registration",
|
||||
),
|
||||
@ -612,142 +614,146 @@ urlpatterns = [
|
||||
),
|
||||
# Bank Account
|
||||
path(
|
||||
"bank_accounts/", views.BankAccountListView.as_view(), name="bank_account_list"
|
||||
"<slug:dealer_slug>/bank_accounts/", views.BankAccountListView.as_view(), name="bank_account_list"
|
||||
),
|
||||
path(
|
||||
"bank_accounts/<uuid:pk>/",
|
||||
"<slug:dealer_slug>/bank_accounts/<uuid:pk>/",
|
||||
views.BankAccountDetailView.as_view(),
|
||||
name="bank_account_detail",
|
||||
),
|
||||
path(
|
||||
"bank_accounts/create/",
|
||||
"<slug:dealer_slug>/bank_accounts/create/",
|
||||
views.BankAccountCreateView.as_view(),
|
||||
name="bank_account_create",
|
||||
),
|
||||
path(
|
||||
"bank_accounts/<uuid:pk>/update/",
|
||||
"<slug:dealer_slug>/bank_accounts/<uuid:pk>/update/",
|
||||
views.BankAccountUpdateView.as_view(),
|
||||
name="bank_account_update",
|
||||
),
|
||||
path(
|
||||
"bank_accounts/<uuid:pk>/delete/",
|
||||
"<slug:dealer_slug>/bank_accounts/<uuid:pk>/delete/",
|
||||
views.bank_account_delete,
|
||||
name="bank_account_delete",
|
||||
),
|
||||
# Account
|
||||
path("coa_accounts/", views.AccountListView.as_view(), name="account_list"),
|
||||
path("<slug:dealer_slug>/coa_accounts/", views.AccountListView.as_view(), name="account_list"),
|
||||
path(
|
||||
"coa_accounts/<uuid:pk>/",
|
||||
"<slug:dealer_slug>/coa_accounts/<uuid:pk>/",
|
||||
views.AccountDetailView.as_view(),
|
||||
name="account_detail",
|
||||
),
|
||||
path(
|
||||
"coa_accounts/create/", views.AccountCreateView.as_view(), name="account_create"
|
||||
"<slug:dealer_slug>/coa_accounts/create/", views.AccountCreateView.as_view(), name="account_create"
|
||||
),
|
||||
path(
|
||||
"coa_accounts/<uuid:pk>/update/",
|
||||
"<slug:dealer_slug>/coa_accounts/<uuid:pk>/update/",
|
||||
views.AccountUpdateView.as_view(),
|
||||
name="account_update",
|
||||
),
|
||||
path("coa_accounts/<uuid:pk>/delete/", views.account_delete, name="account_delete"),
|
||||
path("<slug:dealer_slug>/coa_accounts/<uuid:pk>/delete/", views.account_delete, name="account_delete"),
|
||||
#################################################
|
||||
# Estimate
|
||||
path("sales/estimates/", views.EstimateListView.as_view(), name="estimate_list"),
|
||||
#################################################
|
||||
path("<slug:dealer_slug>/sales/estimates/", views.EstimateListView.as_view(), name="estimate_list"),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/",
|
||||
views.EstimateDetailView.as_view(),
|
||||
name="estimate_detail",
|
||||
),
|
||||
path("sales/estimates/create/", views.create_estimate, name="estimate_create"),
|
||||
path("<slug:dealer_slug>/sales/estimates/create/", views.create_estimate, name="estimate_create"),
|
||||
path(
|
||||
"sales/estimates/create/<slug:slug>/",
|
||||
"<slug:dealer_slug>/sales/estimates/create/<slug:slug>/",
|
||||
views.create_estimate,
|
||||
name="estimate_create_from_opportunity",
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/estimate_mark_as/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/estimate_mark_as/",
|
||||
views.estimate_mark_as,
|
||||
name="estimate_mark_as",
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/preview/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/preview/",
|
||||
views.EstimatePreviewView.as_view(),
|
||||
name="estimate_preview",
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/payment_request/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/payment_request/",
|
||||
views.PaymentRequest.as_view(),
|
||||
name="payment_request",
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/send_email", views.send_email_view, name="send_email"
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/send_email", views.send_email_view, name="send_email"
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/sale_order/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/sale_order/",
|
||||
views.create_sale_order,
|
||||
name="create_sale_order",
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/sale_order/<int:order_pk>/details/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/sale_order/<int:order_pk>/details/",
|
||||
views.SaleOrderDetail.as_view(),
|
||||
name="sale_order_details",
|
||||
),
|
||||
path(
|
||||
"sales/estimates/<uuid:pk>/sale_order/preview/",
|
||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/sale_order/preview/",
|
||||
views.preview_sale_order,
|
||||
name="preview_sale_order",
|
||||
),
|
||||
###############################################
|
||||
# Invoice
|
||||
path("sales/invoices/", views.InvoiceListView.as_view(), name="invoice_list"),
|
||||
###############################################
|
||||
path("<slug:dealer_slug>/sales/invoices/", views.InvoiceListView.as_view(), name="invoice_list"),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/create/", views.invoice_create, name="invoice_create"
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/create/", views.invoice_create, name="invoice_create"
|
||||
),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/",
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/",
|
||||
views.InvoiceDetailView.as_view(),
|
||||
name="invoice_detail",
|
||||
),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/preview/",
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/preview/",
|
||||
views.InvoicePreviewView.as_view(),
|
||||
name="invoice_preview",
|
||||
),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/invoice_mark_as/",
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/invoice_mark_as/",
|
||||
views.invoice_mark_as,
|
||||
name="invoice_mark_as",
|
||||
),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/draft_invoice_update/",
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/draft_invoice_update/",
|
||||
views.DraftInvoiceModelUpdateFormView.as_view(),
|
||||
name="draft_invoice_update",
|
||||
),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/approved_invoice_update/",
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/approved_invoice_update/",
|
||||
views.ApprovedInvoiceModelUpdateFormView.as_view(),
|
||||
name="approved_invoice_update",
|
||||
),
|
||||
path(
|
||||
"sales/invoices/<uuid:pk>/paid_invoice_update/",
|
||||
"<slug:dealer_slug>/sales/invoices/<uuid:pk>/paid_invoice_update/",
|
||||
views.PaidInvoiceModelUpdateFormView.as_view(),
|
||||
name="paid_invoice_update",
|
||||
),
|
||||
# path('sales/estimates/<uuid:pk>/preview/', views.EstimatePreviewView.as_view(), name='estimate_preview'),
|
||||
# path('send_email/<uuid:pk>', views.send_email, name='send_email'),
|
||||
# Payment
|
||||
path("sales/payments/", views.PaymentListView, name="payment_list"),
|
||||
path("<slug:dealer_slug>/sales/payments/", views.PaymentListView, name="payment_list"),
|
||||
path(
|
||||
"sales/payments/<uuid:pk>/create/",
|
||||
"<slug:dealer_slug>/sales/payments/<uuid:pk>/create/",
|
||||
views.PaymentCreateView,
|
||||
name="payment_create",
|
||||
),
|
||||
# path("sales/payments/create/", views.PaymentCreateView, name="payment_create"),
|
||||
path(
|
||||
"sales/payments/<uuid:pk>/payment_details/",
|
||||
"<slug:dealer_slug>/sales/payments/<uuid:pk>/payment_details/",
|
||||
views.PaymentDetailView,
|
||||
name="payment_details",
|
||||
),
|
||||
path(
|
||||
"sales/payments/<uuid:pk>/payment_mark_as_paid/",
|
||||
"<slug:dealer_slug>/sales/payments/<uuid:pk>/payment_mark_as_paid/",
|
||||
views.payment_mark_as_paid,
|
||||
name="payment_mark_as_paid",
|
||||
),
|
||||
@ -787,85 +793,86 @@ urlpatterns = [
|
||||
name="item_expense_update",
|
||||
),
|
||||
# Bills
|
||||
path("items/bills/", views.BillListView.as_view(), name="bill_list"),
|
||||
path("<slug:dealer_slug>/items/bills/", views.BillListView.as_view(), name="bill_list"),
|
||||
# path("items/bills/create/", views.BillModelCreateViewView.as_view(), name="bill_create"),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/create/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/create/",
|
||||
views.BillModelCreateView.as_view(),
|
||||
name="bill-create",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/create/purchase-order/<uuid:po_pk>/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/create/purchase-order/<uuid:po_pk>/",
|
||||
views.BillModelCreateView.as_view(for_purchase_order=True),
|
||||
name="bill-create-po",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/create/estimate/<uuid:ce_pk>/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/create/estimate/<uuid:ce_pk>/",
|
||||
views.BillModelCreateView.as_view(for_estimate=True),
|
||||
name="bill-create-estimate",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/detail/<uuid:bill_pk>/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/detail/<uuid:bill_pk>/",
|
||||
views.BillModelDetailViewView.as_view(),
|
||||
name="bill-detail",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/update/<uuid:bill_pk>/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/update/<uuid:bill_pk>/",
|
||||
views.BillModelUpdateViewView.as_view(),
|
||||
name="bill-update",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/update/<uuid:bill_pk>/items/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/update/<uuid:bill_pk>/items/",
|
||||
views.BillModelUpdateViewView.as_view(action_update_items=True),
|
||||
name="bill-update-items",
|
||||
),
|
||||
############################################################
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-draft/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-draft/",
|
||||
views.BillModelActionMarkAsDraftView.as_view(),
|
||||
name="bill-action-mark-as-draft",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-review/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-review/",
|
||||
views.BillModelActionMarkAsInReviewView.as_view(),
|
||||
name="bill-action-mark-as-review",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-approved/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-approved/",
|
||||
views.BillModelActionMarkAsApprovedView.as_view(),
|
||||
name="bill-action-mark-as-approved",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-paid/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-paid/",
|
||||
views.BillModelActionMarkAsPaidView.as_view(),
|
||||
name="bill-action-mark-as-paid",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-void/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-void/",
|
||||
views.BillModelActionVoidView.as_view(),
|
||||
name="bill-action-mark-as-void",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-canceled/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/mark-as-canceled/",
|
||||
views.BillModelActionCanceledView.as_view(),
|
||||
name="bill-action-mark-as-canceled",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/lock-ledger/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/lock-ledger/",
|
||||
views.BillModelActionLockLedgerView.as_view(),
|
||||
name="bill-action-lock-ledger",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/unlock-ledger/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/unlock-ledger/",
|
||||
views.BillModelActionUnlockLedgerView.as_view(),
|
||||
name="bill-action-unlock-ledger",
|
||||
),
|
||||
path(
|
||||
"items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/force-migration/",
|
||||
"<slug:dealer_slug>/items/bills/<slug:entity_slug>/actions/<uuid:bill_pk>/force-migration/",
|
||||
views.BillModelActionForceMigrateView.as_view(),
|
||||
name="bill-action-force-migrate",
|
||||
),
|
||||
# path("items/bills/create/", views.bill_create, name="bill_create"),
|
||||
# >>>>>>>>>>>>>>>>>>>>>>...
|
||||
path(
|
||||
"items/bills/<uuid:pk>/bill_detail/",
|
||||
views.BillDetailView.as_view(),
|
||||
@ -1039,78 +1046,78 @@ urlpatterns = [
|
||||
#########
|
||||
# Purchase Order
|
||||
path(
|
||||
"purchase_orders/",
|
||||
"<slug:dealer_slug>/purchase_orders/",
|
||||
views.PurchaseOrderListView.as_view(),
|
||||
name="purchase_order_list",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/new/",
|
||||
"<slug:dealer_slug>/purchase_orders/new/",
|
||||
views.PurchaseOrderCreateView,
|
||||
name="purchase_order_create",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/<uuid:pk>/detail/",
|
||||
"<slug:dealer_slug>/purchase_orders/<uuid:pk>/detail/",
|
||||
views.PurchaseOrderDetailView.as_view(),
|
||||
name="purchase_order_detail",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/<slug:entity_slug>/<uuid:po_pk>/update/",
|
||||
"<slug:dealer_slug>/purchase_orders/<slug:entity_slug>/<uuid:po_pk>/update/",
|
||||
views.PurchaseOrderUpdateView.as_view(),
|
||||
name="purchase_order_update",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/<slug:entity_slug>/update/<uuid:po_pk>/update-items/",
|
||||
"<slug:dealer_slug>/purchase_orders/<slug:entity_slug>/update/<uuid:po_pk>/update-items/",
|
||||
views.PurchaseOrderUpdateView.as_view(action_update_items=True),
|
||||
name="purchase_order_update_items",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/inventory_item/create/",
|
||||
"<slug:dealer_slug>/purchase_orders/inventory_item/create/",
|
||||
views.InventoryItemCreateView,
|
||||
name="inventory_item_create",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/inventory_items_filter/",
|
||||
"<slug:dealer_slug>/purchase_orders/inventory_items_filter/",
|
||||
views.inventory_items_filter,
|
||||
name="inventory_items_filter",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/<slug:entity_slug>/delete/<uuid:po_pk>/",
|
||||
"<slug:dealer_slug>/purchase_orders/<slug:entity_slug>/delete/<uuid:po_pk>/",
|
||||
views.PurchaseOrderModelDeleteView.as_view(),
|
||||
name="po-delete",
|
||||
),
|
||||
path(
|
||||
"purchase_orders/<slug:entity_slug>/<uuid:po_pk>/upload/",
|
||||
"<slug:dealer_slug>/purchase_orders/<slug:entity_slug>/<uuid:po_pk>/upload/",
|
||||
view=views.view_items_inventory,
|
||||
name="view_items_inventory",
|
||||
),
|
||||
# Actions....
|
||||
path(
|
||||
"<slug:entity_slug>/action/<uuid:po_pk>/mark-as-draft/",
|
||||
"<slug:dealer_slug>/<slug:entity_slug>/action/<uuid:po_pk>/mark-as-draft/",
|
||||
views.PurchaseOrderMarkAsDraftView.as_view(),
|
||||
name="po-action-mark-as-draft",
|
||||
),
|
||||
path(
|
||||
"<slug:entity_slug>/action/<uuid:po_pk>/mark-as-review/",
|
||||
"<slug:dealer_slug>/<slug:entity_slug>/action/<uuid:po_pk>/mark-as-review/",
|
||||
views.PurchaseOrderMarkAsReviewView.as_view(),
|
||||
name="po-action-mark-as-review",
|
||||
),
|
||||
path(
|
||||
"<slug:entity_slug>/action/<uuid:po_pk>/mark-as-approved/",
|
||||
"<slug:dealer_slug>/<slug:entity_slug>/action/<uuid:po_pk>/mark-as-approved/",
|
||||
views.PurchaseOrderMarkAsApprovedView.as_view(),
|
||||
name="po-action-mark-as-approved",
|
||||
),
|
||||
path(
|
||||
"<slug:entity_slug>/action/<uuid:po_pk>/mark-as-fulfilled/",
|
||||
"<slug:dealer_slug>/<slug:entity_slug>/action/<uuid:po_pk>/mark-as-fulfilled/",
|
||||
views.PurchaseOrderMarkAsFulfilledView.as_view(),
|
||||
name="po-action-mark-as-fulfilled",
|
||||
),
|
||||
path(
|
||||
"<slug:entity_slug>/action/<uuid:po_pk>/mark-as-canceled/",
|
||||
"<slug:dealer_slug>/<slug:entity_slug>/action/<uuid:po_pk>/mark-as-canceled/",
|
||||
views.PurchaseOrderMarkAsCanceledView.as_view(),
|
||||
name="po-action-mark-as-canceled",
|
||||
),
|
||||
path(
|
||||
"<slug:entity_slug>/action/<uuid:po_pk>/mark-as-void/",
|
||||
"<slug:dealer_slug>/<slug:entity_slug>/action/<uuid:po_pk>/mark-as-void/",
|
||||
views.PurchaseOrderMarkAsVoidView.as_view(),
|
||||
name="po-action-mark-as-void",
|
||||
),
|
||||
|
||||
@ -222,7 +222,7 @@ def reserve_car(car, request):
|
||||
except Exception as e:
|
||||
messages.error(request, f"Error reserving car: {e}")
|
||||
|
||||
return redirect("car_detail", slug=car.slug)
|
||||
return redirect("car_detail", dealer_slug=request.dealer.slug, slug=car.slug)
|
||||
|
||||
|
||||
def calculate_vat_amount(amount):
|
||||
@ -1011,7 +1011,7 @@ class CarFinanceCalculator:
|
||||
"make": car_info.get("make"),
|
||||
"model": car_info.get("model"),
|
||||
"year": car_info.get("year"),
|
||||
"logo": item.item_model.car.id_car_make.logo.url,
|
||||
"logo": getattr(item.item_model.car.id_car_make, "logo", ""),
|
||||
"trim": car_info.get("trim"),
|
||||
"mileage": car_info.get("mileage"),
|
||||
"cost_price": car_finance.get("cost_price"),
|
||||
|
||||
@ -20,6 +20,7 @@ from pyzbar.pyzbar import decode
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
#####################################################################
|
||||
from inventory.mixins import DealerSlugMixin
|
||||
from inventory.models import Status as LeadStatus
|
||||
from django.db import IntegrityError
|
||||
from background_task.models import Task
|
||||
@ -348,10 +349,13 @@ 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")
|
||||
if not kwargs.get("dealer_slug"):
|
||||
dealer = get_user_type(request)
|
||||
return redirect("home", dealer_slug=dealer.slug)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
@ -616,8 +620,8 @@ 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")
|
||||
return reverse("inventory_stats")
|
||||
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)
|
||||
@ -628,9 +632,7 @@ class CarCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
dealer = get_user_type(self.request)
|
||||
context["vendor_exists"] = dealer.vendors.exists()
|
||||
|
||||
context["vendor_exists"] = self.request.dealer.vendors.exists()
|
||||
return context
|
||||
|
||||
|
||||
@ -673,7 +675,7 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
:ivar request: Django request object containing HTTP request details.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
def get(self, request,dealer_slug, *args, **kwargs):
|
||||
action = request.GET.get("action")
|
||||
handlers = {
|
||||
"decode_vin": self.decode_vin,
|
||||
@ -986,7 +988,7 @@ class CarColorCreate(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("car_detail", kwargs={"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)
|
||||
@ -1025,7 +1027,7 @@ 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={"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):
|
||||
"""
|
||||
@ -1138,7 +1140,7 @@ class CarListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
|
||||
|
||||
@login_required
|
||||
def inventory_stats_view(request):
|
||||
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.
|
||||
@ -1154,10 +1156,9 @@ def inventory_stats_view(request):
|
||||
"inventory/inventory_stats.html" template.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_user_type(request)
|
||||
|
||||
# Base queryset for cars belonging to the dealer
|
||||
cars = models.Car.objects.filter(dealer=dealer)
|
||||
cars = models.Car.objects.filter(dealer=request.dealer)
|
||||
|
||||
# Count for total, reserved, showroom, and unreserved cars
|
||||
total_cars = cars.count()
|
||||
@ -1241,7 +1242,6 @@ def inventory_stats_view(request):
|
||||
for make_data in inventory.values()
|
||||
],
|
||||
}
|
||||
print(result["makes"])
|
||||
return render(request, "inventory/inventory_stats.html", {"inventory": result})
|
||||
|
||||
|
||||
@ -1427,7 +1427,7 @@ class CarFinanceCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateVi
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("car_detail", kwargs={"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 +1474,7 @@ class CarFinanceUpdateView(
|
||||
permission_required = ["inventory.change_carfinance"]
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("car_detail", kwargs={"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 +1871,7 @@ class CustomCardCreateView(LoginRequiredMixin, CreateView):
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(self.request, _("Custom Card added successfully"))
|
||||
return reverse_lazy("car_detail", kwargs={"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 +1913,11 @@ class CarRegistrationCreateView(LoginRequiredMixin, CreateView):
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(self.request, _("Registration added successfully"))
|
||||
return reverse_lazy("car_detail", kwargs={"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, 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 +1945,7 @@ def reserve_car_view(request, slug):
|
||||
|
||||
|
||||
@login_required
|
||||
def manage_reservation(request, 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 +1974,7 @@ def manage_reservation(request, reservation_id):
|
||||
reservation.reserved_until = timezone.now() + timezone.timedelta(hours=24)
|
||||
reservation.save()
|
||||
messages.success(request, _("Reservation renewed successfully"))
|
||||
return redirect("car_detail", 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 +1982,7 @@ def manage_reservation(request, reservation_id):
|
||||
car.status = models.CarStatusChoices.AVAILABLE
|
||||
car.save()
|
||||
messages.success(request, _("Reservation canceled successfully"))
|
||||
return redirect("car_detail", slug=reservation.car.slug)
|
||||
return redirect("car_detail",dealer_slug=request.dealer.slug, slug=reservation.car.slug)
|
||||
|
||||
else:
|
||||
return JsonResponse(
|
||||
@ -3444,21 +3444,20 @@ class BankAccountUpdateView(
|
||||
model = BankAccountModel
|
||||
form_class = BankAccountUpdateForm
|
||||
template_name = "ledger/bank_accounts/bank_account_form.html"
|
||||
success_url = reverse_lazy("bank_account_list")
|
||||
success_message = _("Bank account updated successfully")
|
||||
permission_required = ["inventory.view_carfinance"]
|
||||
|
||||
def get_form_kwargs(self):
|
||||
dealer = get_user_type(self.request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
||||
entity = dealer.entity
|
||||
kwargs = super().get_form_kwargs()
|
||||
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})
|
||||
@login_required
|
||||
def bank_account_delete(request, pk):
|
||||
def bank_account_delete(request,dealer_slug, pk):
|
||||
"""
|
||||
Delete a bank account entry from the database.
|
||||
|
||||
@ -3478,11 +3477,12 @@ def bank_account_delete(request, pk):
|
||||
rendering the confirmation template if accessed via GET.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
bank_account = get_object_or_404(BankAccountModel, pk=pk)
|
||||
if request.method == "POST":
|
||||
bank_account.delete()
|
||||
messages.success(request, _("Bank account deleted successfully"))
|
||||
return redirect("bank_account_list")
|
||||
return redirect("bank_account_list", dealer_slug=dealer_slug)
|
||||
return render(
|
||||
request,
|
||||
"ledger/bank_accounts/bank_account_delete.html",
|
||||
@ -3568,7 +3568,6 @@ class AccountCreateView(
|
||||
model = AccountModel
|
||||
form_class = AccountModelCreateForm
|
||||
template_name = "ledger/coa_accounts/account_form.html"
|
||||
success_url = reverse_lazy("account_list")
|
||||
success_message = _("Account created successfully")
|
||||
permission_required = ["inventory.view_carfinance"]
|
||||
|
||||
@ -3591,6 +3590,8 @@ 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"]})
|
||||
|
||||
|
||||
class AccountDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
||||
@ -3682,7 +3683,6 @@ class AccountUpdateView(
|
||||
model = AccountModel
|
||||
form_class = AccountModelUpdateForm
|
||||
template_name = "ledger/coa_accounts/account_form.html"
|
||||
success_url = reverse_lazy("account_list")
|
||||
success_message = _("Account updated successfully")
|
||||
permission_required = ["inventory.view_carfinance"]
|
||||
|
||||
@ -3691,11 +3691,12 @@ 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"]})
|
||||
|
||||
@login_required
|
||||
@permission_required("inventory.view_carfinance")
|
||||
def account_delete(request, 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
|
||||
@ -3708,11 +3709,13 @@ def account_delete(request, pk):
|
||||
:return: An HTTP redirect response to the account list page.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
account = get_object_or_404(AccountModel, pk=pk)
|
||||
|
||||
account.delete()
|
||||
messages.success(request, _("Account deleted successfully"))
|
||||
return redirect("account_list")
|
||||
return redirect("account_list",dealer_slug=dealer_slug)
|
||||
|
||||
|
||||
# Sales list
|
||||
@ -3809,7 +3812,7 @@ class EstimateListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
# @csrf_exempt
|
||||
@login_required
|
||||
@permission_required("django_ledger.add_estimatemodel", raise_exception=True)
|
||||
def create_estimate(request, 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
|
||||
@ -3829,7 +3832,7 @@ def create_estimate(request, slug=None):
|
||||
estimate creation form.
|
||||
:rtype: JsonResponse or HttpResponse
|
||||
"""
|
||||
dealer = get_user_type(request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
entity = dealer.entity
|
||||
|
||||
if request.method == "POST":
|
||||
@ -4002,7 +4005,7 @@ def create_estimate(request, slug=None):
|
||||
opportunity.estimate = estimate
|
||||
opportunity.save()
|
||||
|
||||
url = reverse("estimate_detail", kwargs={"pk": estimate.pk})
|
||||
url = reverse("estimate_detail", kwargs={"dealer_slug": dealer.slug,"pk": estimate.pk})
|
||||
return JsonResponse(
|
||||
{
|
||||
"status": "success",
|
||||
@ -4108,7 +4111,7 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
|
||||
|
||||
@login_required
|
||||
@permission_required("inventory.add_saleorder", raise_exception=True)
|
||||
def create_sale_order(request, pk):
|
||||
def create_sale_order(request,dealer_slug, pk):
|
||||
"""
|
||||
Creates a sale order for a given estimate and updates associated item and car data.
|
||||
|
||||
@ -4127,7 +4130,7 @@ def create_sale_order(request, pk):
|
||||
POST data, or redirects to the estimate detail view upon successful creation.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_user_type(request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
||||
items = estimate.get_itemtxs_data()[0].all()
|
||||
if request.method == "POST":
|
||||
@ -4157,7 +4160,7 @@ def create_sale_order(request, pk):
|
||||
else:
|
||||
print(form.errors)
|
||||
messages.error(request, "Invalid form data")
|
||||
return redirect("estimate_detail", pk=estimate.pk)
|
||||
return redirect("estimate_detail", dealer_slug=dealer_slug, pk=estimate.pk)
|
||||
|
||||
form = forms.SaleOrderForm()
|
||||
customer = estimate.customer.customer_set.first()
|
||||
@ -4201,7 +4204,7 @@ class SaleOrderDetail(DetailView):
|
||||
|
||||
|
||||
@login_required
|
||||
def preview_sale_order(request, pk):
|
||||
def preview_sale_order(request, dealer_slug,pk):
|
||||
"""
|
||||
Handles rendering of the sale order preview page for a specific estimate.
|
||||
|
||||
@ -4216,6 +4219,7 @@ def preview_sale_order(request, pk):
|
||||
:return: HTTP response containing the rendered sale order preview page
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
||||
data = get_car_finance_data(estimate)
|
||||
return render(
|
||||
@ -4289,19 +4293,18 @@ class EstimatePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailVie
|
||||
permission_required = ["django_ledger.view_estimatemodel"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
dealer = get_user_type(self.request)
|
||||
estimate = kwargs.get("object")
|
||||
if estimate.get_itemtxs_data():
|
||||
# data = get_financial_values(estimate)
|
||||
calculator = CarFinanceCalculator(estimate)
|
||||
kwargs["data"] = calculator.get_finance_data()
|
||||
kwargs["dealer"] = dealer
|
||||
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("django_ledger.change_estimatemodel", raise_exception=True)
|
||||
def estimate_mark_as(request, 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,
|
||||
@ -4317,35 +4320,36 @@ def estimate_mark_as(request, pk):
|
||||
:return: A redirect response to the estimate detail view.
|
||||
:rtype: HttpResponseRedirect
|
||||
"""
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
||||
mark = request.GET.get("mark")
|
||||
if mark:
|
||||
if mark == "review":
|
||||
if not estimate.can_review():
|
||||
messages.error(request, _("Quotation is not ready for review"))
|
||||
return redirect("estimate_detail", 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", 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", 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", 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", pk=estimate.pk)
|
||||
return redirect("estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk)
|
||||
estimate.mark_as_canceled()
|
||||
try:
|
||||
car = models.Car.objects.get(
|
||||
@ -4359,7 +4363,7 @@ def estimate_mark_as(request, pk):
|
||||
estimate.save()
|
||||
messages.success(request, _("Quotation marked as ") + mark.upper())
|
||||
|
||||
return redirect("estimate_detail", pk=estimate.pk)
|
||||
return redirect("estimate_detail", dealer_slug=dealer.slug, pk=estimate.pk)
|
||||
|
||||
|
||||
# Invoice
|
||||
@ -4392,8 +4396,8 @@ class InvoiceListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
permission_required = ["django_ledger.view_invoicemodel"]
|
||||
|
||||
def get_queryset(self):
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
||||
query = self.request.GET.get("q")
|
||||
dealer = get_user_type(self.request)
|
||||
invoices = dealer.entity.get_invoices()
|
||||
return apply_search_filters(invoices, query)
|
||||
|
||||
@ -4474,7 +4478,7 @@ class DraftInvoiceModelUpdateFormView(
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
dealer = get_user_type(self.request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
||||
kwargs["entity_slug"] = dealer.entity
|
||||
kwargs["user_model"] = dealer.entity.admin
|
||||
return kwargs
|
||||
@ -4516,13 +4520,13 @@ class ApprovedInvoiceModelUpdateFormView(
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
dealer = get_user_type(self.request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
||||
kwargs["entity_slug"] = dealer.entity
|
||||
kwargs["user_model"] = dealer.entity.admin
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("invoice_detail", kwargs={"pk": self.object.pk})
|
||||
return reverse_lazy("invoice_detail", kwargs={"dealer_slug":self.kwargs["dealer_slug"],"pk": self.object.pk})
|
||||
|
||||
|
||||
class PaidInvoiceModelUpdateFormView(
|
||||
@ -4561,13 +4565,13 @@ class PaidInvoiceModelUpdateFormView(
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
dealer = get_user_type(self.request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
||||
kwargs["entity_slug"] = dealer.entity
|
||||
kwargs["user_model"] = dealer.entity.admin
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("invoice_detail", kwargs={"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()
|
||||
@ -4583,7 +4587,7 @@ class PaidInvoiceModelUpdateFormView(
|
||||
|
||||
@login_required
|
||||
@permission_required("django_ledger.change_invoicemodel", raise_exception=True)
|
||||
def invoice_mark_as(request, pk):
|
||||
def invoice_mark_as(request,dealer_slug, pk):
|
||||
"""
|
||||
Marks an invoice as approved if it meets the required conditions.
|
||||
|
||||
@ -4600,23 +4604,23 @@ def invoice_mark_as(request, pk):
|
||||
:return: An HTTP redirect response to the invoice detail page after processing.
|
||||
:rtype: django.http.HttpResponse
|
||||
"""
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
invoice = get_object_or_404(InvoiceModel, pk=pk)
|
||||
dealer = get_user_type(request)
|
||||
mark = request.GET.get("mark")
|
||||
if mark and mark == "accept":
|
||||
if not invoice.can_approve():
|
||||
messages.error(request, "invoice is not ready for approval")
|
||||
return redirect("invoice_detail", 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", 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, 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
|
||||
@ -4632,8 +4636,8 @@ def invoice_create(request, pk):
|
||||
creation or renders the invoice creation form template otherwise.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
|
||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
||||
dealer = get_user_type(request)
|
||||
entity = dealer.entity
|
||||
|
||||
if request.method == "POST":
|
||||
@ -4674,7 +4678,7 @@ def invoice_create(request, pk):
|
||||
estimate.save()
|
||||
invoice.save()
|
||||
messages.success(request, "Invoice created successfully")
|
||||
return redirect("invoice_detail", pk=invoice.pk)
|
||||
return redirect("invoice_detail", dealer_slug=dealer.slug,pk=invoice.pk)
|
||||
else:
|
||||
print(form.errors)
|
||||
form = forms.InvoiceModelCreateForm(
|
||||
@ -4722,7 +4726,7 @@ class InvoicePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
|
||||
permission_required = ["django_ledger.view_invoicemodel"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
dealer = get_user_type(self.request)
|
||||
dealer = get_object_or_404(models.Dealer,slug=self.kwargs["dealer_slug"])
|
||||
invoice = kwargs.get("object")
|
||||
if invoice.get_itemtxs_data():
|
||||
calculator = CarFinanceCalculator(invoice)
|
||||
@ -4737,7 +4741,7 @@ class InvoicePreviewView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
|
||||
|
||||
@login_required
|
||||
@permission_required("django_ledger.add_journalentrymodel", raise_exception=True)
|
||||
def PaymentCreateView(request, 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
|
||||
@ -4760,10 +4764,10 @@ def PaymentCreateView(request, 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)
|
||||
invoice = InvoiceModel.objects.filter(pk=pk).first()
|
||||
bill = BillModel.objects.filter(pk=pk).first()
|
||||
model = invoice if invoice else bill
|
||||
dealer = get_user_type(request)
|
||||
entity = dealer.entity
|
||||
form = forms.PaymentForm()
|
||||
if request.method == "POST":
|
||||
@ -4780,10 +4784,10 @@ def PaymentCreateView(request, 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, 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, pk=model.pk)
|
||||
return redirect(redirect_url, dealer_slug=dealer.slug, pk=model.pk)
|
||||
|
||||
try:
|
||||
if invoice:
|
||||
@ -4791,7 +4795,7 @@ def PaymentCreateView(request, pk):
|
||||
elif bill:
|
||||
set_bill_payment(dealer, entity, bill, amount, payment_method)
|
||||
messages.success(request, _("Payment created successfully"))
|
||||
return redirect(redirect_url, pk=model.pk)
|
||||
return redirect(redirect_url, dealer_slug=dealer.slug, pk=model.pk)
|
||||
except Exception as e:
|
||||
messages.error(request, f"Error creating payment: {str(e)}")
|
||||
else:
|
||||
@ -4812,7 +4816,7 @@ def PaymentCreateView(request, pk):
|
||||
|
||||
@login_required
|
||||
@permission_required("django_ledger.view_journalentrymodel", raise_exception=True)
|
||||
def PaymentListView(request):
|
||||
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
|
||||
@ -4828,7 +4832,7 @@ def PaymentListView(request):
|
||||
:return: The rendered HTML response displaying the list of payments.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_user_type(request)
|
||||
dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
|
||||
entity = dealer.entity
|
||||
|
||||
journals = JournalEntryModel.objects.filter(ledger__entity=entity).all()
|
||||
@ -4842,7 +4846,7 @@ def PaymentListView(request):
|
||||
|
||||
@login_required
|
||||
@permission_required("django_ledger.view_journalentrymodel", raise_exception=True)
|
||||
def PaymentDetailView(request, 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
|
||||
@ -4856,6 +4860,7 @@ def PaymentDetailView(request, pk):
|
||||
entry and its associated transactions.
|
||||
:rtype: HttpResponse
|
||||
"""
|
||||
dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
|
||||
journal = JournalEntryModel.objects.filter(pk=pk).first()
|
||||
transactions = (
|
||||
TransactionModel.objects.filter(journal_entry=journal)
|
||||
@ -4871,7 +4876,7 @@ def PaymentDetailView(request, pk):
|
||||
|
||||
@login_required
|
||||
@permission_required("django_ledger.change_journalentrymodel", raise_exception=True)
|
||||
def payment_mark_as_paid(request, 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
|
||||
@ -4890,6 +4895,7 @@ def payment_mark_as_paid(request, 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)
|
||||
invoice = get_object_or_404(InvoiceModel, pk=pk)
|
||||
if request.method == "POST":
|
||||
try:
|
||||
@ -4914,7 +4920,7 @@ def payment_mark_as_paid(request, pk):
|
||||
)
|
||||
except Exception as e:
|
||||
messages.error(request, f"Error: {str(e)}")
|
||||
return redirect("invoice_detail", pk=invoice.pk)
|
||||
return redirect("invoice_detail",dealer_slug=dealer_slug, pk=invoice.pk)
|
||||
|
||||
|
||||
# activity log
|
||||
@ -6645,7 +6651,8 @@ class BillModelCreateView(CreateView):
|
||||
for_purchase_order = False
|
||||
for_estimate = False
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
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()
|
||||
|
||||
@ -6658,7 +6665,7 @@ class BillModelCreateView(CreateView):
|
||||
)
|
||||
if not estimate_model.can_bind():
|
||||
return HttpResponseNotFound("404 Not Found")
|
||||
return super(BillModelCreateView, self).get(request, **kwargs)
|
||||
return super(BillModelCreateView, self).get(request,dealer_slug, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(BillModelCreateView, self).get_context_data(**kwargs)
|
||||
@ -6687,6 +6694,7 @@ class BillModelCreateView(CreateView):
|
||||
reverse(
|
||||
"bill-create-po",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs["dealer_slug"],
|
||||
"entity_slug": self.kwargs["entity_slug"],
|
||||
"po_pk": po_model.uuid,
|
||||
},
|
||||
@ -6704,6 +6712,7 @@ class BillModelCreateView(CreateView):
|
||||
form_action = reverse(
|
||||
"bill-create-estimate",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs["dealer_slug"],
|
||||
"entity_slug": self.kwargs["entity_slug"],
|
||||
"ce_pk": estimate_model.uuid,
|
||||
},
|
||||
@ -6712,6 +6721,7 @@ class BillModelCreateView(CreateView):
|
||||
form_action = reverse(
|
||||
"bill-create",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs["dealer_slug"],
|
||||
"entity_slug": self.kwargs["entity_slug"],
|
||||
},
|
||||
)
|
||||
@ -6787,28 +6797,33 @@ class BillModelCreateView(CreateView):
|
||||
po_pk = self.kwargs["po_pk"]
|
||||
return reverse(
|
||||
"purchase_order_update",
|
||||
kwargs={"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={"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={"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},
|
||||
)
|
||||
|
||||
|
||||
class BillModelDetailViewView(BillModelDetailView):
|
||||
template_name = "bill/bill_detail.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(BillModelDetailViewView, self).get_context_data(**kwargs)
|
||||
context["dealer"] = self.request.dealer
|
||||
return context
|
||||
|
||||
|
||||
class BillModelUpdateViewView(BillModelUpdateView):
|
||||
template_name = "bill/bill_update.html"
|
||||
|
||||
def post(self, request, *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()
|
||||
@ -6865,6 +6880,7 @@ class BillModelUpdateViewView(BillModelUpdateView):
|
||||
redirect_to=reverse(
|
||||
"bill-update",
|
||||
kwargs={
|
||||
"dealer_slug": dealer_slug,
|
||||
"entity_slug": entity_model.slug,
|
||||
"bill_pk": bill_pk,
|
||||
},
|
||||
@ -6872,12 +6888,13 @@ 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, **kwargs)
|
||||
return super(BillModelUpdateViewView, self).post(request,dealer_slug,entity_slug,bill_pk, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse(
|
||||
"bill-update",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs["dealer_slug"],
|
||||
"entity_slug": self.kwargs["entity_slug"],
|
||||
"bill_pk": self.kwargs["bill_pk"],
|
||||
},
|
||||
@ -7074,7 +7091,7 @@ class OrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
# email
|
||||
@login_required
|
||||
@permission_required("django_ledger.view_estimatemodel", raise_exception=True)
|
||||
def send_email_view(request, 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.
|
||||
@ -7090,15 +7107,15 @@ def send_email_view(request, pk):
|
||||
:rtype: HttpResponseRedirect
|
||||
:raises Http404: If the estimate with the given primary key does not exist.
|
||||
"""
|
||||
dealer = get_user_type(request)
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
||||
|
||||
if not estimate.get_itemtxs_data()[0]:
|
||||
messages.error(request, _("Quotation has no items"))
|
||||
return redirect("estimate_detail", pk=estimate.pk)
|
||||
return redirect("estimate_detail", dealer_slug=dealer_slug,pk=estimate.pk)
|
||||
|
||||
link = request.build_absolute_uri(
|
||||
reverse_lazy("estimate_preview", kwargs={"pk": estimate.pk})
|
||||
reverse_lazy("estimate_preview", kwargs={"dealer_slug":dealer_slug,"pk": estimate.pk})
|
||||
)
|
||||
|
||||
msg = f"""
|
||||
@ -7135,7 +7152,7 @@ def send_email_view(request, pk):
|
||||
estimate.mark_as_review()
|
||||
messages.success(request, _("Email sent successfully"))
|
||||
|
||||
return redirect("estimate_detail", pk=estimate.pk)
|
||||
return redirect("estimate_detail", dealer_slug=dealer.slug,pk=estimate.pk)
|
||||
|
||||
|
||||
# errors
|
||||
@ -9041,15 +9058,15 @@ def permenant_delete_account(request, content_type, slug):
|
||||
#####################################################################
|
||||
|
||||
|
||||
def PurchaseOrderCreateView(request):
|
||||
dealer = get_user_type(request)
|
||||
def PurchaseOrderCreateView(request, dealer_slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
entity = dealer.entity
|
||||
if request.method == "POST":
|
||||
po = entity.create_purchase_order(po_title=request.POST.get("po_title"))
|
||||
po.entity = entity
|
||||
po.save()
|
||||
messages.success(request, _("Purchase order created successfully"))
|
||||
return redirect("purchase_order_detail", pk=po.pk)
|
||||
return redirect("purchase_order_detail", dealer_slug=dealer.slug, pk=po.pk)
|
||||
|
||||
form = PurchaseOrderModelCreateForm(
|
||||
entity_slug=entity.slug, user_model=entity.admin
|
||||
@ -9057,9 +9074,9 @@ def PurchaseOrderCreateView(request):
|
||||
return render(request, "purchase_orders/po_form.html", {"form": form})
|
||||
|
||||
|
||||
def InventoryItemCreateView(request):
|
||||
def InventoryItemCreateView(request,dealer_slug):
|
||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
for_po = request.GET.get("for_po")
|
||||
dealer = get_user_type(request)
|
||||
entity = dealer.entity
|
||||
coa = entity.get_default_coa()
|
||||
|
||||
@ -9098,7 +9115,7 @@ def InventoryItemCreateView(request):
|
||||
.first()
|
||||
):
|
||||
messages.error(request, _("Inventory item already exists"))
|
||||
return redirect(f"{reverse('inventory_item_create')}?for_po={for_po}")
|
||||
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,
|
||||
@ -9108,9 +9125,10 @@ def InventoryItemCreateView(request):
|
||||
coa_model=coa,
|
||||
)
|
||||
messages.success(request, _("Inventory item created successfully"))
|
||||
return redirect("purchase_order_list")
|
||||
return redirect("purchase_order_list", dealer_slug=dealer.slug)
|
||||
if for_po:
|
||||
form = forms.CSVUploadForm()
|
||||
form.fields["vendor"].queryset = dealer.vendors.filter(active=True)
|
||||
context = {
|
||||
"make_data": models.CarMake.objects.all(),
|
||||
"inventory_accounts": inventory_accounts,
|
||||
@ -9129,8 +9147,8 @@ def InventoryItemCreateView(request):
|
||||
)
|
||||
|
||||
|
||||
def inventory_items_filter(request):
|
||||
dealer = get_user_type(request)
|
||||
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")
|
||||
serie = request.GET.get("serie")
|
||||
@ -9175,38 +9193,6 @@ class PurchaseOrderDetailView(PurchaseOrderModelDetailViewBase):
|
||||
return context
|
||||
|
||||
|
||||
# def PurchaseOrderDetailView(request, pk):
|
||||
# po = get_object_or_404(PurchaseOrderModel, pk=pk)
|
||||
# dealer = get_user_type(request)
|
||||
|
||||
# make = request.GET.get('make')
|
||||
# model = request.GET.get('model')
|
||||
# serie = request.GET.get('serie')
|
||||
# make_data = models.CarMake.objects.all()
|
||||
# model_data = models.CarModel.objects.none()
|
||||
# serie_data = models.CarSerie.objects.none()
|
||||
# trim_data = models.CarTrim.objects.none()
|
||||
# if make:
|
||||
# make = models.CarMake.objects.get(pk=make)
|
||||
# model_data = make.carmodel_set.all()
|
||||
# elif model:
|
||||
# model = models.CarModel.objects.get(pk=model)
|
||||
# serie_data = model.carserie_set.all()
|
||||
# elif serie:
|
||||
# serie = models.CarSerie.objects.get(pk=serie)
|
||||
# trim_data = serie.cartrim_set.all()
|
||||
# context = {
|
||||
# 'make_data': make_data,
|
||||
# 'model_data': model_data,
|
||||
# 'serie_data': serie_data,
|
||||
# 'trim_data': trim_data,
|
||||
# 'po': po,
|
||||
# 'inventory_accounts': dealer.entity.get_coa_accounts().filter(role="asset_ca_inv"),
|
||||
# 'inventory_items': dealer.entity.get_items_inventory(),
|
||||
# }
|
||||
# return render(request, "purchase_orders/po_detail.html", context)
|
||||
|
||||
|
||||
class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
model = PurchaseOrderModel
|
||||
context_object_name = "purchase_orders"
|
||||
@ -9231,15 +9217,10 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
||||
context_object_name = "po_model"
|
||||
|
||||
def get_context_data(self, itemtxs_formset=None, **kwargs):
|
||||
dealer = get_user_type(self.request)
|
||||
dealer = self.request.dealer
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["entity_slug"] = dealer.entity.slug
|
||||
po_model: PurchaseOrderModel = self.object
|
||||
# context["make_data"] = models.CarMake.objects.all()
|
||||
# context["model_data"] = models.CarModel.objects.none()
|
||||
# context["serie_data"] = models.CarSerie.objects.none()
|
||||
# context["trim_data"] = models.CarTrim.objects.none()
|
||||
# itemtxs_qs = dealer.entity.get_items_inventory().filter(item_role="inventory")
|
||||
if not itemtxs_formset:
|
||||
itemtxs_qs = self.get_po_itemtxs_qs(po_model)
|
||||
itemtxs_qs, itemtxs_agg = po_model.get_itemtxs_data(queryset=itemtxs_qs)
|
||||
@ -9261,36 +9242,35 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
||||
return reverse(
|
||||
"purchase_order_update",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs["dealer_slug"],
|
||||
"entity_slug": self.kwargs["entity_slug"],
|
||||
"po_pk": self.kwargs["po_pk"],
|
||||
},
|
||||
)
|
||||
|
||||
def get(self, request, entity_slug, po_pk, *args, **kwargs):
|
||||
def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs):
|
||||
if self.action_update_items:
|
||||
return HttpResponseRedirect(
|
||||
redirect_to=reverse(
|
||||
"purchase_order_update",
|
||||
kwargs={"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(
|
||||
request, entity_slug, po_pk, *args, **kwargs
|
||||
request, dealer_slug, entity_slug, po_pk, *args, **kwargs
|
||||
)
|
||||
|
||||
def post(self, request, entity_slug, *args, **kwargs):
|
||||
dealer = get_user_type(self.request)
|
||||
def post(self, request, dealer_slug, entity_slug, *args, **kwargs):
|
||||
if self.action_update_items:
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponseForbidden()
|
||||
|
||||
queryset = self.get_queryset()
|
||||
po_model: PurchaseOrderModel = self.get_object(queryset=queryset)
|
||||
self.object = po_model
|
||||
po_itemtxs_formset_class = get_po_itemtxs_formset_class(po_model)
|
||||
itemtxs_formset = po_itemtxs_formset_class(
|
||||
request.POST,
|
||||
user_model=dealer.entity.admin,
|
||||
user_model=request.dealer.entity.admin,
|
||||
po_model=po_model,
|
||||
entity_slug=entity_slug,
|
||||
)
|
||||
@ -9309,6 +9289,7 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
||||
redirect_url = reverse(
|
||||
"bill-create-po",
|
||||
kwargs={
|
||||
"dealer_slug": self.kwargs["dealer_slug"],
|
||||
"entity_slug": self.kwargs["entity_slug"],
|
||||
"po_pk": po_model.uuid,
|
||||
},
|
||||
@ -9337,7 +9318,7 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
||||
context=self.get_context_data(itemtxs_formset=itemtxs_formset)
|
||||
)
|
||||
return super(PurchaseOrderUpdateView, self).post(
|
||||
request, entity_slug, *args, **kwargs
|
||||
request,dealer_slug, entity_slug, *args, **kwargs
|
||||
)
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
@ -9368,19 +9349,19 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
||||
|
||||
|
||||
class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase):
|
||||
def get_redirect_url(self, 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={"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, *args, **kwargs):
|
||||
def get(self, request,dealer_slug, entity_slug, po_pk, *args, **kwargs):
|
||||
# kwargs["user_model"] = self.request.user
|
||||
dealer = get_user_type(request)
|
||||
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, *args, **kwargs
|
||||
request,dealer_slug,entity_slug,po_pk, *args, **kwargs
|
||||
)
|
||||
po_model: PurchaseOrderModel = self.get_object()
|
||||
|
||||
@ -9393,11 +9374,6 @@ class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase):
|
||||
)
|
||||
except ValidationError as e:
|
||||
print(e)
|
||||
# messages.add_message(
|
||||
# request,
|
||||
# message=e.message,
|
||||
# level=messages.ERROR,
|
||||
# )
|
||||
return response
|
||||
|
||||
|
||||
@ -9405,7 +9381,12 @@ class PurchaseOrderModelDeleteView(PurchaseOrderModelDeleteViewBase):
|
||||
template_name = "purchase_orders/po_delete.html"
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("purchase_order_list")
|
||||
messages.add_message(
|
||||
self.request,
|
||||
message="PO deleted successfully.",
|
||||
level=messages.SUCCESS,
|
||||
)
|
||||
return reverse("purchase_order_list", kwargs={"dealer_slug": self.kwargs["dealer_slug"]})
|
||||
|
||||
|
||||
class PurchaseOrderMarkAsDraftView(BasePurchaseOrderActionActionView):
|
||||
@ -9434,9 +9415,9 @@ class PurchaseOrderMarkAsVoidView(BasePurchaseOrderActionActionView):
|
||||
|
||||
##############################bil
|
||||
class BaseBillActionView(BaseBillActionViewBase):
|
||||
def get_redirect_url(self, entity_slug, bill_pk, *args, **kwargs):
|
||||
def get_redirect_url(self,dealer_slug, entity_slug, bill_pk, *args, **kwargs):
|
||||
return reverse(
|
||||
"bill-update", kwargs={"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}
|
||||
)
|
||||
|
||||
|
||||
@ -9484,8 +9465,8 @@ class BillModelActionForceMigrateView(BaseBillActionView):
|
||||
###############################################################
|
||||
|
||||
|
||||
def view_items_inventory(request, entity_slug, po_pk):
|
||||
dealer = get_user_type(request)
|
||||
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
|
||||
@ -9505,17 +9486,17 @@ def view_items_inventory(request, entity_slug, po_pk):
|
||||
)
|
||||
|
||||
|
||||
def upload_cars(request, pk=None):
|
||||
def upload_cars(request,dealer_slug, pk=None):
|
||||
item = None
|
||||
dealer = get_user_type(request)
|
||||
response = redirect("upload_cars")
|
||||
dealer = get_object_or_404(models.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", 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", entity_slug=dealer.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":
|
||||
@ -9560,7 +9541,7 @@ def upload_cars(request, pk=None):
|
||||
|
||||
if not csv_file.name.endswith(".csv"):
|
||||
messages.error(request, "Please upload a CSV file")
|
||||
return redirect("upload_cars")
|
||||
return redirect("upload_cars",dealer_slug=dealer_slug)
|
||||
try:
|
||||
# Read the file content
|
||||
file_content = csv_file.read().decode("utf-8")
|
||||
|
||||
@ -42,11 +42,11 @@
|
||||
<div class="col-lg-4">
|
||||
<div class="card shadow-sm" >
|
||||
<div class="card-body">
|
||||
{% include 'bill/includes/card_bill.html' with bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %}
|
||||
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %}
|
||||
<hr class="my-4">
|
||||
{% include 'bill/includes/card_vendor.html' with vendor=bill.vendor %}
|
||||
<div class="d-grid mt-4">
|
||||
<a href="{% url 'bill_list' %}"
|
||||
<a href="{% url 'bill_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-primary">
|
||||
<i class="fas fa-arrow-left me-1"></i> {% trans 'Bill List' %}
|
||||
</a>
|
||||
@ -65,7 +65,7 @@
|
||||
<div class="border rounded p-3">
|
||||
<h6 class="text-uppercase text-xs text-muted mb-2">
|
||||
{% trans 'Cash Account' %}:
|
||||
<a href="{% url 'account_detail' bill.cash_account.uuid %}"
|
||||
<a href="{% url 'account_detail' request.dealer.slug bill.cash_account.uuid %}"
|
||||
class="text-decoration-none ms-1">
|
||||
{{ bill.cash_account.code }}
|
||||
</a>
|
||||
@ -80,7 +80,7 @@
|
||||
<div class="border rounded p-3">
|
||||
<h6 class="text-uppercase text-xs text-muted mb-2">
|
||||
{% trans 'Prepaid Account' %}:
|
||||
<a href="{% url 'account_detail' bill.prepaid_account.uuid %}"
|
||||
<a href="{% url 'account_detail' request.dealer.slug bill.prepaid_account.uuid %}"
|
||||
class="text-decoration-none ms-1">
|
||||
{{ bill.prepaid_account.code }}
|
||||
</a>
|
||||
@ -94,7 +94,7 @@
|
||||
<div class="border rounded p-3">
|
||||
<h6 class="text-uppercase text-xs text-muted mb-2">
|
||||
{% trans 'Accounts Payable' %}:
|
||||
<a href="{% url 'account_detail' bill.unearned_account.uuid %}"
|
||||
<a href="{% url 'account_detail' request.dealer.slug bill.unearned_account.uuid %}"
|
||||
class="text-decoration-none ms-1">
|
||||
{{ bill.unearned_account.code }}
|
||||
</a>
|
||||
@ -185,7 +185,7 @@
|
||||
<td class="align-items-start white-space-nowrap pe-2">
|
||||
{% if bill_item.po_model_id %}
|
||||
<a class="btn btn-sm btn-phoenix-primary"
|
||||
href="{% url 'purchase_order_detail' bill_item.po_model_id %}">
|
||||
href="{% url 'purchase_order_detail' request.dealer.slug bill_item.po_model_id %}">
|
||||
{% trans 'View PO' %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
@ -17,9 +17,9 @@
|
||||
<div class="col-12">
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
{% include 'bill/includes/card_bill.html' with bill=bill_model style='bill-detail' entity_slug=view.kwargs.entity_slug %}
|
||||
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill_model style='bill-detail' entity_slug=view.kwargs.entity_slug %}
|
||||
|
||||
<form action="{% url 'bill-update' entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}" method="post">
|
||||
<form action="{% url 'bill-update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="mb-3">
|
||||
@ -30,12 +30,12 @@
|
||||
<i class="fas fa-save me-2"></i>{% trans 'Save Bill' %}
|
||||
</button>
|
||||
|
||||
<a href="{% url 'bill-detail' entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}"
|
||||
<a href="{% url 'bill-detail' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}"
|
||||
class="btn btn-phoenix-secondary w-100 mb-2">
|
||||
<i class="fas fa-arrow-left me-2"></i>{% trans 'Back to Bill Detail' %}
|
||||
</a>
|
||||
|
||||
<a href="{% url 'bill_list' %}"
|
||||
<a href="{% url 'bill_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-info w-100 mb-2">
|
||||
<i class="fas fa-list me-2"></i>{% trans 'Bill List' %}
|
||||
</a>
|
||||
|
||||
@ -201,48 +201,48 @@
|
||||
<div class="card-footer p-0">
|
||||
<div class="d-flex flex-wrap gap-2 mt-2">
|
||||
<!-- Update Button -->
|
||||
<a href="{% url 'bill-update' entity_slug=entity_slug bill_pk=bill.uuid %}" class="btn btn-phoenix-primary">
|
||||
<a href="{% url 'bill-update' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill.uuid %}" class="btn btn-phoenix-primary">
|
||||
<i class="fas fa-edit me-2"></i>{% trans 'Update' %}
|
||||
</a>
|
||||
<!-- Mark as Draft -->
|
||||
{% if bill.can_draft %}
|
||||
<button class="btn btn-phoenix-success"
|
||||
onclick="showPOModal('Mark as Draft', '{% url 'bill-action-mark-as-draft' entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Draft')">
|
||||
onclick="showPOModal('Mark as Draft', '{% url 'bill-action-mark-as-draft' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Draft')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Draft' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
<!-- Mark as Review -->
|
||||
{% if bill.can_review %}
|
||||
<button class="btn btn-phoenix-warning"
|
||||
onclick="showPOModal('Mark as Review', '{% url 'bill-action-mark-as-review' entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Review')">
|
||||
onclick="showPOModal('Mark as Review', '{% url 'bill-action-mark-as-review' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Review')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Review' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
<!-- Mark as Approved -->
|
||||
{% if bill.can_approve %}
|
||||
<button class="btn btn-phoenix-success"
|
||||
onclick="showPOModal('Mark as Approved', '{% url 'bill-action-mark-as-approved' entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Approved')">
|
||||
onclick="showPOModal('Mark as Approved', '{% url 'bill-action-mark-as-approved' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Approved')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Approved' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
<!-- Mark as Paid -->
|
||||
{% if bill.can_pay %}
|
||||
<button class="btn btn-phoenix-success"
|
||||
onclick="showPOModal('Mark as Paid', '{% url 'bill-action-mark-as-paid' entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Paid')">
|
||||
onclick="showPOModal('Mark as Paid', '{% url 'bill-action-mark-as-paid' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Paid')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Paid' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
<!-- Void Button -->
|
||||
{% if bill.can_void %}
|
||||
<button class="btn btn-phoenix-danger"
|
||||
onclick="showPOModal('Mark as Void', '{% url 'bill-action-mark-as-void' entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Void')">
|
||||
onclick="showPOModal('Mark as Void', '{% url 'bill-action-mark-as-void' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Void')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Void' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
<!-- Cancel Button -->
|
||||
{% if bill.can_cancel %}
|
||||
<button class="btn btn-phoenix-danger"
|
||||
onclick="showPOModal('Mark as Canceled', '{% url 'bill-action-mark-as-canceled' entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Canceled')">
|
||||
onclick="showPOModal('Mark as Canceled', '{% url 'bill-action-mark-as-canceled' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Canceled')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Canceled' %}
|
||||
</button>
|
||||
{% modal_action_v2 bill bill.get_mark_as_canceled_url bill.get_mark_as_canceled_message bill.get_mark_as_canceled_html_id %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{% load django_ledger %}
|
||||
{% load widget_tweaks %}
|
||||
|
||||
<form action="{% url 'bill-update-items' entity_slug=entity_slug bill_pk=bill_pk %}" method="post">
|
||||
<form action="{% url 'bill-update-items' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill_pk %}" method="post">
|
||||
<div class="container-fluid py-4">
|
||||
<!-- Page Header -->
|
||||
<div class="row mb-4">
|
||||
@ -72,7 +72,7 @@
|
||||
{% currency_symbol %}{{ f.instance.po_total_amount | currency_format }}
|
||||
</span>
|
||||
<a class="btn btn-sm btn-phoenix-info mt-1"
|
||||
href="{% url 'purchase_order_detail' f.instance.po_model_id %}">
|
||||
href="{% url 'purchase_order_detail' dealer_slug f.instance.po_model_id %}">
|
||||
{% trans 'View PO' %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 ">
|
||||
<span class="uil fs-5 lh-1 uil-bill text-info"></span>
|
||||
<a href="{% url 'invoice_list' %}"><h4 class="fs-6 pt-3">{{ invoices }}</h4></a>
|
||||
<a href="{% url 'invoice_list' request.dealer.slug %}"><h4 class="fs-6 pt-3">{{ invoices }}</h4></a>
|
||||
<p class="fs-9 mb-0">{{ _("Invoices")}}</p>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end border-bottom pb-4 pb-xxl-0 ">
|
||||
|
||||
@ -43,6 +43,6 @@
|
||||
<div class="error-page">
|
||||
<h1 class="error-code">{% trans "400" %}</h1>
|
||||
<p class="error-message">{% trans "Bad Request" %}</p>
|
||||
<a href="{% url 'inventory_stats' %}" class="error-button">{% trans "Go Back" %}</a>
|
||||
<a href="{% url 'inventory_stats' request.dealer.slug %}" class="error-button">{% trans "Go Back" %}</a>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@ -22,44 +22,44 @@
|
||||
<li class="collapsed-nav-item-title d-none">{% trans "Inventory"|capfirst %}</li>
|
||||
{% if perms.inventory.add_car %}
|
||||
<li class="nav-item">
|
||||
<a id="btn-add-car" class="nav-link btn-add-car" href="{% url 'car_add' %}">
|
||||
<a id="btn-add-car" class="nav-link btn-add-car" href="{% url 'car_add' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-plus-circle"></span></span><span class="nav-link-text">{% trans "add car"|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'inventory_item_create' %}">
|
||||
<a class="nav-link" href="{% url 'inventory_item_create' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-plus-circle"></span></span><span class="nav-link-text">{% trans "add invenotry item"|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'purchase_order_list' %}">
|
||||
<a class="nav-link" href="{% url 'purchase_order_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-warehouse"></span></span><span class="nav-link-text">{% trans "purchase Orders"|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'upload_cars' %}">
|
||||
<a class="nav-link" href="{% url 'upload_cars' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-file-invoice"></span></span><span class="nav-link-text">{% trans "Upload Cars"|capfirst %}</span>
|
||||
<span class="nav-link-icon"><span class="fas fa-file-import"></span></span><span class="nav-link-text">{% trans "Bulk Upload"|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
|
||||
<a class="nav-link" href="{% url 'inventory_stats' %}">
|
||||
<a class="nav-link" href="{% url 'inventory_stats' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-car-side"></span></span><span class="nav-link-text">{% trans 'Cars'|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'car_list' %}">
|
||||
<a class="nav-link" href="{% url 'car_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-car-side"></span></span><span class="nav-link-text">{% trans 'Stock'|capfirst %}</span>
|
||||
</div>
|
||||
@ -82,7 +82,7 @@
|
||||
<li class="collapsed-nav-item-title d-none">{% trans 'sales'|capfirst %}</li>
|
||||
{% if perms.django_ledger.add_estimatemodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'estimate_create' %}">
|
||||
<a class="nav-link" href="{% url 'estimate_create' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-list-ul"></span></span><span class="nav-link-text">{% trans "create quotation"|capfirst %}</span>
|
||||
</div>
|
||||
@ -91,7 +91,7 @@
|
||||
{% endif %}
|
||||
{% if perms.django_ledger.view_estimatemodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'estimate_list' %}">
|
||||
<a class="nav-link" href="{% url 'estimate_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-clipboard-list"></span></span><span class="nav-link-text">{% trans "quotations"|capfirst %}</span>
|
||||
</div>
|
||||
@ -101,7 +101,7 @@
|
||||
|
||||
{% if perms.django_ledger.view_invoicemodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'invoice_list' %}">
|
||||
<a class="nav-link" href="{% url 'invoice_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-file-invoice"></span></span><span class="nav-link-text">{% trans "invoices"|capfirst %}</span>
|
||||
</div>
|
||||
@ -110,7 +110,7 @@
|
||||
{% endif %}
|
||||
{% if perms.django_ledger.view_journalentrymodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'payment_list' %}">
|
||||
<a class="nav-link" href="{% url 'payment_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-money-check"></span></span><span class="nav-link-text">{% trans "payments"|capfirst %}</span>
|
||||
</div>
|
||||
@ -212,7 +212,7 @@
|
||||
<li class="collapsed-nav-item-title d-none">{% trans 'Financials' %}</li>
|
||||
{% if perms.django_ledger.view_accountmodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'account_list' %}">
|
||||
<a class="nav-link" href="{% url 'account_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-book-open"></span></span><span class="nav-link-text">{% trans 'Chart of Accounts'|capfirst %}</span>
|
||||
</div>
|
||||
@ -221,7 +221,7 @@
|
||||
{% endif %}
|
||||
{% if perms.django_ledger.view_bankaccountmodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'bank_account_list' %}">
|
||||
<a class="nav-link" href="{% url 'bank_account_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span data-feather="credit-card"></span></span><span class="nav-link-text">{% trans 'Bank Accounts'|capfirst %}</span>
|
||||
</div>
|
||||
@ -264,7 +264,7 @@
|
||||
{% endif %}
|
||||
{% if perms.django_ledger.view_billmodel %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'bill_list' %}">
|
||||
<a class="nav-link" href="{% url 'bill_list' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fa-solid fa-money-bills"></span></span><span class="nav-link-text">{% trans 'bills'|capfirst %}</span>
|
||||
</div>
|
||||
@ -362,7 +362,7 @@
|
||||
aria-label="Toggle Navigation">
|
||||
<span class="navbar-toggle-icon"><span class="toggle-line"></span></span>
|
||||
</button>
|
||||
<a class="navbar-brand me-1 me-sm-3" href="{% url 'home' %}">
|
||||
<a class="navbar-brand me-1 me-sm-3" href="{% url 'home' request.dealer.slug %}">
|
||||
<div class="d-flex align-items-center">
|
||||
<img class="logo-img d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="haikal" width="27" />
|
||||
<img class="logo-img d-light-none" src="{% static 'images/logos/logo.png' %}" alt="haikal" width="27" />
|
||||
|
||||
@ -15,5 +15,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
@ -2,7 +2,7 @@
|
||||
{% load crispy_forms_filters %}
|
||||
<form method="post"
|
||||
id="customCardForm"
|
||||
action="{% url 'add_custom_card' car.slug %}">
|
||||
action="{% url 'add_custom_card' request.dealer.slug car.slug %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<div class="d-flex gap-1">
|
||||
|
||||
@ -163,10 +163,14 @@
|
||||
<tr>
|
||||
<th>{% trans "Custom Card" %}</th>
|
||||
<td>
|
||||
<button type="button"
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-phoenix-success"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#customCardModal">{% trans 'Add' %}</button>
|
||||
data-bs-target="#mainModal"
|
||||
hx-get="{% url 'add_custom_card' request.dealer.slug car.slug %}"
|
||||
hx-target=".main-modal-body"
|
||||
hx-swap="innerHTML"
|
||||
>{% trans 'Add' %}</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
@ -188,7 +192,12 @@
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-phoenix-success"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#registrationModal">{% trans 'Add' %}</button>
|
||||
data-bs-target="#mainModal"
|
||||
hx-get="{% url 'add_registration' request.dealer.slug car.slug %}"
|
||||
hx-target=".main-modal-body"
|
||||
hx-swap="innerHTML"
|
||||
>{% trans 'Add' %}</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
@ -219,7 +228,7 @@
|
||||
<div>
|
||||
{% if not car.get_transfer %}
|
||||
{% if perms.inventory.change_car %}
|
||||
<a href="{% url 'car_update' car.slug %}"
|
||||
<a href="{% url 'car_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-warning btn-sm mt-1">{% trans "Edit" %}</a>
|
||||
<a href="{% url 'transfer' car.slug %}"
|
||||
class="btn btn-phoenix-danger btn-sm">
|
||||
@ -277,7 +286,7 @@
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if not car.get_transfer %}
|
||||
<a href="{% url 'car_finance_update' car.finances.pk %}"
|
||||
<a href="{% url 'car_finance_update' request.dealer.slug car.finances.pk %}"
|
||||
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
|
||||
@ -285,7 +294,7 @@
|
||||
{% else %}
|
||||
<p>{% trans "No finance details available." %}</p>
|
||||
{% if perms.inventory.add_carfinance %}
|
||||
<a href="{% url 'car_finance_create' car.slug %}"
|
||||
<a href="{% url 'car_finance_create' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-success btn-sm mb-3">{% trans "Add" %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
@ -327,7 +336,7 @@
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if not car.get_transfer %}
|
||||
<a href="{% url 'car_colors_update' car.slug %}"
|
||||
<a href="{% url 'car_colors_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
|
||||
@ -340,7 +349,7 @@
|
||||
<td colspan="2">
|
||||
<p>{% trans "No color details available." %}</p>
|
||||
{% if perms.inventory.add_carcolors %}
|
||||
<a class="btn btn-phoenix-success btn-sm mb-3" href="{% url 'add_color' car.slug %}">{{ _("Add Color") }}</a>
|
||||
<a class="btn btn-phoenix-success btn-sm mb-3" href="{% url 'add_color' request.dealer.slug car.slug %}">{{ _("Add Color") }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
@ -372,7 +381,7 @@
|
||||
<td>{{ reservation.reserved_until }}</td>
|
||||
<td>
|
||||
{% if reservation.is_active %}
|
||||
<form method="post" action="{% url 'reservations' reservation.id %}">
|
||||
<form method="post" action="{% url 'reservations' request.dealer.slug reservation.id %}">
|
||||
{% csrf_token %}
|
||||
<div class="btn-group">
|
||||
<button type="submit"
|
||||
@ -495,22 +504,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Registration Modal -->
|
||||
<!-- Main Modal -->
|
||||
<div class="modal fade"
|
||||
id="registrationModal"
|
||||
id="mainModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="registrationModalLabel"
|
||||
aria-labelledby="mainModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="registrationModalLabel">{% trans 'Registration' %}</h5>
|
||||
<h5 class="modal-title" id="mainModalLabel">{% trans 'Registration' %}</h5>
|
||||
<button type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="main-modal-body" style="padding: 20px;">
|
||||
<!-- Content will be loaded here via AJAX -->
|
||||
</div>
|
||||
</div>
|
||||
@ -532,7 +541,7 @@
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">{% trans 'Are you sure you want to reserve this car?' %}</div>
|
||||
<form method="POST" action="{% url 'reserve_car' car.slug %}" class="form ">
|
||||
<form method="POST" action="{% url 'reserve_car' request.dealer.slug car.slug %}" class="form">
|
||||
{% csrf_token %}
|
||||
<div class="p-1">
|
||||
<div class="d-flex gap-1">
|
||||
@ -577,52 +586,11 @@
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const csrftoken = getCookie("csrftoken");
|
||||
const ajaxUrl = "{% url 'ajax_handler' %}";
|
||||
const ajaxUrl = "{% url 'ajax_handler' request.dealer.slug %}";
|
||||
|
||||
|
||||
const customCardModal = document.getElementById("customCardModal");
|
||||
const modalBody = customCardModal.querySelector(".modal-body");
|
||||
|
||||
// When the modal is triggered, load the form
|
||||
customCardModal.addEventListener("show.bs.modal", function () {
|
||||
const url = "{% url 'add_custom_card' car.slug %}";
|
||||
|
||||
fetch(url)
|
||||
.then((response) => response.text())
|
||||
.then((html) => {
|
||||
modalBody.innerHTML = html;
|
||||
})
|
||||
.catch((error) => {
|
||||
modalBody.innerHTML = '<p class="text-danger">Error loading form. Please try again later.</p>';
|
||||
console.error("Error loading form:", error);
|
||||
});
|
||||
});
|
||||
|
||||
customCardModal.addEventListener("hidden.bs.modal", function () {
|
||||
modalBody.innerHTML = "";
|
||||
});
|
||||
|
||||
const registrationModal = document.getElementById("registrationModal");
|
||||
const modalBody_r = registrationModal.querySelector(".modal-body");
|
||||
|
||||
// When the modal is triggered, load the form
|
||||
registrationModal.addEventListener("show.bs.modal", function () {
|
||||
const url = "{% url 'add_registration' car.slug %}";
|
||||
|
||||
fetch(url)
|
||||
.then((response) => response.text())
|
||||
.then((html) => {
|
||||
modalBody_r.innerHTML = html;
|
||||
})
|
||||
.catch((error) => {
|
||||
modalBody_r.innerHTML = '<p class="text-danger">{{_("Error loading form. Please try again later")}}.</p>';
|
||||
console.error("Error loading form:", error);
|
||||
});
|
||||
});
|
||||
|
||||
registrationModal.addEventListener("hidden.bs.modal", function () {
|
||||
modalBody_r.innerHTML = "";
|
||||
});
|
||||
|
||||
const showSpecificationButton = document.getElementById("specification-btn");
|
||||
const specificationsContent = document.getElementById("specificationsContent");
|
||||
|
||||
@ -689,7 +657,7 @@
|
||||
document.querySelectorAll(".reserve-btn").forEach((button) => {
|
||||
button.addEventListener("click", async function () {
|
||||
try {
|
||||
const response = await fetch(`{% url 'reserve_car' car.slug %}`, {
|
||||
const response = await fetch(`{% url 'reserve_car' request.dealer.slug car.slug %}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRFToken": csrfToken,
|
||||
|
||||
@ -29,13 +29,6 @@
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
</div>
|
||||
{% comment %} <div class="row g-1">
|
||||
<div class="btn-group">
|
||||
<button type="submit" class="btn btn-sm btn-success me-1"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
</div> {% endcomment %}
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="btn btn-sm btn-phoenix-success me-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
|
||||
@ -346,7 +346,7 @@
|
||||
const optionsContent = document.getElementById("optionsContent")
|
||||
const generationContainer = document.getElementById("generation-div")
|
||||
|
||||
const ajaxUrl = "{% url 'ajax_handler' %}";
|
||||
const ajaxUrl = "{% url 'ajax_handler' request.dealer.slug %}";
|
||||
|
||||
const closeButton = document.querySelector(".btn-close");
|
||||
const scanVinBtn = document.getElementById("scan-vin-btn");
|
||||
|
||||
@ -330,7 +330,7 @@
|
||||
const optionsContent = document.getElementById("optionsContent")
|
||||
const generationContainer = document.getElementById("generation-div")
|
||||
|
||||
const ajaxUrl = "{% url 'ajax_handler' %}";
|
||||
const ajaxUrl = "{% url 'ajax_handler' request.dealer.slug %}";
|
||||
|
||||
const closeButton = document.querySelector(".btn-close");
|
||||
const scanVinBtn = document.getElementById("scan-vin-btn");
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-start">
|
||||
<a class="fs-9 fw-bold" href="{% url 'car_detail' car.slug %}">{{ car.vin }}</a>
|
||||
<a class="fs-9 fw-bold" href="{% url 'car_detail' request.dealer.slug car.slug %}">{{ car.vin }}</a>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-center fw-bold">{{ car.year }}</td>
|
||||
{% if car.colors %}
|
||||
@ -147,14 +147,14 @@
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-end pe-0 ps-4">
|
||||
<a class="btn btn-sm btn-phoenix-success"
|
||||
href="{% url 'car_detail' car.slug %}">{% trans "view"|capfirst %}</a>
|
||||
href="{% url 'car_detail' request.dealer.slug car.slug %}">{% trans "view"|capfirst %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="7" class="d-flex flex-column align-items-center">
|
||||
<p class="text-muted">{% trans "No cars available." %}</p>
|
||||
<a href="{% url 'add_car' %}" class="btn btn-phoenix-primary">{% trans "Add a Car" %}</a>
|
||||
<a href="{% url 'add_car' request.dealer.slug %}" class="btn btn-phoenix-primary">{% trans "Add a Car" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@ -44,19 +44,19 @@
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1 active" aria-current="page" href="{% url 'car_list' %}"><span>{{ _("All") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.all }})</span></a>
|
||||
<a class="nav-link px-2 py-1 active" aria-current="page" href="{% url 'car_list' request.dealer.slug %}"><span>{{ _("All") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.all }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=available"><span>{{ _("Available") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.available }})</span></a>
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' request.dealer.slug %}?status=available"><span>{{ _("Available") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.available }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=reserved"><span>{{ _("Reserved") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.reserved }})</span></a>
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' request.dealer.slug %}?status=reserved"><span>{{ _("Reserved") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.reserved }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=transfer"><span>{{ _("Transfer") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.transfer }})</span></a>
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' request.dealer.slug %}?status=transfer"><span>{{ _("Transfer") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.transfer }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=sold"><span>{{ _("Sold") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.sold }})</span></a>
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' request.dealer.slug %}?status=sold"><span>{{ _("Sold") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.sold }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button hx-on:click="toggle_filter()" class="btn btn-sm btn-phoenix-primary px-2 py-1">
|
||||
@ -88,7 +88,7 @@
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-get="{% url 'car_list' request.dealer.slug %}"
|
||||
hx-trigger="keyup changed delay:500ms"
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
@ -106,7 +106,7 @@
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center d-none filter">
|
||||
<select
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-get="{% url 'car_list' request.dealer.slug %}"
|
||||
name="make"
|
||||
hx-target=".model-select"
|
||||
hx-select=".model-select"
|
||||
@ -122,7 +122,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-get="{% url 'car_list' request.dealer.slug %}"
|
||||
hx-include=".make"
|
||||
name="model"
|
||||
hx-target=".year"
|
||||
@ -153,7 +153,7 @@
|
||||
</select>
|
||||
<button
|
||||
id="search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-get="{% url 'car_list' request.dealer.slug %}"
|
||||
hx-include=".make,.model,.year,.car_status"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-target=".table-responsive"
|
||||
@ -177,121 +177,119 @@
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()">
|
||||
</div>
|
||||
<table class="table fs-9 mb-0 border-top border-translucent">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="select-all" />
|
||||
</div>
|
||||
</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("VIN") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col" data-sort="make">{{ _("Make") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col" data-sort="model">{{ _("Model") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col" data-sort="year">{{ _("Year") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Trim") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Color") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Date Received") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col" data-sort="car_status">{{ _("Status") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Inventory Ready") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="project-list-table-body">
|
||||
{% for car in cars %}
|
||||
<tr class="position-static">
|
||||
<td class="align-middle time white-space-nowrap">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input car-checkbox"
|
||||
type="checkbox"
|
||||
name="car"
|
||||
value="{{ car.pk }}"
|
||||
id="car-{{car.pk}}" />
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap assignees">
|
||||
<a class="fw-bold" href="{% url 'car_detail' car.slug %}">{{ car.vin }}</a>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap make">
|
||||
<p class="mb-0 fs-9 text-body">{{ car.id_car_make.get_local_name|default:car.id_car_make.name }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap model">
|
||||
<p class="mb-0 fs-9 text-body">{{ car.id_car_model.get_local_name|default:car.id_car_model.name }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap year">
|
||||
<p class="fw-bo text-body fs-9 mb-0">{{ car.year }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<p class="text-body-secondary fs-10 mb-0">{{ car.id_car_trim }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<div class="d-flex flex-row align-items-center">
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<span class="color-div"
|
||||
style="background: linear-gradient(90deg, rgba({{ car.colors.exterior.rgb }},1) 10%, rgba({{ car.colors.exterior.rgb }},0.10) 100%)"
|
||||
title="{{ car.colors.exterior.get_local_name }}"></span><span>{{ car.colors.exterior.get_local_name }}</span>
|
||||
</div>
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<span class="color-div"
|
||||
style="background: linear-gradient(90deg, rgba({{ car.colors.interior.rgb }},1) 10%, rgba({{ car.colors.interior.rgb }},0.10) 100%)"
|
||||
title="{{ car.colors.interior.get_local_name }}"></span><span>{{ car.colors.interior.get_local_name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<p class="fw-bold text-body mb-0">{{ car.receiving_date|naturalday|capfirst }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap statuses">
|
||||
{% if car.status == "available" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-success">{{ _("Available") }}</span>
|
||||
{% elif car.status == "reserved" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-danger">{{ _("Reserved") }}</span>
|
||||
{% elif car.status == "sold" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-info">{{ _("Sold") }}</span>
|
||||
{% elif car.status == "transfer" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-warning">{{ _("Transfer") }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
{% if not car.ready %}
|
||||
<span class="text-danger"> {{ _("NO") }} </span>
|
||||
{%else%}
|
||||
<span class="text-success"> {{ _("YES") }} </span>
|
||||
{%endif%}
|
||||
</td>
|
||||
<td class="align-middle text-end white-space-nowrap pe-0 action">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a class="dropdown-item" href="{% url 'car_detail' car.slug %}">{{ _("View") }}</a>
|
||||
<a class="dropdown-item" href="#!">{{ _("Export") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<div class="col-12">
|
||||
<div class="text-center py-5">
|
||||
<div class="text-body-secondary">
|
||||
<i class="fas fa-car fa-4x mb-3 opacity-50"></i>
|
||||
<h4 class="text-body-secondary">{{ _("No vehicles found") }}</h4>
|
||||
<p class="text-body-tertiary">{{ _("Try adjusting your search criteria or filters") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
hx-on::after-request="on_after_request()"></div>
|
||||
<div class="w-100 list table-responsive" >
|
||||
<div class="form-check">
|
||||
<input class="form-check-input ms-4" type="checkbox" id="select-all" /> <span class="ms-1 text-body-tertiary">{{ _("Select All") }}</span>
|
||||
</div>
|
||||
{% for car in cars %}
|
||||
<div class="card border mb-3 py-0 px-0" id="project-list-table-body">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input car-checkbox" type="checkbox" name="car" value="{{ car.pk }}" id="car-{{car.pk}}" />
|
||||
</div>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Vehicle Image/Icon -->
|
||||
<div class="col-auto">
|
||||
<div class="avatar avatar-3xl">
|
||||
<img class="rounded-soft shadow shadow-lg" src="{% static 'images/cars/' %}{{ car.vin }}.png" alt="{{ car.vin }}" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- Vehicle Details -->
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<!-- Make/Model/Specs -->
|
||||
<div class="col-md-4">
|
||||
<h5 class="text-body-emphasis fw-bold">{{ car.year }}</h5>
|
||||
<p class="text-body-emphasis fw-bold">
|
||||
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="text-decoration-none text-body-emphasis">
|
||||
{{ car.id_car_make.get_local_name }}
|
||||
</a>
|
||||
<small>{{ car.id_car_model.get_local_name }}</small>
|
||||
</p>
|
||||
<small class="text-body-secondary" dir="ltr">
|
||||
{{ car.id_car_trim }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Color and Date -->
|
||||
<div class="col-md-3">
|
||||
<p class="text-body mb-1">
|
||||
{{ car.colors.exterior.get_local_name }}
|
||||
</p>
|
||||
<small class="text-body-secondary">
|
||||
{{ car.receiving_date|naturalday|capfirst }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Status Badge -->
|
||||
<div class="col-md-3">
|
||||
{% if car.status == "available" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-success text-uppercase px-3 py-2">{{ _("Available") }}</span>
|
||||
{% elif car.status == "reserved" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-warning text-uppercase px-3 py-2">{{ _("Reserved") }}</span>
|
||||
{% elif car.status == "sold" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-danger text-uppercase px-3 py-2">{{ _("Sold") }}</span>
|
||||
{% elif car.status == "transfer" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-info text-uppercase px-3 py-2">{{ _("Transfer") }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Ready Status -->
|
||||
<div class="col-md-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="fs-10 fw-light me-2">{{ _("Inventory Ready") }}</span>
|
||||
{% if car.ready %}
|
||||
<span class="badge bg-success rounded-circle p-1 me-2">
|
||||
<span class="visually-hidden">Ready</span>
|
||||
</span>
|
||||
<span class="text-success fw-bold">{{ _("Yes") }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger rounded-circle p-1 me-2">
|
||||
<span class="visually-hidden">Not Ready</span>
|
||||
</span>
|
||||
<span class="text-danger fw-bold">{{ _("No") }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Menu -->
|
||||
<div class="col-auto">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a class="dropdown-item" href="{% url 'car_detail' request.dealer.slug car.slug %}"> <span class="fas fa-eye me-2"></span>{{ _("View") }} </a>
|
||||
<a class="dropdown-item" href="{% url 'car_update' request.dealer.slug car.slug %}"> <span class="fas fa-edit me-2"></span>{{ _("Edit") }} </a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="{% url 'car_delete' request.dealer.slug car.slug %}"> <span class="fas fa-trash me-2"></span>{{ _("Remove") }} </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="text-center py-5">
|
||||
<div class="text-body-secondary">
|
||||
<span class="fas fa-car fa-4x mb-3 opacity-50"></span>
|
||||
<h4 class="text-body-secondary">{{ _("No vehicles found") }}</h4>
|
||||
<p class="text-body-tertiary">{{ _("Try adjusting your search criteria or filters") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="w-100 g-3">
|
||||
<form method="post"
|
||||
id="registrationForm"
|
||||
action="{% url 'add_registration' car.slug %}">
|
||||
action="{% url 'add_registration' request.dealer.slug car.slug %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<div class="d-flex gap-1">
|
||||
|
||||
@ -67,7 +67,7 @@
|
||||
<ul>
|
||||
{% for trim in model.trims %}
|
||||
<li>
|
||||
<a href="{% url 'car_inventory' make_id=make.slug model_id=model.slug trim_id=trim.slug %}">{{ trim.trim_name }}</a> - {% trans "Total" %}:
|
||||
<a href="{% url 'car_inventory' dealer_slug=request.dealer.slug make_id=make.slug model_id=model.slug trim_id=trim.slug %}">{{ trim.trim_name }}</a> - {% trans "Total" %}:
|
||||
<strong>{{ trim.total_cars }}</strong>
|
||||
</li>
|
||||
{% empty %}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<div class="row mt-4">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<h3 class="">{% trans "Bills" %}</h3>
|
||||
<a href="{% url 'bill-create' entity.slug %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'New Bill' %}</a>
|
||||
<a href="{% url 'bill-create' request.dealer.slug entity.slug %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'New Bill' %}</a>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
@ -81,7 +81,7 @@
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'bill-detail' entity_slug=entity.slug bill_pk=bill.pk %}" class="dropdown-item text-success-dark">{% trans 'View Bill detail' %}</a>
|
||||
<a href="{% url 'bill-detail' dealer_slug=request.dealer.slug entity_slug=entity.slug bill_pk=bill.pk %}" class="dropdown-item text-success-dark">{% trans 'View' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@ -97,13 +97,13 @@
|
||||
</table>
|
||||
</div>
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
|
||||
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
|
||||
|
||||
<div class="d-flex">
|
||||
{% include 'partials/pagination.html'%}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-phoenix-secondary" data-bs-dismiss="modal">{% trans 'No' %}</button>
|
||||
<div class="btn btn-sm btn-phoenix-danger">
|
||||
<form action="{% url 'account_delete' account.pk %}" method="post">
|
||||
<form action="{% url 'account_delete' request.dealer.slug account.pk %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-phoenix-danger">{% trans 'Yes' %}</button>
|
||||
</form>
|
||||
@ -99,7 +99,7 @@
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a class="dropdown-item text-success" href="{% url 'payment_details' tx.journal_entry.pk %}">{% trans 'View Transacrions'|capfirst %}</a>
|
||||
<a class="dropdown-item" href="{% url 'payment_details' request.dealer.slug tx.journal_entry.pk %}">{% trans 'view'|capfirst %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@ -135,7 +135,7 @@
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex">
|
||||
<a class="btn btn-sm btn-phoenix-primary me-1" href="{% url 'account_update' account.pk %}">
|
||||
<a class="btn btn-sm btn-phoenix-primary me-1" href="{% url 'account_update' request.dealer.slug account.pk %}">
|
||||
<!-- <i class="bi bi-pencil-square"></i> -->
|
||||
<i class="fa-solid fa-pen-to-square"></i> {{ _('Edit') }}
|
||||
</a>
|
||||
@ -143,7 +143,7 @@
|
||||
<!-- <i class="bi bi-trash-fill"></i> -->
|
||||
<i class="fa-solid fa-trash"></i> {{ _('Delete') }}
|
||||
</a>
|
||||
<a class="btn btn-sm btn-phoenix-secondary" href="{% url 'account_list' %}">
|
||||
<a class="btn btn-sm btn-phoenix-secondary" href="{% url 'account_list' request.dealer.slug %}">
|
||||
<!-- <i class="bi bi-arrow-left-square-fill"></i> -->
|
||||
<i class="fa-regular fa-circle-left"></i> {% trans 'Back to List' %}
|
||||
</a>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="row mt-4">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<h3 class=""><i class="fa-solid fa-book"></i> {% trans "Accounts" %}</h3>
|
||||
<a href="{% url 'account_create' %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'New Account' %}</a>
|
||||
<a href="{% url 'account_create' request.dealer.slug %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'New Account' %}</a>
|
||||
</div>
|
||||
|
||||
<!-- Account Type Tabs -->
|
||||
|
||||
@ -38,8 +38,8 @@
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'account_detail' account.uuid %}" class="dropdown-item text-success-dark">
|
||||
{% trans "View Journal Entries" %}
|
||||
<a href="{% url 'account_detail' request.dealer.slug account.uuid %}" class="dropdown-item text-success-dark">
|
||||
{% trans "View" %}
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button>
|
||||
|
||||
@ -88,11 +88,11 @@
|
||||
{% endif %}
|
||||
{% for bill in bills %}
|
||||
<div class="col">
|
||||
{% include 'django_ledger/bills/includes/card_bill.html' with bill=bill entity_slug=entity.slug style='dashboard' %}
|
||||
{% include 'django_ledger/bills/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=entity.slug style='dashboard' %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="col">
|
||||
{% include 'django_ledger/bills/includes/card_bill.html' with create_bill=True entity_slug=entity.slug style='dashboard' %}
|
||||
{% include 'django_ledger/bills/includes/card_bill.html' with dealer_slug=request.dealer.slug create_bill=True entity_slug=entity.slug style='dashboard' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-phoenix-primary">Save</button>
|
||||
<a href="{% url 'purchase_order_list' %}" class="btn btn-phoenix-secondary">Cancel</a>
|
||||
<a href="{% url 'purchase_order_list' request.dealer.slug %}" class="btn btn-phoenix-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -162,7 +162,7 @@
|
||||
|
||||
<div class="card-footer bg-light">
|
||||
<div class="d-flex flex-wrap gap-2 justify-content-between">
|
||||
<a href="{% url 'purchase_order_update' entity_slug=entity_slug po_pk=po_model.pk %}"
|
||||
<a href="{% url 'purchase_order_update' dealer_slug=request.dealer.slug entity_slug=entity_slug po_pk=po_model.pk %}"
|
||||
class="btn btn-phoenix-primary">
|
||||
<i class="fas fa-edit me-2"></i>{% trans 'Update' %}
|
||||
</a>
|
||||
@ -171,28 +171,28 @@
|
||||
{# Status Action Buttons #}
|
||||
{% if po_model.can_draft %}
|
||||
<button class="btn btn-phoenix-secondary"
|
||||
onclick="showPOModal('Draft PO', '{% url 'po-action-mark-as-draft' entity_slug po_model.pk %}', 'Mark As Draft')">
|
||||
onclick="showPOModal('Draft PO', '{% url 'po-action-mark-as-draft' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Draft')">
|
||||
<i class="fas fa-file me-2"></i>{% trans 'Mark as Draft' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if po_model.can_review %}
|
||||
<button class="btn btn-phoenix-warning"
|
||||
onclick="showPOModal('Review PO', '{% url 'po-action-mark-as-review' entity_slug po_model.pk %}', 'Mark As Review')">
|
||||
onclick="showPOModal('Review PO', '{% url 'po-action-mark-as-review' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Review')">
|
||||
<i class="fas fa-search me-2"></i>{% trans 'Mark as Review' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if po_model.can_approve %}
|
||||
<button class="btn btn-phoenix-success"
|
||||
onclick="showPOModal('Approve PO', '{% url 'po-action-mark-as-approved' entity_slug po_model.pk %}', 'Mark As Approved')">
|
||||
onclick="showPOModal('Approve PO', '{% url 'po-action-mark-as-approved' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Approved')">
|
||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Approved' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if po_model.can_fulfill %}
|
||||
<button class="btn btn-phoenix-primary"
|
||||
onclick="showPOModal('Fulfill PO', '{% url 'po-action-mark-as-fulfilled' entity_slug po_model.pk %}', 'Mark As Fulfilled')">
|
||||
onclick="showPOModal('Fulfill PO', '{% url 'po-action-mark-as-fulfilled' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Fulfilled')">
|
||||
<i class="fas fa-truck me-2"></i>{% trans 'Mark as Fulfilled' %}
|
||||
</button>
|
||||
|
||||
@ -201,21 +201,21 @@
|
||||
{# Danger Action Buttons #}
|
||||
{% if po_model.can_delete %}
|
||||
<button class="btn btn-outline-danger"
|
||||
onclick="showPOModal('Cancel PO', '{% url 'po-delete' entity_slug po_model.pk %}', 'Mark As Cancelled')">
|
||||
onclick="showPOModal('Delete PO', '{% url 'po-delete' request.dealer.slug entity_slug po_model.pk %}', 'Delete')">
|
||||
<i class="fas fa-ban me-2"></i>{% trans 'Delete' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if po_model.can_void %}
|
||||
<button class="btn btn-outline-danger"
|
||||
onclick="showPOModal('Void PO', '{% url 'po-action-mark-as-void' entity_slug po_model.pk %}', 'Mark As Void')">
|
||||
onclick="showPOModal('Void PO', '{% url 'po-action-mark-as-void' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Void')">
|
||||
<i class="fas fa-times-circle me-2"></i>{% trans 'Void' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if po_model.can_cancel %}
|
||||
<button class="btn btn-outline-danger"
|
||||
onclick="showPOModal('Cancel PO', '{% url 'po-action-mark-as-canceled' entity_slug po_model.pk %}', 'Mark As Cancelled')">
|
||||
onclick="showPOModal('Cancel PO', '{% url 'po-action-mark-as-canceled' request.dealer.slug entity_slug po_model.pk %}', 'Mark As Cancelled')">
|
||||
<i class="fas fa-ban me-2"></i>{% trans 'Cancel' %}
|
||||
</button>
|
||||
|
||||
@ -228,7 +228,7 @@
|
||||
{% else %}
|
||||
<div class="card border-0 shadow-sm text-center py-5">
|
||||
<div class="card-body">
|
||||
<a href="{% url 'purchase_order_create' %}" class="text-decoration-none">
|
||||
<a href="{% url 'purchase_order_create' request.dealer.slug %}" class="text-decoration-none">
|
||||
<span class="text-muted mb-3 d-inline-block">{% icon "ic:baseline-add-circle-outline" 48 %}</span>
|
||||
<h3 class="h4 text-muted">{% trans 'New Purchase Order' %}</h3>
|
||||
</a>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form action="{% url 'inventory_item_create' po_model.pk %}" method="post">
|
||||
<form action="{% url 'inventory_item_create' request.dealer.slug po_model.pk %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% include "purchase_orders/partials/po-select.html" with name="make" target="model" data=make_data pk=po_model.pk %}
|
||||
{% include "purchase_orders/partials/po-select.html" with name="model" target="serie" data=model_data pk=po_model.pk %}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
{% load custom_filters %}
|
||||
{% load widget_tweaks %}
|
||||
|
||||
<form action="{% url 'purchase_order_update_items' entity_slug=entity_slug po_pk=po_model.uuid %}"
|
||||
<form action="{% url 'purchase_order_update_items' dealer_slug=dealer_slug entity_slug=entity_slug po_pk=po_model.uuid %}"
|
||||
method="post">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
@ -60,7 +60,7 @@
|
||||
{{ f.create_bill|add_class:"form-check-input" }}
|
||||
{% elif f.instance.bill_model %}
|
||||
<a class="btn btn-sm btn-phoenix-secondary"
|
||||
href="{% url 'bill-detail' entity_slug=entity_slug bill_pk=f.instance.bill_model_id %}">
|
||||
href="{% url 'bill-detail' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=f.instance.bill_model_id %}">
|
||||
{% trans 'View Bill' %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<select class="form-control"
|
||||
name="{{name}}" id="{{name}}"
|
||||
{% if name != "trim" %}
|
||||
hx-get="{% url 'inventory_items_filter' %}"
|
||||
hx-get="{% url 'inventory_items_filter' request.dealer.slug %}"
|
||||
hx-target="#form-{{target}}"
|
||||
hx-select="#form-{{target}}"
|
||||
hx-swap="outerHTML"
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<form action="{% url 'po-delete' entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"
|
||||
<form action="{% url 'po-delete' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<div class="card shadow">
|
||||
@ -15,10 +15,10 @@
|
||||
Purchase Order {{ po_model.po_number }}?</h2>
|
||||
|
||||
<p class="card-text text-muted mb-4">All transactions associated with this Purchase Order will be deleted.
|
||||
If you want to void the PO instead, <a href="{% url 'purchase_order_detail' entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}" class="text-decoration-none">click here</a></p>
|
||||
If you want to void the PO instead, <a href="{% url 'purchase_order_detail' dealer_slug=request.dealer.slug pk=po_model.uuid %}" class="text-decoration-none">click here</a></p>
|
||||
|
||||
<div class="d-flex justify-content-center gap-3 mt-4">
|
||||
<a href="{% url 'purchase_order_update' entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"
|
||||
<a href="{% url 'purchase_order_update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"
|
||||
class="btn btn-phoenix-primary px-4">{% trans 'Go Back' %}</a>
|
||||
<button type="submit" class="btn btn-phoenix-danger px-4">{% trans 'Delete' %}</button>
|
||||
</div>
|
||||
|
||||
@ -7,19 +7,28 @@
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<div class="row g-1">
|
||||
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<!-- PO Card -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% include 'purchase_orders/includes/card_po.html' with po_model=po_model entity_slug=entity_slug style='po-detail' %}
|
||||
{% include 'purchase_orders/includes/card_po.html' with dealer_slug=request.dealer.slug po_model=po_model entity_slug=entity_slug style='po-detail' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PO Stats Card-->
|
||||
|
||||
<div class="card mb-4">
|
||||
<!-- PO List Button -->
|
||||
<a class="btn btn-phoenix-primary w-100 py-2"
|
||||
href="{% url 'purchase_order_list' request.dealer.slug %}">
|
||||
<i class="fas fa-list me-2"></i>{% trans 'PO List' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="col-lg-8">
|
||||
<!-- Stats Cards -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="row text-center">
|
||||
<div class="col-md-6 border-end">
|
||||
|
||||
@ -19,9 +19,9 @@
|
||||
{{ _("Purchase Orders") |capfirst }}
|
||||
</h2>
|
||||
<div>
|
||||
<a href="{% url 'purchase_order_create' %}"
|
||||
<a href="{% url 'purchase_order_create' request.dealer.slug %}"
|
||||
class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{{ _("Create New PO") }}</a>
|
||||
<a href="{% url 'inventory_item_create' %}?for_po=1"
|
||||
<a href="{% url 'inventory_item_create' request.dealer.slug %}?for_po=1"
|
||||
class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{{ _("Create Inventory Item for PO") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -67,8 +67,8 @@
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'purchase_order_detail' po.pk %}" class="dropdown-item text-success-dark">{% trans 'PO Detail' %}</a>
|
||||
<a href="{% url 'view_items_inventory' entity_slug=entity_slug po_pk=po.pk %}" class="dropdown-item text-success-dark">{% trans 'View Inventory Items' %}</a>
|
||||
<a href="{% url 'purchase_order_detail' request.dealer.slug po.pk %}" class="dropdown-item text-success-dark">{% trans 'Detail' %}</a>
|
||||
<a href="{% url 'view_items_inventory' dealer_slug=request.dealer.slug entity_slug=entity_slug po_pk=po.pk %}" class="dropdown-item text-success-dark">{% trans 'View Inventory Items' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@ -83,13 +83,13 @@
|
||||
</table>
|
||||
</div>
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
|
||||
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
|
||||
|
||||
<div class="d-flex">
|
||||
{% include 'partials/pagination.html'%}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@ -12,12 +12,12 @@
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-12">
|
||||
{% include 'purchase_orders/includes/card_po.html' with style='po-detail' po_model=po_model entity_slug=entity_slug %}
|
||||
{% include 'purchase_orders/includes/card_po.html' with style='po-detail' dealer_slug=request.dealer.slug po_model=po_model entity_slug=entity_slug %}
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<form action="{% url 'purchase_order_update' entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"
|
||||
<form action="{% url 'purchase_order_update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"
|
||||
method="post">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
@ -26,9 +26,9 @@
|
||||
<button type="submit"
|
||||
class="btn btn-phoenix-success w-100 my-2">{% trans 'Save PO' %}
|
||||
</button>
|
||||
<a href="{% url 'purchase_order_detail' po_model.uuid %}"
|
||||
<a href="{% url 'purchase_order_detail' request.dealer.slug po_model.uuid %}"
|
||||
class="btn btn-phoenix-secondary w-100 my-2">{% trans 'Back to PO Detail' %}</a>
|
||||
<a href="{% url 'purchase_order_list' %}"
|
||||
<a href="{% url 'purchase_order_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-info
|
||||
info w-100 my-2">{% trans 'PO List' %}</a>
|
||||
</div>
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
</td>
|
||||
<td class="has-text-centered">{% if item.bill_model_id %}
|
||||
<a class="is-small is-info button"
|
||||
href="{% url 'bill-detail' entity_slug=entity_slug bill_pk=item.bill_model_id %}">View
|
||||
href="{% url 'bill-detail' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=item.bill_model_id %}">View
|
||||
Bill</a>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<p>{% trans "Are you sure you want to Cancel this Estimate?" %}</p>
|
||||
</div>
|
||||
<div class="modal-footer flex justify-content-center border-top-0">
|
||||
<a type="button" class="btn btn-sm btn-phoenix-danger w-100" href="{% url 'estimate_mark_as' estimate.pk %}?mark=canceled">
|
||||
<a type="button" class="btn btn-sm btn-phoenix-danger w-100" href="{% url 'estimate_mark_as' request.dealer.slug estimate.pk %}?mark=canceled">
|
||||
<i class="fa-solid fa-circle-check"></i> {% trans "Yes" %}
|
||||
</a>
|
||||
</div>
|
||||
@ -40,7 +40,7 @@
|
||||
<div class="modal-body">
|
||||
{% trans 'Are you sure ?' %}
|
||||
<div class="modal-footer flex justify-content-center border-top-0">
|
||||
<form id="confirmForm" method="POST" action="{% url 'estimate_mark_as' estimate.pk %}?mark=approved" class="form">
|
||||
<form id="confirmForm" method="POST" action="{% url 'estimate_mark_as' request.dealer.slug estimate.pk %}?mark=approved" class="form">
|
||||
{% csrf_token %}
|
||||
<div class="container-fluid m-0 p-0">
|
||||
<button type="button" class="btn btn-phoenix-danger btn-sm" data-bs-dismiss="modal"><i class="fa-solid fa-ban"></i> {% trans 'No' %}</button>
|
||||
@ -74,32 +74,28 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
{% if estimate.status == 'draft' %}
|
||||
<a href="{% url 'send_email' estimate.pk %}" class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-sm-2"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a>
|
||||
{% if estimate.invoicemodel_set.first %}
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug estimate.invoicemodel_set.first.pk %}" class="btn btn-phoenix-primary btn-sm" type="button"><i class="fa-solid fa-receipt"></i>
|
||||
{{ _("View Invoice")}}</a>
|
||||
<button class="btn btn-phoenix-primary" data-bs-toggle="modal" data-bs-target="#POModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'View Purchase Order' %}</span></button>
|
||||
{% endif %}
|
||||
|
||||
{% if estimate.status == 'draft' %}
|
||||
<a href="{% url 'send_email' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-sm-2"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a>
|
||||
<button id="mark_as_sent_estimate" class="btn btn-phoenix-secondary" onclick="setFormAction('review')" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Sent' %}</span></button>
|
||||
{% elif estimate.status == 'in_review' %}
|
||||
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Accept' %}</span></button>
|
||||
{% elif estimate.status == 'approved' %}
|
||||
|
||||
|
||||
{% if estimate.sale_orders.first %}
|
||||
<!--if there is a sales order for an estimate-->
|
||||
<!--View sales Order-->
|
||||
<a href="{% url 'order_detail' estimate.sale_orders.first.pk %}" class="btn btn-phoenix-primary btn-sm" type="button"><i class="fa-solid fa-cart-shopping"></i>
|
||||
{{ _("View Sales Order")}}
|
||||
</a>
|
||||
{% if estimate.sale_orders.first.invoice %}
|
||||
<a href="{% url 'invoice_detail' estimate.invoicemodel_set.first.pk %}" class="btn btn-phoenix-primary btn-sm" type="button"><i class="fa-solid fa-receipt"></i>
|
||||
{{ _("View Invoice")}}</a>
|
||||
{% else %}
|
||||
<!--if there is no invoice for a sale order create invoice -->
|
||||
<a href="{% url 'invoice_create' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'Create Invoice' %}</span></a>
|
||||
{% endif %}
|
||||
<a href="{% url 'invoice_create' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'Create Invoice' %}</span></a>
|
||||
<a href="{% url 'preview_sale_order' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a>
|
||||
{% else %}
|
||||
<!--if no sales order for the estimate Create sales order-->
|
||||
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-file-import"></i> {% trans 'Create Sale Order' %}</span></a>
|
||||
<a href="{% url 'create_sale_order' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-file-import"></i> {% trans 'Create Sale Order' %}</span></a>
|
||||
{% comment %} {% endcomment %}
|
||||
{% endif %}
|
||||
{% elif estimate.status == 'in_review' %}
|
||||
<a href="{% url 'estimate_preview' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
||||
<a href="{% url 'estimate_preview' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
||||
{% endif %}
|
||||
{% if estimate.can_cancel %}
|
||||
{% if perms.django_ledger.change_estimatemodel %}
|
||||
@ -144,7 +140,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="px-0">
|
||||
<div class="table-responsive scrollbar">
|
||||
<table id="estimate-table" class="table fs-9 text-body mb-0">
|
||||
@ -245,7 +241,7 @@
|
||||
// Get the form element
|
||||
const form = document.getElementById('confirmForm');
|
||||
// Set the form action with the query parameter
|
||||
form.action = "{% url 'estimate_mark_as' estimate.pk %}?mark=" + action;
|
||||
form.action = "{% url 'estimate_mark_as' request.dealer.slug estimate.pk %}?mark=" + action;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -17,14 +17,14 @@
|
||||
{% if not items %}
|
||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("Please add at least one car before creating a quotation.") }}<a class="ms-3 text-body-primary fs-9" href="{% url 'car_add' %}"> {{ _("Add Car") }} </a></p>
|
||||
<p class="mb-0 flex-1">{{ _("Please add at least one car before creating a quotation.") }}<a class="ms-3 text-body-primary fs-9" href="{% url 'car_add' request.dealer.slug %}"> {{ _("Add Car") }} </a></p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not customer_count %}
|
||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1"> {{ _("Please add at least one customer before creating a quotation.") }}<a class="ms-3 text-body-primary fs-9" href="{% url 'customer_create' %}"> {{ _("Add Customer") }} </a></p>
|
||||
<p class="mb-0 flex-1"> {{ _("Please add at least one customer before creating a quotation.") }}<a class="ms-3 text-body-primary fs-9" href="{% url 'customer_create' request.dealer.slug %}"> {{ _("Add Customer") }} </a></p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -163,7 +163,7 @@
|
||||
|
||||
try {
|
||||
// Send data to the server using fetch
|
||||
const response = await fetch("{% url 'estimate_create' %}", {
|
||||
const response = await fetch("{% url 'estimate_create' request.dealer.slug %}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': formData.csrfmiddlewaretoken,
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
<td class="align-middle product white-space-nowrap">{{ estimate.get_status_action_date }}</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ estimate.created }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
<a href="{% url 'estimate_detail' estimate.pk %}"
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">
|
||||
<i class="fa-regular fa-eye me-1"></i>
|
||||
{% trans "view"|capfirst %}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'estimate_detail' estimate.pk %}" class="btn btn-sm btn-phoenix-secondary text-body fs-10 me-1">{{ _("Cancel") }}</a>
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}" class="btn btn-sm btn-phoenix-secondary text-body fs-10 me-1">{{ _("Cancel") }}</a>
|
||||
<button class="btn btn-sm btn-phoenix-primary fs-10" type="submit">{{ _("Send") }}<span class="fa-solid fa-paper-plane ms-1"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -172,7 +172,7 @@
|
||||
<!-- Form Actions -->
|
||||
<div class="form-actions mt-4">
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{% url 'estimate_detail' estimate.pk %}" type="button" class="btn btn-phoenix-secondary">
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}" type="button" class="btn btn-phoenix-secondary">
|
||||
<i class="fas fa-times me-2"></i> Cancel
|
||||
</a>
|
||||
<div>
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
class="btn btn-sm btn-phoenix-danger"
|
||||
data-bs-dismiss="modal"><i class="fa-solid fa-ban"></i> {% trans 'No' %}
|
||||
</button>
|
||||
<form id="confirmForm" method="POST" action="{% url 'invoice_mark_as' invoice.pk %}?mark=accept" class="d-inline">
|
||||
<form id="confirmForm" method="POST" action="{% url 'invoice_mark_as' request.dealer.slug invoice.pk %}?mark=accept" class="d-inline">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-phoenix-success btn-sm"><i class="fa-solid fa-circle-check"></i> {% trans "Yes" %}</button>
|
||||
</form>
|
||||
@ -35,7 +35,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ============================================-->
|
||||
<!-- ============================================-->
|
||||
<div class="modal fade" id="mark_as_paid_Modal" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
@ -51,7 +51,7 @@
|
||||
data-bs-dismiss="modal">
|
||||
<i class="fa-solid fa-ban"></i> {% trans 'No' %}
|
||||
</button>
|
||||
<form id="confirmForm" method="POST" action="{% url 'payment_mark_as_paid' invoice.pk %}" class="d-inline">
|
||||
<form id="confirmForm" method="POST" action="{% url 'payment_mark_as_paid' request.dealer.slug invoice.pk %}" class="d-inline">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-phoenix-success btn-sm"><i class="fa-solid fa-circle-check"></i> {% trans "Yes" %}</button>
|
||||
</form>
|
||||
@ -60,7 +60,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ============================================-->
|
||||
<!-- ============================================-->
|
||||
<!-- <section> begin ============================-->
|
||||
<section class="pt-5 pb-9 bg-body-emphasis dark__bg-gray-1200 border-top">
|
||||
<div class="row-small mt-3 mx-3">
|
||||
@ -82,40 +82,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
{# Accept Invoice Button #}
|
||||
{% if invoice.invoice_status == 'in_review' %}
|
||||
<button id="accept_invoice" class="btn btn-phoenix-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#confirmModal">
|
||||
<i class="fa-solid fa-check-double me-1 me-sm-0 me-md-1"></i> {# Icon always visible, adjusted margin #}
|
||||
<span class="d-none d-sm-inline-block">{% trans 'Accept' %}</span> {# Text hidden on xs, shown on sm+ #}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{# Record Payment Button #}
|
||||
{% if invoice.invoice_status == 'approved' %}
|
||||
<a href="{% url 'payment_create' invoice.pk %}" class="btn btn-phoenix-success btn-sm">
|
||||
<i class="fa-solid fa-money-bill me-1 me-sm-0 me-md-1"></i> {# Icon always visible, adjusted margin #}
|
||||
<span class="d-none d-sm-inline-block">{% trans 'Record Payment' %}</span> {# Text hidden on xs, shown on sm+ #}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{# Mark as Paid Button #}
|
||||
{% if not invoice.is_paid %}
|
||||
<button {% if invoice.is_review or invoice.amount_paid|to_int < invoice.amount_due|to_int %}disabled{% endif %} id="mark_invoice_as_paid" class="btn btn-phoenix-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#mark_as_paid_Modal">
|
||||
<span class="icon-saudi_riyal me-1 me-sm-0 me-md-1"></span> {# Icon always visible, adjusted margin #}
|
||||
<span class="d-none d-sm-inline-block">{% trans 'Mark as Paid' %}</span> {# Text hidden on xs, shown on sm+ #}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{# Preview Button #}
|
||||
<a href="{% url 'invoice_preview' invoice.pk %}" class="btn btn-phoenix-primary btn-sm">
|
||||
<i class="fa-regular fa-eye me-1 me-sm-0 me-md-1"></i> {# Icon always visible, adjusted margin #}
|
||||
<span class="d-none d-sm-inline-block">{% trans 'Preview' %}</span> {# Text hidden on xs, shown on sm+ #}
|
||||
</a>
|
||||
</div>
|
||||
{% if invoice.invoice_status == 'in_review' %}
|
||||
<button id="accept_invoice" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Accept' %}</span></button>
|
||||
{% endif %}
|
||||
{% if invoice.invoice_status == 'approved' %}
|
||||
<a href="{% url 'payment_create' request.user.dealer.slug invoice.pk %}" class="btn btn-phoenix-success"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-money-bill"></i> {% trans 'Record Payment' %}</span></a>
|
||||
{% endif %}
|
||||
{% if not invoice.is_paid %}
|
||||
<button {% if invoice.is_review or invoice.amount_paid|to_int < invoice.amount_due|to_int %}disabled{% endif %} id="mark_invoice_as_paid" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#mark_as_paid_Modal"><span class="d-none d-sm-inline-block"><span class="icon-saudi_riyal"></span> {% trans 'Mark as Paid' %}</span></button>
|
||||
{% endif %}
|
||||
<a href="{% url 'invoice_preview' request.user.dealer.slug invoice.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
||||
</div>
|
||||
</div>
|
||||
{{invoice.amount_owned}}
|
||||
|
||||
<!-- ============================================-->
|
||||
<!-- ============================================-->
|
||||
<div class="card mb-5 {% if invoice.is_review %}disabled{% endif %}">
|
||||
<div class="card-body">
|
||||
<div class="row g-4 g-xl-1 g-xxl-3 justify-content-between">
|
||||
@ -190,7 +171,7 @@
|
||||
<!-- <section> begin ============================-->
|
||||
<div class="container bg-body dark__bg-gray-1100 p-4 mb-4 rounded-2 text-body-tertiary {% if invoice.is_review %}disabled{% endif %}">
|
||||
<!---->
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col mb-2">
|
||||
<h6 class="mb-0 me-3"><i class="fa-solid fa-hashtag"></i> {% trans "Invoice Number" %} :</h6>
|
||||
@ -223,7 +204,7 @@
|
||||
<span class="badge text-bg-success">{% trans "Paid" %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
{% block title %}{{ _("Invoices") }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row mt-4">
|
||||
<h3 class="mb-3"><i class="fa-solid fa-receipt"></i> {% trans "Invoices" %}</h3>
|
||||
|
||||
@ -55,7 +54,7 @@
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ invoice.created }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
<a href="{% url 'invoice_detail' invoice.pk %}"
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug invoice.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">
|
||||
<i class="fa-regular fa-eye me-1"></i>
|
||||
{% trans "View" %}
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
<td class="align-middle product white-space-nowrap">{{ journal. }}</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ journal. }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'invoice_detail' invoice.pk %}"
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug invoice.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">
|
||||
{% trans "view" %}
|
||||
</a>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
{% if model %}
|
||||
<form method="post" action="{% url 'payment_create' pk=model.pk %}">
|
||||
<form method="post" action="{% url 'payment_create' request.dealer.slug model.pk %}">
|
||||
{% endif %}
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
@ -30,11 +30,11 @@
|
||||
<td class="align-middle product white-space-nowrap py-0">{{ journal.je_number }}</td>
|
||||
{% if journal.ledger.invoicemodel %}
|
||||
<td class="align-middle product white-space-nowrap py-0">
|
||||
<a href="{% url 'invoice_detail' journal.ledger.invoicemodel.pk %}"><i class="fa-solid fa-receipt"></i> {{ journal.ledger.invoicemodel }}</a>
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug journal.ledger.invoicemodel.pk %}"><i class="fa-solid fa-receipt"></i> {{ journal.ledger.invoicemodel }}</a>
|
||||
</td>
|
||||
{% elif journal.ledger.billmodel %}
|
||||
<td class="align-middle product white-space-nowrap py-0">
|
||||
<a href="{% url 'bill_detail' journal.ledger.billmodel.pk %}"><i class="fa-solid fa-money-bill"></i> {{ journal.ledger.billmodel }}</a>
|
||||
<a href="{% url 'bill-detail' request.dealer.slug request.dealer.entity.slug journal.ledger.billmodel.pk %}"><i class="fa-solid fa-money-bill"></i> {{ journal.ledger.billmodel }}</a>
|
||||
</td>
|
||||
{% else %}
|
||||
<td class="align-middle product white-space-nowrap py-0"></td>
|
||||
@ -42,7 +42,7 @@
|
||||
<td class="align-middle product white-space-nowrap py-0">{{ journal.timestamp }}</td>
|
||||
<td class="align-middle product white-space-nowrap py-0">{{ journal.description }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
<a href="{% url 'payment_details' journal.pk %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-eye me-1"></i> {% trans "View Tranactions"|capfirst %}</a>
|
||||
<a href="{% url 'payment_details' request.dealer.slug journal.pk %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-eye me-1"></i> {% trans "View Tranactions"|capfirst %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
|
||||
@ -253,13 +253,13 @@
|
||||
|
||||
<!-- Add links to view full estimate and invoice if they exist -->
|
||||
{% if sale_order.estimate %}
|
||||
<a href="{% url 'estimate_detail' sale_order.estimate.pk %}" class="btn btn-phoenix-info ms-2">
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug sale_order.estimate.pk %}" class="btn btn-info ms-2">
|
||||
{% trans "View Full Estimate" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if sale_order.invoice %}
|
||||
<a href="{% url 'invoice_detail' sale_order.invoice.pk %}" class="btn btn-phoenix-info ms-2">
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug sale_order.invoice.pk %}" class="btn btn-info ms-2">
|
||||
{% trans "View Full Invoice" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
<div class="spinner-border mx-3 htmx-indicator" role="status"><span class="visually-hidden">Loading...</span></div>
|
||||
<div class="search-box me-3">
|
||||
<form class="position-relative">
|
||||
<input class="form-control search-input search" name='search' type="search" placeholder="{{ _("Search") }}" aria-label="Search" hx-get="{% url 'car_list' %}" hx-trigger='keyup changed delay:500ms' hx-target='.table-responsive' hx-select='.table-responsive' hx-swap="innerHTML show:window:top" hx-indicator=".htmx-indicator"
|
||||
<input class="form-control search-input search" name='search' type="search" placeholder="{{ _("Search") }}" aria-label="Search" hx-get="{% url 'car_list' request.dealer.slug %}" hx-trigger='keyup changed delay:500ms' hx-target='.table-responsive' hx-select='.table-responsive' hx-swap="innerHTML show:window:top" hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()"
|
||||
/>
|
||||
@ -58,7 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center d-none filter">
|
||||
<select hx-get="{% url 'car_list' %}" name="make" hx-target='.model-select' hx-select='.model-select' hx-swap="outerHTML show:window:top" hx-indicator=".htmx-indicator" class="form-select make" aria-label="Default select example"
|
||||
<select hx-get="{% url 'car_list' request.dealer.slug %}" name="make" hx-target='.model-select' hx-select='.model-select' hx-swap="outerHTML show:window:top" hx-indicator=".htmx-indicator" class="form-select make" aria-label="Default select example"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()"
|
||||
>
|
||||
@ -67,7 +67,7 @@
|
||||
<option value="{{ m.pk }}">{{ m.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select hx-get="{% url 'car_list' %}" hx-include=".make" name="model" hx-target='.year' hx-select='.year' hx-swap="outerHTML show:window:top" hx-indicator=".htmx-indicator" class="form-select model-select" aria-label="Default select example"
|
||||
<select hx-get="{% url 'car_list' request.dealer.slug %}" hx-include=".make" name="model" hx-target='.year' hx-select='.year' hx-swap="outerHTML show:window:top" hx-indicator=".htmx-indicator" class="form-select model-select" aria-label="Default select example"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()"
|
||||
>
|
||||
@ -89,7 +89,7 @@
|
||||
<option value="sold">Sold</option>
|
||||
<option value="transfer">Transfer</option>
|
||||
</select>
|
||||
<button id="search" hx-get="{% url 'car_list' %}" hx-include=".make,.model,.year,.car_status" hx-indicator=".htmx-indicator" hx-target='.table-responsive' hx-select='.table-responsive' hx-swap="outerHTML show:window:top" class="btn btn-sm btn-phoenix-primary"
|
||||
<button id="search" hx-get="{% url 'car_list' request.dealer.slug %}" hx-include=".make,.model,.year,.car_status" hx-indicator=".htmx-indicator" hx-target='.table-responsive' hx-select='.table-responsive' hx-swap="outerHTML show:window:top" class="btn btn-sm btn-phoenix-primary"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">Search</button>
|
||||
</div>
|
||||
@ -149,7 +149,7 @@
|
||||
<td class="align-middle white-space-nowrap quotation">
|
||||
{% if tx.estimate %}
|
||||
<p class="fw-bo text-body fs-9 mb-0">
|
||||
<a href="{% url 'estimate_detail' tx.estimate.uuid %}">
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug tx.estimate.uuid %}">
|
||||
{{tx.estimate.estimate_number}}
|
||||
</a><br>
|
||||
{% if tx.estimate.status == "draft" %}
|
||||
@ -167,7 +167,7 @@
|
||||
<td class="align-middle white-space-nowrap invoice">
|
||||
{% if tx.invoice %}
|
||||
<p class="fw-bo text-body fs-9 mb-0">
|
||||
<a href="{% url 'invoice_detail' tx.invoice.uuid %}">
|
||||
<a href="{% url 'invoice_detail' request.dealer.slug tx.invoice.uuid %}">
|
||||
{{tx.invoice.invoice_number}}
|
||||
</a><br>
|
||||
{% if tx.invoice.is_draft %}
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
<input class="d-none" id="emailPhotos" type="file" accept="image/*" />
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'estimate_detail' estimate.pk %}" class="btn btn-link text-body fs-10 text-decoration-none">Discard</a>
|
||||
<a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}" class="btn btn-link text-body fs-10 text-decoration-none">Discard</a>
|
||||
<button class="btn btn-phoenix-primary fs-10" type="submit">Send<span class="fa-solid fa-paper-plane ms-1"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user