This commit is contained in:
Faheedkhan 2025-06-15 20:10:42 +03:00
commit f6d59da008
20 changed files with 1180 additions and 123 deletions

View File

@ -1,4 +1,4 @@
# Generated by Django 5.2.1 on 2025-06-12 16:25 # Generated by Django 5.2.1 on 2025-06-12 14:22
import django.db.models.deletion import django.db.models.deletion
import django.utils.timezone import django.utils.timezone

View File

@ -20,6 +20,9 @@ from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormB
from django_ledger.forms.journal_entry import ( from django_ledger.forms.journal_entry import (
JournalEntryModelCreateForm as JournalEntryModelCreateFormBase, JournalEntryModelCreateForm as JournalEntryModelCreateFormBase,
) )
import csv
from io import TextIOWrapper
from django.utils.translation import gettext_lazy as _
from .models import ( from .models import (
Dealer, Dealer,
@ -1928,3 +1931,66 @@ class ItemInventoryForm(forms.Form):
label=_("Trim"), label=_("Trim"),
) )
#####################################################################
class CSVUploadForm(forms.Form):
dealer = forms.ModelChoiceField(
queryset=Dealer.objects.all(),
label=_('Dealer'),
widget=forms.HiddenInput()
)
vendor = forms.ModelChoiceField(
queryset=Vendor.objects.all(),
label=_('Vendor'),
widget=forms.Select(attrs={'class': 'form-select'}),
required=True
)
year = forms.IntegerField(
label=_('Year'),
widget=forms.NumberInput(attrs={'class': 'form-control'}),
required=True
)
exterior = forms.ModelChoiceField(
queryset=ExteriorColors.objects.all(),
label=_('Exterior Color'),
widget=forms.RadioSelect(attrs={'class': 'form-select'}),
required=True
)
interior = forms.ModelChoiceField(
queryset=InteriorColors.objects.all(),
label=_('Interior Color'),
widget=forms.RadioSelect(attrs={'class': 'form-select'}),
required=True
)
receiving_date = forms.DateField(
label=_('Receiving Date'),
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
required=True
)
def clean_csv_file(self):
csv_file = self.cleaned_data['csv_file']
if not csv_file.name.endswith('.csv'):
raise forms.ValidationError(_('File is not a CSV file'))
# Read and validate CSV structure
try:
csv_data = TextIOWrapper(csv_file.file, encoding='utf-8')
reader = csv.DictReader(csv_data)
required_fields = ['vin', 'make', 'model', 'year']
if not all(field in reader.fieldnames for field in required_fields):
missing = set(required_fields) - set(reader.fieldnames)
raise forms.ValidationError(
_('CSV is missing required columns: %(missing)s'),
params={'missing': ', '.join(missing)}
)
except Exception as e:
raise forms.ValidationError(_('Error reading CSV file: %(error)s') % {'error': str(e)})
# Reset file pointer for later processing
csv_file.file.seek(0)
return csv_file

View File

