Merge pull request 'Dashboard fix' (#209) from frontend into main

Reviewed-on: #209
This commit is contained in:
ismail 2025-08-28 14:15:25 +03:00
commit 572bdbafd4
11 changed files with 11821 additions and 11929 deletions

View File

@ -762,7 +762,8 @@ class Car(Base):
make = self.id_car_make.name if self.id_car_make else "Unknown Make"
model = self.id_car_model.name if self.id_car_model else "Unknown Model"
trim = self.id_car_trim.name if self.id_car_trim else "Unknown Trim"
return f"{self.year} - {make} - {model} - {trim}"
vin=self.vin if self.vin else None
return f"{self.year} - {make} - {model} - {trim}-{vin}"
@property
def product(self):

View File

@ -10,8 +10,8 @@ urlpatterns = [
# main URLs
path("", views.WelcomeView, name="welcome"),
path("signup/", views.dealer_signup, name="account_signup"),
path("", views.HomeView.as_view(), name="home"),
path("<slug:dealer_slug>/", views.HomeView.as_view(), name="home"),
path("", views.HomeView, name="home"),
path("<slug:dealer_slug>/", views.HomeView, name="home"),
# Tasks
path("legal/", views.terms_and_privacy, name="terms_and_privacy"),
# path('tasks/<int:task_id>/detail/', views.task_detail, name='task_detail'),
@ -40,18 +40,13 @@ urlpatterns = [
views.assign_car_makes,
name="assign_car_makes",
),
# dashboards for manager, dealer, inventory and accounatant
path(
"dashboards/<slug:dealer_slug>/general/",
views.general_dashboard,
name="general_dashboard",
),
# dashboard for sales
path(
"dashboards/<slug:dealer_slug>/sales/",
views.sales_dashboard,
name="sales_dashboard",
),
#dashboards for manager, dealer, inventory and accounatant
path("dashboards/<slug:dealer_slug>/general/", views.general_dashboard,name="general_dashboard"),
#dashboard for sales
path("dashboards/<slug:dealer_slug>/sales/", views.sales_dashboard, name="sales_dashboard"),
path(
"<slug:dealer_slug>/cars/aging-inventory/list",
views.aging_inventory_list_view,
@ -782,11 +777,7 @@ urlpatterns = [
views.EstimateDetailView.as_view(),
name="estimate_detail",
),
path(
"<slug:dealer_slug>/sales/estimates/print/<uuid:pk>/",
views.EstimatePrintView.as_view(),
name="estimate_print",
),
path('<slug:dealer_slug>/sales/estimates/print/<uuid:pk>/', views.EstimatePrintView.as_view(), name='estimate_print'),
path(
"<slug:dealer_slug>/sales/estimates/create/",
views.create_estimate,
@ -943,6 +934,7 @@ urlpatterns = [
views.ItemServiceUpdateView.as_view(),
name="item_service_update",
),
# Expanese
path(
"<slug:dealer_slug>/items/expeneses/",
@ -1101,47 +1093,32 @@ urlpatterns = [
name="entity-ic-date",
),
# Chart of Accounts...
path(
"<slug:dealer_slug>/chart-of-accounts/<slug:entity_slug>/list/",
path('<slug:dealer_slug>/chart-of-accounts/<slug:entity_slug>/list/',
views.ChartOfAccountModelListView.as_view(),
name="coa-list",
),
path(
"<slug:dealer_slug>/chart-of-accounts/<slug:entity_slug>/list/inactive/",
views.ChartOfAccountModelListView.as_view(inactive=True),
name="coa-list-inactive",
),
path(
"<slug:dealer_slug>/<slug:entity_slug>/create/",
views.ChartOfAccountModelCreateView.as_view(),
name="coa-create",
),
path(
"<slug:dealer_slug>/<slug:entity_slug>/detail/<slug:coa_slug>/",
views.ChartOfAccountModelListView.as_view(),
name="coa-detail",
),
path(
"<slug:dealer_slug>/<slug:entity_slug>/update/<slug:coa_slug>/",
views.ChartOfAccountModelUpdateView.as_view(),
name="coa-update",
),
name='coa-list'),
path('<slug:dealer_slug>/chart-of-accounts/<slug:entity_slug>/list/inactive/',
views.ChartOfAccountModelListView.as_view(inactive=True),
name='coa-list-inactive'),
path('<slug:dealer_slug>/<slug:entity_slug>/create/',
views.ChartOfAccountModelCreateView.as_view(),
name='coa-create'),
path('<slug:dealer_slug>/<slug:entity_slug>/detail/<slug:coa_slug>/',
views.ChartOfAccountModelListView.as_view(),
name='coa-detail'),
path('<slug:dealer_slug>/<slug:entity_slug>/update/<slug:coa_slug>/',
views.ChartOfAccountModelUpdateView.as_view(),
name='coa-update'),
# ACTIONS....
path(
"<slug:dealer_slug>/<slug:entity_slug>/action/<slug:coa_slug>/mark-as-default/",
views.CharOfAccountModelActionView.as_view(action_name="mark_as_default"),
name="coa-action-mark-as-default",
),
path(
"<slug:dealer_slug>/<slug:entity_slug>/action/<slug:coa_slug>/mark-as-active/",
views.CharOfAccountModelActionView.as_view(action_name="mark_as_active"),
name="coa-action-mark-as-active",
),
path(
"<slug:dealer_slug>/<slug:entity_slug>/action/<slug:coa_slug>/mark-as-inactive/",
views.CharOfAccountModelActionView.as_view(action_name="mark_as_inactive"),
name="coa-action-mark-as-inactive",
),
path('<slug:dealer_slug>/<slug:entity_slug>/action/<slug:coa_slug>/mark-as-default/',
views.CharOfAccountModelActionView.as_view(action_name='mark_as_default'),
name='coa-action-mark-as-default'),
path('<slug:dealer_slug>/<slug:entity_slug>/action/<slug:coa_slug>/mark-as-active/',
views.CharOfAccountModelActionView.as_view(action_name='mark_as_active'),
name='coa-action-mark-as-active'),
path('<slug:dealer_slug>/<slug:entity_slug>/action/<slug:coa_slug>/mark-as-inactive/',
views.CharOfAccountModelActionView.as_view(action_name='mark_as_inactive'),
name='coa-action-mark-as-inactive'),
# CASH FLOW STATEMENTS...
# Entities...
path(
@ -1317,74 +1294,40 @@ urlpatterns = [
views.PurchaseOrderMarkAsVoidView.as_view(),
name="po-action-mark-as-void",
),
# reports
path(
path(
"<slug:dealer_slug>/purchase-report/",
views.purchase_report_view,
name="po-report",
),
path(
"purchase-report/<slug:dealer_slug>/csv/",
views.purchase_report_csv_export,
name="purchase-report-csv-export",
),
path(
path('purchase-report/<slug:dealer_slug>/csv/', views.purchase_report_csv_export, name='purchase-report-csv-export'),
path(
"<slug:dealer_slug>/car-sale-report/",
views.car_sale_report_view,
name="car-sale-report",
),
path(
"car-sale-report/<slug:dealer_slug>/csv/",
views.car_sale_report_csv_export,
name="car-sale-report-csv-export",
),
path("feature/recall/", views.RecallListView.as_view(), name="recall_list"),
path("feature/recall/filter/", views.RecallFilterView, name="recall_filter"),
path(
"feature/recall/<int:pk>/view/",
views.RecallDetailView.as_view(),
name="recall_detail",
),
path(
"feature/recall/create/", views.RecallCreateView.as_view(), name="recall_create"
),
path(
"feature/recall/success/",
views.RecallSuccessView.as_view(),
name="recall_success",
),
path(
"<slug:dealer_slug>/schedules/calendar/",
views.schedule_calendar,
name="schedule_calendar",
),
path('car-sale-report/<slug:dealer_slug>/csv/', views.car_sale_report_csv_export, name='car-sale-report-csv-export'),
path('feature/recall/', views.RecallListView.as_view(), name='recall_list'),
path('feature/recall/filter/', views.RecallFilterView, name='recall_filter'),
path('feature/recall/<int:pk>/view/', views.RecallDetailView.as_view(), name='recall_detail'),
path('feature/recall/create/', views.RecallCreateView.as_view(), name='recall_create'),
path('feature/recall/success/', views.RecallSuccessView.as_view(), name='recall_success'),
path('<slug:dealer_slug>/schedules/calendar/', views.schedule_calendar, name='schedule_calendar'),
# staff profile
path(
"<slug:dealer_slug>/staff/<slug:slug>detail/",
views.StaffDetailView.as_view(),
name="staff_detail",
),
path('<slug:dealer_slug>/staff/<slug:slug>detail/', views.StaffDetailView.as_view(), name='staff_detail'),
# tickets
path("help_center/view/", views.help_center, name="help_center"),
path(
"<slug:dealer_slug>/help_center/tickets/", views.ticket_list, name="ticket_list"
),
path(
"help_center/tickets/<slug:dealer_slug>/create/",
views.create_ticket,
name="create_ticket",
),
path(
"<slug:dealer_slug>/help_center/tickets/<int:ticket_id>/",
views.ticket_detail,
name="ticket_detail",
),
path(
"help_center/tickets/<int:ticket_id>/update/",
views.ticket_update,
name="ticket_update",
),
path('help_center/view/', views.help_center, name='help_center'),
path('<slug:dealer_slug>/help_center/tickets/', views.ticket_list, name='ticket_list'),
path('help_center/tickets/<slug:dealer_slug>/create/', views.create_ticket, name='create_ticket'),
path('<slug:dealer_slug>/help_center/tickets/<int:ticket_id>/', views.ticket_detail, name='ticket_detail'),
path('help_center/tickets/<int:ticket_id>/update/', views.ticket_update, name='ticket_update'),
# path('help_center/tickets/<int:ticket_id>/ticket_mark_resolved/', views.ticket_mark_resolved, name='ticket_mark_resolved'),
]
handler404 = "inventory.views.custom_page_not_found_view"

View File

@ -362,24 +362,31 @@ def dealer_signup(request):
"account/signup-wizard.html",
)
class HomeView(LoginRequiredMixin, TemplateView):
"""
HomeView class responsible for rendering the home page.
# class HomeView(LoginRequiredMixin, TemplateView):
# """
# HomeView class responsible for rendering the home page.
This class ensures that only authenticated users can access the home page.
Unauthenticated users are redirected to the welcome page. It is built on top of
Django's TemplateView and includes additional functionality by inheriting from
LoginRequiredMixin. The purpose of this class is to control the accessibility
of the main index page of the application and manage context data for frontend
rendering.
# This class ensures that only authenticated users can access the home page.
# Unauthenticated users are redirected to the welcome page. It is built on top of
# Django's TemplateView and includes additional functionality by inheriting from
# LoginRequiredMixin. The purpose of this class is to control the accessibility
# of the main index page of the application and manage context data for frontend
# rendering.
:ivar template_name: The path to the template used for rendering the view's
output.
:type template_name: str
"""
# :ivar template_name: The path to the template used for rendering the view's
# output.
# :type template_name: str
# """
template_name = "index.html"
# template_name = "index.html"
@login_required
def HomeView(request,dealer_slug=None):
dealer_slug=request.dealer.slug
if request.is_sales and not request.is_manager and not request.is_dealer:
return redirect('sales_dashboard', dealer_slug=dealer_slug)
else:
return redirect('general_dashboard',dealer_slug=dealer_slug)
class TestView(TemplateView):
"""
@ -6328,6 +6335,7 @@ def lead_create(request, dealer_slug):
qs = form.fields["id_car_make"].queryset.filter(
is_sa_import=True, pk__in=dealer_make_list
)
# print(qs)
form.fields["staff"].queryset = (
form.fields["staff"]
.queryset.select_related("user")
@ -6346,10 +6354,12 @@ def lead_create(request, dealer_slug):
form.fields["staff"].queryset = models.Staff.objects.filter(
dealer=dealer, pk=request.staff.pk
)
qs = qs.order_by("name")
form.fields["id_car_make"].queryset = qs
form.fields["id_car_make"].choices = [
(obj.id_car_make, obj.get_local_name()) for obj in qs
]
if first_make := qs.first():
form.fields["id_car_model"].queryset = first_make.carmodel_set.all()
@ -6505,34 +6515,6 @@ def update_lead_actions(request, dealer_slug):
# return JsonResponse({"success": False, "message": str(e)}, status=500)
def lead_update(request,dealer_slug,slug):
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
lead = get_object_or_404(models.Lead, slug=slug)
form = forms.LeadForm(instance=lead)
if "HX-Request" in request.headers:
make_id = request.GET.get("id_car_make")
make = models.CarMake.objects.get(pk=make_id)
form.fields[
"id_car_model"
].queryset = make.carmodel_set.all()
else:
form.fields[
"id_car_model"
].queryset = form.instance.id_car_make.carmodel_set.all()
form.fields["staff"].queryset = (
form.fields["staff"]
.queryset.select_related("user")
.filter(
dealer=dealer,
user__groups__permissions__codename__contains="add_lead",
)
.distinct()
)
context = {
"form":form
}
return render(request,"crm/leads/lead_form.html",context)
class LeadUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
"""
Handles the update view for Lead objects.
@ -8463,7 +8445,7 @@ class FiscalYearIncomeStatementViewBase(
"""
template_name = "ledger/reports/income_statement.html"
permission_required = ["inventory.view_carfinance"]
permission_required = ["django_ledger.view_ledgermodel"]
def get_login_url(self):
return reverse("account_login")
@ -8602,7 +8584,7 @@ class FiscalYearCashFlowStatementViewBase(
"""
template_name = "ledger/reports/cash_flow_statement.html"
permission_required = ["inventory.view_carfinance"]
permission_required = ["django_ledger.view_ledgermodel"]
def get_login_url(self):
return reverse("account_login")
@ -8791,7 +8773,7 @@ class FiscalYearEntityModelDashboardView(
:type permission_required: list
"""
permission_required = ["inventory.view_carfinance"]
permission_required = ["django_ledger.view_ledgermodel"]
def get_login_url(self):
return reverse("account_login")
@ -11461,6 +11443,10 @@ def create_ticket(request,dealer_slug):
def ticket_list(request,dealer_slug):
dealer= get_object_or_404(models.Dealer, slug=dealer_slug)
tickets = models.Ticket.objects.filter(dealer=dealer).order_by('-created_at')
query=request.GET.get('q')
if query:
tickets=tickets.filter(Q(id__icontains=query)| Q(subject__icontains=query))
return render(request, 'support/ticket_list.html', {'tickets': tickets})
@login_required

View File

@ -88,7 +88,7 @@
</div>
<div id="main_content"
class="fade-me-in"
hx-boost="false"
hx-boost="true"
hx-target="#main_content"
hx-select="#main_content"
hx-swap="outerHTML transition:true"

View File

@ -12,7 +12,7 @@
<h5 class="fw-bold mb-0 text-dark">{% trans "Monthly Revenue & Profit" %}</h5>
</div>
<div class="card-body" style="height: 400px;">
<canvas id="revenueProfitChart"></canvas>
<canvas id="revenueProfitChart" ></canvas>
</div>
</div>
</div>

View File

@ -11,6 +11,7 @@
hx-swap="outerHTML"
hx-select-oob="#toast-container"
hx-indicator="#spinner">
<li class="nav-item">
{% comment %} <p class="navbar-vertical-label text-primary fs-8 text-truncate">{{request.dealer|default:"Apps"}}</p>
<hr class="navbar-vertical-line"> {% endcomment %}
@ -439,25 +440,23 @@
</div>
</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="#">
<div class="d-flex align-items-center">
{% if user.is_authenticated %}
<span class="nav-link-icon"><span class="fa-solid fa-car"></span></span>
<span class="nav-link-text">{{ request.dealer.user.username }}</span>
{% endif %}
</div>
</a>
</li>
</ul>
</div>
{% endif %}
</div>
</div>
<div class="navbar-vertical-footer">
<button class="btn navbar-vertical-toggle border-0 fw-semibold w-100 white-space-nowrap d-flex align-items-center">
<span class="fas fa-angle-double-left fs-8"></span><span class="fas fa-angle-double-right fs-8"></span><span class="navbar-vertical-footer-text ms-2">Collapsed View</span>
</button>
<a class="nav-link ps-2" href="{% if request.is_dealer%}{% url 'ticket_list' request.dealer.slug %} {% else %}#{%endif%}">
<div class="d-flex align-items-center">
{% if user.is_authenticated%}
<span class="nav-link-icon"><span class="fa-solid fa-gear me-1 fs-5"></span></span>
<span class="nav-link-text">{{ request.dealer.user.username }}</span>
{% endif %}
</div>
</a>
</div>
</nav>
<nav class="navbar navbar-top fixed-top navbar-expand" id="navbarDefault">
@ -626,10 +625,12 @@
href="{% url 'management' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="shield"></span>{{ _("Admin Managemnet") }}</a>
{% endif %}
</li>
{% if request.is_dealer%}
<li class="nav-item">
<a class="nav-link px-3 d-block"
href="{% url 'ticket_list' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="help-circle"></span>{{ _("Help Center") }}</a>
</li>
{% endif %}
{% if request.is_staff %}
<li class="nav-item">
<a hx-boost="false"

View File

@ -1,9 +1,16 @@
{% extends 'base.html' %}
{% comment %} {% extends 'base.html' %}
{% load i18n static custom_filters django_ledger %}
{% block content %}
{% if request.user.is_authenticated %}
{% if request.is_sales and not request.is_manager and not request.is_dealer %}
{% url 'sales_dashboard' request.dealer.slug as dashboard_url %}
{% else %}
{% url 'general_dashboard' request.dealer.slug as dashboard_url %}
{% endif %}
<div id="dashboard-content"
hx-get="{% if request.is_sales and not request.is_manager %} {% url 'sales_dashboard' request.dealer.slug %} {% else %} {% url 'general_dashboard' request.dealer.slug %} {% endif %}"
hx-get="{{ dashboard_url }}"
hx-trigger="load"
hx-target="#dashboard-content"
hx-swap="innerHTML">
@ -13,4 +20,6 @@
</div>
</div>
{% endif %}
{% endblock %}
{% endblock %} {% endcomment %}

View File

@ -77,15 +77,182 @@
<div class="row-fluid {% if car.status == 'sold' %}disabled{% endif %}">
<div class="row g-3 justify-content-between">
<div class="col-md-6">
<div class="row mb-2">
<div class="col-md-4">
<div class="card mb-3 rounded shadow d-flex justify-content-center align-item-center{% if car.get_transfer %}disabled{% endif %}">
<p class="card-header rounded-top fw-bold">{% trans 'Car Details' %}</p>
<div class="col-md-4 ms-4 mt-2">
<div class="avatar avatar-6xl mb-3">
<img class="rounded"
src="{% static 'images/car_images/' %}{{ car.get_hash }}.png"
alt="{{ car.vin }}" />
</div>
</div>
<div class="col-md-8">
<div class="card-body">
<div class="table-responsive scrollbar mb-3">
<table class="table table-sm fs-9 mb-0 overflow-hidden">
<tr>
<th>{% trans "VIN" %}</th>
<td>{{ car.vin }}</td>
</tr>
<tr>
<th>{% trans "year"|capfirst %}</th>
<td>{{ car.year }}</td>
</tr>
<tr>
<th>{% trans "make"|capfirst %}</th>
<td>{{ car.id_car_make.get_local_name }}</td>
</tr>
<tr>
<th>{% trans "model"|capfirst %}</th>
<td>{{ car.id_car_model.get_local_name }}</td>
</tr>
<tr>
<th>{% trans "series"|capfirst %}</th>
<td>{{ car.id_car_serie.name }}</td>
</tr>
<tr>
<th>{% trans "trim"|capfirst %}</th>
<td>{{ car.id_car_trim.name }}</td>
</tr>
<tr>
<th>{% trans "Status"|capfirst %}</th>
<td>{{ car.get_status_display }}</td>
</tr>
<tr>
<th>{% trans "Stock Type"|capfirst %}</th>
<td>{{ car.get_stock_type_display }}</td>
</tr>
<tr>
<th>{% trans "Mileage"|capfirst %}</th>
<td>{{ car.mileage }}</td>
</tr>
<tr>
<th>{% trans "Receiving Date"|capfirst %}</th>
<td>{{ car.receiving_date|timesince }}</td>
</tr>
{% if car.vendor %}
<tr>
<th>{% trans "Vendor"|capfirst %}</th>
<td>{{ car.vendor.name }}</td>
</tr>
{% endif %}
<tr>
<th>{% trans "Remarks"|capfirst %}</th>
<td>{{ car.remarks }}</td>
</tr>
<tr>
<th>{% trans 'specifications'|capfirst %}</th>
<td>
<button type="button"
class="btn btn-phoenix-primary btn-sm"
id="specification-btn"
data-bs-toggle="modal"
data-bs-target="#specificationsModal">
{% trans 'view'|capfirst %}
</button>
</td>
</tr>
{% if car.custom_cards %}
<tr>
<th>{% trans "Custom Number"|capfirst %}</th>
<td>{{ car.custom_cards.custom_number }}</td>
</tr>
<tr>
<th>{% trans "Custom Date"|capfirst %}</th>
<td>{{ car.custom_cards.custom_date|date }}</td>
</tr>
{% else %}
<tr>
<th>{% trans "Custom Card" %}</th>
<td>
{% if perms.inventory.add_customcard %}
<button type="button"
class="btn btn-sm btn-phoenix-success"
data-bs-toggle="modal"
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>
{% endif %}
</td>
</tr>
{% endif %}
{% if car.registrations %}
<tr>
<th>{% trans "Registration"|capfirst %}</th>
<td>
{{ car.registrations.plate_number }} | {{ car.registrations.text1 }} {{ car.registrations.text2 }} {{ car.registrations.text3 }}
</td>
</tr>
<tr>
<th>{% trans "Registration Date"|capfirst %}</th>
<td>{{ car.registrations.registration_date|date }}</td>
</tr>
{% else %}
<tr>
<th>{% trans "Registration" %}</th>
<td>
{% if perms.inventory.add_carregistration %}
<button type="button"
class="btn btn-sm btn-phoenix-success"
data-bs-toggle="modal"
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>
{% endif %}
</td>
</tr>
{% endif %}
<tr>
<th>{% trans 'Location'|capfirst %}</th>
<td>
{% if car.marked_price and not car.get_transfer %}
{% if car.location %}
{% if car.location.is_owner_showroom %}
{% trans 'Our Showroom' %}
{% else %}
{{ car.location.showroom.get_local_name }}
{% endif %}
{% if perms.inventory.add_cartransfer %}
<a href="{% url 'update_car_location' car.slug car.location.pk %}"
class="btn btn-phoenix-danger btn-sm">
{% trans "transfer"|capfirst %}
</a>
{% endif %}
{% else %}
{% trans "No location available." %}
{% if perms.inventory.add_carlocation %}
<a href="{% url 'add_car_location' car.slug %}"
class="btn btn-phoenix-success btn-sm ms-2">{% trans "Add" %}</a>
{% endif %}
{% endif %}
{% endif %}
</td>
</tr>
</table>
</div>
<div>
{% if not car.get_transfer %}
{% if perms.inventory.change_car %}
<a href="{% url 'car_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-primary btn-sm mt-1 me-3 mb-3">{% trans "Edit" %}
<span class="fas fa-solid fa-pencil ms-1"></span>
</a>
<a href="{% url 'transfer' car.slug %}"
class="btn btn-phoenix-danger btn-sm">
{% trans "Sell to another dealer"|capfirst %}
</a>
{% endif %}
{% else %}
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
{% endif %}
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="row mb-2">
<div class="col-md-12">
<div class="card rounded shadow d-flex align-content-center {% if car.get_transfer %}transfer{% endif %}">
<p class="card-header rounded-top fw-bold">{% trans 'Financial Details' %}</p>
<div class="card-body">
@ -100,34 +267,7 @@
<th>{% trans "Marked Price"|capfirst %}</th>
<td>{{ car.marked_price|floatformat:2 }}</td>
</tr>
{% comment %} <tr>
<th>{% trans "Selling Price"|capfirst %}</th>
<td>{{ car.finances.selling_price|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Discount Amount"|capfirst %}</th>
<td>{{ car.finances.discount_amount|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Additional Fee"|capfirst %}</th>
<td></td>
</tr>
{% if car.finances.additional_services.first.pk %}
{% for service in car.finances.additional_services.all %}
<tr>
<td>{{ service.name }}</td>
<td>{{ service.price_|floatformat:2 }}</td>
</tr>
{% endfor %}
{% endif %}
<tr>
<th>{% trans "VAT Amount"|capfirst %}</th>
<td>{{ car.finances.vat_amount|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Total"|capfirst %}</th>
<td>{{ car.finances.total_vat|floatformat:2 }}</td>
</tr> {% endcomment %}
<tr>
<td colspan="2">
{% if not car.get_transfer %}
@ -327,173 +467,7 @@
</div>
{% endif %}
</div>
<div class="col-md-6">
<div class="card mb-3 rounded shadow d-flex align-content-center {% if car.get_transfer %}disabled{% endif %}">
<p class="card-header rounded-top fw-bold">{% trans 'Car Details' %}</p>
<div class="card-body">
<div class="table-responsive scrollbar mb-3">
<table class="table table-sm fs-9 mb-0 overflow-hidden">
<tr>
<th>{% trans "VIN" %}</th>
<td>{{ car.vin }}</td>
</tr>
<tr>
<th>{% trans "year"|capfirst %}</th>
<td>{{ car.year }}</td>
</tr>
<tr>
<th>{% trans "make"|capfirst %}</th>
<td>{{ car.id_car_make.get_local_name }}</td>
</tr>
<tr>
<th>{% trans "model"|capfirst %}</th>
<td>{{ car.id_car_model.get_local_name }}</td>
</tr>
<tr>
<th>{% trans "series"|capfirst %}</th>
<td>{{ car.id_car_serie.name }}</td>
</tr>
<tr>
<th>{% trans "trim"|capfirst %}</th>
<td>{{ car.id_car_trim.name }}</td>
</tr>
<tr>
<th>{% trans "Status"|capfirst %}</th>
<td>{{ car.get_status_display }}</td>
</tr>
<tr>
<th>{% trans "Stock Type"|capfirst %}</th>
<td>{{ car.get_stock_type_display }}</td>
</tr>
<tr>
<th>{% trans "Mileage"|capfirst %}</th>
<td>{{ car.mileage }}</td>
</tr>
<tr>
<th>{% trans "Receiving Date"|capfirst %}</th>
<td>{{ car.receiving_date|timesince }}</td>
</tr>
{% if car.vendor %}
<tr>
<th>{% trans "Vendor"|capfirst %}</th>
<td>{{ car.vendor.name }}</td>
</tr>
{% endif %}
<tr>
<th>{% trans "Remarks"|capfirst %}</th>
<td>{{ car.remarks }}</td>
</tr>
<tr>
<th>{% trans 'specifications'|capfirst %}</th>
<td>
<button type="button"
class="btn btn-phoenix-primary btn-sm"
id="specification-btn"
data-bs-toggle="modal"
data-bs-target="#specificationsModal">
{% trans 'view'|capfirst %}
</button>
</td>
</tr>
{% if car.custom_cards %}
<tr>
<th>{% trans "Custom Number"|capfirst %}</th>
<td>{{ car.custom_cards.custom_number }}</td>
</tr>
<tr>
<th>{% trans "Custom Date"|capfirst %}</th>
<td>{{ car.custom_cards.custom_date|date }}</td>
</tr>
{% else %}
<tr>
<th>{% trans "Custom Card" %}</th>
<td>
{% if perms.inventory.add_customcard %}
<button type="button"
class="btn btn-sm btn-phoenix-success"
data-bs-toggle="modal"
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>
{% endif %}
</td>
</tr>
{% endif %}
{% if car.registrations %}
<tr>
<th>{% trans "Registration"|capfirst %}</th>
<td>
{{ car.registrations.plate_number }} | {{ car.registrations.text1 }} {{ car.registrations.text2 }} {{ car.registrations.text3 }}
</td>
</tr>
<tr>
<th>{% trans "Registration Date"|capfirst %}</th>
<td>{{ car.registrations.registration_date|date }}</td>
</tr>
{% else %}
<tr>
<th>{% trans "Registration" %}</th>
<td>
{% if perms.inventory.add_carregistration %}
<button type="button"
class="btn btn-sm btn-phoenix-success"
data-bs-toggle="modal"
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>
{% endif %}
</td>
</tr>
{% endif %}
<tr>
<th>{% trans 'Location'|capfirst %}</th>
<td>
{% if car.marked_price and not car.get_transfer %}
{% if car.location %}
{% if car.location.is_owner_showroom %}
{% trans 'Our Showroom' %}
{% else %}
{{ car.location.showroom.get_local_name }}
{% endif %}
{% if perms.inventory.add_cartransfer %}
<a href="{% url 'update_car_location' car.slug car.location.pk %}"
class="btn btn-phoenix-danger btn-sm">
{% trans "transfer"|capfirst %}
</a>
{% endif %}
{% else %}
{% trans "No location available." %}
{% if perms.inventory.add_carlocation %}
<a href="{% url 'add_car_location' car.slug %}"
class="btn btn-phoenix-success btn-sm ms-2">{% trans "Add" %}</a>
{% endif %}
{% endif %}
{% endif %}
</td>
</tr>
</table>
</div>
<div>
{% if not car.get_transfer %}
{% if perms.inventory.change_car %}
<a href="{% url 'car_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-primary btn-sm mt-1 me-3 mb-3">{% trans "Edit" %}
<span class="fas fa-solid fa-pencil ms-1"></span>
</a>
<a href="{% url 'transfer' car.slug %}"
class="btn btn-phoenix-danger btn-sm">
{% trans "Sell to another dealer"|capfirst %}
</a>
{% endif %}
{% else %}
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% if car.status == 'sold' %}
<img class="car_status"

View File

@ -239,12 +239,12 @@
<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 class="visually-hidden">{% trans "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 class="visually-hidden">{% trans "Not Ready" %}</span>
</span>
<span class="text-danger fw-bold">{{ _("No") }}</span>
{% endif %}
@ -306,3 +306,11 @@
{% include "empty-illustration-page.html" with value="car" url=create_car_url %}
{% endif %}
{% endblock %}
{% block customJS%}
<script>
function toggle_filter() {
const filterContainer = document.querySelector('.filter');
filterContainer.classList.toggle('d-none');
}
</script>
{% endblock %}

View File

@ -5,6 +5,7 @@
{% endblock title %}
{% block content %}
{% if expenses or request.GET.q %}
<div class="row mt-4">
<div class="d-flex justify-content-between mb-2">
<h3 class="">

View File

@ -1,68 +1,37 @@
{% extends 'base.html' %}
{% load i18n crispy_forms_filters %}
{% block title %}
{% trans 'Billing Information' %}
{% trans 'Billing Information' %}
{% endblock %}
{% block content %}
{% comment %} <div class="row mb-3">
<div class="col-sm-6">
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="post" class="form">
<h3>{% trans "Provide billing data"|upper %}</h3>
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-sm btn-phoenix-success me-2">
<i class="fa fa-save me-1"></i>{{ _("Save") }}
</button>
{% if object %}
<a class="btn btn-sm btn-phoenix-danger " href="{% url 'billing_info_delete' %}"><i class="fa-solid fa-trash me-1"></i> {{ _("Delete") }}</a>
{% endif %}
</form>
</div>
</div> {% endcomment %}
<!---->
<div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center">
{% trans "Provide billing data"|upper %}<span class="fas fa-file-invoice-dollar ms-2 text-primary"></span>
</h3>
{% trans 'Billing Information' %}
{% endblock %}
{% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="col-md-8">
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 fw-bold text-center">
{% trans "Provide billing data"|upper %}
<i class="fas fa-file-invoice-dollar ms-2"></i>
</h3>
</div>
<div class="card-body p-4 p-md-5">
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}"
method="post"
class="needs-validation"
novalidate>
{% csrf_token %}
{{ form|crispy }}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'dealer_detail' request.dealer.slug %}"
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="col-md-8">
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 fw-bold text-center">
{% trans "Provide billing data"|upper %}
<i class="fas fa-file-invoice-dollar ms-2"></i>
</h3>
</div>
<div class="card-body p-4 p-md-5">
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}"
method="post" class="needs-validation" novalidate>
{% csrf_token %}
{{ form|crispy }}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'dealer_detail' request.dealer.slug %}"
class="btn btn-lg btn-phoenix-secondary md-me-2"
type="submit"><i class="fa-solid fa-ban me-1"></i>{{ _("Cancel") }}</a>
</div>
</form>
</div>
</div>
</div>
</main>
{% endblock %}
</div>
</form>
</div>
</div>
</div>
</main>
{% endblock %}