Compare commits
6 Commits
56f5025c58
...
88769d4a89
| Author | SHA1 | Date | |
|---|---|---|---|
| 88769d4a89 | |||
| 39f617fc93 | |||
| 6eb77e3158 | |||
| 696daf92bd | |||
| 8168753bbf | |||
| 6a70c762f0 |
@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from django.conf import settings
|
||||
@ -51,6 +52,10 @@ from imagekit.processors import ResizeToFill
|
||||
# from simple_history.models import HistoricalRecords
|
||||
from plans.models import Invoice
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
class Base(models.Model):
|
||||
id = models.UUIDField(
|
||||
unique=True,
|
||||
@ -881,11 +886,11 @@ class Car(Base):
|
||||
@property
|
||||
def get_additional_services_vat(self):
|
||||
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
|
||||
return sum([Decimal((x.price)*(vat.rate)) for x in self.additional_services.all()])
|
||||
return sum([Decimal((x.price)*(vat.rate)) for x in self.additional_services.filter(taxable=True)])
|
||||
|
||||
def get_additional_services(self):
|
||||
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
|
||||
return {"services": [[x,(x.price)*(vat.rate)] for x in self.additional_services.all()],
|
||||
return {"services": [[x,((x.price)*(vat.rate) if x.taxable else 0)] for x in self.additional_services.all()],
|
||||
"total_":self.get_additional_services_amount_,
|
||||
"total":self.get_additional_services_amount,
|
||||
"services_vat":self.get_additional_services_vat}
|
||||
@ -3720,4 +3725,32 @@ class Ticket(models.Model):
|
||||
return ", ".join(parts)
|
||||
|
||||
def __str__(self):
|
||||
return f"#{self.id} - {self.subject} ({self.status})"
|
||||
return f"#{self.id} - {self.subject} ({self.status})"
|
||||
|
||||
|
||||
class CarImage(models.Model):
|
||||
car = models.OneToOneField('Car', on_delete=models.CASCADE, related_name='generated_image')
|
||||
image_hash = models.CharField(max_length=64, unique=True)
|
||||
image = models.ImageField(upload_to='car_images/', null=True, blank=True)
|
||||
is_generating = models.BooleanField(default=False)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def generate_hash(self):
|
||||
"""Simple hash generation"""
|
||||
car = self.car
|
||||
hash_string = f"{car.id_car_make.name if car.id_car_make else ''}-{car.id_car_model.name if car.id_car_model else ''}-{car.year}-{getattr(car, 'color', 'default')}"
|
||||
return hashlib.sha256(hash_string.encode()).hexdigest()
|
||||
|
||||
def schedule_generation(self):
|
||||
"""Schedule image generation"""
|
||||
from django_q.tasks import async_task
|
||||
from inventory.tasks import generate_car_image_task
|
||||
|
||||
self.is_generating = True
|
||||
self.save()
|
||||
|
||||
async_task(
|
||||
generate_car_image_task,
|
||||
self.id,
|
||||
task_name=f"generate_car_image_{self.car.vin}"
|
||||
)
|
||||
@ -413,24 +413,26 @@ def create_item_model(sender, instance, created, **kwargs):
|
||||
# quotation.save()
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.CarColors)
|
||||
def update_car_when_color_changed(sender, instance, **kwargs):
|
||||
"""
|
||||
Signal receiver to handle updates to a car instance when its related
|
||||
CarColors instance is modified. Triggered by the `post_save` signal
|
||||
for the `CarColors` model. Ensures that the associated `Car` instance
|
||||
is saved, propagating changes effectively.
|
||||
# @receiver(post_save, sender=models.CarColors)
|
||||
# def update_car_hash_when_color_changed(sender, instance, **kwargs):
|
||||
# """
|
||||
# Signal receiver to handle updates to a car instance when its related
|
||||
# CarColors instance is modified. Triggered by the `post_save` signal
|
||||
# for the `CarColors` model. Ensures that the associated `Car` instance
|
||||
# is saved, propagating changes effectively.
|
||||
|
||||
:param sender: The model class (`CarColors`) that was saved.
|
||||
:type sender: Type[models.CarColors]
|
||||
:param instance: The specific instance of `CarColors` that was saved.
|
||||
:type instance: models.CarColors
|
||||
:param kwargs: Additional keyword arguments passed by the signal.
|
||||
:type kwargs: dict
|
||||
:return: None
|
||||
"""
|
||||
car = instance.car
|
||||
car.save()
|
||||
# :param sender: The model class (`CarColors`) that was saved.
|
||||
# :type sender: Type[models.CarColors]
|
||||
# :param instance: The specific instance of `CarColors` that was saved.
|
||||
# :type instance: models.CarColors
|
||||
# :param kwargs: Additional keyword arguments passed by the signal.
|
||||
# :type kwargs: dict
|
||||
# :return: None
|
||||
# """
|
||||
|
||||
# car = instance.car
|
||||
# car.hash = car.get_hash
|
||||
# car.save()
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.Opportunity)
|
||||
@ -1260,4 +1262,41 @@ def send_ticket_notification(sender, instance, created, **kwargs):
|
||||
kwargs={"dealer_slug": instance.dealer.slug, "ticket_id": instance.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.CarColors)
|
||||
def handle_car_image(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Simple handler for car image generation
|
||||
"""
|
||||
try:
|
||||
# Create or get car image record
|
||||
car = instance.car
|
||||
car_image, created = models.CarImage.objects.get_or_create(car=car, defaults={'image_hash': car.get_hash})
|
||||
|
||||
# Check for existing image with same hash
|
||||
existing = models.CarImage.objects.filter(
|
||||
image_hash=car_image.image_hash,
|
||||
image__isnull=False
|
||||
).exclude(car=car).first()
|
||||
|
||||
if existing:
|
||||
# Copy existing image
|
||||
car_image.image.save(
|
||||
existing.image.name,
|
||||
existing.image.file,
|
||||
save=True
|
||||
)
|
||||
logger.info(f"Reused image for car {car.vin}")
|
||||
else:
|
||||
# Schedule async generation
|
||||
async_task(
|
||||
'inventory.tasks.generate_car_image_task',
|
||||
car_image.id,
|
||||
task_name=f"generate_car_image_{car.vin}"
|
||||
)
|
||||
logger.info(f"Scheduled image generation for car {car.vin}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error handling car image for {car.vin}: {e}")
|
||||
@ -1,5 +1,8 @@
|
||||
import base64
|
||||
import logging
|
||||
import requests
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
from plans.models import Plan
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
@ -18,7 +21,8 @@ from .utils import get_accounts_data,create_account
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.contrib.auth.models import User, Group, Permission
|
||||
from inventory.models import DealerSettings, Dealer,Schedule,Notification,CarReservation,CarStatusChoices
|
||||
from inventory.models import DealerSettings, Dealer,Schedule,Notification,CarReservation,CarStatusChoices,CarImage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
@ -928,4 +932,30 @@ def remove_reservation_by_id(reservation_id):
|
||||
logger.error(f"Error removing reservation with ID {reservation_id}: {e}")
|
||||
|
||||
def test_task(**kwargs):
|
||||
print("TASK : ",kwargs.get("dealer"))
|
||||
print("TASK : ",kwargs.get("dealer"))
|
||||
|
||||
|
||||
def generate_car_image_task(car_image_id):
|
||||
"""
|
||||
Simple async task to generate car image
|
||||
"""
|
||||
from inventory.utils import generate_car_image_simple
|
||||
try:
|
||||
car_image = CarImage.objects.get(id=car_image_id)
|
||||
result = generate_car_image_simple(car_image)
|
||||
|
||||
return {
|
||||
'success': result.get('success', False),
|
||||
'car_image_id': car_image_id,
|
||||
'error': result.get('error'),
|
||||
'message': 'Image generated' if result.get('success') else 'Generation failed'
|
||||
}
|
||||
|
||||
except CarImage.DoesNotExist:
|
||||
error_msg = f"CarImage with id {car_image_id} not found"
|
||||
logger.error(error_msg)
|
||||
return {'success': False, 'error': error_msg}
|
||||
except Exception as e:
|
||||
error_msg = f"Unexpected error: {e}"
|
||||
logger.error(error_msg)
|
||||
return {'success': False, 'error': error_msg}
|
||||
@ -3,11 +3,15 @@ import secrets
|
||||
import logging
|
||||
import datetime
|
||||
import requests
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
from decimal import Decimal
|
||||
from inventory import models
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
from urllib.parse import urljoin
|
||||
from django.utils import timezone
|
||||
from django.db import transaction
|
||||
from django_ledger.io import roles
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import redirect
|
||||
@ -20,16 +24,17 @@ from django_ledger.models import (
|
||||
BillModel,
|
||||
VendorModel,
|
||||
)
|
||||
from django.core.files.base import ContentFile
|
||||
from django_ledger.models.items import ItemModel
|
||||
from django.utils.translation import get_language
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_q.models import Schedule as DjangoQSchedule
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django_ledger.models.transactions import TransactionModel
|
||||
from django_ledger.models.journal_entry import JournalEntryModel
|
||||
from django.db import transaction
|
||||
from django_q.models import Schedule as DjangoQSchedule
|
||||
from django_ledger.io import roles
|
||||
# from .tasks import generate_car_image_task
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -1301,7 +1306,7 @@ def get_finance_data(estimate,dealer):
|
||||
additional_services = car.get_additional_services()
|
||||
discounted_price=(Decimal(car.marked_price) - discount)
|
||||
vat_amount = discounted_price * vat.rate
|
||||
total_services_vat=sum([ x[1] for x in additional_services.get("services")])
|
||||
total_services_vat=sum([x[1] for x in additional_services.get("services")])
|
||||
total_vat=vat_amount+total_services_vat
|
||||
return {
|
||||
"car": car,
|
||||
@ -1311,7 +1316,7 @@ def get_finance_data(estimate,dealer):
|
||||
"vat_rate": vat.rate,
|
||||
"discount_amount": discount,
|
||||
"additional_services": additional_services,
|
||||
"final_price": discounted_price+ vat_amount,
|
||||
"final_price": discounted_price + vat_amount,
|
||||
"total_services_vat":total_services_vat,
|
||||
"total_vat":total_vat,
|
||||
"grand_total": discounted_price + total_vat + additional_services.get("total")
|
||||
@ -1649,7 +1654,7 @@ def _post_sale_and_cogs(invoice, dealer):
|
||||
)
|
||||
TransactionModel.objects.create(
|
||||
journal_entry=je_sale,
|
||||
|
||||
|
||||
account=vat_acc,
|
||||
amount=car.get_additional_services_vat,
|
||||
tx_type='credit',
|
||||
@ -2348,4 +2353,274 @@ def create_account(entity, coa, account_data):
|
||||
account.save()
|
||||
logger.info(f"Created default account: {account}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating default account: {account_data['code']}, {e}")
|
||||
logger.error(f"Error creating default account: {account_data['code']}, {e}")
|
||||
|
||||
|
||||
def get_or_generate_car_image(car):
|
||||
"""
|
||||
Utility function to get or generate car image asynchronously
|
||||
"""
|
||||
try:
|
||||
car_image, created = models.CarImage.objects.get_or_create(car=car)
|
||||
|
||||
if created:
|
||||
car_image.image_hash = car.get_hash
|
||||
car_image.save()
|
||||
|
||||
if car_image.image:
|
||||
return car_image.image.url
|
||||
|
||||
# Check for existing image with same hash
|
||||
existing = models.CarImage.objects.filter(
|
||||
image_hash=car_image.image_hash,
|
||||
image__isnull=False
|
||||
).exclude(car=car).first()
|
||||
|
||||
if existing:
|
||||
car_image.image.save(
|
||||
existing.image.name,
|
||||
existing.image.file,
|
||||
save=True
|
||||
)
|
||||
return car_image.image.url
|
||||
|
||||
# If no image exists and not already generating, schedule generation
|
||||
if not car_image.is_generating:
|
||||
car_image.schedule_image_generation()
|
||||
|
||||
return None # Return None while image is being generated
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting/generating car image: {e}")
|
||||
return None
|
||||
|
||||
def force_regenerate_car_image(car):
|
||||
"""
|
||||
Force regeneration of car image (useful for admin actions)
|
||||
"""
|
||||
try:
|
||||
car_image, created = models.CarImage.objects.get_or_create(car=car)
|
||||
car_image.image_hash = car.get_hash
|
||||
car_image.image.delete(save=False) # Remove old image
|
||||
car_image.is_generating = False
|
||||
car_image.generation_attempts = 0
|
||||
car_image.last_generation_error = None
|
||||
car_image.save()
|
||||
|
||||
car_image.schedule_image_generation()
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error forcing image regeneration: {e}")
|
||||
return False
|
||||
|
||||
class CarImageAPIClient:
|
||||
"""Simple client to handle authenticated requests to the car image API"""
|
||||
|
||||
BASE_URL = "http://10.10.1.111:8888"
|
||||
USERNAME = "faheed"
|
||||
PASSWORD = "Tenhal@123"
|
||||
|
||||
def __init__(self):
|
||||
self.session = None
|
||||
self.csrf_token = None
|
||||
|
||||
def login(self):
|
||||
"""Login to the API and maintain session"""
|
||||
try:
|
||||
# Start fresh session
|
||||
self.session = requests.Session()
|
||||
|
||||
# Step 1: Get CSRF token
|
||||
response = self.session.get(f"{self.BASE_URL}/login")
|
||||
response.raise_for_status()
|
||||
|
||||
# Get CSRF token from cookies
|
||||
self.csrf_token = self.session.cookies.get('csrftoken')
|
||||
if not self.csrf_token:
|
||||
raise Exception("CSRF token not found in cookies")
|
||||
|
||||
# Step 2: Login
|
||||
login_data = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASSWORD,
|
||||
"csrfmiddlewaretoken": self.csrf_token
|
||||
}
|
||||
|
||||
login_response = self.session.post(
|
||||
f"{self.BASE_URL}/login",
|
||||
data=login_data
|
||||
)
|
||||
|
||||
if login_response.status_code != 200:
|
||||
raise Exception(f"Login failed with status {login_response.status_code}")
|
||||
|
||||
logger.info("Successfully logged in to car image API")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Login failed: {e}")
|
||||
self.session = None
|
||||
self.csrf_token = None
|
||||
return False
|
||||
|
||||
def generate_image(self, payload):
|
||||
"""Generate car image using authenticated session"""
|
||||
if not self.session or not self.csrf_token:
|
||||
if not self.login():
|
||||
raise Exception("Cannot generate image: Login failed")
|
||||
|
||||
try:
|
||||
headers = {
|
||||
'X-CSRFToken': self.csrf_token,
|
||||
'Referer': self.BASE_URL,
|
||||
}
|
||||
print(payload)
|
||||
generate_data = {
|
||||
"year": payload['year'],
|
||||
"make": payload['make'],
|
||||
"model": payload['model'],
|
||||
"exterior_color": payload['color'],
|
||||
"angle": "3/4 rear",
|
||||
"reference_image": ""
|
||||
}
|
||||
|
||||
response = self.session.post(
|
||||
f"{self.BASE_URL}/generate",
|
||||
json=generate_data,
|
||||
headers=headers,
|
||||
timeout=160
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
# Parse response
|
||||
result = response.json()
|
||||
image_url = result.get('url')
|
||||
|
||||
if not image_url:
|
||||
raise Exception("No image URL in response")
|
||||
|
||||
# Download the actual image
|
||||
image_response = self.session.get(
|
||||
f"{self.BASE_URL}{image_url}",
|
||||
timeout=160
|
||||
)
|
||||
|
||||
image_response.raise_for_status()
|
||||
|
||||
return image_response.content, None
|
||||
|
||||
except requests.RequestException as e:
|
||||
error_msg = f"API request failed: {e}"
|
||||
logger.error(error_msg)
|
||||
return None, error_msg
|
||||
except Exception as e:
|
||||
error_msg = f"Unexpected error: {e}"
|
||||
logger.error(error_msg)
|
||||
return None, error_msg
|
||||
|
||||
# Global client instance
|
||||
api_client = CarImageAPIClient()
|
||||
|
||||
def resize_image(image_data, max_size=(800, 600)):
|
||||
"""
|
||||
Resize image to make it smaller while maintaining aspect ratio
|
||||
Returns resized image data in the same format
|
||||
"""
|
||||
try:
|
||||
img = Image.open(BytesIO(image_data))
|
||||
original_format = img.format
|
||||
original_mode = img.mode
|
||||
|
||||
# Calculate new size maintaining aspect ratio
|
||||
img.thumbnail(max_size, Image.Resampling.LANCZOS)
|
||||
|
||||
# Save back to bytes in original format
|
||||
output_buffer = BytesIO()
|
||||
|
||||
if original_format and original_format.upper() in ['JPEG', 'JPG']:
|
||||
img.save(output_buffer, format='JPEG', quality=95, optimize=True)
|
||||
elif original_format and original_format.upper() == 'PNG':
|
||||
# Preserve transparency for PNG
|
||||
if original_mode == 'RGBA':
|
||||
img.save(output_buffer, format='PNG', optimize=True)
|
||||
else:
|
||||
img.save(output_buffer, format='PNG', optimize=True)
|
||||
else:
|
||||
# Default to JPEG for other formats
|
||||
if img.mode in ('RGBA', 'LA', 'P'):
|
||||
# Convert to RGB if image has transparency
|
||||
background = Image.new('RGB', img.size, (255, 255, 255))
|
||||
if img.mode == 'RGBA':
|
||||
background.paste(img, mask=img.split()[3])
|
||||
else:
|
||||
background.paste(img, (0, 0))
|
||||
img = background
|
||||
img.save(output_buffer, format='JPEG', quality=95, optimize=True)
|
||||
|
||||
resized_data = output_buffer.getvalue()
|
||||
|
||||
logger.info(f"Resized image from {len(image_data)} to {len(resized_data)} bytes")
|
||||
return resized_data, None
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Image resizing failed: {e}"
|
||||
logger.error(error_msg)
|
||||
return None, error_msg
|
||||
|
||||
def generate_car_image_simple(car_image):
|
||||
"""
|
||||
Simple function to generate car image with authentication and resizing
|
||||
"""
|
||||
car = car_image.car
|
||||
|
||||
# Prepare payload
|
||||
payload = {
|
||||
'make': car.id_car_make.name if car.id_car_make else '',
|
||||
'model': car.id_car_model.name if car.id_car_model else '',
|
||||
'year': car.year,
|
||||
'color': car.colors.exterior.name
|
||||
}
|
||||
|
||||
logger.info(f"Generating image for car {car.vin}")
|
||||
|
||||
# Generate image using API client
|
||||
image_data, error = api_client.generate_image(payload)
|
||||
|
||||
if error:
|
||||
return {'success': False, 'error': error}
|
||||
|
||||
if not image_data:
|
||||
return {'success': False, 'error': 'No image data received'}
|
||||
|
||||
try:
|
||||
# Resize the image to make it smaller
|
||||
resized_data, resize_error = resize_image(image_data, max_size=(800, 600))
|
||||
|
||||
if resize_error:
|
||||
# If resizing fails, use original image but log warning
|
||||
logger.warning(f"Resizing failed, using original image: {resize_error}")
|
||||
resized_data = image_data
|
||||
|
||||
# Determine file extension based on content
|
||||
try:
|
||||
img = Image.open(BytesIO(resized_data))
|
||||
file_extension = img.format.lower() if img.format else 'jpg'
|
||||
except:
|
||||
file_extension = 'jpg'
|
||||
|
||||
# Save the resized image
|
||||
car_image.image.save(
|
||||
f"{car_image.image_hash}.{file_extension}",
|
||||
ContentFile(resized_data),
|
||||
save=False
|
||||
)
|
||||
|
||||
logger.info(f"Successfully generated and resized image for car {car.vin}")
|
||||
return {'success': True}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Image processing failed: {e}"
|
||||
logger.error(error_msg)
|
||||
return {'success': False, 'error': error_msg}
|
||||
@ -4979,6 +4979,7 @@ def create_estimate(request, dealer_slug, slug=None):
|
||||
.annotate(hash_count=Count("hash"))
|
||||
.distinct()
|
||||
)
|
||||
|
||||
context = {
|
||||
"form": form,
|
||||
"items": [
|
||||
@ -6328,6 +6329,7 @@ def lead_create(request, dealer_slug):
|
||||
qs = form.fields["id_car_make"].queryset.filter(
|
||||
is_sa_import=True, pk__in=dealer_make_list
|
||||
)
|
||||
# print(qs)
|
||||
form.fields["staff"].queryset = (
|
||||
form.fields["staff"]
|
||||
.queryset.select_related("user")
|
||||
@ -6346,10 +6348,12 @@ def lead_create(request, dealer_slug):
|
||||
form.fields["staff"].queryset = models.Staff.objects.filter(
|
||||
dealer=dealer, pk=request.staff.pk
|
||||
)
|
||||
qs = qs.order_by("name")
|
||||
form.fields["id_car_make"].queryset = qs
|
||||
form.fields["id_car_make"].choices = [
|
||||
(obj.id_car_make, obj.get_local_name()) for obj in qs
|
||||
]
|
||||
]
|
||||
|
||||
if first_make := qs.first():
|
||||
form.fields["id_car_model"].queryset = first_make.carmodel_set.all()
|
||||
|
||||
@ -8435,7 +8439,7 @@ class FiscalYearIncomeStatementViewBase(
|
||||
"""
|
||||
|
||||
template_name = "ledger/reports/income_statement.html"
|
||||
permission_required = ["inventory.view_carfinance"]
|
||||
permission_required = ["django_ledger.view_ledgermodel"]
|
||||
|
||||
def get_login_url(self):
|
||||
return reverse("account_login")
|
||||
@ -8574,7 +8578,7 @@ class FiscalYearCashFlowStatementViewBase(
|
||||
"""
|
||||
|
||||
template_name = "ledger/reports/cash_flow_statement.html"
|
||||
permission_required = ["inventory.view_carfinance"]
|
||||
permission_required = ["django_ledger.view_ledgermodel"]
|
||||
|
||||
def get_login_url(self):
|
||||
return reverse("account_login")
|
||||
@ -8763,7 +8767,7 @@ class FiscalYearEntityModelDashboardView(
|
||||
:type permission_required: list
|
||||
"""
|
||||
|
||||
permission_required = ["inventory.view_carfinance"]
|
||||
permission_required = ["django_ledger.view_ledgermodel"]
|
||||
|
||||
def get_login_url(self):
|
||||
return reverse("account_login")
|
||||
@ -11433,6 +11437,10 @@ def create_ticket(request,dealer_slug):
|
||||
def ticket_list(request,dealer_slug):
|
||||
dealer= get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||
tickets = models.Ticket.objects.filter(dealer=dealer).order_by('-created_at')
|
||||
query=request.GET.get('q')
|
||||
if query:
|
||||
tickets=tickets.filter(Q(id__icontains=query)| Q(subject__icontains=query))
|
||||
|
||||
return render(request, 'support/ticket_list.html', {'tickets': tickets})
|
||||
|
||||
@login_required
|
||||
|
||||
|
After Width: | Height: | Size: 418 KiB |
|
After Width: | Height: | Size: 432 KiB |
|
After Width: | Height: | Size: 401 KiB |
|
After Width: | Height: | Size: 422 KiB |
|
After Width: | Height: | Size: 448 KiB |
|
After Width: | Height: | Size: 336 KiB |
|
After Width: | Height: | Size: 327 KiB |
|
After Width: | Height: | Size: 431 KiB |
|
After Width: | Height: | Size: 401 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 422 KiB |
|
After Width: | Height: | Size: 398 KiB |
|
After Width: | Height: | Size: 438 KiB |
|
After Width: | Height: | Size: 4.4 MiB |
@ -3,52 +3,45 @@
|
||||
{% load i18n static %}
|
||||
{% load allauth account %}
|
||||
{% block title %}
|
||||
{% trans 'User Settings' %}
|
||||
{% trans 'Dealer Settings' %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
Dealer Settings
|
||||
<span class="fas fa-solid fa-gear ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans "Dealer Settings" %}
|
||||
<i class="fas fa-solid fa-gear ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle ">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="col-12">
|
||||
<div class=" mb-4">
|
||||
<div class="row gx-3 mb-4 gy-6 gy-sm-3">
|
||||
<div class="col-12">
|
||||
<h4 class="mb-4">{% trans 'Default Invoice Accounts' %}</h4>
|
||||
<div class="form-icon-container mb-3">{{ form.invoice_cash_account|as_crispy_field }}</div>
|
||||
<div class="form-icon-container mb-3">{{ form.invoice_prepaid_account|as_crispy_field }}</div>
|
||||
<div class="form-icon-container mb-3">{{ form.invoice_unearned_account|as_crispy_field }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row gx-3 mb-4 gy-6 gy-sm-3">
|
||||
<div class="col-12">
|
||||
<h4 class="mb-4">{% trans 'Default Bill Accounts' %}</h4>
|
||||
<div class="form-icon-container mb-3">{{ form.bill_cash_account|as_crispy_field }}</div>
|
||||
<div class="form-icon-container mb-3">{{ form.bill_prepaid_account|as_crispy_field }}</div>
|
||||
<div class="form-icon-container mb-3">{{ form.bill_unearned_account|as_crispy_field }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mb-6">
|
||||
<div>
|
||||
<button type="submit" class="btn btn-phoenix-primary"><i class="fa-solid fa-pen-to-square me-1"></i>{% trans 'Update' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form action="" method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
<div class="row g-1">
|
||||
<div class="col-12">
|
||||
<h4 class="mb-4 text-center">{% trans 'Default Invoice Accounts' %}</h4>
|
||||
{{ form.invoice_cash_account|as_crispy_field }}
|
||||
{{ form.invoice_prepaid_account|as_crispy_field }}
|
||||
{{ form.invoice_unearned_account|as_crispy_field }}
|
||||
</div>
|
||||
<div class="col-12 mt-4">
|
||||
<h4 class="mb-4 text-center">{% trans 'Default Bill Accounts' %}</h4>
|
||||
{{ form.bill_cash_account|as_crispy_field }}
|
||||
{{ form.bill_prepaid_account|as_crispy_field }}
|
||||
{{ form.bill_unearned_account|as_crispy_field }}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg" type="submit">
|
||||
<i class="fa-solid fa-pen-to-square me-1"></i>
|
||||
{% trans 'Update' %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -8,50 +8,46 @@
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% trans 'Create Bill' %}<span class="fas fa-money-bills ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans 'Create Bill' %}
|
||||
<i class="fas fa-money-bills ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<form action="{{ form_action_url }}" method="post" id="djl-bill-model-create-form-id">
|
||||
<div class="card-body">
|
||||
|
||||
{% csrf_token %}
|
||||
{% if po_model %}
|
||||
<div class="text-center mb-4">
|
||||
<h3 class="h5">{% trans 'Bill for' %} {{ po_model.po_number }}</h3>
|
||||
<p class="text-muted mb-3">{% trans 'Bill for' %} {{ po_model.po_title }}</p>
|
||||
<div class="d-flex flex-column gap-2">
|
||||
{% for itemtxs in po_itemtxs_qs %}
|
||||
<span class="badge bg-secondary">{{ itemtxs }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form action="{{ form_action_url }}" method="post" id="djl-bill-model-create-form-id" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{% if po_model %}
|
||||
<div class="text-center mb-4">
|
||||
<h3 class="h5">{% trans 'Bill for' %} {{ po_model.po_number }}</h3>
|
||||
<p class="text-muted mb-3">{% trans 'Bill for' %} {{ po_model.po_title }}</p>
|
||||
<div class="d-flex flex-column gap-2">
|
||||
{% for itemtxs in po_itemtxs_qs %}
|
||||
<span class="badge bg-secondary">{{ itemtxs }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mb-4">
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'bill_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="mb-4">
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'bill_list' request.dealer.slug%}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,54 +1,59 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load i18n static %}
|
||||
{% load django_ledger %}
|
||||
{% load widget_tweaks %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 text-center mb-4">
|
||||
<h1 class="display-4">{% trans 'Create Chart of Accounts' %}</h1>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans 'Create Chart of Accounts' %}
|
||||
<i class="fa-solid fa-chart-pie ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<form method="post" id="{{ form.get_form_id }}">
|
||||
{% csrf_token %}
|
||||
|
||||
{# Bootstrap form rendering #}
|
||||
<div class="mb-3">
|
||||
{{ form.name.label_tag }}
|
||||
{{ form.name|add_class:"form-control" }}
|
||||
{% if form.name.help_text %}
|
||||
<small class="form-text text-muted">{{ form.name.help_text }}</small>
|
||||
{% endif %}
|
||||
{% for error in form.name.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{{ form.description.label_tag }}
|
||||
{{ form.description|add_class:"form-control" }}
|
||||
{% if form.description.help_text %}
|
||||
<small class="form-text text-muted">{{ form.description.help_text }}</small>
|
||||
{% endif %}
|
||||
{% for error in form.description.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="d-flex justify-content-center gap-2 mt-4">
|
||||
<button type="submit" class="btn btn-phoenix-primary">Submit</button>
|
||||
<a href="{% url 'coa-list' request.dealer.slug request.entity.slug %}" class="btn btn-phoenix-secondary">
|
||||
{% trans 'Back' %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" id="{{ form.get_form_id }}" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
{# Bootstrap form rendering #}
|
||||
<div class="mb-3">
|
||||
{{ form.name.label_tag }}
|
||||
{{ form.name|add_class:"form-control" }}
|
||||
{% if form.name.help_text %}
|
||||
<small class="form-text text-muted">{{ form.name.help_text }}</small>
|
||||
{% endif %}
|
||||
{% for error in form.name.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{{ form.description.label_tag }}
|
||||
{{ form.description|add_class:"form-control" }}
|
||||
{% if form.description.help_text %}
|
||||
<small class="form-text text-muted">{{ form.description.help_text }}</small>
|
||||
{% endif %}
|
||||
{% for error in form.description.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button type="submit" class="btn btn-phoenix-primary btn-lg me-md-2">
|
||||
<i class="fa-solid fa-plus me-1"></i>
|
||||
{% trans 'Create' %}
|
||||
</button>
|
||||
<a href="{% url 'coa-list' request.dealer.slug request.entity.slug %}"
|
||||
class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans 'Cancel' %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,5 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static crispy_forms_filters %}
|
||||
|
||||
{% block title %}
|
||||
{% if object %}
|
||||
{% trans 'Update Lead' %}
|
||||
@ -7,6 +8,7 @@
|
||||
{% trans 'Add New Lead' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block customcss %}
|
||||
<style>
|
||||
.htmx-indicator{
|
||||
@ -28,51 +30,41 @@
|
||||
}
|
||||
</style>
|
||||
{% endblock customcss %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if object %}
|
||||
{{ _("Update Lead") }}
|
||||
{% else %}
|
||||
{{ _("Create New Lead") }}
|
||||
{% endif %}
|
||||
<li class="fas fa-bullhorn text-primary ms-2"></li>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form class="form" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'lead_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Lead" %}
|
||||
<i class="fa-solid fa-edit ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Create New Lead" %}
|
||||
<i class="fa-solid fa-bullhorn ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form class="form" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
<a href="{% url 'lead_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const spinner = document.createElement('div');
|
||||
spinner.id = 'spinner';
|
||||
spinner.className = 'htmx-indicator spinner-border text-primary inline-spinner';
|
||||
spinner.innerHTML = '<span class="visually-hidden">Loading...</span>';
|
||||
const targetFieldDiv = document.getElementById('div_id_id_car_model');
|
||||
|
||||
if (targetFieldDiv) {
|
||||
targetFieldDiv.parentNode.insertBefore(spinner, targetFieldDiv.nextSibling);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,42 +1,60 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n static %}
|
||||
{% load crispy_forms_filters %}
|
||||
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Customer' %}
|
||||
{% else %}
|
||||
{% trans 'Add New Customer' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-o rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if customer.created %}
|
||||
{{ _("Edit Customer") }}
|
||||
{% else %}
|
||||
{{ _("Add Customer") }}
|
||||
{% endif %}
|
||||
<i class="fa-solid fa-user ms-2 text-primary"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form method="post"
|
||||
class="form row g-3 needs-validation"
|
||||
enctype="multipart/form-data"
|
||||
novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'customer_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5 ">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Customer" %}
|
||||
<i class="fa-solid fa-user-edit ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Add New Customer" %}
|
||||
<i class="fa-solid fa-user-plus ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" class="form" enctype="multipart/form-data" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
<a href="{% url 'customer_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -5,32 +5,34 @@
|
||||
{{ _("Update Dealer Information") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{{ _("Update Dealer Information") }}<span class="fas fa-car ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{{ _("Update Dealer Information") }}
|
||||
<i class="fas fa-car ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form hx-boost="false" method="post" enctype="multipart/form-data" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-2">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'dealer_detail' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'dealer_detail' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Group' %}
|
||||
{% else %}
|
||||
@ -10,41 +10,49 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if staff.created %}
|
||||
{{ _("Edit Group") }}
|
||||
{% else %}
|
||||
{{ _("Create Group") }}
|
||||
{% endif %}
|
||||
<i class="fa-solid fa-user-group text-primary ms-2"></i>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Group" %}
|
||||
<i class="fa-solid fa-user-group ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Create Group" %}
|
||||
<i class="fa-solid fa-user-plus ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<form class="row g-3 " method="post" class="form" novalidate>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'group_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
|
||||
<button class="btn btn-phoenix-primary btn-lg md-me-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>{% trans "Save" %}
|
||||
</button>
|
||||
<a href="{% url 'group_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -6,62 +6,70 @@
|
||||
{% trans "Groups" %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
{% if groups or request.GET.q%}
|
||||
<section class="">
|
||||
<div class="row mt-4">
|
||||
<div class="col-auto">
|
||||
<div class="d-md-flex justify-content-between">
|
||||
<div>
|
||||
<main class="py-5">
|
||||
<div class="container">
|
||||
{% if groups or request.GET.q %}
|
||||
<div class="card border-0 rounded-4 animate__animated animate__fadeInUp">
|
||||
<div class="card-header border-bottom d-flex flex-column flex-md-row justify-content-between align-items-md-center p-4">
|
||||
<h5 class="card-title mb-2 mb-md-0 me-md-4 fw-bold"> <i class="fa-solid fa-user-group fs-3 me-1 text-primary "></i>{% trans "Groups" %}</h5>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{% url 'group_create' request.dealer.slug %}"
|
||||
class="btn btn-sm btn-phoenix-primary me-5"><span class="fas fa-plus me-2"></span>{% trans "Add Group" %}</a>
|
||||
class="btn btn-phoenix-primary">
|
||||
<i class="fa-solid fa-user-group fs-9 me-1"></i>
|
||||
<span class="fas fa-plus me-2"></span>{% trans "Add Group" %}
|
||||
</a>
|
||||
<a href="{% url 'user_list' request.dealer.slug %}"
|
||||
class="btn btn-sm btn-phoenix-secondary"><span class="fas fas fa-arrow-left me-2"></span>{% trans "Back to Staffs" %}</a>
|
||||
class="btn btn-phoenix-secondary">
|
||||
<span class="fas fas fa-arrow-left me-2"></span>{% trans "Back to Staffs" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive scrollbar mx-n1 px-1 mt-3">
|
||||
<table class="table align-items-center table-flush table-hover">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<th>{% trans 'name'|capfirst %}</th>
|
||||
<th>{% trans 'total Users'|capfirst %}</th>
|
||||
<th>{% trans 'total permission'|capfirst %}</th>
|
||||
<th>{% trans 'actions'|capfirst %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for group in groups %}
|
||||
<tr>
|
||||
<td class="align-middle white-space-nowrap ps-1">{{ group.name }}</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<i class="fa-solid fa-users me-1"></i> {{ group.users.count }}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<i class="fa-solid fa-unlock me-1"></i> {{ group.permissions.count }}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<a class="btn btn-phoenix-success"
|
||||
href="{% url 'group_detail' request.dealer.slug group.id %}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
{% trans 'view'|capfirst %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">{% include 'partials/pagination.html' %}</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive scrollbar mx-n1 px-1 mt-3">
|
||||
<table class="table align-items-center table-hover mb-0">
|
||||
<thead>
|
||||
<tr class="bg-light">
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold ps-4">{% trans 'name'|capfirst %}</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold">{% trans 'total Users'|capfirst %}</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold">{% trans 'total permission'|capfirst %}</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold text-end pe-4">{% trans 'actions'|capfirst %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for group in groups %}
|
||||
<tr>
|
||||
<td class="align-middle white-space-nowrap ps-4">{{ group.name }}</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<i class="fa-solid fa-users me-1"></i> {{ group.users.count }}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<i class="fa-solid fa-unlock me-1"></i> {{ group.permissions.count }}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-end pe-4">
|
||||
<a class="btn btn-phoenix-secondary btn-sm"
|
||||
href="{% url 'group_detail' request.dealer.slug group.id %}">
|
||||
<i class="fa-solid fa-eye me-1"></i>
|
||||
{% trans 'view'|capfirst %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% else %}
|
||||
{% url "group_create" request.dealer.slug as create_group_url %}
|
||||
{% include "empty-illustration-page.html" with value="group" url=create_group_url %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
<div class="card-footer bg-light border-top">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% include 'partials/pagination.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{% url "group_create" request.dealer.slug as create_group_url %}
|
||||
{% include "empty-illustration-page.html" with value="group" url=create_group_url %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -3,10 +3,10 @@
|
||||
<nav class="navbar navbar-vertical navbar-expand-lg ">
|
||||
<div class="collapse navbar-collapse" id="navbarVerticalCollapse">
|
||||
<div class="navbar-vertical-content d-flex flex-column">
|
||||
<ul class="navbar-nav flex-column" id="navbarVerticalNav" hx-boost="true" hx-target="#main_content" hx-select="#main_content" hx-swap="outerHTML" hx-select-oob="#toast-container" hx-indicator="#spinner">
|
||||
<ul class="navbar-nav flex-column" id="navbarVerticalNav" hx-boost="false" hx-target="#main_content" hx-select="#main_content" hx-swap="outerHTML" hx-select-oob="#toast-container" hx-indicator="#spinner">
|
||||
<li class="nav-item">
|
||||
<p class="navbar-vertical-label text-primary fs-8 text-truncate">{{request.dealer|default:"Apps"}}</p>
|
||||
<hr class="navbar-vertical-line">
|
||||
{% comment %} <p class="navbar-vertical-label text-primary fs-8 text-truncate">{{request.dealer|default:"Apps"}}</p>
|
||||
<hr class="navbar-vertical-line"> {% endcomment %}
|
||||
{% if perms.inventory.can_view_inventory %}
|
||||
<div class="nav-item-wrapper">
|
||||
<a id="inventory-nav" class="nav-link dropdown-indicator label-1 inventory-nav" href="#nv-inventory" role="button" data-bs-toggle="collapse" aria-expanded="false" aria-controls="nv-inventory">
|
||||
@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if perms.inventory.view_car%}
|
||||
@ -386,7 +386,7 @@
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<li class="nav-item mb-4">
|
||||
<a class="nav-link" href="#">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="nav-link-icon"><span class="fas fa-robot"></span></span>
|
||||
@ -394,9 +394,22 @@
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="#">
|
||||
<div class="d-flex align-items-center">
|
||||
{% if user.is_authenticated %}
|
||||
<span class="nav-link-icon"><span class="fa-solid fa-car"></span></span>
|
||||
<span class="nav-link-text">{{ request.dealer.user.username }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
@ -433,15 +446,15 @@
|
||||
</a>
|
||||
</div>
|
||||
{% if request.user.is_authenticated%}
|
||||
|
||||
|
||||
<div class="navbar-logo">
|
||||
<div class="d-flex align-items-center">
|
||||
{% with name_to_display=request.user.first_name|default:request.dealer.name %}
|
||||
<h6 class="text-info ms-2 d-none d-sm-block fs-7"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
<h6 class="text-gray-600 ms-2 d-none d-sm-block fs-8"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
title="{% trans 'Logged in as ' %}{{request.user.username }}">
|
||||
{% trans 'Hello, ' %}{{ name_to_display }}
|
||||
{% trans 'Hello, ' %}{{ name_to_display }}
|
||||
</h6>
|
||||
{% endwith %}
|
||||
</div>
|
||||
@ -518,11 +531,12 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 d-block" href="{% url 'user_list' request.dealer.slug %}"><span class="me-2 text-body align-bottom" data-feather="users"></span>{{ _("Staff & Groups") }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
{% comment %} <li class="nav-item">
|
||||
<a class="nav-link px-3 d-block" href="{% url 'dealer_activity' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="lock"></span>{{ _("Activities") }}</a>
|
||||
</li>
|
||||
</li> {% endcomment %}
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
|
||||
{% if request.is_dealer %}
|
||||
<a class="nav-link px-3 d-block" href="{% url 'dealer_settings' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="settings"></span>{{ _("Settings") }}</a>
|
||||
{% endif %}
|
||||
|
||||
@ -1,16 +1,41 @@
|
||||
<!-- templates/cars/car_confirm_delete.html -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}Delete Car{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="mt-4 ms-4">
|
||||
<h1>Delete Car</h1>
|
||||
<p class="text-danger">Are you sure you want to delete the car "{{ car }}"?</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-phoenix-danger">Confirm Delete</button>
|
||||
<a href="{% url 'car_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-secondary">{% trans 'Cancel' %}</a>
|
||||
</form>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-50 py-5">
|
||||
<div class="col-md-6 ">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
|
||||
<div class="card-body p-4 p-md-5 text-center bg-gradient">
|
||||
<div class="mb-4">
|
||||
<i class="fa-solid fa-triangle-exclamation text-danger" style="font-size: 2rem;"></i>
|
||||
</div>
|
||||
|
||||
<h1 class="card-title fw-bold mb-3 fs-4">{% trans 'Confirm Deletion' %}</h1>
|
||||
|
||||
<p class="fs-7 mb-4">
|
||||
{% trans "Are you absolutely sure you want to delete the car" %}
|
||||
</p>
|
||||
<p class="fs-6 mb-4">
|
||||
"<strong class="">{{ car }}</strong>"?
|
||||
</p>
|
||||
<p class="fs-7 mb-4">
|
||||
{% trans "This action is permanent and cannot be undone." %}
|
||||
</p>
|
||||
|
||||
<form method="post" class="d-grid gap-3 d-sm-flex justify-content-sm-center">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-phoenix-danger btn-lg px-5">
|
||||
<i class="fa-solid fa-trash-can me-2"></i>{% trans 'Confirm Delete' %}
|
||||
</button>
|
||||
<a href="{% url 'car_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg px-5">
|
||||
<i class="fa-solid fa-ban me-2"></i>{% trans 'Cancel' %}
|
||||
</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -76,13 +76,279 @@
|
||||
{% if perms.inventory.view_car %}
|
||||
<div class="row-fluid {% if car.status == 'sold' %}disabled{% endif %}">
|
||||
<div class="row g-3 justify-content-between">
|
||||
<div class="col-lg-12 col-xl-6">
|
||||
<div class="avatar avatar-5xl mb-3">
|
||||
<img class="rounded h-100 w-100"
|
||||
src="{% static 'images/cars/' %}{{ car.vin }}.png"
|
||||
alt="{{ car.vin }}" />
|
||||
</div>
|
||||
<div class="card mb-3 rounded shadow d-flex align-content-center
|
||||
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-4">
|
||||
<div class="avatar avatar-6xl mb-3">
|
||||
<img class="rounded"
|
||||
src="{% static 'images/car_images/' %}{{ car.get_hash }}.png"
|
||||
alt="{{ car.vin }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="card rounded shadow d-flex align-content-center
|
||||
{% if car.get_transfer %}transfer{% endif %}">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Financial Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
{% if car.marked_price %}
|
||||
<tr>
|
||||
|
||||
<th>{% trans "Cost Price"|capfirst %}</th>
|
||||
<td>{{ car.cost_price|floatformat:2 }}</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Marked Price"|capfirst %}</th>
|
||||
<td>{{ car.marked_price|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% comment %} <tr>
|
||||
<th>{% trans "Selling Price"|capfirst %}</th>
|
||||
<td>{{ car.finances.selling_price|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Discount Amount"|capfirst %}</th>
|
||||
<td>{{ car.finances.discount_amount|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Additional Fee"|capfirst %}</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% if car.finances.additional_services.first.pk %}
|
||||
{% for service in car.finances.additional_services.all %}
|
||||
<tr>
|
||||
<td>{{ service.name }}</td>
|
||||
<td>{{ service.price_|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>{% trans "VAT Amount"|capfirst %}</th>
|
||||
<td>{{ car.finances.vat_amount|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Total"|capfirst %}</th>
|
||||
<td>{{ car.finances.total_vat|floatformat:2 }}</td>
|
||||
</tr> {% endcomment %}
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if not car.get_transfer %}
|
||||
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% else %}
|
||||
<p>{% trans "No finance details available." %}</p>
|
||||
|
||||
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-success btn-sm mb-3">{% trans "Add" %}</a>
|
||||
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% if perms.inventory.view_carcolors %}
|
||||
<div class="card rounded shadow d-flex align-content-center mt-3
|
||||
{% if car.get_transfer %}transfer{% endif %}">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Colors Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
<!--test-->
|
||||
{% if car.colors %}
|
||||
<tr>
|
||||
<th>{% trans 'Exterior' %}</th>
|
||||
<td>
|
||||
<span>{{ car.colors.exterior.get_local_name }}</span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<div class="text-end color-div"
|
||||
style="background-color: rgb({{ car.colors.exterior.rgb }})">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans 'Interior' %}</th>
|
||||
<td>
|
||||
<span>{{ car.colors.interior.get_local_name }}</span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<div class="text-end color-div"
|
||||
style="background-color: rgb({{ car.colors.interior.rgb }})">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% if perms.inventory.change_carcolors %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if not car.get_transfer %}
|
||||
<a href="{% url 'car_colors_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p>{% trans "No color details available." %}</p>
|
||||
{% if perms.inventory.add_carcolors %}
|
||||
<a class="btn btn-phoenix-success btn-sm mb-3"
|
||||
href="{% url 'add_color' request.dealer.slug car.slug %}">{{ _("Add Color") }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<!--test-->
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if car.status != 'transfer' %}
|
||||
{% if perms.inventory.view_carreservation %}
|
||||
<div class="card rounded shadow d-flex align-content-center mt-3 h-full w-100">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Reservations Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
{% if car.is_reserved %}
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Reserved By" %}</th>
|
||||
<th>{% trans "Expires At" %}</th>
|
||||
<th>{% trans 'Actions' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for reservation in car.reservations.all %}
|
||||
<tr>
|
||||
<td>{{ reservation.reserved_by.dealer }}</td>
|
||||
<td>{{ reservation.reserved_until }}</td>
|
||||
{% if perms.inventory.change_carreservation %}
|
||||
<td>
|
||||
{% if reservation.is_active %}
|
||||
<form method="post"
|
||||
action="{% url 'reservations' request.dealer.slug reservation.id %}">
|
||||
{% csrf_token %}
|
||||
<div class="btn-group">
|
||||
<button type="submit"
|
||||
name="action"
|
||||
value="renew"
|
||||
class="btn btn-sm btn-phoenix-success px-3 py-1">
|
||||
{% trans "Renew" %}
|
||||
</button>
|
||||
<button type="submit"
|
||||
name="action"
|
||||
value="cancel"
|
||||
class="btn btn-sm btn-phoenix-secondary px-3 py-1">
|
||||
{% trans "Cancel" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<span class="badge badge-phoenix badge-phoenix-danger fs-10">{% trans "Expired" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% if perms.inventory.add_carreservation %}
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-phoenix-success"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#reserveModal">
|
||||
{% trans 'Reserve' %}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
<!-- Transfer Table -->
|
||||
{% if car.status == 'transfer' and car.get_transfer %}
|
||||
<div class="card rounded shadow d-flex align-content-center mt-3">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Transfer Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Action" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "From Showroom" %}</th>
|
||||
<th>{% trans "To Showroom" %}</th>
|
||||
<th>{% trans 'Date' %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="badge badge-phoenix badge-phoenix-info">{% trans "Transfer" %}</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if car.get_transfer.status == "draft" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-warning">{% trans "waiting for approval" %}</span>
|
||||
{% elif car.get_transfer.status == "approved" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-info">{% trans "waiting for dealer acceptance" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ car.get_transfer.from_dealer|title }}</td>
|
||||
<td>{{ car.get_transfer.to_dealer|title }}</td>
|
||||
<td>{{ car.get_transfer.transfer_date|date:"Y-m-d" }}</td>
|
||||
<td>
|
||||
{% if car.get_transfer.status == "draft" %}
|
||||
<a class="btn btn-sm btn-phoenix-success"
|
||||
href="{% url 'transfer_detail' car.get_transfer.pk %}">{% trans "Approve" %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-phoenix-success"
|
||||
href="{% url 'transfer_detail' car.get_transfer.pk %}?action=cancel">{% trans "Cancel" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 rounded shadow d-flex align-content-center
|
||||
{% if car.get_transfer %}disabled{% endif %}">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Car Details' %}</p>
|
||||
<div class="card-body">
|
||||
@ -234,7 +500,7 @@
|
||||
{% if not car.get_transfer %}
|
||||
{% if perms.inventory.change_car %}
|
||||
<a href="{% url 'car_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-primary btn-sm mt-1">{% trans "Edit" %}
|
||||
class="btn btn-phoenix-primary btn-sm mt-1 me-3 mb-3">{% trans "Edit" %}
|
||||
<span class="fas fa-solid fa-pencil ms-1"></span>
|
||||
</a>
|
||||
<a href="{% url 'transfer' car.slug %}"
|
||||
@ -249,257 +515,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-xl-6">
|
||||
{% if perms.inventory.view_carfinance %}
|
||||
<div class="card rounded shadow d-flex align-content-center
|
||||
{% if car.get_transfer %}transfer{% endif %}">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Financial Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
{% if car.marked_price %}
|
||||
<tr>
|
||||
{% if perms.inventory.view_carfinance %}
|
||||
<th>{% trans "Cost Price"|capfirst %}</th>
|
||||
<td>{{ car.cost_price|floatformat:2 }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Marked Price"|capfirst %}</th>
|
||||
<td>{{ car.marked_price|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% comment %} <tr>
|
||||
<th>{% trans "Selling Price"|capfirst %}</th>
|
||||
<td>{{ car.finances.selling_price|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Discount Amount"|capfirst %}</th>
|
||||
<td>{{ car.finances.discount_amount|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Additional Fee"|capfirst %}</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% if car.finances.additional_services.first.pk %}
|
||||
{% for service in car.finances.additional_services.all %}
|
||||
<tr>
|
||||
<td>{{ service.name }}</td>
|
||||
<td>{{ service.price_|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>{% trans "VAT Amount"|capfirst %}</th>
|
||||
<td>{{ car.finances.vat_amount|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Total"|capfirst %}</th>
|
||||
<td>{{ car.finances.total_vat|floatformat:2 }}</td>
|
||||
</tr> {% endcomment %}
|
||||
{% if perms.inventory.change_carfinance %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if not car.get_transfer %}
|
||||
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>{% trans "No finance details available." %}</p>
|
||||
{% if perms.inventory.add_carfinance %}
|
||||
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-success btn-sm mb-3">{% trans "Add" %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if perms.inventory.view_carcolors %}
|
||||
<div class="card rounded shadow d-flex align-content-center mt-3
|
||||
{% if car.get_transfer %}transfer{% endif %}">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Colors Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
<!--test-->
|
||||
{% if car.colors %}
|
||||
<tr>
|
||||
<th>{% trans 'Exterior' %}</th>
|
||||
<td>
|
||||
<span>{{ car.colors.exterior.get_local_name }}</span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<div class="text-end color-div"
|
||||
style="background-color: rgb({{ car.colors.exterior.rgb }})">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans 'Interior' %}</th>
|
||||
<td>
|
||||
<span>{{ car.colors.interior.get_local_name }}</span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<div class="text-end color-div"
|
||||
style="background-color: rgb({{ car.colors.interior.rgb }})">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% if perms.inventory.change_carcolors %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if not car.get_transfer %}
|
||||
<a href="{% url 'car_colors_update' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p>{% trans "No color details available." %}</p>
|
||||
{% if perms.inventory.add_carcolors %}
|
||||
<a class="btn btn-phoenix-success btn-sm mb-3"
|
||||
href="{% url 'add_color' request.dealer.slug car.slug %}">{{ _("Add Color") }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<!--test-->
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if car.status != 'transfer' %}
|
||||
{% if perms.inventory.view_carreservation %}
|
||||
<div class="card rounded shadow d-flex align-content-center mt-3">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Reservations Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
{% if car.is_reserved %}
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Reserved By" %}</th>
|
||||
<th>{% trans "Expires At" %}</th>
|
||||
<th>{% trans 'Actions' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for reservation in car.reservations.all %}
|
||||
<tr>
|
||||
<td>{{ reservation.reserved_by.dealer }}</td>
|
||||
<td>{{ reservation.reserved_until }}</td>
|
||||
{% if perms.inventory.change_carreservation %}
|
||||
<td>
|
||||
{% if reservation.is_active %}
|
||||
<form method="post"
|
||||
action="{% url 'reservations' request.dealer.slug reservation.id %}">
|
||||
{% csrf_token %}
|
||||
<div class="btn-group">
|
||||
<button type="submit"
|
||||
name="action"
|
||||
value="renew"
|
||||
class="btn btn-sm btn-phoenix-success px-3 py-1">
|
||||
{% trans "Renew" %}
|
||||
</button>
|
||||
<button type="submit"
|
||||
name="action"
|
||||
value="cancel"
|
||||
class="btn btn-sm btn-phoenix-secondary px-3 py-1">
|
||||
{% trans "Cancel" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<span class="badge badge-phoenix badge-phoenix-danger fs-10">{% trans "Expired" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% if perms.inventory.add_carreservation %}
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-phoenix-success"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#reserveModal">
|
||||
{% trans 'Reserve' %}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<!-- Transfer Table -->
|
||||
{% if car.status == 'transfer' and car.get_transfer %}
|
||||
<div class="card rounded shadow d-flex align-content-center mt-3">
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Transfer Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Action" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "From Showroom" %}</th>
|
||||
<th>{% trans "To Showroom" %}</th>
|
||||
<th>{% trans 'Date' %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="badge badge-phoenix badge-phoenix-info">Transfer</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if car.get_transfer.status == "draft" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-warning">waiting for approval</span>
|
||||
{% elif car.get_transfer.status == "approved" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-info">waiting for dealer acceptance</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ car.get_transfer.from_dealer|title }}</td>
|
||||
<td>{{ car.get_transfer.to_dealer|title }}</td>
|
||||
<td>{{ car.get_transfer.transfer_date|date:"Y-m-d" }}</td>
|
||||
<td>
|
||||
{% if car.get_transfer.status == "draft" %}
|
||||
<a class="btn btn-sm btn-phoenix-success"
|
||||
href="{% url 'transfer_detail' car.get_transfer.pk %}">Approve</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-phoenix-success"
|
||||
href="{% url 'transfer_detail' car.get_transfer.pk %}?action=cancel">Cancel</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% if car.status == 'sold' %}
|
||||
<img class="car_status"
|
||||
src="{% static 'images/sold.png' %}"
|
||||
@ -508,6 +527,7 @@
|
||||
alt="">
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Custom Card Modal -->
|
||||
<div class="modal fade"
|
||||
id="customCardModal"
|
||||
|
||||
@ -6,34 +6,34 @@
|
||||
{% trans 'Edit Car' %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% trans 'Edit Car' %}
|
||||
<span class="fas fa-solid fa-car text-primary ms-2"></span>
|
||||
</h3>
|
||||
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans 'Edit Car' %}
|
||||
<i class="fas fa-solid fa-car ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %} {{ form|crispy }}
|
||||
<!-- Save and Back Buttons -->
|
||||
<hr class="my-2">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'car_detail' request.dealer.slug car.slug %}"
|
||||
class="btn btn-phoenix-danger btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,50 +1,54 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% load custom_filters %}
|
||||
{% block title %}
|
||||
{% trans "Car Finance Details" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% trans "Finance Details for" %}<span class="fas fa-solid fa-car text-primary ms-2"></span> {{ car.id_car_make.get_local_name }} - {{ car.id_car_model.get_local_name }}
|
||||
</h3>
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
{% for field in form %}
|
||||
{% for error in field.errors %}<li>{{ field.label }}: {{ error }}</li>{% endfor %}
|
||||
{% endfor %}
|
||||
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans "Finance Details for" %}
|
||||
<span class="text-gray-300">{{car.id_car_make.name}} {{car.id_car_model.name}} {{car.id_car_serie.serie}} {{car.year}}</span>
|
||||
<i class="fas fa-solid fa-car ms-2"></i>
|
||||
</h3>
|
||||
<p class="text-center mt-1">VIN: {{car.vin}}</p>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
<div class="row g-1">
|
||||
<div class="col-lg-4 col-xl-12">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="row g-1">
|
||||
<div class="col-lg-4 col-xl-12">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<!-- JavaScript Section -->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -70,7 +70,7 @@
|
||||
<div class="card-body bg-primary-subtle">
|
||||
<label class="label" for="vin">{% trans 'VIN'|capfirst %}:</label>
|
||||
<div class="input-group">
|
||||
<input id="vin"
|
||||
<input id="vin"
|
||||
name="vin"
|
||||
type="text"
|
||||
class="form-control form-control-sm"
|
||||
@ -180,7 +180,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stock Type Card -->
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body bg-info-subtle">
|
||||
<label class="label" for="stock_type">{% trans 'Stock Type'|capfirst %}:</label>
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
{% block content %}
|
||||
|
||||
{% if cars or request.GET.q%}
|
||||
<div class="container-fluid" id="projectSummary">
|
||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||
@ -189,17 +188,17 @@
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()"></div>
|
||||
<div class="w-100 list table-responsive">
|
||||
|
||||
|
||||
{% for car in cars %}
|
||||
<div class="card border mb-3 py-0 px-0" id="project-list-table-body">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
|
||||
|
||||
<!-- Vehicle Image/Icon -->
|
||||
<div class="col-auto">
|
||||
<div class="avatar avatar-3xl">
|
||||
<img class="rounded-soft shadow shadow-lg"
|
||||
src="{% static 'images/cars/' %}{{ car.vin }}.png"
|
||||
src="{% static 'images/car_images/' %}{{ car.get_hash }}.png"
|
||||
alt="{{ car.vin }}" />
|
||||
</div>
|
||||
</div>
|
||||
@ -269,11 +268,11 @@
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a class="dropdown-item"
|
||||
href="{% url 'car_detail' request.dealer.slug car.slug %}"> <span class="fas fa-eye me-2"></span>{{ _("View") }} </a>
|
||||
{% if perms.inventory.change_car %}
|
||||
{% if perms.inventory.change_car and not car.status == 'sold' %}
|
||||
<a class="dropdown-item"
|
||||
href="{% url 'car_update' request.dealer.slug car.slug %}"> <span class="fas fa-edit me-2"></span>{{ _("Edit") }} </a>
|
||||
{% endif %}
|
||||
{% if perms.inventory.delete_car %}
|
||||
{% if perms.inventory.delete_car and not car.status == 'sold' %}
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger"
|
||||
href="{% url 'car_delete' request.dealer.slug car.slug %}"> <span class="fas fa-trash me-2"></span>{{ _("Remove") }} </a>
|
||||
@ -311,5 +310,4 @@
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -6,31 +6,35 @@
|
||||
{{ _("Add New Expense") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{{ _("Add Expense") }}
|
||||
<span class="fas fa-money-bill-wave ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{{ _("Add Expense") }}
|
||||
<i class="fas fa-money-bill-wave ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" action="" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'item_expense_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'item_expense_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock content %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -6,48 +6,34 @@
|
||||
{{ _("Update Expense") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
{% comment %} <div class="row">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ _("Update Expense") }}</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button type="submit" class="btn btn-phoenix-primary">{% trans 'Save' %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{{ _("Update Expense") }}
|
||||
<i class="fas fa-money-bill-wave ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{{ _("Update Expense") }}
|
||||
<span class="fas fa-money-bill-wave ms-2 text-primary"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-2">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" action="" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'item_expense_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'item_expense_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-danger btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock content %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -3,7 +3,7 @@
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Service' %}
|
||||
{% else %}
|
||||
@ -11,39 +11,50 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if service.pk %}
|
||||
{{ _("Update Service") }}
|
||||
{% else %}
|
||||
{{ _("Add Service") }}
|
||||
{% endif %}
|
||||
<span class="fas fa-tools ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Service" %}
|
||||
<i class="fas fa-tools ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Add New Service" %}
|
||||
<i class="fas fa-tools ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" action="" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'item_service_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'item_service_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock content %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Bank Account' %}
|
||||
{% else %}
|
||||
@ -10,41 +10,50 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if customer.created %}
|
||||
{{ _("Edit Bank Account") }}
|
||||
{% else %}
|
||||
{{ _("Add Bank Account") }}
|
||||
{% endif %}
|
||||
<span class="fas fa-bank ms-2 text-primary"></span>
|
||||
</h3>
|
||||
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Bank Account" %}
|
||||
<i class="fa-solid fa-bank ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Add New Bank Account" %}
|
||||
<i class="fa-solid fa-bank ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<form method="post" class="form" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'bank_account_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
<a href="{% url 'bank_account_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -34,9 +34,27 @@
|
||||
<td class="align-middle product white-space-nowrap">{{ bank.account_type|capfirst }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if perms.django_ledger.change_bankaccountmodel %}
|
||||
<a href="{% url 'bank_account_update' request.dealer.slug bank.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">{% trans "Update" %}</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
|
||||
<a class="dropdown-item" href="{% url 'bank_account_update' request.dealer.slug bank.pk %}" >
|
||||
<i class="fa fa-edit me-2"></i>{% trans "Update" %}
|
||||
</a>
|
||||
<a class="text-danger dropdown-item" href="#" >
|
||||
<i class="fa fa-trash me-2"></i>{% trans "Delete" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
|
||||
@ -5,42 +5,36 @@
|
||||
{{ _("Create Journal Entry") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
{% comment %} <div class="row mt-4">
|
||||
<h3 class="text-center">{% trans "Create Journal Entry" %}</h3>
|
||||
<form id="mainForm" method="post" class="needs-validation">
|
||||
{% csrf_token %}
|
||||
<div class="row g-3">
|
||||
{{ form|crispy }}
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans "Create Journal Entry" %}
|
||||
<i class="fas fa-book-open ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="mt-5 text-center">
|
||||
<button type="submit" class="btn btn-phoenix-success me-2"><i class="fa-solid fa-floppy-disk me-1"></i>{% trans "Save" %}</button>
|
||||
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}" class="btn btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div> {% endcomment %}
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center text-white">{% trans "Create Journal Entry" %}</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form id="mainForm" method="post" class="needs-validation">
|
||||
{% csrf_token %}
|
||||
<div class="row g-3">{{ form|crispy }}</div>
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}"
|
||||
class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form id="mainForm" method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
<div class="row g-3">
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}"
|
||||
class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock content %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -5,38 +5,36 @@
|
||||
{{ _("Create Ledger") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% trans "Create Ledger" %}
|
||||
<span class="fas fa-book-open ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5 ">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans "Create Ledger" %}
|
||||
<i class="fas fa-book-open ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
<form id="mainForm" method="post" class="needs-validation">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form id="mainForm" method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
<div class="row g-3">
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'ledger_list' request.dealer.slug request.entity.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<div class="row g-3">
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'ledger_list' request.dealer.slug request.entity.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock content %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -4,37 +4,69 @@
|
||||
{% trans "Organization Details" %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="row my-4">
|
||||
<h2 class="mb-2">{{ organization.get_local_name }}</h2>
|
||||
<ul class="list-group mb-4">
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "CRN" %}:</strong> {{ organization.crn }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "VRN" %}:</strong> {{ organization.vrn }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Phone" %}:</strong> {{ organization.phone_number }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Address" %}:</strong> {{ organization.address }}
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-flex">
|
||||
{% if perms.inventory.change_organization %}
|
||||
<a href="{% url 'organization_update' request.dealer.slug organization.slug %}"
|
||||
class="btn btn-sm btn-phoenix-primary me-2"><span class="fas fa-edit me-1"></span>{% trans "Edit" %}</a>
|
||||
{% endif %}
|
||||
{% if perms.inventory.delete_organization %}
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn"
|
||||
data-url="{% url 'organization_delete' request.dealer.slug organization.slug %}"
|
||||
data-message="Are you sure you want to delete this organization?"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#deleteModal">
|
||||
<i class="fas fa-trash me-1"></i> {% trans 'Delete' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
<main class="py-5 min-vh-80 d-flex justify-content-center align-items-center">
|
||||
<div class="container py-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-8 col-xl-6">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h2 class="card-title mb-0 fs-3 fw-bold text-center">
|
||||
<i class="fas fa-building me-2"></i>
|
||||
{{ organization.get_local_name }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<ul class="list-group list-group-flush rounded-3 border">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center p-3">
|
||||
<div class=" fw-semibold">
|
||||
<i class="fas fa-id-card-alt me-2 text-primary"></i>
|
||||
{% trans "CRN" %}:
|
||||
</div>
|
||||
<span class="">{{ organization.crn }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center p-3">
|
||||
<div class=" fw-semibold">
|
||||
<i class="fas fa-receipt me-2 text-primary"></i>
|
||||
{% trans "VRN" %}:
|
||||
</div>
|
||||
<span class="">{{ organization.vrn }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center p-3">
|
||||
<div class="fw-semibold">
|
||||
<i class="fas fa-phone-alt me-2 text-primary"></i>
|
||||
{% trans "Phone" %}:
|
||||
</div>
|
||||
<span class="">{{ organization.phone_number }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center p-3">
|
||||
<div class="fw-semibold">
|
||||
<i class="fas fa-map-marker-alt me-2 text-primary"></i>
|
||||
{% trans "Address" %}:
|
||||
</div>
|
||||
<span class=" text-end ms-3">{{ organization.address }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center mt-4 pt-2">
|
||||
{% if perms.inventory.change_organization %}
|
||||
<a href="{% url 'organization_update' request.dealer.slug organization.slug %}"
|
||||
class="btn btn-phoenix-primary btn-lg flex-grow-1"><i class="fas fa-edit me-2"></i>{% trans "Edit Details" %}</a>
|
||||
{% endif %}
|
||||
{% if perms.inventory.delete_organization %}
|
||||
<button class="btn btn-phoenix-danger btn-lg delete-btn flex-grow-1"
|
||||
data-url="{% url 'organization_delete' request.dealer.slug organization.slug %}"
|
||||
data-message="Are you sure you want to delete this organization?"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#deleteModal">
|
||||
<i class="fas fa-trash me-2"></i>{% trans 'Delete' %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'modal/delete_modal.html' %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% include 'modal/delete_modal.html' %}
|
||||
{% endblock %}
|
||||
@ -1,44 +1,61 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Organization' %}
|
||||
{% else %}
|
||||
{% trans 'Add New Organization' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if object %}
|
||||
{% trans 'Update Organization'%}
|
||||
{% else %}
|
||||
{% trans 'Add New Organization'%}
|
||||
{% endif %}
|
||||
<span class=" fas fa-solid fa-city ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans 'Update Organization' %}
|
||||
<i class="fa-solid fa-edit ms-2"></i>
|
||||
{% else %}
|
||||
{% trans 'Add New Organization' %}
|
||||
<i class="fa-solid fa-building ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form class="form" method="post" enctype="multipart/form-data">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form class="form" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'organization_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
<a href="{% url 'organization_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,60 +1,39 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n crispy_forms_filters %}
|
||||
{% block title %}
|
||||
{% trans 'Billing Information' %}{% endblock %}
|
||||
{% block content %}
|
||||
{% comment %} <div class="row mb-3">
|
||||
<div class="col-sm-6">
|
||||
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="post" class="form">
|
||||
|
||||
|
||||
<h3>{% trans "Provide billing data"|upper %}</h3>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<button type="submit" class="btn btn-sm btn-phoenix-success me-2">
|
||||
<i class="fa fa-save me-1"></i>{{ _("Save") }}
|
||||
</button>
|
||||
{% if object %}
|
||||
<a class="btn btn-sm btn-phoenix-danger " href="{% url 'billing_info_delete' %}"><i class="fa-solid fa-trash me-1"></i> {{ _("Delete") }}</a>
|
||||
{% endif %}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
|
||||
|
||||
<!---->
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% trans "Provide billing data"|upper %}<span class="fas fa-file-invoice-dollar ms-2 text-primary"></span>
|
||||
</h3>
|
||||
{% trans 'Billing Information' %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans "Provide billing data"|upper %}
|
||||
<i class="fas fa-file-invoice-dollar ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
|
||||
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}"
|
||||
method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
{% if object %}
|
||||
<a class="btn btn-lg btn-phoenix-danger" href="{% url 'billing_info_delete' %}"><i class="fa-solid fa-trash me-1"></i> {{ _("Delete") }}</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
{% if object %}
|
||||
<a class="btn btn-phoenix-danger btn-lg" href="{% url 'billing_info_delete' %}">
|
||||
<i class="fa-solid fa-trash me-1"></i>
|
||||
{{ _("Delete") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -280,7 +280,7 @@
|
||||
<tr class="bg-body-secondary total-sum">
|
||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Vat" %} ({{ data.vat_rate }})</td>
|
||||
<td class="align-middle text-start fw-semibold">
|
||||
<span id="">+ {{ data.vat_amount }}<span class="icon-saudi_riyal"></span></span>
|
||||
<span id="">+ {{ data.vat_amount|floatformat:2 }}<span class="icon-saudi_riyal"></span></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="bg-body-secondary total-sum">
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
width: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
<div class="row d-flex justify-content-center align-items-center mt-5 mb-3 ms-6 ps-3" >
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{% if not items %}
|
||||
@ -137,19 +137,19 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-lg-12 col-md-10 needs-validation {% if not items or not customer_count %}d-none{% endif %}">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<div class="col-md-10 ms-4 needs-validation {% if not items or not customer_count %}d-none{% endif %}">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% trans "Create Quotation" %}<i class="fa-regular fa-file-lines text-primary ms-2"></i>
|
||||
{% trans "Create Quotation" %}<i class="fa-regular fa-file-lines ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
|
||||
|
||||
<form id="mainForm" method="post" class="needs-validation {% if not items and not customer_count %}d-none{% endif %}">
|
||||
{% csrf_token %}
|
||||
<div class="row g-3 col-12">
|
||||
<div class="row g-3">
|
||||
{{ form|crispy }}
|
||||
<div class="custom-select">
|
||||
<!-- Hidden native select for form submission -->
|
||||
|
||||
@ -6,20 +6,33 @@
|
||||
{{ _("Sale Order") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ _("Sale Order") }}</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="{% url 'create_sale_order' request.dealer.slug estimate.pk %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button type="submit" class="btn btn-phoenix-primary">{% trans 'Save' %}</button>
|
||||
</form>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{{ _("Create Sale Order") }}
|
||||
<i class="fas fa-file-invoice-dollar ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" action="{% url 'create_sale_order' request.dealer.slug estimate.pk %}" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{% trans 'Save' %}
|
||||
</button>
|
||||
<a href="{% url 'home' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -6,30 +6,34 @@
|
||||
{{ _("Invoice") }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="row paid justify-content-center mt-5 mb-3">
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{{ _("Add Invoice") }}<i class="fa-solid fa-receipt ms-2 text-primary"></i>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{{ _("Add Invoice") }}
|
||||
<i class="fa-solid fa-receipt ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
|
||||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'invoice_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" action="" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'invoice_list' request.dealer.slug %}"
|
||||
class="btn btn-phoenix-danger btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock content %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
@ -4,18 +4,33 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h2 class="h4 mb-0">Create Support Ticket</h2>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans "Create Support Ticket" %}
|
||||
<i class="fa-solid fa-headset ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button type="submit" class="btn btn-phoenix-primary btn-lg me-md-2">
|
||||
<i class="fa-solid fa-paper-plane me-1"></i>
|
||||
{% trans "Submit Ticket" %}
|
||||
</button>
|
||||
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{form|crispy}}
|
||||
|
||||
<button type="submit" class="btn btn-primary">Submit Ticket</button>
|
||||
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -2,59 +2,76 @@
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'Ticket' %} #{{ ticket.id }}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2 class="h4 mb-0">Ticket #{{ ticket.id }}: {{ ticket.subject }}</h2>
|
||||
<div>
|
||||
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-sm btn-outline-secondary">
|
||||
Back to List
|
||||
</a>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% trans 'Ticket' %} #{{ ticket.id }}
|
||||
<i class="fas fa-headset ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<div class="row g-3">
|
||||
<div class="col-12 text-center mb-3">
|
||||
<h4 class="h5 fw-bold">{{ ticket.subject }}</h4>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<strong>{% trans 'Status:' %}</strong>
|
||||
<span class="badge
|
||||
{% if ticket.status == 'open' %}bg-primary
|
||||
{% elif ticket.status == 'in_progress' %}bg-info
|
||||
{% elif ticket.status == 'resolved' %}bg-success
|
||||
{% else %}bg-secondary{% endif %}">
|
||||
{{ ticket.get_status_display }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-sm-6 text-sm-end">
|
||||
<strong>{% trans 'Priority:' %}</strong>
|
||||
<span class="badge
|
||||
{% if ticket.priority == 'low' %}bg-success
|
||||
{% elif ticket.priority == 'medium' %}bg-warning
|
||||
{% elif ticket.priority == 'high' %}bg-danger
|
||||
{% else %}bg-dark{% endif %}">
|
||||
{{ ticket.get_priority_display }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<strong>{% trans 'Created:' %}</strong>
|
||||
<br class="d-sm-none">{{ ticket.created_at|date:"M d, Y" }}
|
||||
</div>
|
||||
<div class="col-sm-6 text-sm-end">
|
||||
<strong>{% trans 'Last Updated:' %}</strong>
|
||||
<br class="d-sm-none">{{ ticket.updated_at|date:"M d, Y" }}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold mb-2">{% trans 'Description' %}</h5>
|
||||
<div class="p-3 bg-light rounded-3">
|
||||
{{ ticket.description|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
{% if ticket.resolution_notes %}
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold mb-2">{% trans 'Resolution Notes' %}</h5>
|
||||
<div class="p-3 bg-light rounded-3">
|
||||
{{ ticket.resolution_notes|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="d-grid mt-4">
|
||||
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-arrow-left me-1"></i>
|
||||
{% trans 'Back to Tickets' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<p><strong>Status:</strong>
|
||||
<span class="badge
|
||||
{% if ticket.status == 'open' %}bg-primary
|
||||
{% elif ticket.status == 'in_progress' %}bg-info
|
||||
{% elif ticket.status == 'resolved' %}bg-success
|
||||
{% else %}bg-secondary{% endif %}">
|
||||
{{ ticket.get_status_display }}
|
||||
</span>
|
||||
</p>
|
||||
<p><strong>Priority:</strong>
|
||||
<span class="badge
|
||||
{% if ticket.priority == 'low' %}bg-success
|
||||
{% elif ticket.priority == 'medium' %}bg-warning
|
||||
{% elif ticket.priority == 'high' %}bg-danger
|
||||
{% else %}bg-dark{% endif %}">
|
||||
{{ ticket.get_priority_display }}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p><strong>Created:</strong> {{ ticket.created_at|date:"M d, Y H:i" }}</p>
|
||||
<p><strong>Last Updated:</strong> {{ ticket.updated_at|date:"M d, Y H:i" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h3 class="h5">Description</h3>
|
||||
<div class="p-3 rounded">
|
||||
{{ ticket.description|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<h3 class="h5">Resolution Notes</h3>
|
||||
<div class="p-3 rounded">
|
||||
{{ ticket.resolution_notes|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- You can add comments/replies section here later -->
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,80 +1,116 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block title %}
|
||||
{% trans "My Tickets" %}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Need help?</h5>
|
||||
<p class="card-text">Raise a ticket and we will get back to you as soon as possible.</p>
|
||||
<a href="{% url 'create_ticket' request.dealer.slug %}" class="btn btn-phoenix-primary">Raise a Ticket</a>
|
||||
<main class="py-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center mb-5">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInDown">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4 text-center">
|
||||
<i class="fa-solid fa-headset fa-2x mb-2"></i>
|
||||
<h2 class="card-title fw-bold mb-0">
|
||||
{% trans "Need Help?" %}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5 text-center bg-white">
|
||||
<p class="card-text text-muted mb-4">
|
||||
{% blocktrans %}
|
||||
Our support team is ready to assist you. Raise a new ticket below, and we'll get back to you as soon as possible.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<a href="{% url 'create_ticket' request.dealer.slug %}" class="btn btn-phoenix-primary btn-lg shadow-sm">
|
||||
<i class="fa-solid fa-plus me-1"></i>
|
||||
{% trans "Raise a New Ticket" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Tickets</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead class="">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Subject</th>
|
||||
<th>Status</th>
|
||||
<th>Priority</th>
|
||||
<th>Created</th>
|
||||
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ticket in tickets %}
|
||||
<tr>
|
||||
<td>#{{ ticket.id }}</td>
|
||||
<td>{{ ticket.subject }}</td>
|
||||
<td>
|
||||
<span class="badge
|
||||
{% if ticket.status == 'open' %}bg-primary
|
||||
{% elif ticket.status == 'in_progress' %}bg-info
|
||||
{% elif ticket.status == 'resolved' %}bg-success
|
||||
{% else %}bg-secondary{% endif %}">
|
||||
{{ ticket.get_status_display }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge
|
||||
{% if ticket.priority == 'low' %}bg-success
|
||||
{% elif ticket.priority == 'medium' %}bg-warning
|
||||
{% elif ticket.priority == 'high' %}bg-danger
|
||||
{% else %}bg-dark{% endif %}">
|
||||
{{ ticket.get_priority_display }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ ticket.created_at|date:"M d, Y H:i" }}</td>
|
||||
|
||||
<td>
|
||||
<a href="{% url 'ticket_detail' request.dealer.slug ticket.id %}" class="btn btn-sm btn-outline-primary">
|
||||
View
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center">No tickets found.</td>
|
||||
</tr>
|
||||
|
||||
{% if messages %}
|
||||
<div class="alert-container mb-4">
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card shadow-lg border-0 rounded-4 animate__animated animate__fadeInUp">
|
||||
<div class="card-header border-bottom d-flex flex-column flex-md-row justify-content-between align-items-md-center p-4">
|
||||
<h5 class="card-title mb-2 mb-md-0 me-md-4 fw-bold">{% trans "My Tickets" %}</h5>
|
||||
<div class="input-group w-100 w-md-50">
|
||||
{% include 'partials/search_box.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover mb-0">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold ps-4">ID</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold">Subject</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold">Status</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold">Priority</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold">Created</th>
|
||||
<th scope="col" class="text-secondary text-uppercase fw-bold text-end pe-4">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ticket in tickets %}
|
||||
<tr>
|
||||
<td class="text-muted ps-4">#{{ ticket.id }}</td>
|
||||
<td>{{ ticket.subject }}</td>
|
||||
<td>
|
||||
<span class="badge
|
||||
{% if ticket.status == 'open' %}bg-primary
|
||||
{% elif ticket.status == 'in_progress' %}bg-info
|
||||
{% elif ticket.status == 'resolved' %}bg-success
|
||||
{% else %}bg-secondary{% endif %}">
|
||||
{{ ticket.get_status_display }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge
|
||||
{% if ticket.priority == 'low' %}bg-success
|
||||
{% elif ticket.priority == 'medium' %}bg-warning
|
||||
{% elif ticket.priority == 'high' %}bg-danger
|
||||
{% else %}bg-dark{% endif %}">
|
||||
{{ ticket.get_priority_display }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="d-block">{{ ticket.created_at|date:"M d, Y" }}</span>
|
||||
<span class="text-muted small d-block">{{ ticket.created_at|time:"H:i" }}</span>
|
||||
</td>
|
||||
<td class="text-end pe-4">
|
||||
<a href="{% url 'ticket_detail' request.dealer.slug ticket.id %}" class="btn btn-phoenix-primary btn-sm">
|
||||
<i class="fa-solid fa-eye me-1"></i>
|
||||
{% trans "View" %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted py-5">
|
||||
<i class="fas fa-ticket-alt fs-2 mb-3"></i>
|
||||
<p class="mb-0">{% trans "No tickets found." %}</p>
|
||||
<p class="text-muted small">{% trans "All your past and present tickets will appear here." %}</p>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,8 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% load i18n crispy_forms_filters %}
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Staff' %}
|
||||
{% else %}
|
||||
@ -10,49 +8,51 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if staff.created %}
|
||||
{{ _("Edit Staff") }}
|
||||
{% else %}
|
||||
{{ _("Add Staff") }}
|
||||
{% endif %}
|
||||
<i class="fa-solid fa-user-tie text-primary ms-2"></i>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Staff" %}
|
||||
<i class="fa-solid fa-user-tie ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Add New Staff" %}
|
||||
<i class="fa-solid fa-user-tie ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form class="row g-3 mb-3" method="post" class="form" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form.first_name|as_crispy_field }}
|
||||
{{ form.last_name|as_crispy_field }}
|
||||
{{ form.arabic_name|as_crispy_field }}
|
||||
{{ form.email|as_crispy_field }}
|
||||
{{ form.phone_number|as_crispy_field }}
|
||||
{{ form.address|as_crispy_field }}
|
||||
{{ form.logo|as_crispy_field }}
|
||||
{{ form.group|as_crispy_field }}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'user_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form class="needs-validation" method="post" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'user_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -5,37 +5,46 @@
|
||||
{% trans "Group" %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-5 text-center">
|
||||
{{ _("Manage Groups") }}<i class="fa-solid fa-users ms-2 text-primary"></i>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{{ _("Manage Groups") }}
|
||||
<i class="fa-solid fa-users ms-2"></i>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form class="row g-3 mb-3" method="post" class="form" enctype="multipart/form-data" novalidate >
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
{% for error in form.errors %}<div class="text-danger">{{ error }}</div>{% endfor %}
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'user_detail' request.dealer.slug staff.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form class="needs-validation" method="post" enctype="multipart/form-data" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'user_detail' request.dealer.slug staff.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,18 +1,20 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp" style="background-color: #f8f9fa;">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h1 class="h3 fw-bold mb-0 text-center">
|
||||
<i class="fas fa-lock me-2"></i> {% trans "Set New Password" %}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<div class="text-center mb-4">
|
||||
<h1 class="h3 fw-bold text-dark mb-2">{% trans "Set New Password" %}</h1>
|
||||
<p class="text-muted">{% trans "Enter your new password below." %}</p>
|
||||
<p class="mb-0 fs-5">{% trans "Enter your new password below." %}</p>
|
||||
</div>
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
{% for field in form %}
|
||||
<div class="form-floating mb-3">
|
||||
{{ field.errors }}
|
||||
@ -20,17 +22,16 @@
|
||||
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="d-grid mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-lg rounded-pill fw-bold">
|
||||
<button type="submit" class="btn btn-phoenix-primary btn-lg rounded-pill fw-bold">
|
||||
{% trans "Change Password" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer bg-light border-0 py-3 text-center">
|
||||
<div class="card-footer bg-gray-300 border-0 py-3 text-center">
|
||||
<small class="text-muted">
|
||||
{% trans "Remember to choose a strong password." %}
|
||||
<i class="fas fa-info-circle me-1"></i> {% trans "Remember to choose a strong password." %}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
75
templates/vendors/vendor_form.html
vendored
@ -2,7 +2,6 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Vendor' %}
|
||||
{% else %}
|
||||
@ -10,37 +9,51 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="row justify-content-center mt-5 mb-3">
|
||||
|
||||
<div class="col-lg-8 col-md-10">
|
||||
<div class="card shadow-sm border-0 rounded-3">
|
||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
||||
<h3 class="mb-0 fs-4 text-center">
|
||||
{% if vendor.created %}
|
||||
{{ _("Edit Vendor") }}
|
||||
{% else %}
|
||||
{{ _("Add Vendor") }}
|
||||
{% endif %}
|
||||
<span class="fas fa-cube ms-2 text-primary"></span>
|
||||
</h3>
|
||||
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
|
||||
<div class="col-md-8 ">
|
||||
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
|
||||
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
|
||||
<h3 class="mb-0 fs-4 fw-bold text-center">
|
||||
{% if object %}
|
||||
{% trans "Update Vendor" %}
|
||||
<i class="fas fa-cube ms-2"></i>
|
||||
{% else %}
|
||||
{% trans "Add New Vendor" %}
|
||||
<i class="fas fa-cube ms-2"></i>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body bg-light-subtle">
|
||||
<form class="row g-3 mb-3" method="post" class="form" enctype="multipart/form-data" novalidate >
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
{% for error in form.errors %}<div class="text-danger">{{ error }}</div>{% endfor %}
|
||||
<hr class="my-2">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{% url 'vendor_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<form class="needs-validation" method="post" enctype="multipart/form-data" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4" role="alert">
|
||||
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr class="my-4">
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
||||
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{% url 'vendor_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
|
||||
<i class="fa-solid fa-ban me-1"></i>
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
{% endblock %}
|
||||
</main>
|
||||
{% endblock %}
|
||||