@ -712,7 +712,9 @@ class Car(Base):
.filter(name=f"Cogs:{self.id_car_make.name}") .filter(name=f"Cogs:{self.id_car_make.name}")
.first() .first()
) )
def add_colors(self,exterior,interior):
self.colors = CarColors.objects.create(car=self,exterior=exterior,interior=interior)
self.save()
class CarTransfer(models.Model): class CarTransfer(models.Model):
car = models.ForeignKey( car = models.ForeignKey(

View File

@ -234,7 +234,7 @@ urlpatterns = [
name="fetch_notifications", name="fetch_notifications",
), ),
path( path(
"crm/notifications/<int:pk>/mark_as_read/", "crm/notifications/<int:notification_id>/mark_as_read/",
views.mark_notification_as_read, views.mark_notification_as_read,
name="mark_notification_as_read", name="mark_notification_as_read",
), ),
@ -254,6 +254,8 @@ urlpatterns = [
name="vendor_delete", name="vendor_delete",
), ),
# Car URLs # Car URLs
path('cars/upload_cars/', views.upload_cars, name='upload_cars'),
path('cars/<uuid:po_pk>/upload_cars/', views.upload_cars, name='upload_cars'),
path("cars/add/", views.CarCreateView.as_view(), name="car_add"), path("cars/add/", views.CarCreateView.as_view(), name="car_add"),
path("cars/inventory/", views.CarInventory.as_view(), name="car_inventory_all"), path("cars/inventory/", views.CarInventory.as_view(), name="car_inventory_all"),
path( path(
@ -696,13 +698,13 @@ path(
path("items/bills/", views.BillListView.as_view(), name="bill_list"), path("items/bills/", views.BillListView.as_view(), name="bill_list"),
# path("items/bills/create/", views.BillModelCreateViewView.as_view(), name="bill_create"), # path("items/bills/create/", views.BillModelCreateViewView.as_view(), name="bill_create"),
path('items/bills/<slug:entity_slug>/create/', path('items/bills/<slug:entity_slug>/create/',
views.BillModelCreateViewView.as_view(), views.BillModelCreateView.as_view(),
name='bill-create'), name='bill-create'),
path('items/bills/<slug:entity_slug>/create/purchase-order/<uuid:po_pk>/', path('items/bills/<slug:entity_slug>/create/purchase-order/<uuid:po_pk>/',
views.BillModelCreateViewView.as_view(for_purchase_order=True), views.BillModelCreateView.as_view(for_purchase_order=True),
name='bill-create-po'), name='bill-create-po'),
path('items/bills/<slug:entity_slug>/create/estimate/<uuid:ce_pk>/', path('items/bills/<slug:entity_slug>/create/estimate/<uuid:ce_pk>/',
views.BillModelCreateViewView.as_view(for_estimate=True), views.BillModelCreateView.as_view(for_estimate=True),
name='bill-create-estimate'), name='bill-create-estimate'),
path('items/bills/<slug:entity_slug>/detail/<uuid:bill_pk>/', path('items/bills/<slug:entity_slug>/detail/<uuid:bill_pk>/',
views.BillModelDetailViewView.as_view(), views.BillModelDetailViewView.as_view(),
@ -769,7 +771,6 @@ path(
name="bill_mark_as_paid", name="bill_mark_as_paid",
), ),
# orders # orders
path("orders/", views.OrderListView.as_view(), name="order_list_view"), path("orders/", views.OrderListView.as_view(), name="order_list_view"),
@ -858,7 +859,7 @@ path(
path('management/<str:content_type>/<slug:slug>/permenant_delete_account/', views.permenant_delete_account, name='permenant_delete_account'), path('management/<str:content_type>/<slug:slug>/permenant_delete_account/', views.permenant_delete_account, name='permenant_delete_account'),
path('management/audit_log_dashboard/', views.AuditLogDashboardView, name='audit_log_dashboard'), path('management/audit_log_dashboard/', views.AuditLogDashboardView, name='audit_log_dashboard'),
######### #########
# Purchase Order # Purchase Order
path('purchase_orders/', views.PurchaseOrderListView.as_view(), name='purchase_order_list'), path('purchase_orders/', views.PurchaseOrderListView.as_view(), name='purchase_order_list'),

View File

@ -1,14 +1,19 @@
# Standard # Standard
import os
import io
import csv
import cv2 import cv2
import json import json
import logging import logging
from datetime import datetime import tempfile
from time import sleep
import numpy as np import numpy as np
from time import sleep
# from rich import print # from rich import print
from random import randint from random import randint
from decimal import Decimal from decimal import Decimal
from io import TextIOWrapper
from django.apps import apps from django.apps import apps
from datetime import datetime
from calendar import month_name from calendar import month_name
from pyzbar.pyzbar import decode from pyzbar.pyzbar import decode
from urllib.parse import urlparse, urlunparse from urllib.parse import urlparse, urlunparse
@ -17,6 +22,7 @@ from urllib.parse import urlparse, urlunparse
from inventory.models import Status as LeadStatus from inventory.models import Status as LeadStatus
from django.db import IntegrityError from django.db import IntegrityError
from background_task.models import Task from background_task.models import Task
from django.views.generic import FormView
from django.db.models.deletion import RestrictedError from django.db.models.deletion import RestrictedError
from django.http.response import StreamingHttpResponse from django.http.response import StreamingHttpResponse
from django.core.exceptions import ImproperlyConfigured, ValidationError from django.core.exceptions import ImproperlyConfigured, ValidationError
@ -26,7 +32,7 @@ from django.db.models import Q
from django.conf import settings from django.conf import settings
from django.db.models import Func from django.db.models import Func
from django.contrib import messages from django.contrib import messages
from django.http import Http404, HttpResponseNotFound, HttpResponseRedirect, JsonResponse, HttpResponseForbidden from django.http import Http404, HttpResponseBadRequest, HttpResponseNotFound, HttpResponseRedirect, JsonResponse, HttpResponseForbidden
from django.forms import HiddenInput, ValidationError from django.forms import HiddenInput, ValidationError
from django.shortcuts import HttpResponse from django.shortcuts import HttpResponse
@ -85,15 +91,17 @@ from django_ledger.forms.bank_account import (
BankAccountUpdateForm, BankAccountUpdateForm,
) )
from django_ledger.views.bill import ( from django_ledger.views.bill import (
BillModelCreateView, # BillModelCreateView,
BillModelDetailView, BillModelDetailView,
BillModelUpdateView, BillModelUpdateView,
BaseBillActionView as BaseBillActionViewBase, BaseBillActionView as BaseBillActionViewBase,
BillModelModelBaseView
) )
from django_ledger.forms.bill import ( from django_ledger.forms.bill import (
ApprovedBillModelUpdateForm, ApprovedBillModelUpdateForm,
InReviewBillModelUpdateForm, InReviewBillModelUpdateForm,
get_bill_itemtxs_formset_class, get_bill_itemtxs_formset_class,
BillModelCreateForm
) )
from django_ledger.forms.invoice import ( from django_ledger.forms.invoice import (
@ -980,23 +988,23 @@ class CarColorsUpdateView( LoginRequiredMixin, PermissionRequiredMixin, SuccessM
template_name = "inventory/add_colors.html" template_name = "inventory/add_colors.html"
success_message = _("Car Colors details updated successfully") success_message = _("Car Colors details updated successfully")
permission_required = ["inventory.change_car"] permission_required = ["inventory.change_car"]
def get_object(self, queryset=None): def get_object(self, queryset=None):
""" """
Retrieves the CarColors instance associated with the Car slug from the URL. Retrieves the CarColors instance associated with the Car slug from the URL.
This ensures we are updating the colors for the correct car. This ensures we are updating the colors for the correct car.
""" """
# Get the car_slug from the URL keywords arguments # Get the car_slug from the URL keywords arguments
slug = self.kwargs.get('slug') slug = self.kwargs.get('slug')
# If no car_slug is provided, it's an invalid request # If no car_slug is provided, it's an invalid request
if not slug: if not slug:
# You might want to raise Http404 or a more specific error here # You might want to raise Http404 or a more specific error here
raise ValueError("Car slug is required to identify the colors to update.") raise ValueError("Car slug is required to identify the colors to update.")
return get_object_or_404(models.CarColors, car__slug=slug) return get_object_or_404(models.CarColors, car__slug=slug)
def get_success_url(self): def get_success_url(self):
@ -1008,7 +1016,7 @@ class CarColorsUpdateView( LoginRequiredMixin, PermissionRequiredMixin, SuccessM
return reverse("car_detail", kwargs={"slug": self.object.car.slug}) return reverse("car_detail", kwargs={"slug": self.object.car.slug})
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
""" """
Adds the related Car object to the template context. Adds the related Car object to the template context.
""" """
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -6118,6 +6126,7 @@ class BillDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
permission_required = ["django_ledger.view_billmodel"] permission_required = ["django_ledger.view_billmodel"]
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
dealer = get_user_type(self.request)
bill = kwargs.get("object") bill = kwargs.get("object")
if bill.get_itemtxs_data(): if bill.get_itemtxs_data():
txs = bill.get_itemtxs_data()[0] txs = bill.get_itemtxs_data()[0]
@ -6133,6 +6142,7 @@ class BillDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
kwargs["transactions"] = transactions kwargs["transactions"] = transactions
kwargs["grand_total"] = grand_total kwargs["grand_total"] = grand_total
kwargs["entity"] = dealer.entity
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
@ -6307,13 +6317,299 @@ def bill_mark_as_paid(request, pk):
return redirect("bill_detail", pk=bill.pk) return redirect("bill_detail", pk=bill.pk)
# class BillModelCreateViewView(Create):
# template_name = 'bill/bill_create.html'
class BillModelCreateViewView(BillModelCreateView): # def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# context["entity"] = get_user_type(self.request).entity
# return context
# def post(self, request, *args, **kwargs):
# """
# Completely override the post method to ensure our form handling is called
# """
# print("Custom post method called") # Debugging
# form = self.get_form()
# if form.is_valid():
# return self.custom_form_valid(form)
# else:
# return self.form_invalid(form)
# def custom_form_valid(self, form):
# """
# Our own form_valid implementation that will definitely be called
# """
# print("Custom form_valid called") # Debugging
# # Handle PO case
# if self.for_purchase_order:
# print("Handling PO case") # Debugging
# return self.handle_po_case(form)
# # Handle Estimate case
# if self.for_estimate:
# print("Handling Estimate case") # Debugging
# return self.handle_estimate_case(form)
# # Default case
# print("Handling default case") # Debugging
# return self.handle_default_case(form)
# def handle_po_case(self, form):
# """Special handling for purchase orders"""
# po_pk = self.kwargs['po_pk']
# item_uuids = self.request.GET.get('item_uuids', '').split(',')
# if not item_uuids or not all(item_uuids):
# return HttpResponseBadRequest()
# # Create bill
# bill_model = form.save(commit=False)
# ledger_model, bill_model = bill_model.configure(
# entity_slug=self.AUTHORIZED_ENTITY_MODEL,
# commit_ledger=True
# )
# # Get PO
# po_qs = PurchaseOrderModel.objects.for_entity(
# entity_slug=self.kwargs['entity_slug'],
# user_model=self.request.user
# )
# po_model = get_object_or_404(po_qs, uuid__exact=po_pk)
# # Validate
# try:
# bill_model.can_bind_po(po_model, raise_exception=True)
# except ValidationError as e:
# messages.error(self.request, e.message)
# return self.render_to_response(self.get_context_data(form=form))
# # Update models
# po_model_items_qs = po_model.itemtransactionmodel_set.filter(uuid__in=item_uuids)
# if po_model.is_contract_bound():
# bill_model.ce_model_id = po_model.ce_model_id
# bill_model.update_amount_due()
# bill_model.get_state(commit=True)
# bill_model.clean()
# bill_model.save()
# po_model_items_qs.update(bill_model=bill_model)
# # Redirect to our custom URL
# return HttpResponseRedirect(
# reverse('purchase_order_update',
# kwargs={
# 'entity_slug': self.kwargs['entity_slug'],
# 'po_pk': po_pk
# })
# )
# def handle_estimate_case(self, form):
# """Special handling for estimates"""
# bill_model = form.save(commit=False)
# ledger_model, bill_model = bill_model.configure(
# entity_slug=self.AUTHORIZED_ENTITY_MODEL,
# commit_ledger=True
# )
# ce_pk = self.kwargs['ce_pk']
# estimate_model_qs = EstimateModel.objects.for_entity(
# entity_slug=self.kwargs['entity_slug'],
# user_model=self.request.user
# )
# estimate_model = get_object_or_404(estimate_model_qs, uuid__exact=ce_pk)
# bill_model.bind_estimate(estimate_model=estimate_model, commit=True)
# # Redirect to our custom URL
# return HttpResponseRedirect(
# reverse('estimate_detail',
# kwargs={
# 'pk': ce_pk
# })
# )
# def handle_default_case(self, form):
# """Default form handling"""
# bill_model = form.save(commit=False)
# ledger_model, bill_model = bill_model.configure(
# entity_slug=self.AUTHORIZED_ENTITY_MODEL,
# commit_ledger=True
# )
# bill_model.save()
# # Redirect to our custom URL
# return HttpResponseRedirect(
# reverse('bill-detail',
# kwargs={
# 'entity_slug': self.kwargs['entity_slug'],
# 'bill_pk': bill_model.uuid
# })
# )
class BillModelCreateView(CreateView):
template_name = 'bill/bill_create.html' template_name = 'bill/bill_create.html'
PAGE_TITLE = _('Create Bill')
extra_context = {
'page_title': PAGE_TITLE,
'header_title': PAGE_TITLE,
'header_subtitle_icon': 'uil:bill'
}
for_purchase_order = False
for_estimate = False
def get(self, request, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
if self.for_estimate and 'ce_pk' in self.kwargs:
estimate_qs = EstimateModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'],
user_model=self.request.user
)
estimate_model: EstimateModel = get_object_or_404(estimate_qs, uuid__exact=self.kwargs['ce_pk'])
if not estimate_model.can_bind():
return HttpResponseNotFound('404 Not Found')
return super(BillModelCreateView, self).get(request, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super(BillModelCreateView, self).get_context_data(**kwargs)
context["entity"] = get_user_type(self.request).entity
if self.for_purchase_order:
po_pk = self.kwargs['po_pk']
po_item_uuids_qry_param = self.request.GET.get('item_uuids')
if po_item_uuids_qry_param:
try:
po_item_uuids = po_item_uuids_qry_param.split(',')
except:
return HttpResponseBadRequest()
else:
return HttpResponseBadRequest()
po_qs = PurchaseOrderModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'],
user_model=self.request.user
).prefetch_related('itemtransactionmodel_set')
po_model: PurchaseOrderModel = get_object_or_404(po_qs, uuid__exact=po_pk)
po_itemtxs_qs = po_model.itemtransactionmodel_set.filter(
bill_model__isnull=True,
uuid__in=po_item_uuids
)
context['po_model'] = po_model
context['po_itemtxs_qs'] = po_itemtxs_qs
form_action = reverse('bill-create-po',
kwargs={
'entity_slug': self.kwargs['entity_slug'],
'po_pk': po_model.uuid
}) + f'?item_uuids={po_item_uuids_qry_param}'
elif self.for_estimate:
estimate_qs = EstimateModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'],
user_model=self.request.user
)
estimate_uuid = self.kwargs['ce_pk']
estimate_model: EstimateModel = get_object_or_404(estimate_qs, uuid__exact=estimate_uuid)
form_action = reverse('bill-create-estimate',
kwargs={
'entity_slug': self.kwargs['entity_slug'],
'ce_pk': estimate_model.uuid
})
else:
form_action = reverse('bill-create',
kwargs={
'entity_slug': self.kwargs['entity_slug'],
})
context['form_action_url'] = form_action
return context return context
def get_initial(self):
return {
'date_draft': get_localdate()
}
def get_form(self, form_class=None):
dealer = get_user_type(self.request)
return BillModelCreateForm(
entity_model=dealer.entity,
**self.get_form_kwargs()
)
def form_valid(self, form):
dealer = get_user_type(self.request)
bill_model: BillModel = form.save(commit=False)
ledger_model, bill_model = bill_model.configure(
entity_slug=dealer.entity.slug,
user_model=self.request.user,
commit_ledger=True
)
if self.for_estimate:
ce_pk = self.kwargs['ce_pk']
estimate_model_qs = EstimateModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'],
user_model=self.request.user)
estimate_model = get_object_or_404(estimate_model_qs, uuid__exact=ce_pk)
bill_model.bind_estimate(estimate_model=estimate_model, commit=False)
elif self.for_purchase_order:
po_pk = self.kwargs['po_pk']
item_uuids = self.request.GET.get('item_uuids')
if not item_uuids:
return HttpResponseBadRequest()
item_uuids = item_uuids.split(',')
po_qs = PurchaseOrderModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'],
user_model=self.request.user
)
po_model: PurchaseOrderModel = get_object_or_404(po_qs, uuid__exact=po_pk)
try:
bill_model.can_bind_po(po_model, raise_exception=True)
except ValidationError as e:
messages.add_message(self.request,
message=e.message,
level=messages.ERROR,
extra_tags='is-danger')
return self.render_to_response(self.get_context_data(form=form))
po_model_items_qs = po_model.itemtransactionmodel_set.filter(uuid__in=item_uuids)
if po_model.is_contract_bound():
bill_model.ce_model_id = po_model.ce_model_id
bill_model.update_amount_due()
bill_model.get_state(commit=True)
bill_model.clean()
bill_model.save()
po_model_items_qs.update(bill_model=bill_model)
return HttpResponseRedirect(self.get_success_url())
return super(BillModelCreateView, self).form_valid(form)
def get_success_url(self):
entity_slug = self.kwargs['entity_slug']
if self.for_purchase_order:
po_pk = self.kwargs['po_pk']
return reverse('purchase_order_update',
kwargs={
'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']
})
bill_model: BillModel = self.object
return reverse('bill-detail',
kwargs={
'entity_slug': entity_slug,
'bill_pk': bill_model.uuid
})
class BillModelDetailViewView(BillModelDetailView): class BillModelDetailViewView(BillModelDetailView):
template_name = 'bill/bill_detail.html' template_name = 'bill/bill_detail.html'
class BillModelUpdateViewView(BillModelUpdateView): class BillModelUpdateViewView(BillModelUpdateView):
@ -8385,7 +8681,7 @@ def AuditLogDashboardView(request):
page_obj = paginator.page(1) page_obj = paginator.page(1)
except EmptyPage: except EmptyPage:
page_obj = paginator.page(paginator.num_pages) page_obj = paginator.page(paginator.num_pages)
elif q == 'loginEvents': elif q == 'loginEvents':
template_name = 'admin_management/auth_logs.html' template_name = 'admin_management/auth_logs.html'
@ -8408,7 +8704,7 @@ def AuditLogDashboardView(request):
# 1. Paginate the raw QuerySet FIRST # 1. Paginate the raw QuerySet FIRST
paginator = Paginator(model_events_queryset, logs_per_page) paginator = Paginator(model_events_queryset, logs_per_page)
try: try:
# Get the page object, which contains only the raw QuerySet objects for the current page # Get the page object, which contains only the raw QuerySet objects for the current page
page_obj_raw = paginator.page(current_pagination_page) page_obj_raw = paginator.page(current_pagination_page)
@ -8462,18 +8758,18 @@ def AuditLogDashboardView(request):
'new': 'Invalid JSON in changed_fields' 'new': 'Invalid JSON in changed_fields'
}) })
processed_model_events_for_page.append(event_data) processed_model_events_for_page.append(event_data)
# 3. Replace the object_list of the original page_obj with the processed data # 3. Replace the object_list of the original page_obj with the processed data
# This keeps all pagination properties (has_next, number, etc.) intact. # This keeps all pagination properties (has_next, number, etc.) intact.
page_obj_raw.object_list = processed_model_events_for_page page_obj_raw.object_list = processed_model_events_for_page
page_obj = page_obj_raw # This will be passed to the context page_obj = page_obj_raw # This will be passed to the context
# Pass the final page object to the context # Pass the final page object to the context
context['page_obj'] = page_obj context['page_obj'] = page_obj
return render(request, template_name, context) return render(request, template_name, context)
def activate_account(request, content_type, slug): def activate_account(request, content_type, slug):
@ -8533,6 +8829,7 @@ def PurchaseOrderCreateView(request):
return render(request, "purchase_orders/po_form.html", {"form": form}) return render(request, "purchase_orders/po_form.html", {"form": form})
def InventoryItemCreateView(request): def InventoryItemCreateView(request):
for_po = request.GET.get('for_po')
dealer = get_user_type(request) dealer = get_user_type(request)
entity = dealer.entity entity = dealer.entity
coa = entity.get_default_coa() coa = entity.get_default_coa()
@ -8552,13 +8849,16 @@ def InventoryItemCreateView(request):
model = request.POST.get("model") model = request.POST.get("model")
serie = request.POST.get("serie") serie = request.POST.get("serie")
trim = request.POST.get("trim") trim = request.POST.get("trim")
year = request.POST.get("year")
exterior = models.ExteriorColors.objects.get(pk=request.POST.get("exterior"))
interior = models.InteriorColors.objects.get(pk=request.POST.get("interior"))
make_name = models.CarMake.objects.get(pk=make) make_name = models.CarMake.objects.get(pk=make)
model_name = models.CarModel.objects.get(pk=model) model_name = models.CarModel.objects.get(pk=model)
serie_name = models.CarSerie.objects.get(pk=serie) serie_name = models.CarSerie.objects.get(pk=serie)
trim_name = models.CarTrim.objects.get(pk=trim) trim_name = models.CarTrim.objects.get(pk=trim)
inventory_name = f"{make_name.name} - {model_name.name} - {serie_name.name} - {trim_name.name}" inventory_name = f"{make_name.name} - {model_name.name} - {serie_name.name} - {trim_name.name} - {year} - {exterior.name} - {interior.name}"
uom = entity.get_uom_all().get(name='Unit') uom = entity.get_uom_all().get(name='Unit')
entity.create_item_inventory( entity.create_item_inventory(
name=inventory_name, name=inventory_name,
@ -8569,6 +8869,10 @@ def InventoryItemCreateView(request):
) )
messages.success(request, _("Inventory item created successfully")) messages.success(request, _("Inventory item created successfully"))
return redirect('purchase_order_list') return redirect('purchase_order_list')
if for_po:
form = forms.CSVUploadForm()
context = {"make_data":models.CarMake.objects.all(),"inventory_accounts":inventory_accounts,"cogs_accounts":cogs_accounts,"form":form}
return render(request,'purchase_orders/car_inventory_item_form.html',context)
return render(request,'purchase_orders/inventory_item_form.html',{"make_data":models.CarMake.objects.all(),"inventory_accounts":inventory_accounts,"cogs_accounts":cogs_accounts}) return render(request,'purchase_orders/inventory_item_form.html',{"make_data":models.CarMake.objects.all(),"inventory_accounts":inventory_accounts,"cogs_accounts":cogs_accounts})
@ -8878,4 +9182,64 @@ class BillModelActionUnlockLedgerView(BaseBillActionView):
class BillModelActionForceMigrateView(BaseBillActionView): class BillModelActionForceMigrateView(BaseBillActionView):
action_name = 'migrate_state' action_name = 'migrate_state'
###############################################################
###############################################################
def upload_cars(request,po_pk=None):
dealer = get_user_type(request)
if request.method == 'POST':
csv_file = request.FILES.get('csv_file')
year = request.POST.get("year")
receiving_date = datetime.strptime(request.POST.get("receiving_date"), "%Y-%m-%d")
receiving_date = timezone.make_aware(receiving_date)
try:
make = models.CarMake.objects.get(pk=request.POST.get("make"))
model = models.CarModel.objects.get(pk=request.POST.get("model"))
serie = models.CarSerie.objects.get(pk=request.POST.get("serie"))
trim = models.CarTrim.objects.get(pk=request.POST.get("trim"))
vendor = models.Vendor.objects.get(pk=request.POST.get("vendor"))
exterior = models.ExteriorColors.objects.get(pk=request.POST.get("exterior"))
interior = models.InteriorColors.objects.get(pk=request.POST.get("interior"))
except Exception as e:
messages.error(request, f"Error processing CSV: {str(e)}")
if po_pk:
return redirect('upload_cars',po_pk=po_pk)
else:
return redirect('upload_cars')
if not csv_file.name.endswith('.csv'):
messages.error(request, "Please upload a CSV file")
return redirect('upload_cars')
try:
# Read the file content
file_content = csv_file.read().decode('utf-8')
csv_data = io.StringIO(file_content)
reader = csv.DictReader(csv_data)
cars_created = 0
for row in reader:
car = models.Car.objects.create(
dealer=dealer,
vin=row['vin'],
id_car_make=make,
id_car_model=model,
id_car_serie=serie,
id_car_trim=trim,
year=year,
vendor=vendor,
receiving_date=receiving_date,
)
car.add_colors(exterior=exterior, interior=interior)
cars_created += 1
messages.success(request, f"Successfully imported {cars_created} cars")
return redirect('car_list') # redirect to your car list view
except Exception as e:
messages.error(request, f"Error processing CSV: {str(e)}")
form = forms.CSVUploadForm()
return render(request, 'csv_upload.html',{"make_data":models.CarMake.objects.all(),"form":form})
###############################################################
###############################################################

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-13 02:11+0300\n" "POT-Creation-Date: 2025-06-15 19:29+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -32,32 +32,34 @@ msgstr ""
#: templates/sales/estimates/sale_order_form.html:122 #: templates/sales/estimates/sale_order_form.html:122
#: templates/sales/estimates/sale_order_preview.html:178 #: templates/sales/estimates/sale_order_preview.html:178
#: templates/sales/invoices/invoice_detail.html:241 #: templates/sales/invoices/invoice_detail.html:241
#: templates/sales/orders/order_details.html:201
#: templates/sales/orders/order_details.html:486
#: templates/sales/sales_list.html:115 #: templates/sales/sales_list.html:115
msgid "VIN" msgid "VIN"
msgstr "رقم الهيكل" msgstr "رقم الهيكل"
#: api/views.py:146 inventory/views.py:681 #: api/views.py:147 inventory/views.py:681
msgid "Invalid VIN number provided" msgid "Invalid VIN number provided"
msgstr "تم تقديم رقم تعريف مركبة (VIN) غير صالح" msgstr "تم تقديم رقم تعريف مركبة (VIN) غير صالح"
#: api/views.py:154 #: api/views.py:155
msgid "VIN not found in any source" msgid "VIN not found in any source"
msgstr "لم يتم العثور على رقم الهيكل (VIN) في أي مصدر" msgstr "لم يتم العثور على رقم الهيكل (VIN) في أي مصدر"
#: car_inventory/settings.py:174 #: car_inventory/settings.py:173
msgid "SAR" msgid "SAR"
msgstr "ريال" msgstr "ريال"
#: car_inventory/settings.py:270 #: car_inventory/settings.py:269
#: venv/lib/python3.11/site-packages/appointments/settings.py:136 #: venv/lib/python3.11/site-packages/appointments/settings.py:136
msgid "English" msgid "English"
msgstr "الإنجليزية" msgstr "الإنجليزية"
#: car_inventory/settings.py:271 #: car_inventory/settings.py:270
msgid "Arabic" msgid "Arabic"
msgstr "العربية" msgstr "العربية"
#: car_inventory/settings.py:360 templates/header.html:358 #: car_inventory/settings.py:359 templates/header.html:358
#: templates/welcome-temp.html:57 templates/welcome_header.html:7 #: templates/welcome-temp.html:57 templates/welcome_header.html:7
msgid "Haikal" msgid "Haikal"
msgstr "هيكل" msgstr "هيكل"
@ -358,6 +360,7 @@ msgstr "الكمية"
#: templates/plans/create_order.html:29 templates/plans/invoices/layout.html:11 #: templates/plans/create_order.html:29 templates/plans/invoices/layout.html:11
#: templates/sales/invoices/invoice_create.html:5 #: templates/sales/invoices/invoice_create.html:5
#: templates/sales/invoices/invoice_detail.html:69 #: templates/sales/invoices/invoice_detail.html:69
#: templates/sales/orders/order_details.html:439
#: templates/sales/orders/order_list.html:17 #: templates/sales/orders/order_list.html:17
#: templates/sales/payments/payment_list.html:21 #: templates/sales/payments/payment_list.html:21
#: templates/sales/sales_list.html:119 #: templates/sales/sales_list.html:119
@ -413,6 +416,7 @@ msgid "SADAD"
msgstr "سداد" msgstr "سداد"
#: inventory/forms.py:1009 templates/sales/estimates/sale_order_form.html:177 #: inventory/forms.py:1009 templates/sales/estimates/sale_order_form.html:177
#: templates/sales/orders/order_details.html:128
msgid "Payment Method" msgid "Payment Method"
msgstr "طريقة الدفع" msgstr "طريقة الدفع"
@ -446,6 +450,7 @@ msgstr "إلى"
#: templates/sales/estimates/sale_order_form.html:124 #: templates/sales/estimates/sale_order_form.html:124
#: templates/sales/estimates/sale_order_preview.html:179 #: templates/sales/estimates/sale_order_preview.html:179
#: templates/sales/invoices/invoice_detail.html:238 #: templates/sales/invoices/invoice_detail.html:238
#: templates/sales/orders/order_details.html:189
#: templates/sales/sales_list.html:113 #: templates/sales/sales_list.html:113
msgid "Make" msgid "Make"
msgstr "الصانع" msgstr "الصانع"
@ -460,6 +465,7 @@ msgstr "الصانع"
#: templates/sales/estimates/sale_order_form.html:126 #: templates/sales/estimates/sale_order_form.html:126
#: templates/sales/estimates/sale_order_preview.html:180 #: templates/sales/estimates/sale_order_preview.html:180
#: templates/sales/invoices/invoice_detail.html:239 #: templates/sales/invoices/invoice_detail.html:239
#: templates/sales/orders/order_details.html:193
#: templates/sales/sales_list.html:114 #: templates/sales/sales_list.html:114
msgid "Model" msgid "Model"
msgstr "الموديل" msgstr "الموديل"
@ -908,6 +914,7 @@ msgstr "المورد"
#: templates/sales/estimates/sale_order_form.html:128 #: templates/sales/estimates/sale_order_form.html:128
#: templates/sales/estimates/sale_order_preview.html:181 #: templates/sales/estimates/sale_order_preview.html:181
#: templates/sales/invoices/invoice_detail.html:240 #: templates/sales/invoices/invoice_detail.html:240
#: templates/sales/orders/order_details.html:197
msgid "Year" msgid "Year"
msgstr "السنة" msgstr "السنة"
@ -932,6 +939,7 @@ msgstr "ملاحظات"
#: templates/inventory/car_form.html:177 #: templates/inventory/car_form.html:177
#: templates/inventory/car_form_qabl alfalsafa.html:157 #: templates/inventory/car_form_qabl alfalsafa.html:157
#: templates/inventory/car_list.html:197 templates/inventory/car_list.html:203 #: templates/inventory/car_list.html:197 templates/inventory/car_list.html:203
#: templates/sales/orders/order_details.html:205
msgid "Mileage" msgid "Mileage"
msgstr "عدد الكيلومترات" msgstr "عدد الكيلومترات"
@ -1065,6 +1073,7 @@ msgstr "وصف اختياري حول وضع السيارة في صالة الع
#: inventory/models.py:965 #: inventory/models.py:965
#: templates/crm/opportunities/opportunity_detail.html:139 #: templates/crm/opportunities/opportunity_detail.html:139
#: templates/sales/orders/order_details.html:148
msgid "Last Updated" msgid "Last Updated"
msgstr "آخر تحديث" msgstr "آخر تحديث"
@ -1384,11 +1393,13 @@ msgstr "إلغاء العرض"
msgid "Create Order" msgid "Create Order"
msgstr "إنشاء طلب" msgstr "إنشاء طلب"
#: inventory/models.py:1276 #: inventory/models.py:1276 templates/sales/orders/order_details.html:389
#: templates/sales/orders/order_details.html:528
msgid "Cancel Order" msgid "Cancel Order"
msgstr "إلغاء الطلب" msgstr "إلغاء الطلب"
#: inventory/models.py:1277 templates/sales/estimates/estimate_detail.html:108 #: inventory/models.py:1277 templates/sales/estimates/estimate_detail.html:108
#: templates/sales/orders/order_details.html:377
#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/invoice_create.html:24 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/invoice_create.html:24
#: venv/lib/python3.11/site-packages/django_ledger/views/invoice.py:68 #: venv/lib/python3.11/site-packages/django_ledger/views/invoice.py:68
msgid "Create Invoice" msgid "Create Invoice"
@ -1402,6 +1413,7 @@ msgstr "إلغاء الفاتورة"
msgid "Qualification" msgid "Qualification"
msgstr "التأهيل" msgstr "التأهيل"
#: inventory/models.py:1283
msgid "Test Drive" msgid "Test Drive"
msgstr "تجربة القيادة" msgstr "تجربة القيادة"
@ -1409,6 +1421,7 @@ msgstr "تجربة القيادة"
#: templates/sales/estimates/estimate_detail.html:79 #: templates/sales/estimates/estimate_detail.html:79
#: templates/sales/estimates/estimate_send.html:5 #: templates/sales/estimates/estimate_send.html:5
#: templates/sales/estimates/sale_order_form.html:171 #: templates/sales/estimates/sale_order_form.html:171
#: templates/sales/orders/order_details.html:431
#: templates/sales/sales_list.html:118 #: templates/sales/sales_list.html:118
msgid "Quotation" msgid "Quotation"
msgstr "عرض سعر" msgstr "عرض سعر"
@ -1478,6 +1491,8 @@ msgstr "الصورة"
#: templates/sales/estimates/sale_order_preview.html:167 #: templates/sales/estimates/sale_order_preview.html:167
#: templates/sales/invoices/invoice_list.html:16 #: templates/sales/invoices/invoice_list.html:16
#: templates/sales/journals/journal_list.html:16 #: templates/sales/journals/journal_list.html:16
#: templates/sales/orders/order_details.html:124
#: templates/sales/orders/order_details.html:461
#: templates/sales/orders/order_list.html:15 #: templates/sales/orders/order_list.html:15
#: venv/lib/python3.11/site-packages/django_ledger/models/customer.py:189 #: venv/lib/python3.11/site-packages/django_ledger/models/customer.py:189
#: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:252 #: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:252
@ -1653,6 +1668,7 @@ msgstr "المُعرّف الفريد للفرصة (slug)."
#: inventory/models.py:2008 templates/crm/leads/lead_detail.html:110 #: inventory/models.py:2008 templates/crm/leads/lead_detail.html:110
#: templates/crm/leads/lead_list.html:75 templates/header.html:148 #: templates/crm/leads/lead_list.html:75 templates/header.html:148
#: templates/sales/orders/order_details.html:453
msgid "Opportunity" msgid "Opportunity"
msgstr "فرصة" msgstr "فرصة"
@ -1680,6 +1696,7 @@ msgstr "ملاحظة"
#: templates/crm/opportunities/opportunity_detail.html:329 #: templates/crm/opportunities/opportunity_detail.html:329
#: templates/customers/view_customer.html:192 #: templates/customers/view_customer.html:192
#: templates/plans/invoices/layout.html:175 #: templates/plans/invoices/layout.html:175
#: templates/sales/orders/order_details.html:568
#: venv/lib/python3.11/site-packages/django_ledger/forms/bill.py:154 #: venv/lib/python3.11/site-packages/django_ledger/forms/bill.py:154
#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/includes/card_markdown.html:9 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/includes/card_markdown.html:9
msgid "Notes" msgid "Notes"
@ -2194,6 +2211,8 @@ msgstr "المخزون"
msgid "Car Colors details updated successfully" msgid "Car Colors details updated successfully"
msgstr "تم تحديث تفاصيل ألوان السيارة بنجاح" msgstr "تم تحديث تفاصيل ألوان السيارة بنجاح"
#: inventory/views.py:1017
#, python-format
msgid "Update Colors for %(car_name)s" msgid "Update Colors for %(car_name)s"
msgstr "تحديث الألوان لـ %(car_name)s" msgstr "تحديث الألوان لـ %(car_name)s"
@ -2334,7 +2353,8 @@ msgstr "لقد وصلت إلى الحد الأقصى لعدد أعضاء الف
#: inventory/views.py:2743 #: inventory/views.py:2743
msgid "A user with this email already exists. Please use a different email." msgid "A user with this email already exists. Please use a different email."
msgstr "يوجد مستخدم بهذا البريد الإلكتروني بالفعل. يرجى استخدام بريد إلكتروني مختلف." msgstr ""
"يوجد مستخدم بهذا البريد الإلكتروني بالفعل. يرجى استخدام بريد إلكتروني مختلف."
#: inventory/views.py:2790 #: inventory/views.py:2790
msgid "User updated successfully" msgid "User updated successfully"
@ -2624,9 +2644,11 @@ msgstr "تم حذف الحساب بنجاح"
msgid "You cannot delete this account,it is related to another account" msgid "You cannot delete this account,it is related to another account"
msgstr "لا يمكنك حذف هذا الحساب، لأنه مرتبط بحساب آخر" msgstr "لا يمكنك حذف هذا الحساب، لأنه مرتبط بحساب آخر"
#: inventory/views.py:8529
msgid "Purchase order created successfully" msgid "Purchase order created successfully"
msgstr "تم إنشاء أمر الشراء بنجاح" msgstr "تم إنشاء أمر الشراء بنجاح"
#: inventory/views.py:8570
msgid "Inventory item created successfully" msgid "Inventory item created successfully"
msgstr "تم إنشاء عنصر المخزون بنجاح" msgstr "تم إنشاء عنصر المخزون بنجاح"
@ -3499,12 +3521,16 @@ msgstr "الطابع الزمني"
msgid "User" msgid "User"
msgstr "المستخدم" msgstr "المستخدم"
#: templates/admin_management/auth_logs.html:32
msgid "Event Type" msgid "Event Type"
msgstr "نوع الحدث" msgstr "نوع الحدث"
#: templates/admin_management/auth_logs.html:33
msgid "username" msgid "username"
msgstr "اسم المستخدم" msgstr "اسم المستخدم"
#: templates/admin_management/auth_logs.html:34
#: templates/admin_management/request_logs.html:33
msgid "IP Address" msgid "IP Address"
msgstr "عنوان IP" msgstr "عنوان IP"
@ -3544,39 +3570,51 @@ msgstr "لوحة سجل التدقيق"
msgid "Action" msgid "Action"
msgstr "الإجراء" msgstr "الإجراء"
#: templates/admin_management/model_logs.html:34
msgid "Object ID" msgid "Object ID"
msgstr "معرّف الكائن" msgstr "معرّف الكائن"
#: templates/admin_management/model_logs.html:35
msgid "Object Representation" msgid "Object Representation"
msgstr "تمثيل الكائن" msgstr "تمثيل الكائن"
#: templates/admin_management/model_logs.html:36
msgid "Field" msgid "Field"
msgstr "الحقل" msgstr "الحقل"
#: templates/admin_management/model_logs.html:37
msgid "Old Value" msgid "Old Value"
msgstr "القيمة القديمة" msgstr "القيمة القديمة"
#: templates/admin_management/model_logs.html:38
msgid "New Value" msgid "New Value"
msgstr "القيمة الجديدة" msgstr "القيمة الجديدة"
#: templates/admin_management/model_logs.html:99
msgid "Object created." msgid "Object created."
msgstr "تم إنشاء الكائن." msgstr "تم إنشاء الكائن."
#: templates/admin_management/model_logs.html:101
msgid "Object deleted." msgid "Object deleted."
msgstr "تم حذف الكائن." msgstr "تم حذف الكائن."
#: templates/admin_management/model_logs.html:103
msgid "No specific field changes recorded." msgid "No specific field changes recorded."
msgstr "لم يتم تسجيل تغييرات محددة في الحقول." msgstr "لم يتم تسجيل تغييرات محددة في الحقول."
#: templates/admin_management/model_logs.html:116
msgid "No model change audit events found." msgid "No model change audit events found."
msgstr "لم يتم العثور على أحداث تدقيق لتغييرات النماذج." msgstr "لم يتم العثور على أحداث تدقيق لتغييرات النماذج."
#: templates/admin_management/nav.html:6
msgid "User Actions" msgid "User Actions"
msgstr "إجراءات المستخدم" msgstr "إجراءات المستخدم"
#: templates/admin_management/nav.html:11
msgid "User Login Events" msgid "User Login Events"
msgstr "أحداث تسجيل دخول المستخدم" msgstr "أحداث تسجيل دخول المستخدم"
#: templates/admin_management/nav.html:16
msgid "User Page Requests" msgid "User Page Requests"
msgstr "طلبات صفحات المستخدم" msgstr "طلبات صفحات المستخدم"
@ -3925,6 +3963,7 @@ msgstr "المدة"
#: templates/administration/manage_service.html:66 #: templates/administration/manage_service.html:66
#: templates/appointment/appointment_client_information.html:108 #: templates/appointment/appointment_client_information.html:108
#: templates/sales/orders/order_details.html:234
#: venv/lib/python3.11/site-packages/appointment/templates/appointment/appointment_client_information.html:115 #: venv/lib/python3.11/site-packages/appointment/templates/appointment/appointment_client_information.html:115
msgid "Down Payment" msgid "Down Payment"
msgstr "دفعة مقدمة" msgstr "دفعة مقدمة"
@ -4440,6 +4479,7 @@ msgstr "تفاصيل الدفع"
#: templates/sales/estimates/estimate_detail.html:197 #: templates/sales/estimates/estimate_detail.html:197
#: templates/sales/estimates/sale_order_preview.html:184 #: templates/sales/estimates/sale_order_preview.html:184
#: templates/sales/invoices/invoice_detail.html:244 #: templates/sales/invoices/invoice_detail.html:244
#: templates/sales/orders/order_details.html:269
#: venv/lib/python3.11/site-packages/appointment/templates/appointment/appointment_client_information.html:103 #: venv/lib/python3.11/site-packages/appointment/templates/appointment/appointment_client_information.html:103
#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:98 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:98
#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:127 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:127
@ -5146,6 +5186,7 @@ msgstr "السيارة المطلوبة"
msgid "Related Records" msgid "Related Records"
msgstr "السجلات المرتبطة" msgstr "السجلات المرتبطة"
#: templates/crm/leads/lead_detail.html:114
msgid "No Opportunity" msgid "No Opportunity"
msgstr "لا توجد فرصة" msgstr "لا توجد فرصة"
@ -5194,6 +5235,7 @@ msgid "Add Note"
msgstr "إضافة ملاحظة" msgstr "إضافة ملاحظة"
#: templates/crm/leads/lead_detail.html:296 #: templates/crm/leads/lead_detail.html:296
#: templates/sales/orders/order_details.html:132
msgid "Created By" msgid "Created By"
msgstr "تم الإنشاء بواسطة" msgstr "تم الإنشاء بواسطة"
@ -5269,6 +5311,10 @@ msgstr "نعم"
msgid "In Progress" msgid "In Progress"
msgstr "قيد التنفيذ" msgstr "قيد التنفيذ"
#: templates/crm/leads/lead_list.html:138
msgid "View Schedules"
msgstr "عرض الجداول"
#: templates/crm/leads/lead_list.html:214 #: templates/crm/leads/lead_list.html:214
#: templates/crm/opportunities/opportunity_list copy.html:27 #: templates/crm/opportunities/opportunity_list copy.html:27
#: templates/dealers/dealer_detail.html:22 #: templates/dealers/dealer_detail.html:22
@ -5320,9 +5366,11 @@ msgstr "متابعات"
msgid "Negotiation Ups" msgid "Negotiation Ups"
msgstr "مفاوضات إضافية" msgstr "مفاوضات إضافية"
#: templates/crm/leads/partials/update_action.html:5
msgid "Update Lead Actions" msgid "Update Lead Actions"
msgstr "تحديث إجراءات العميل المحتمل" msgstr "تحديث إجراءات العميل المحتمل"
#: templates/crm/leads/partials/update_action.html:16
msgid "Select Stage" msgid "Select Stage"
msgstr "اختر المرحلة" msgstr "اختر المرحلة"
@ -5347,6 +5395,8 @@ msgstr "لا يوجد إجراء"
#: templates/modal/event_details_modal.html:21 #: templates/modal/event_details_modal.html:21
#: templates/partials/scanner_modal.html:6 #: templates/partials/scanner_modal.html:6
#: templates/partials/specifications_modal.html:8 #: templates/partials/specifications_modal.html:8
#: templates/sales/orders/order_details.html:542
#: templates/sales/orders/order_details.html:573
#: venv/lib/python3.11/site-packages/appointment/templates/modal/confirm_modal.html:18 #: venv/lib/python3.11/site-packages/appointment/templates/modal/confirm_modal.html:18
#: venv/lib/python3.11/site-packages/appointment/templates/modal/error_modal.html:17 #: venv/lib/python3.11/site-packages/appointment/templates/modal/error_modal.html:17
#: venv/lib/python3.11/site-packages/appointment/templates/modal/event_details_modal.html:19 #: venv/lib/python3.11/site-packages/appointment/templates/modal/event_details_modal.html:19
@ -5376,24 +5426,34 @@ msgstr "تفاصيل الفرصة"
msgid "View Quotation" msgid "View Quotation"
msgstr "مشاهدة عرض السعر" msgstr "مشاهدة عرض السعر"
#: templates/crm/opportunities/opportunity_detail.html:77
msgid "Upcoming Events" msgid "Upcoming Events"
msgstr "الأحداث القادمة" msgstr "الأحداث القادمة"
#: templates/crm/opportunities/opportunity_detail.html:90
msgid "No upcoming events" msgid "No upcoming events"
msgstr "لا توجد أحداث قادمة" msgstr "لا توجد أحداث قادمة"
#: templates/crm/opportunities/opportunity_detail.html:109
msgid "No Estimate" msgid "No Estimate"
msgstr "لا يوجد تقدير" msgstr "لا يوجد تقدير"
#: templates/crm/opportunities/opportunity_detail.html:117
#: templates/payment_success.html:29
#: templates/sales/estimates/estimate_detail.html:97
#: templates/sales/invoices/invoice_detail.html:5
msgid "View Invoice" msgid "View Invoice"
msgstr "عرض الفاتورة" msgstr "عرض الفاتورة"
#: templates/crm/opportunities/opportunity_detail.html:119
msgid "No Invoice" msgid "No Invoice"
msgstr "لا توجد فاتورة" msgstr "لا توجد فاتورة"
#: templates/crm/opportunities/opportunity_detail.html:128
msgid "System Information" msgid "System Information"
msgstr "معلومات النظام" msgstr "معلومات النظام"
#: templates/crm/opportunities/opportunity_detail.html:133
msgid "Created " msgid "Created "
msgstr "تم الإنشاء" msgstr "تم الإنشاء"
@ -5418,6 +5478,7 @@ msgstr "تاريخ الإنشاء"
msgid "Meetings" msgid "Meetings"
msgstr "الاجتماعات" msgstr "الاجتماعات"
#: templates/crm/opportunities/opportunity_detail.html:333
msgid "Calls" msgid "Calls"
msgstr "المكالمات" msgstr "المكالمات"
@ -5606,6 +5667,7 @@ msgstr "حالة الدفع"
#: templates/sales/invoices/invoice_detail.html:80 #: templates/sales/invoices/invoice_detail.html:80
#: templates/sales/invoices/invoice_detail.html:224 #: templates/sales/invoices/invoice_detail.html:224
#: templates/sales/invoices/invoice_list.html:40 #: templates/sales/invoices/invoice_list.html:40
#: templates/sales/orders/order_details.html:268
#: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:346 #: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:346
#: venv/lib/python3.11/site-packages/django_ledger/models/invoice.py:303 #: venv/lib/python3.11/site-packages/django_ledger/models/invoice.py:303
msgid "Paid" msgid "Paid"
@ -6471,6 +6533,7 @@ msgid "Cannot Edit, Car in Transfer."
msgstr "لا يمكن التعديل، السيارة قيد النقل." msgstr "لا يمكن التعديل، السيارة قيد النقل."
#: templates/inventory/car_detail.html:233 #: templates/inventory/car_detail.html:233
#: templates/sales/orders/order_details.html:224
msgid "Financial Details" msgid "Financial Details"
msgstr "التفاصيل المالية" msgstr "التفاصيل المالية"
@ -6597,9 +6660,11 @@ msgstr "يرجى إضافة مورد قبل إضافة السيارة."
msgid "Add Vendor" msgid "Add Vendor"
msgstr "إضافة مورد" msgstr "إضافة مورد"
#: templates/inventory/car_form.html:58
msgid "Scan VIN" msgid "Scan VIN"
msgstr "مسح رقم الهيكل" msgstr "مسح رقم الهيكل"
#: templates/inventory/car_form.html:64
msgid "Decode VIN" msgid "Decode VIN"
msgstr "تحليل رقم الهيكل" msgstr "تحليل رقم الهيكل"
@ -7333,9 +7398,13 @@ msgstr "الأصول"
msgid "COGS" msgid "COGS"
msgstr "تكلفة البضائع المباعة" msgstr "تكلفة البضائع المباعة"
#: templates/ledger/coa_accounts/account_list.html:32
#: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:483
#: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:569
msgid "Capital" msgid "Capital"
msgstr "رأس المال" msgstr "رأس المال"
#: templates/ledger/coa_accounts/account_list.html:37
msgid "Income" msgid "Income"
msgstr "الإيرادات" msgstr "الإيرادات"
@ -8080,9 +8149,11 @@ msgstr "تم الدفع بنجاح"
msgid "Thank You" msgid "Thank You"
msgstr "شكرًا لك" msgstr "شكرًا لك"
#: templates/payment_success.html:26
msgid "Your payment was successful" msgid "Your payment was successful"
msgstr "تمت عملية الدفع بنجاح" msgstr "تمت عملية الدفع بنجاح"
#: templates/payment_success.html:26
msgid "Your order is being processed" msgid "Your order is being processed"
msgstr "يتم الآن معالجة طلبك" msgstr "يتم الآن معالجة طلبك"
@ -8341,6 +8412,7 @@ msgid "Issued"
msgstr "تاريخ الإصدار" msgstr "تاريخ الإصدار"
#: templates/plans/invoices/layout.html:27 #: templates/plans/invoices/layout.html:27
#: templates/sales/orders/order_details.html:120
msgid "Order Date" msgid "Order Date"
msgstr "تاريخ الطلب" msgstr "تاريخ الطلب"
@ -8613,6 +8685,7 @@ msgid "Confirm Your Information"
msgstr "تأكيد معلوماتك" msgstr "تأكيد معلوماتك"
#: templates/pricing_page.html:178 #: templates/pricing_page.html:178
#: templates/sales/orders/order_details.html:106
msgid "Order Summary" msgid "Order Summary"
msgstr "ملخص الطلب" msgstr "ملخص الطلب"
@ -8749,9 +8822,11 @@ msgstr "مورد جديد"
msgid "Edit Purchase Order" msgid "Edit Purchase Order"
msgstr "تعديل أمر الشراء" msgstr "تعديل أمر الشراء"
#: templates/purchase_orders/po_form.html:24
msgid "Add New Purchase Order" msgid "Add New Purchase Order"
msgstr "إضافة أمر شراء جديد" msgstr "إضافة أمر شراء جديد"
#: templates/purchase_orders/po_list.html:22
msgid "Create New PO" msgid "Create New PO"
msgstr "إنشاء أمر شراء جديد" msgstr "إنشاء أمر شراء جديد"
@ -8874,6 +8949,7 @@ msgstr "إرسال"
#: templates/sales/estimates/sale_order_form.html:5 #: templates/sales/estimates/sale_order_form.html:5
#: templates/sales/estimates/sale_order_form1.html:5 #: templates/sales/estimates/sale_order_form1.html:5
#: templates/sales/estimates/sale_order_preview.html:159 #: templates/sales/estimates/sale_order_preview.html:159
#: templates/sales/orders/order_details.html:84
msgid "Sale Order" msgid "Sale Order"
msgstr "أمر بيع" msgstr "أمر بيع"
@ -8922,7 +8998,7 @@ msgstr "قبول"
#: templates/sales/invoices/invoice_detail.html:109 #: templates/sales/invoices/invoice_detail.html:109
msgid "Owned" msgid "Owned"
msgstr "مملوك" msgstr "متبقي"
#: templates/sales/invoices/invoice_detail.html:179 #: templates/sales/invoices/invoice_detail.html:179
#: templates/sales/invoices/invoice_list.html:15 #: templates/sales/invoices/invoice_list.html:15
@ -8953,6 +9029,145 @@ msgstr "لم يتم العثور على فاتورة"
msgid "Create Payment" msgid "Create Payment"
msgstr "إجراء الدفع" msgstr "إجراء الدفع"
#: templates/sales/orders/order_details.html:88
#: templates/sales/orders/purchase_order.html:37
msgid "Print"
msgstr "طباعة"
#: templates/sales/orders/order_details.html:91
msgid "Share"
msgstr "مشاركة"
#: templates/sales/orders/order_details.html:138
#: templates/sales/orders/order_list.html:19
#, fuzzy
#| msgid "Expected Revenue"
msgid "Expected Delivery"
msgstr "الإيرادات المتوقعة"
#: templates/sales/orders/order_details.html:143
msgid "Not scheduled"
msgstr "لم يتم الجدولة"
#: templates/sales/orders/order_details.html:156
msgid "Cancellation Reason"
msgstr "سبب الإلغاء"
#: templates/sales/orders/order_details.html:164
msgid "Order Comments"
msgstr "ملاحظات الطلب"
#: templates/sales/orders/order_details.html:176
msgid "Vehicle Details"
msgstr "تفاصيل المركبة"
#: templates/sales/orders/order_details.html:206
#: templates/sales/orders/order_details.html:493
msgid "km"
msgstr "كم"
#: templates/sales/orders/order_details.html:214
msgid "No vehicle assigned to this order"
msgstr "لم يتم تخصيص مركبة لهذا الطلب"
#: templates/sales/orders/order_details.html:230
msgid "Agreed Price"
msgstr "السعر المتفق عليه"
#: templates/sales/orders/order_details.html:238
msgid "Trade-In Value"
msgstr "قيمة الاستبدال"
#: templates/sales/orders/order_details.html:244
msgid "Loan Amount"
msgstr "قيمة القرض"
#: templates/sales/orders/order_details.html:248
msgid "Total Paid"
msgstr "المبلغ المدفوع"
#: templates/sales/orders/order_details.html:252
msgid "Remaining Balance"
msgstr "المبلغ المتبقي"
#: templates/sales/orders/order_details.html:277
msgid "Documents"
msgstr "المستندات"
#: templates/sales/orders/order_details.html:279
msgid "Add Document"
msgstr "إضافة مستند"
#: templates/sales/orders/order_details.html:285
msgid "Drag & drop files here or click to browse"
msgstr "اسحب وأفلت الملفات هنا أو انقر للتصفح"
#: templates/sales/orders/order_details.html:305
msgid "No documents uploaded yet"
msgstr "لم يتم تحميل أي مستندات بعد"
#: templates/sales/orders/order_details.html:315
msgid "Comments & Notes"
msgstr "التعليقات والملاحظات"
#: templates/sales/orders/order_details.html:325
msgid "Post Comment"
msgstr "نشر تعليق"
#: templates/sales/orders/order_details.html:344
msgid "No comments yet"
msgstr "لا توجد تعليقات بعد"
#: templates/sales/orders/order_details.html:357
msgid "Order Actions"
msgstr "إجراءات الطلب"
#: templates/sales/orders/order_details.html:370
msgid "Edit Order"
msgstr "تعديل الطلب"
#: templates/sales/orders/order_details.html:383
#: templates/sales/orders/order_details.html:555
#: templates/sales/orders/order_details.html:574
msgid "Schedule Delivery"
msgstr "جدولة التسليم"
#: templates/sales/orders/order_details.html:399
msgid "Order Status Timeline"
msgstr "الجدول الزمني لحالة الطلب"
#: templates/sales/orders/order_details.html:412
msgid "Changed by"
msgstr "تم التغيير بواسطة"
#: templates/sales/orders/order_details.html:417
msgid "No status history available"
msgstr "لا يوجد سجل للحالة"
#: templates/sales/orders/order_details.html:427
msgid "Related Items"
msgstr "العناصر ذات الصلة"
#: templates/sales/orders/order_details.html:448
msgid "Not created yet"
msgstr "لم يتم الإنشاء بعد"
#: templates/sales/orders/order_details.html:475
msgid "Trade-In Vehicle"
msgstr "مركبة الاستبدال"
#: templates/sales/orders/order_details.html:537
msgid "Reason for Cancellation"
msgstr "سبب الإلغاء"
#: templates/sales/orders/order_details.html:543
msgid "Confirm Cancellation"
msgstr "تأكيد الإلغاء"
#: templates/sales/orders/order_details.html:564
msgid "Delivery Date"
msgstr "تاريخ التسليم"
#: templates/sales/orders/order_list.html:14 #: templates/sales/orders/order_list.html:14
msgid "Order Number" msgid "Order Number"
msgstr "رقم الطلب" msgstr "رقم الطلب"
@ -8961,14 +9176,6 @@ msgstr "رقم الطلب"
msgid "For Quotation" msgid "For Quotation"
msgstr "لعرض سعر" msgstr "لعرض سعر"
#: templates/sales/orders/order_list.html:19
msgid "Expected Delivery"
msgstr "موعد التسليم المتوقع"
#: templates/sales/orders/purchase_order.html:37
msgid "Print"
msgstr "طباعة"
#: templates/sales/orders/purchase_order.html:45 #: templates/sales/orders/purchase_order.html:45
#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3170 #: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3170
msgid "Purchase Order" msgid "Purchase Order"
@ -10385,9 +10592,13 @@ msgstr "الفرنسية"
msgid "not allowed with argument %s" msgid "not allowed with argument %s"
msgstr "غير مسموح به مع الوسيط %s" msgstr "غير مسموح به مع الوسيط %s"
#: venv/lib/python3.11/site-packages/argcomplete/packages/_argparse.py:201
#: venv/lib/python3.11/site-packages/argcomplete/packages/_argparse.py:215
#, python-format
msgid "ignored explicit argument %r" msgid "ignored explicit argument %r"
msgstr "تم تجاهل الوسيط المحدد %r" msgstr "تم تجاهل الوسيط المحدد %r"
#: venv/lib/python3.11/site-packages/argcomplete/packages/_argparse.py:317
msgid "too few arguments" msgid "too few arguments"
msgstr "عدد غير كافٍ من الوسائط" msgstr "عدد غير كافٍ من الوسائط"

