new
This commit is contained in:
commit
f6d59da008
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
@ -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(
|
||||||
|
|||||||
@ -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'),
|
||||||
|
|||||||
@ -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.
@ -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 "عدد غير كافٍ من الوسائط"
|
||||||
|
|
||||||
|
|||||||
@ -277,5 +277,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% include "bill/includes/mark_as.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -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">
|
||||||
|
|||||||
@ -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
186
templates/csv_upload.html
Normal 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 %}
|
||||||
@ -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 %}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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 %}
|
||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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 %}"
|
||||||
|
|||||||
@ -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%}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user