View File

@ -277,5 +277,5 @@
</div> </div>
</div> </div>
</div> </div>
{% include "bill/includes/mark_as.html" %}
{% endblock %} {% endblock %}

View File

@ -135,7 +135,7 @@
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header" id="headingTwo"> <h2 class="accordion-header" id="headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{lead.slug}}" aria-expanded="false" aria-controls="collapseTwo"> <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{lead.slug}}" aria-expanded="false" aria-controls="collapseTwo">
View Schedules ({{lead.get_latest_schedules.count}}) {{ _("View Schedules")}} ({{lead.get_latest_schedules.count}})
</button> </button>
</h2> </h2>
<div class="accordion-collapse collapse" id="collapse{{lead.slug}}" aria-labelledby="headingTwo" data-bs-parent="#accordionExample"> <div class="accordion-collapse collapse" id="collapse{{lead.slug}}" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">

View File

@ -22,7 +22,7 @@
</div> </div>
<div class="dropdown"> <div class="dropdown">
<button class="btn fs-10 btn-sm dropdown-toggle dropdown-caret-none transition-none notification-dropdown-toggle" 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 text-body"></span></button> <button class="btn fs-10 btn-sm dropdown-toggle dropdown-caret-none transition-none notification-dropdown-toggle" 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 text-body"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2"><a class="dropdown-item" href="{% url 'mark_notification_as_read' notification.pk %}">{{ _("Mark as Read")}}</a></div> <div class="dropdown-menu dropdown-menu-end py-2"><a class="dropdown-item" href="{% url 'mark_notification_as_read' notification.id %}">{{ _("Mark as Read")}}</a></div>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

186
templates/csv_upload.html Normal file
View File

@ -0,0 +1,186 @@
{% extends "base.html" %}
{% load static i18n %}
{% block customCSS %}
<style>
.color-card {
cursor: pointer;
transition: all 0.3s ease;
border: 2px solid transparent;
width: 80px; /* Increased from 3rem for better visibility */
height: 80px; /* Increased from 3rem for better visibility */
margin-right: 10px;
}
.color-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.color-option {
display: block;
position: relative;
margin: 0;
padding: 0;
height: 100%;
}
.color-radio {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.color-radio:checked + .color-display {
border: 2px solid #0d6efd;
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.25);
}
.color-radio:focus + .color-display {
border-color: #86b7fe;
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.25);
}
.color-display {
height: 100%;
display: flex;
align-items: flex-end;
justify-content: center;
padding: 10px;
border-radius: 0.25rem;
transition: all 0.2s ease;
}
.color-name {
background-color: rgba(255, 255, 255, 0.8);
padding: 2px 5px;
border-radius: 3px;
text-align: center;
width: 100%;
font-size: 0.8rem;
}
/* Added for better layout of color options */
.color-options-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
}
</style>
{% endblock customCSS %}
{% block content %}
<div class="container mt-4">
<h2>Upload Cars CSV</h2>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
<form method="post" enctype="multipart/form-data" class="mt-4">
{% csrf_token %}
<div class="row g-4">
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="make" target="model" data=make_data pk=po_model.pk %}
</div>
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="model" target="serie" data=model_data pk=po_model.pk %}
</div>
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="serie" target="trim" data=serie_data pk=po_model.pk %}
</div>
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="trim" target="none" data=trim_data pk=po_model.pk %}
</div>
</div>
<div class="row g-4">
<div class="col">
{{form.vendor.label}}
{{form.vendor}}
</div>
<div class="col">
{{form.year.label}}
{{form.year}}
</div>
<div class="col">
{{form.receiving_date.label}}
{{form.receiving_date}}
</div>
</div>
<div class="mb-3">
<div class="row g-4">
<p class="fs-5 mb-2">{% trans 'Exterior Colors' %}</p>
<div class="color-options-container">
{% for color in form.fields.exterior.queryset %}
<div class="color-card">
<label class="color-option">
<input class="color-radio" type="radio" name="exterior" value="{{ color.id }}" {% if color.id == form.instance.exterior.id %}checked{% endif %}>
<div class="color-display" style="background-color: rgb({{ color.rgb }})">
<span class="color-name">{{ color.get_local_name }}</span>
</div>
</label>
</div>
{% endfor %}
</div>
<p class="fs-5 mb-2">{% trans 'Interior Colors' %}</p>
<div class="color-options-container">
{% for color in form.fields.interior.queryset %}
<div class="color-card">
<label class="color-option">
<input class="color-radio" type="radio" name="interior" value="{{ color.id }}" {% if color.id == form.instance.interior.id %}checked{% endif %}>
<div class="color-display" style="background-color: rgb({{ color.rgb }})">
<span class="color-name">{{ color.get_local_name }}</span>
</div>
</label>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="mb-3">
<label for="csv_file" class="form-label">CSV File</label>
<input type="file" class="form-control" id="csv_file" name="csv_file" accept=".csv" required>
<div class="form-text">
CSV should include columns: vin, make, model, year (required)
</div>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
<a href="{% url 'car_list' %}" class="btn btn-secondary">Cancel</a>
</form>
<div class="mt-4">
<h4>CSV Format Example</h4>
<table class="table table-bordered">
<thead>
<tr>
<th>vin</th>
<th>make</th>
<th>model</th>
<th>year</th>
</tr>
</thead>
<tbody>
<tr>
<td>1HGCM82633A123456</td>
<td>Honda</td>
<td>Accord</td>
<td>2023</td>
</tr>
</tbody>
</table>
<a href="{% static 'sample/cars_sample.csv' %}" class="btn btn-outline-primary">
Download Sample CSV
</a>
</div>
</div>
{% endblock %}

View File

@ -28,6 +28,20 @@
</div> </div>
</a> </a>
</li> </li>
<li class="nav-item">
<a class="nav-link" href="{% url 'inventory_item_create' %}">
<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' %}">
<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 "purchase Orders"|capfirst %}</span>
</div>
</a>
</li>
{% endif %} {% endif %}
<li class="nav-item"> <li class="nav-item">
@ -416,7 +430,7 @@
<div class="overflow-auto scrollbar" style="height: 10rem;"> <div class="overflow-auto scrollbar" style="height: 10rem;">
<ul class="nav d-flex flex-column mb-2 pb-1"> <ul class="nav d-flex flex-column mb-2 pb-1">
{% if request.is_dealer %} {% if request.is_dealer %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link px-3 d-block" href="{% url 'dealer_detail' request.user.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="user"></span><span>{% translate 'profile'|capfirst %}</span></a> <a class="nav-link px-3 d-block" href="{% url 'dealer_detail' request.user.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="user"></span><span>{% translate 'profile'|capfirst %}</span></a>
</li> </li>
{% else %} {% else %}

View File

@ -67,7 +67,9 @@
{% elif bill.is_approved %} {% elif bill.is_approved %}
<span class="badge badge-phoenix badge-phoenix-success"> <span class="badge badge-phoenix badge-phoenix-success">
{% elif bill.is_paid %} {% elif bill.is_paid %}
<span class="badge badge-phoenix badge-phoenix-success"> <span class="badge badge-phoenix badge-phoenix-success">
{% elif bill.is_canceled %}
<span class="badge badge-phoenix badge-phoenix-danger">
{% endif %} {% endif %}
{{ bill.bill_status }} {{ bill.bill_status }}
</span> </span>
@ -79,10 +81,10 @@
<div class="btn-reveal-trigger position-static"> <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> <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"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'bill_detail' bill.pk %}" class="dropdown-item text-success-dark">{% trans 'View' %}</a> <a href="{% url 'bill-detail' entity_slug=entity.slug bill_pk=bill.pk %}" class="dropdown-item text-success-dark">{% trans 'View' %}</a>
</div> </div>
</div> </div>
</td>
</tr> </tr>
{% empty %} {% empty %}
<tr> <tr>

View File

@ -1,13 +1,103 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static i18n crispy_forms_tags %} {% load static i18n crispy_forms_tags %}
{% block customCSS %}
<style>
.color-card {
cursor: pointer;
transition: all 0.3s ease;
border: 2px solid transparent;
width: 80px; /* Increased from 3rem for better visibility */
height: 80px; /* Increased from 3rem for better visibility */
margin-right: 10px;
}
.color-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.color-option {
display: block;
position: relative;
margin: 0;
padding: 0;
height: 100%;
}
.color-radio {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.color-radio:checked + .color-display {
border: 2px solid #0d6efd;
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.25);
}
.color-radio:focus + .color-display {
border-color: #86b7fe;
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.25);
}
.color-display {
height: 100%;
display: flex;
align-items: flex-end;
justify-content: center;
padding: 10px;
border-radius: 0.25rem;
transition: all 0.2s ease;
}
.color-name {
background-color: rgba(255, 255, 255, 0.8);
padding: 2px 5px;
border-radius: 3px;
text-align: center;
width: 100%;
font-size: 0.8rem;
}
/* Added for better layout of color options */
.color-options-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
}
</style>
{% endblock %}
{% block content %} {% block content %}
<form action="" method="post"> <form action="" method="post">
{% csrf_token %} {% csrf_token %}
{% include "purchase_orders/partials/po-select.html" with name="make" target="model" data=make_data pk=po_model.pk %} <div class="row g-4">
{% include "purchase_orders/partials/po-select.html" with name="model" target="serie" data=model_data pk=po_model.pk %} <div class="col">
{% include "purchase_orders/partials/po-select.html" with name="serie" target="trim" data=serie_data pk=po_model.pk %} {% 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="trim" target="none" data=trim_data pk=po_model.pk %} </div>
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="model" target="serie" data=model_data pk=po_model.pk %}
</div>
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="serie" target="trim" data=serie_data pk=po_model.pk %}
</div>
<div class="col">
{% include "purchase_orders/partials/po-select.html" with name="trim" target="none" data=trim_data pk=po_model.pk %}
</div>
</div>
<div class="row g-4">
<div class="col">
{{form.vendor.label}}
{{form.vendor}}
</div>
<div class="col">
{{form.year.label}}
{{form.year}}
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="account">Account</label> <label for="account">Account</label>
<select class="form-control" name="account" id="account"> <select class="form-control" name="account" id="account">
@ -16,6 +106,43 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<<<<<<< HEAD
<button type="submit" class="btn btn-phoenix-primary">Add New Item To Inventory</button> <button type="submit" class="btn btn-phoenix-primary">Add New Item To Inventory</button>
=======
<div class="row g-4 mt-4">
<div class="col">
<p class="fs-5 mb-2">{% trans 'Exterior Colors' %}</p>
<div class="color-options-container">
{% for color in form.fields.exterior.queryset %}
<div class="color-card">
<label class="color-option">
<input class="color-radio" type="radio" name="exterior" value="{{ color.id }}" {% if color.id == form.instance.exterior.id %}checked{% endif %}>
<div class="color-display" style="background-color: rgb({{ color.rgb }})">
<span class="color-name">{{ color.get_local_name }}</span>
</div>
</label>
</div>
{% endfor %}
</div>
</div>
<div class="col">
<p class="fs-5 mb-2">{% trans 'Interior Colors' %}</p>
<div class="color-options-container">
{% for color in form.fields.interior.queryset %}
<div class="color-card">
<label class="color-option">
<input class="color-radio" type="radio" name="interior" value="{{ color.id }}" {% if color.id == form.instance.interior.id %}checked{% endif %}>
<div class="color-display" style="background-color: rgb({{ color.rgb }})">
<span class="color-name">{{ color.get_local_name }}</span>
</div>
</label>
</div>
{% endfor %}
</div>
</div>
</div>
<button type="submit" class="btn btn-primary mt-5">Add New Item To Inventory</button>
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</form> </form>
{% endblock content %} {% endblock content %}

View File

@ -58,8 +58,13 @@ document.addEventListener('DOMContentLoaded', function() {
<h4 class="h6 mb-1">{% trans 'Contract' %}</h4> <h4 class="h6 mb-1">{% trans 'Contract' %}</h4>
<p class="mb-0">{{ po_model.ce_model.estimate_number }}</p> <p class="mb-0">{{ po_model.ce_model.estimate_number }}</p>
</div> </div>
<<<<<<< HEAD
<a href="{% url 'django_ledger:customer-estimate-detail' entity_slug=view.kwargs.entity_slug ce_pk=po_model.ce_model_id %}" <a href="{% url 'django_ledger:customer-estimate-detail' entity_slug=view.kwargs.entity_slug ce_pk=po_model.ce_model_id %}"
class="btn btn-sm btn-phoenix-info ms-auto"> class="btn btn-sm btn-phoenix-info ms-auto">
=======
<a href="{% url 'estimate_detail' po_model.ce_model_id %}"
class="btn btn-sm btn-outline-info ms-auto">
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
{% trans 'View Contract' %} {% trans 'View Contract' %}
</a> </a>
</div> </div>
@ -192,6 +197,7 @@ document.addEventListener('DOMContentLoaded', function() {
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' entity_slug po_model.pk %}', 'Mark As Fulfilled')">
<i class="fas fa-truck me-2"></i>{% trans 'Mark as Fulfilled' %} <i class="fas fa-truck me-2"></i>{% trans 'Mark as Fulfilled' %}
</button> </button>
<<<<<<< HEAD
<button class="btn btn-phoenix-danger" <button class="btn btn-phoenix-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' entity_slug po_model.pk %}', 'Mark As Cancelled')">
<i class="fas fa-ban me-2"></i>{% trans 'Cancel' %} <i class="fas fa-ban me-2"></i>{% trans 'Cancel' %}
@ -219,6 +225,30 @@ document.addEventListener('DOMContentLoaded', function() {
<i class="fas fa-window-close me-2"></i>{% trans 'Cancel' %} <i class="fas fa-window-close me-2"></i>{% trans 'Cancel' %}
</button> </button>
{% modal_action_v2 bill po_model.get_mark_as_canceled_url po_model.get_mark_as_canceled_message po_model.get_mark_as_canceled_html_id %} {% modal_action_v2 bill po_model.get_mark_as_canceled_url po_model.get_mark_as_canceled_message po_model.get_mark_as_canceled_html_id %}
=======
{% endif %}
{# 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')">
<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')">
<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')">
<i class="fas fa-ban me-2"></i>{% trans 'Cancel' %}
</button>
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -228,7 +258,7 @@ document.addEventListener('DOMContentLoaded', function() {
{% else %} {% else %}
<div class="card border-0 shadow-sm text-center py-5"> <div class="card border-0 shadow-sm text-center py-5">
<div class="card-body"> <div class="card-body">
<a href="{% url 'django_ledger:po-create' entity_slug=entity_slug %}" class="text-decoration-none"> <a href="{% url 'purchase_order_create' %}" class="text-decoration-none">
<span class="text-muted mb-3 d-inline-block">{% icon "ic:baseline-add-circle-outline" 48 %}</span> <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> <h3 class="h4 text-muted">{% trans 'New Purchase Order' %}</h3>
</a> </a>

View File

@ -34,9 +34,9 @@
</div> </div>
<div class="dropdown-menu" id="dropdown-menu-{{ po.uuid }}" role="menu"> <div class="dropdown-menu" id="dropdown-menu-{{ po.uuid }}" role="menu">
<div class="dropdown-content"> <div class="dropdown-content">
<a href="{% url 'django_ledger:po-detail' entity_slug=entity_slug po_pk=po.uuid %}" <a href="{% url 'purchase_order_detail' po_pk=po.uuid %}"
class="dropdown-item has-text-success">Details</a> class="dropdown-item has-text-success">Details</a>
<a href="{% url 'django_ledger:po-delete' entity_slug=entity_slug po_pk=po.uuid %}" <a href="{% url 'po-delete' entity_slug=entity_slug po_pk=po.uuid %}"
class="dropdown-item has-text-weight-bold has-text-danger">{% trans ' Delete' %}</a> class="dropdown-item has-text-weight-bold has-text-danger">{% trans ' Delete' %}</a>
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@
Purchase Order {{ po_model.po_number }}?</h2> 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. <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 'django_ledger:po-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' entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}" class="text-decoration-none">click here</a></p>
<div class="d-flex justify-content-center gap-3 mt-4"> <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' entity_slug=view.kwargs.entity_slug po_pk=po_model.uuid %}"

View File

@ -18,11 +18,15 @@
<h3 class=""> <h3 class="">
{{ _("Purchase Orders") |capfirst }} {{ _("Purchase Orders") |capfirst }}
</h2> </h2>
<a href="{% url 'purchase_order_create' %}" <div>
class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{{ _("Create New PO") }}</a> <a href="{% url 'purchase_order_create' %}"
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"
class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{{ _("Create Inventory Item for PO") }}</a>
</div>
</div> </div>
{% include "partials/search_box.html" %} {% include "partials/search_box.html" %}
<div class="table-responsive px-1 scrollbar mt-3"> <div class="table-responsive px-1 scrollbar mt-3">
<table class= "table align-items-center table-flush table-hover"> <table class= "table align-items-center table-flush table-hover">
<thead> <thead>
@ -31,13 +35,13 @@
<th class="sort white-space-nowrap align-middle" scope="col" style="width:40%">Description</th> <th class="sort white-space-nowrap align-middle" scope="col" style="width:40%">Description</th>
<th class="sort white-space-nowrap align-middle" scope="col" style="width:15%">Status</th> <th class="sort white-space-nowrap align-middle" scope="col" style="width:15%">Status</th>
<th class="sort white-space-nowrap align-middle" scope="col" style="width:15%">Created At</th> <th class="sort white-space-nowrap align-middle" scope="col" style="width:15%">Created At</th>
<th class="sort white-space-nowrap align-middle" scope="col" style="width:15%">Actions</th> <th class="sort white-space-nowrap align-middle" scope="col" style="width:15%">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody class="list"> <tbody class="list">
{% if purchase_orders %} {% if purchase_orders %}
{% for po in purchase_orders %} {% for po in purchase_orders %}
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="align-middle product white-space-nowrap">{{ po.po_number }}</td> <td class="align-middle product white-space-nowrap">{{ po.po_number }}</td>
<td class="align-middle product white-space-nowrap">{{ po.po_title }}</td> <td class="align-middle product white-space-nowrap">{{ po.po_title }}</td>
@ -48,11 +52,13 @@
</td> </td>
<td class="align-middle product white-space-nowrap">{{ po.created|date:"M d, Y" }}</td> <td class="align-middle product white-space-nowrap">{{ po.created|date:"M d, Y" }}</td>
<td class="align-middle product white-space-nowrap"> <td class="align-middle product white-space-nowrap">
<a href="{% url 'purchase_order_detail' po.pk %}" <div class="btn-reveal-trigger position-static">
class="btn btn-sm btn-phoenix-success"> <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>
<i class="fa-regular fa-eye me-1"></i> <div class="dropdown-menu dropdown-menu-end py-2">
{% trans "view"|capfirst %} <a href="{% url 'purchase_order_detail' po.pk %}" class="dropdown-item text-success-dark">{% trans 'View' %}</a>
</a> <a href="{% url 'upload_cars' po.pk %}" class="dropdown-item text-success-dark">{% trans 'Upload Data' %}</a>
</div>
</div>
</td> </td>
</tr> </tr>
{%endfor%} {%endfor%}

View File

@ -28,7 +28,7 @@
</td> </td>
<td class="has-text-centered">{% if item.bill_model_id %} <td class="has-text-centered">{% if item.bill_model_id %}
<a class="is-small is-info button" <a class="is-small is-info button"
href="{% url 'django_ledger:bill-detail' entity_slug=entity_slug bill_pk=item.bill_model_id %}">View href="{% url 'bill-detail' entity_slug=entity_slug bill_pk=item.bill_model_id %}">View
Bill</a>{% endif %} Bill</a>{% endif %}
</td> </td>
</tr> </tr>

View File

@ -76,19 +76,27 @@
{% block content %} {% block content %}
<div class="container-fluid px-0"> <div class="container-fluid px-0">
<!-- Header --> <!-- Header -->
<header class="bg-primary text-white py-3"> <header class="bg-primary py-3">
<div class="container"> <div class="container">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h1 class="h4 mb-0"> <h1 class="h4 mb-0">
<i class="fas fa-file-invoice me-2"></i> <i class="fas fa-file-invoice me-2"></i>
Sale Order #{{ saleorder.formatted_order_id }} {{ _("Sale Order")}} #{{ saleorder.formatted_order_id }}
</h1> </h1>
<div> <div>
<<<<<<< HEAD
<button class="btn btn-sm btn-phoenix-light me-2"> <button class="btn btn-sm btn-phoenix-light me-2">
<i class="fas fa-print me-1"></i> Print <i class="fas fa-print me-1"></i> Print
</button> </button>
<button class="btn btn-sm btn-phoenix-light"> <button class="btn btn-sm btn-phoenix-light">
<i class="fas fa-share-alt me-1"></i> Share <i class="fas fa-share-alt me-1"></i> Share
=======
<button class="btn btn-sm btn-outline-light me-2">
<i class="fas fa-print me-1"></i> {{ _("Print") }}
</button>
<button class="btn btn-sm btn-outline-light">
<i class="fas fa-share-alt me-1"></i> {{ _("Share") }}
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</button> </button>
</div> </div>
</div> </div>
@ -103,7 +111,7 @@
<!-- Order Summary Card --> <!-- Order Summary Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center bg-light"> <div class="card-header d-flex justify-content-between align-items-center bg-light">
<h5 class="mb-0 text-primary">Order Summary</h5> <h5 class="mb-0 text-primary">{{ _("Order Summary")}}</h5>
<span class="status-badge <span class="status-badge
{% if saleorder.status == 'approved' %}bg-success text-white {% if saleorder.status == 'approved' %}bg-success text-white
{% elif saleorder.status == 'cancelled' %}bg-danger text-white {% elif saleorder.status == 'cancelled' %}bg-danger text-white
@ -117,35 +125,35 @@
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Order Date</label> <label class="form-label text-muted small mb-1">{{ _("Order Date")}}</label>
<p class="mb-0 fw-bold">{{ saleorder.order_date|date }}</p> <p class="mb-0 fw-bold">{{ saleorder.order_date|date }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Customer</label> <label class="form-label text-muted small mb-1">{{ _("Customer") }}</label>
<p class="mb-0 fw-bold">{{ saleorder.customer.full_name|capfirst }}</p> <p class="mb-0 fw-bold">{{ saleorder.customer.full_name|capfirst }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Payment Method</label> <label class="form-label text-muted small mb-1">{{ _("Payment Method")}}</label>
<p class="mb-0 fw-bold">{{ saleorder.get_payment_method_display }}</p> <p class="mb-0 fw-bold">{{ saleorder.get_payment_method_display }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Created By</label> <label class="form-label text-muted small mb-1">{{ _("Created By")}}</label>
<p class="mb-0 fw-bold">{{ saleorder.created_by }}</p> <p class="mb-0 fw-bold">{{ saleorder.created_by }}</p>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Expected Delivery</label> <label class="form-label text-muted small mb-1">{{ _("Expected Delivery")}}</label>
<p class="mb-0 fw-bold"> <p class="mb-0 fw-bold">
{% if saleorder.expected_delivery_date %} {% if saleorder.expected_delivery_date %}
{{ saleorder.expected_delivery_date|date }} {{ saleorder.expected_delivery_date|date }}
{% else %} {% else %}
<span class="text-warning">Not scheduled</span> <span class="text-warning">{{ _("Not scheduled")}}</span>
{% endif %} {% endif %}
</p> </p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Last Updated</label> <label class="form-label text-muted small mb-1">{{ _("Last Updated")}}</label>
<p class="mb-0 fw-bold"> <p class="mb-0 fw-bold">
{{ saleorder.updated_at|naturaltime|capfirst }} by {{ saleorder.updated_at|naturaltime|capfirst }} by
{{ saleorder.last_modified_by }} {{ saleorder.last_modified_by }}
@ -153,7 +161,7 @@
</div> </div>
{% if saleorder.status == 'cancelled' %} {% if saleorder.status == 'cancelled' %}
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Cancellation Reason</label> <label class="form-label text-muted small mb-1">{{ _("Cancellation Reason")}}</label>
<p class="mb-0 fw-bold text-danger">{{ saleorder.cancellation_reason|default:"Not specified" }}</p> <p class="mb-0 fw-bold text-danger">{{ saleorder.cancellation_reason|default:"Not specified" }}</p>
</div> </div>
{% endif %} {% endif %}
@ -161,7 +169,7 @@
</div> </div>
{% if saleorder.comments %} {% if saleorder.comments %}
<div class="mt-3"> <div class="mt-3">
<label class="form-label text-muted small mb-1">Order Comments</label> <label class="form-label text-muted small mb-1">{{ _("Order Comments")}}</label>
<blockquote class="blockquote mb-0"> <blockquote class="blockquote mb-0">
<p class="mb-0">{{ saleorder.comments }}</p> <p class="mb-0">{{ saleorder.comments }}</p>
</blockquote> </blockquote>
@ -173,7 +181,7 @@
<!-- Vehicle Details Card --> <!-- Vehicle Details Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Vehicle Details</h5> <h5 class="mb-0">{{ _("Vehicle Details")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
@ -186,24 +194,24 @@
<div class="col-md-8"> <div class="col-md-8">
<div class="row"> <div class="row">
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Make</label> <label class="form-label text-muted small mb-1">{{ _("Make") }}</label>
<p class="mb-0">{{ car.make }}</p> <p class="mb-0">{{ car.make }}</p>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Model</label> <label class="form-label text-muted small mb-1">{{ _("Model") }}</label>
<p class="mb-0">{{ car.model }}</p> <p class="mb-0">{{ car.model }}</p>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Year</label> <label class="form-label text-muted small mb-1">{{ _("Year") }}</label>
<p class="mb-0">{{ car.year }}</p> <p class="mb-0">{{ car.year }}</p>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">VIN</label> <label class="form-label text-muted small mb-1">{{ _("VIN") }}</label>
<p class="mb-0">{{ car.vin }}</p> <p class="mb-0">{{ car.vin }}</p>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Mileage</label> <label class="form-label text-muted small mb-1">{{ _("Mileage") }}</label>
<p class="mb-0">{{ car.mileage|intcomma }} km</p> <p class="mb-0">{{ car.mileage|intcomma }} {{ _("km") }}</p>
</div> </div>
</div> </div>
</div> </div>
@ -211,7 +219,7 @@
{% endfor %} {% endfor %}
{% else %} {% else %}
<div class="col-12 text-center py-4"> <div class="col-12 text-center py-4">
<p class="text-muted">No vehicle assigned to this order</p> <p class="text-muted">{{ _("No vehicle assigned to this order")}}</p>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -221,35 +229,35 @@
<!-- Financial Details Card --> <!-- Financial Details Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Financial Details</h5> <h5 class="mb-0">{{ _("Financial Details")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Agreed Price</label> <label class="form-label text-muted small mb-1">{{ _("Agreed Price")}}</label>
<p class="mb-0 fw-bold">SAR {{ saleorder.agreed_price|intcomma }}</p> <p class="mb-0 fw-bold">SAR {{ saleorder.agreed_price|intcomma }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Down Payment</label> <label class="form-label text-muted small mb-1">{{ _("Down Payment")}}</label>
<p class="mb-0">SAR {{ saleorder.down_payment_amount|intcomma }}</p> <p class="mb-0">SAR {{ saleorder.down_payment_amount|intcomma }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Trade-In Value</label> <label class="form-label text-muted small mb-1">{{ _("Trade-In Value")}}</label>
<p class="mb-0">SAR {{ saleorder.trade_in_value|intcomma }}</p> <p class="mb-0">SAR {{ saleorder.trade_in_value|intcomma }}</p>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Loan Amount</label> <label class="form-label text-muted small mb-1">{{ _("Loan Amount")}}</label>
<p class="mb-0">SAR {{ saleorder.loan_amount|intcomma }}</p> <p class="mb-0">SAR {{ saleorder.loan_amount|intcomma }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Total Paid</label> <label class="form-label text-muted small mb-1">{{ _("Total Paid")}}</label>
<p class="mb-0">SAR {{ saleorder.total_paid_amount|intcomma }}</p> <p class="mb-0">SAR {{ saleorder.total_paid_amount|intcomma }}</p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Remaining Balance</label> <label class="form-label text-muted small mb-1">{{ _("Remaining Balance")}}</label>
<p class="mb-0 fw-bold {% if saleorder.remaining_balance > 0 %}text-danger{% else %}text-success{% endif %}"> <p class="mb-0 fw-bold {% if saleorder.remaining_balance > 0 %}text-danger{% else %}text-success{% endif %}">
SAR {{ saleorder.remaining_balance|intcomma }} SAR {{ saleorder.remaining_balance|intcomma }}
</p> </p>
@ -265,8 +273,8 @@
aria-valuemax="100"></div> aria-valuemax="100"></div>
</div> </div>
<div class="d-flex justify-content-between mt-1 small text-muted"> <div class="d-flex justify-content-between mt-1 small text-muted">
<span>{{ payment_percentage }}% Paid</span> <span>{{ payment_percentage }}% {{ _("Paid") }}</span>
<span>SAR {{ saleorder.agreed_price|intcomma }} Total</span> <span>SAR {{ saleorder.agreed_price|intcomma }} {{ _("Total") }}</span>
</div> </div>
</div> </div>
</div> </div>
@ -274,15 +282,21 @@
<!-- Documents Card --> <!-- Documents Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="card-header d-flex justify-content-between align-items-center">
<<<<<<< HEAD
<h5 class="mb-0">Documents</h5> <h5 class="mb-0">Documents</h5>
<button class="btn btn-sm btn-phoenix-primary"> <button class="btn btn-sm btn-phoenix-primary">
<i class="fas fa-plus me-1"></i> Add Document <i class="fas fa-plus me-1"></i> Add Document
=======
<h5 class="mb-0">{{ _("Documents") }}</h5>
<button class="btn btn-sm btn-primary">
<i class="fas fa-plus me-1"></i> {{ _("Add Document")}}
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</button> </button>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="file-upload mb-3"> <div class="file-upload mb-3">
<i class="fas fa-cloud-upload-alt fa-3x text-muted mb-2"></i> <i class="fas fa-cloud-upload-alt fa-3x text-muted mb-2"></i>
<p class="mb-1">Drag & drop files here or click to browse</p> <p class="mb-1">{{ _("Drag & drop files here or click to browse")}}</p>
<p class="small text-muted mb-0">PDF, JPG, PNG up to 10MB</p> <p class="small text-muted mb-0">PDF, JPG, PNG up to 10MB</p>
</div> </div>
<div class="row"> <div class="row">
@ -290,7 +304,7 @@
<div class="col-md-3 mb-3"> <div class="col-md-3 mb-3">
<div class="card"> <div class="card">
{% if document.file.url|lower|slice:'-3:' == 'pdf' %} {% if document.file.url|lower|slice:'-3:' == 'pdf' %}
<img src="{% static 'images/pdf-icon.png' %}" class="document-thumbnail card-img-top" alt="PDF Document"> <img src="{% static 'images/icons/file.png' %}" class="document-thumbnail card-img-top" alt="PDF Document">
{% else %} {% else %}
<img src="{{ document.file.url }}" class="document-thumbnail card-img-top" alt="Document"> <img src="{{ document.file.url }}" class="document-thumbnail card-img-top" alt="Document">
{% endif %} {% endif %}
@ -302,7 +316,7 @@
</div> </div>
{% empty %} {% empty %}
<div class="col-12 text-center py-3"> <div class="col-12 text-center py-3">
<p class="text-muted">No documents uploaded yet</p> <p class="text-muted">{{ _("No documents uploaded yet")}}</p>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -312,7 +326,7 @@
<!-- Comments Card --> <!-- Comments Card -->
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Comments & Notes</h5> <h5 class="mb-0">{{ _("Comments & Notes")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
{% comment %} <form method="post" action="{% url 'add_sale_order_comment' saleorder.pk %}"> {% endcomment %} {% comment %} <form method="post" action="{% url 'add_sale_order_comment' saleorder.pk %}"> {% endcomment %}
@ -321,7 +335,11 @@
<div class="mb-3"> <div class="mb-3">
<textarea class="form-control" name="comment" rows="3" placeholder="Add a comment or note..." required></textarea> <textarea class="form-control" name="comment" rows="3" placeholder="Add a comment or note..." required></textarea>
<div class="d-flex justify-content-end mt-2"> <div class="d-flex justify-content-end mt-2">
<<<<<<< HEAD
<button type="submit" class="btn btn-phoenix-primary btn-sm">Post Comment</button> <button type="submit" class="btn btn-phoenix-primary btn-sm">Post Comment</button>
=======
<button type="submit" class="btn btn-primary btn-sm">{{ _("Post Comment")}}</button>
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</div> </div>
</div> </div>
</form> </form>
@ -340,7 +358,7 @@
</div> </div>
{% empty %} {% empty %}
<div class="text-center py-3"> <div class="text-center py-3">
<p class="text-muted">No comments yet</p> <p class="text-muted">{{ _("No comments yet")}}</p>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -353,7 +371,7 @@
<!-- Actions Card --> <!-- Actions Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Order Actions</h5> <h5 class="mb-0">{{ _("Order Actions")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-grid gap-2"> <div class="d-grid gap-2">
@ -364,26 +382,46 @@
{% endif %} {% endif %}
{% comment %} <a href="{% url 'edit_sale_order' saleorder.pk %}" class="btn btn-primary"> {% endcomment %} {% comment %} <a href="{% url 'edit_sale_order' saleorder.pk %}" class="btn btn-primary"> {% endcomment %}
<<<<<<< HEAD
<a href="" class="btn btn-phoenix-primary"> <a href="" class="btn btn-phoenix-primary">
<i class="fas fa-edit me-2"></i> Edit Order <i class="fas fa-edit me-2"></i> Edit Order
=======
<a href="" class="btn btn-primary">
<i class="fas fa-edit me-2"></i> {{ _("Edit Order")}}
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</a> </a>
{% if not saleorder.invoice %} {% if not saleorder.invoice %}
{% comment %} <a href="{% url 'create_invoice_from_order' saleorder.pk %}" class="btn btn-info"> {% endcomment %} {% comment %} <a href="{% url 'create_invoice_from_order' saleorder.pk %}" class="btn btn-info"> {% endcomment %}
<<<<<<< HEAD
<a href="" class="btn btn-phoenix-info"> <a href="" class="btn btn-phoenix-info">
<i class="fas fa-file-invoice-dollar me-2"></i> Create Invoice <i class="fas fa-file-invoice-dollar me-2"></i> Create Invoice
=======
<a href="" class="btn btn-info">
<i class="fas fa-file-invoice-dollar me-2"></i> {{ _("Create Invoice")}}
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</a> </a>
{% endif %} {% endif %}
{% if saleorder.status == 'approved' and not saleorder.actual_delivery_date %} {% if saleorder.status == 'approved' and not saleorder.actual_delivery_date %}
<<<<<<< HEAD
<button class="btn btn-phoenix-warning" data-bs-toggle="modal" data-bs-target="#deliveryModal"> <button class="btn btn-phoenix-warning" data-bs-toggle="modal" data-bs-target="#deliveryModal">
<i class="fas fa-truck me-2"></i> Schedule Delivery <i class="fas fa-truck me-2"></i> Schedule Delivery
=======
<button class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#deliveryModal">
<i class="fas fa-truck me-2"></i> {{ _("Schedule Delivery")}}
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</button> </button>
{% endif %} {% endif %}
{% if saleorder.status != 'cancelled' %} {% if saleorder.status != 'cancelled' %}
<<<<<<< HEAD
<button class="btn btn-phoenix-danger" data-bs-toggle="modal" data-bs-target="#cancelModal"> <button class="btn btn-phoenix-danger" data-bs-toggle="modal" data-bs-target="#cancelModal">
<i class="fas fa-times-circle me-2"></i> Cancel Order <i class="fas fa-times-circle me-2"></i> Cancel Order
=======
<button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#cancelModal">
<i class="fas fa-times-circle me-2"></i> {{ _("Cancel Order")}}
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</button> </button>
{% endif %} {% endif %}
</div> </div>
@ -393,7 +431,7 @@
<!-- Status Timeline Card --> <!-- Status Timeline Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Order Status Timeline</h5> <h5 class="mb-0">{{ _("Order Status Timeline")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="timeline"> <div class="timeline">
@ -406,12 +444,12 @@
<p class="small mb-0"> <p class="small mb-0">
{% if log.note %}{{ log.note }}{% endif %} {% if log.note %}{{ log.note }}{% endif %}
<br> <br>
<small class="text-muted">Changed by: {{ log.changed_by.get_full_name|default:log.changed_by.username }}</small> <small class="text-muted">{{ _("Changed by")}}: {{ log.changed_by.get_full_name|default:log.changed_by.username }}</small>
</p> </p>
</div> </div>
{% empty %} {% empty %}
<div class="text-center py-3"> <div class="text-center py-3">
<p class="text-muted">No status history available</p> <p class="text-muted">{{ _("No status history available")}}</p>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -421,11 +459,11 @@
<!-- Related Items Card --> <!-- Related Items Card -->
<div class="card mb-4 shadow-sm"> <div class="card mb-4 shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Related Items</h5> <h5 class="mb-0">{{ _("Related Items")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Estimate</label> <label class="form-label text-muted small mb-1">{{ _("Quotation") }}</label>
<a href="{% url 'estimate_detail' saleorder.estimate.pk %}" target="_blank" rel="noopener noreferrer"> <a href="{% url 'estimate_detail' saleorder.estimate.pk %}" target="_blank" rel="noopener noreferrer">
<p class="mb-0"> <p class="mb-0">
<span class="badge bg-success ms-1">{{ saleorder.estimate.estimate_number }} <i class="fas fa-external-link-alt ms-2" style="font-size: 0.8rem;"></i></span> <span class="badge bg-success ms-1">{{ saleorder.estimate.estimate_number }} <i class="fas fa-external-link-alt ms-2" style="font-size: 0.8rem;"></i></span>
@ -433,7 +471,7 @@
</a> </a>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Invoice</label> <label class="form-label text-muted small mb-1">{{ _("Invoice") }}</label>
<p class="mb-0"> <p class="mb-0">
{% if saleorder.invoice %} {% if saleorder.invoice %}
<a href="{% url 'invoice_detail' saleorder.invoice.pk %}" target="_blank" rel="noopener noreferrer"> <a href="{% url 'invoice_detail' saleorder.invoice.pk %}" target="_blank" rel="noopener noreferrer">
@ -442,12 +480,12 @@
</p> </p>
</a> </a>
{% else %} {% else %}
<span class="text-muted">Not created yet</span> <span class="text-muted">{{ _("Not created yet")}}</span>
{% endif %} {% endif %}
</p> </p>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Opportunity</label> <label class="form-label text-muted small mb-1">{{ _("Opportunity") }}</label>
<a href="{% url 'opportunity_detail' saleorder.opportunity.slug %}" target="_blank" rel="noopener noreferrer"> <a href="{% url 'opportunity_detail' saleorder.opportunity.slug %}" target="_blank" rel="noopener noreferrer">
<p class="mb-0"> <p class="mb-0">
<span class="badge bg-success ms-1">{{ saleorder.opportunity }} <i class="fas fa-external-link-alt ms-2" style="font-size: 0.8rem;"></i></span> <span class="badge bg-success ms-1">{{ saleorder.opportunity }} <i class="fas fa-external-link-alt ms-2" style="font-size: 0.8rem;"></i></span>
@ -455,7 +493,7 @@
</a> </a>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Customer</label> <label class="form-label text-muted small mb-1">{{ _("Customer") }}</label>
<a href="{% url 'customer_detail' saleorder.customer.slug %}" target="_blank" rel="noopener noreferrer"> <a href="{% url 'customer_detail' saleorder.customer.slug %}" target="_blank" rel="noopener noreferrer">
<p class="mb-0"> <p class="mb-0">
<span class="badge bg-success ms-1">{{ saleorder.customer.full_name|capfirst }} <i class="fas fa-external-link-alt ms-2" style="font-size: 0.8rem;"></i></span> <span class="badge bg-success ms-1">{{ saleorder.customer.full_name|capfirst }} <i class="fas fa-external-link-alt ms-2" style="font-size: 0.8rem;"></i></span>
@ -469,7 +507,7 @@
{% if saleorder.trade_in_vehicle %} {% if saleorder.trade_in_vehicle %}
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-header"> <div class="card-header">
<h5 class="mb-0">Trade-In Vehicle</h5> <h5 class="mb-0">{{ _("Trade-In Vehicle")}}</h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="text-center mb-3"> <div class="text-center mb-3">
@ -480,14 +518,14 @@
{{ saleorder.trade_in_vehicle.make }} {{ saleorder.trade_in_vehicle.make }}
{{ saleorder.trade_in_vehicle.model }} {{ saleorder.trade_in_vehicle.model }}
</h6> </h6>
<p class="small text-muted mb-2">VIN: {{ saleorder.trade_in_vehicle.vin }}</p> <p class="small text-muted mb-2">{{ _("VIN") }}: {{ saleorder.trade_in_vehicle.vin }}</p>
<p class="fw-bold">SAR {{ saleorder.trade_in_value|intcomma }}</p> <p class="fw-bold">SAR {{ saleorder.trade_in_value|intcomma }}</p>
</div> </div>
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<p class="small mb-1"> <p class="small mb-1">
<i class="fas fa-tachometer-alt me-1 text-muted"></i> <i class="fas fa-tachometer-alt me-1 text-muted"></i>
{{ saleorder.trade_in_vehicle.mileage|intcomma }} km {{ saleorder.trade_in_vehicle.mileage|intcomma }} {{ _("km") }}
</p> </p>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -522,7 +560,7 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="cancelModalLabel">Cancel Order</h5> <h5 class="modal-title" id="cancelModalLabel">{{ _("Cancel Order")}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
{% comment %} <form method="post" action="{% url 'cancel_sale_order' saleorder.pk %}"> {% endcomment %} {% comment %} <form method="post" action="{% url 'cancel_sale_order' saleorder.pk %}"> {% endcomment %}
@ -530,13 +568,18 @@
{% csrf_token %} {% csrf_token %}
<div class="modal-body"> <div class="modal-body">
<div class="mb-3"> <div class="mb-3">
<label for="cancellationReason" class="form-label">Reason for Cancellation</label> <label for="cancellationReason" class="form-label">{{ _("Reason for Cancellation")}}</label>
<textarea class="form-control" id="cancellationReason" name="cancellation_reason" rows="3" required></textarea> <textarea class="form-control" id="cancellationReason" name="cancellation_reason" rows="3" required></textarea>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<<<<<<< HEAD
<button type="button" class="btn btn-phoenix-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-phoenix-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-phoenix-danger">Confirm Cancellation</button> <button type="submit" class="btn btn-phoenix-danger">Confirm Cancellation</button>
=======
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button>
<button type="submit" class="btn btn-danger">{{ _("Confirm Cancellation")}}</button>
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</div> </div>
</form> </form>
</div> </div>
@ -548,7 +591,7 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="deliveryModalLabel">Schedule Delivery</h5> <h5 class="modal-title" id="deliveryModalLabel">{{ _("Schedule Delivery")}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
{% comment %} <form method="post" action="{% url 'schedule_delivery' saleorder.pk %}"> {% endcomment %} {% comment %} <form method="post" action="{% url 'schedule_delivery' saleorder.pk %}"> {% endcomment %}
@ -556,17 +599,22 @@
{% csrf_token %} {% csrf_token %}
<div class="modal-body"> <div class="modal-body">
<div class="mb-3"> <div class="mb-3">
<label for="deliveryDate" class="form-label">Delivery Date</label> <label for="deliveryDate" class="form-label">{{ _("Delivery Date")}}</label>
<input type="date" class="form-control" id="deliveryDate" name="delivery_date" required> <input type="date" class="form-control" id="deliveryDate" name="delivery_date" required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="deliveryNotes" class="form-label">Notes</label> <label for="deliveryNotes" class="form-label">{{ _("Notes") }}</label>
<textarea class="form-control" id="deliveryNotes" name="notes" rows="3"></textarea> <textarea class="form-control" id="deliveryNotes" name="notes" rows="3"></textarea>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<<<<<<< HEAD
<button type="button" class="btn btn-phoenix-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-phoenix-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-phoenix-primary">Schedule Delivery</button> <button type="submit" class="btn btn-phoenix-primary">Schedule Delivery</button>
=======
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button>
<button type="submit" class="btn btn-primary">{{ _("Schedule Delivery")}}</button>
>>>>>>> 90fea4d25623ba4dd0f6fd2390e23b40857b6dff
</div> </div>
</form> </form>
</div> </div>