update
This commit is contained in:
commit
0f9b2cff5f
@ -367,6 +367,18 @@ class CarSelectionTable(tables.Table):
|
|||||||
|
|
||||||
|
|
||||||
class WizardForm1(forms.Form):
|
class WizardForm1(forms.Form):
|
||||||
|
username = forms.CharField(
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control",
|
||||||
|
"placeholder": "Username",
|
||||||
|
"required": "required",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
error_messages={
|
||||||
|
"required": _("You must add a username."),
|
||||||
|
},
|
||||||
|
)
|
||||||
email = forms.EmailField(
|
email = forms.EmailField(
|
||||||
widget=forms.EmailInput(
|
widget=forms.EmailInput(
|
||||||
attrs={
|
attrs={
|
||||||
|
|||||||
@ -38,18 +38,22 @@ class DealerUserManager(UserManager):
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
class UnitOfMeasure(models.TextChoices):
|
||||||
UNIT_CHOICES = (
|
EACH = 'EA', 'Each'
|
||||||
("Unit", _("Unit")),
|
PAIR = 'PR', 'Pair'
|
||||||
("Kg", _("Kg")),
|
SET = 'SET', 'Set'
|
||||||
("L", _("L")),
|
GALLON = 'GAL', 'Gallon'
|
||||||
("m", _("m")),
|
LITER = 'L', 'Liter'
|
||||||
("cm", _("cm")),
|
METER = 'M', 'Meter'
|
||||||
("m2", _("m2")),
|
KILOGRAM = 'KG', 'Kilogram'
|
||||||
("m3", _("m3")),
|
HOUR = 'HR', 'Hour'
|
||||||
("m3", _("m3")),
|
BOX = 'BX', 'Box'
|
||||||
)
|
ROLL = 'RL', 'Roll'
|
||||||
|
PACKAGE = 'PKG', 'Package'
|
||||||
|
DOZEN = 'DZ', 'Dozen'
|
||||||
|
SQUARE_METER = 'SQ_M', 'Square Meter'
|
||||||
|
PIECE = 'PC', 'Piece'
|
||||||
|
BUNDLE = 'BDL', 'Bundle'
|
||||||
class VatRate(models.Model):
|
class VatRate(models.Model):
|
||||||
rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.15'))
|
rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.15'))
|
||||||
is_active = models.BooleanField(default=True)
|
is_active = models.BooleanField(default=True)
|
||||||
@ -173,7 +177,7 @@ class AdditionalServices(models.Model, LocalizedNameMixin):
|
|||||||
description = models.TextField(verbose_name=_("Description"))
|
description = models.TextField(verbose_name=_("Description"))
|
||||||
price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Price"))
|
price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Price"))
|
||||||
taxable = models.BooleanField(default=False, verbose_name=_("taxable"))
|
taxable = models.BooleanField(default=False, verbose_name=_("taxable"))
|
||||||
uom = models.CharField(max_length=10, choices=UNIT_CHOICES, verbose_name=_("Unit of Measurement"))
|
uom = models.CharField(max_length=10, choices=UnitOfMeasure.choices, verbose_name=_("Unit of Measurement"))
|
||||||
dealer = models.ForeignKey("Dealer", on_delete=models.CASCADE, verbose_name=_("Dealer"))
|
dealer = models.ForeignKey("Dealer", on_delete=models.CASCADE, verbose_name=_("Dealer"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -334,8 +338,7 @@ class CarFinance(models.Model):
|
|||||||
# custom_card_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Custom Card Fee"),
|
# custom_card_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Custom Card Fee"),
|
||||||
# default=Decimal('0.00'))
|
# default=Decimal('0.00'))
|
||||||
@property
|
@property
|
||||||
def total(self):
|
def total(self):
|
||||||
vat = VatRate.objects.filter(is_active=True).first()
|
|
||||||
total = 0
|
total = 0
|
||||||
if self.additional_services.count() != 0:
|
if self.additional_services.count() != 0:
|
||||||
total_additional_services = sum(x.default_amount for x in self.additional_services.all())
|
total_additional_services = sum(x.default_amount for x in self.additional_services.all())
|
||||||
@ -344,9 +347,19 @@ class CarFinance(models.Model):
|
|||||||
total = self.selling_price
|
total = self.selling_price
|
||||||
if self.discount_amount != 0:
|
if self.discount_amount != 0:
|
||||||
total = total - self.discount_amount
|
total = total - self.discount_amount
|
||||||
total = (total * vat.vat_rate).quantize(Decimal('0.01')) + total
|
|
||||||
return total
|
return total
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vat_amount(self):
|
||||||
|
vat = VatRate.objects.filter(is_active=True).first()
|
||||||
|
return (self.total * vat.vat_rate).quantize(Decimal('0.01'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_vat(self):
|
||||||
|
return self.total + self.vat_amount
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Car: {self.car}, Selling Price: {self.selling_price}"
|
return f"Car: {self.car}, Selling Price: {self.selling_price}"
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,10 @@ from django.dispatch import receiver
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django_ledger.io import roles
|
from django_ledger.io import roles
|
||||||
from django_ledger.models import EntityModel, AccountModel, ItemModel, ItemModelAbstract, UnitOfMeasureModel, \
|
from django_ledger.models import EntityModel,AccountModel,ItemModel,ItemModelAbstract,UnitOfMeasureModel, VendorModel
|
||||||
VendorModel, ChartOfAccountModel
|
|
||||||
from . import models
|
from . import models
|
||||||
from .models import OpportunityLog
|
from .models import OpportunityLog
|
||||||
|
from .utils import get_dealer_from_instance
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
@ -45,42 +44,49 @@ User = get_user_model()
|
|||||||
# instance.save()
|
# instance.save()
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=models.Car)
|
|
||||||
|
# check with marwan
|
||||||
|
@receiver(post_save, sender=models.Car)
|
||||||
def create_car_location(sender, instance, created, **kwargs):
|
def create_car_location(sender, instance, created, **kwargs):
|
||||||
"""
|
"""
|
||||||
Signal to create or update the car's location when a car instance is saved.
|
Signal to create or update the car's location when a car instance is saved.
|
||||||
"""
|
"""
|
||||||
if created:
|
try:
|
||||||
print(instance)
|
if created:
|
||||||
models.CarLocation.objects.create(
|
if instance.dealer is None:
|
||||||
car=instance,
|
raise ValueError(f"Cannot create CarLocation for car {instance.vin}: dealer is missing.")
|
||||||
owner=instance.dealer,
|
|
||||||
showroom=instance.dealer,
|
models.CarLocation.objects.create(
|
||||||
description=f"Initial location set for car {instance.vin}."
|
car=instance,
|
||||||
)
|
owner=instance.dealer,
|
||||||
print("Car Location created")
|
showroom=instance.dealer,
|
||||||
|
description=f"Initial location set for car {instance.vin}."
|
||||||
|
)
|
||||||
|
print("Car Location created")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to create CarLocation for car {instance.vin}: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
# @receiver(post_save, sender=models.CarReservation)
|
||||||
@receiver(post_save, sender=models.CarReservation)
|
# def update_car_status_on_reservation(sender, instance, created, **kwargs):
|
||||||
def update_car_status_on_reservation(sender, instance, created, **kwargs):
|
# if created:
|
||||||
if created:
|
# car = instance.car
|
||||||
car = instance.car
|
# car.status = models.CarStatusChoices.RESERVED
|
||||||
car.status = models.CarStatusChoices.RESERVED
|
# car.save()
|
||||||
car.save()
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=models.CarReservation)
|
# @receiver(post_delete, sender=models.CarReservation)
|
||||||
def update_car_status_on_reservation_delete(sender, instance, **kwargs):
|
# def update_car_status_on_reservation_delete(sender, instance, **kwargs):
|
||||||
car = instance.car
|
# car = instance.car
|
||||||
if not car.is_reserved():
|
# if not car.is_reserved():
|
||||||
car.status = models.CarStatusChoices.AVAILABLE
|
# car.status = models.CarStatusChoices.AVAILABLE
|
||||||
car.save()
|
# car.save()
|
||||||
|
|
||||||
|
|
||||||
# Create Entity
|
# Create Entity
|
||||||
@receiver(post_save, sender=models.Dealer)
|
@receiver(post_save, sender=models.Dealer)
|
||||||
def create_ledger_entity(sender, instance, created, **kwargs):
|
def create_ledger_entity(sender, instance, created, **kwargs):
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
entity_name = instance.user.dealer.name
|
entity_name = instance.user.dealer.name
|
||||||
entity = EntityModel.create_entity(
|
entity = EntityModel.create_entity(
|
||||||
@ -100,18 +106,27 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
# entity.populate_default_coa(activate_accounts=True, coa_model=coa)
|
# entity.populate_default_coa(activate_accounts=True, coa_model=coa)
|
||||||
print(f"Ledger entity created for Dealer: {instance.name}")
|
print(f"Ledger entity created for Dealer: {instance.name}")
|
||||||
|
|
||||||
# Create Cash Account
|
|
||||||
entity.create_account(
|
|
||||||
|
# Create unit of measures
|
||||||
|
|
||||||
|
entity.create_uom(
|
||||||
|
name="Unit",
|
||||||
|
unit_abbr="unit")
|
||||||
|
|
||||||
|
# Create Cash Account
|
||||||
|
asset_ca_cash = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="1101",
|
code="1010",
|
||||||
role=roles.ASSET_CA_CASH,
|
role=roles.ASSET_CA_CASH,
|
||||||
name=_("Cash"),
|
name=_("Cash"),
|
||||||
balance_type="debit",
|
balance_type="debit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
asset_ca_cash.role_default = True
|
||||||
|
asset_ca_cash.save()
|
||||||
# Create Accounts Receivable Account
|
# Create Accounts Receivable Account
|
||||||
entity.create_account(
|
asset_ca_receivables = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="1102",
|
code="1102",
|
||||||
role=roles.ASSET_CA_RECEIVABLES,
|
role=roles.ASSET_CA_RECEIVABLES,
|
||||||
@ -119,9 +134,11 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="debit",
|
balance_type="debit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
asset_ca_receivables.role_default = True
|
||||||
|
asset_ca_receivables.save()
|
||||||
|
|
||||||
# Create Inventory Account
|
# Create Inventory Account
|
||||||
entity.create_account(
|
asset_ca_inventory = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="1103",
|
code="1103",
|
||||||
role=roles.ASSET_CA_INVENTORY,
|
role=roles.ASSET_CA_INVENTORY,
|
||||||
@ -130,8 +147,10 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
asset_ca_inventory.role_default = True
|
||||||
|
asset_ca_inventory.save()
|
||||||
# Create Accounts Payable Account
|
# Create Accounts Payable Account
|
||||||
entity.create_account(
|
asset_ca_accounts_payable = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="2101",
|
code="2101",
|
||||||
role=roles.LIABILITY_CL_ACC_PAYABLE,
|
role=roles.LIABILITY_CL_ACC_PAYABLE,
|
||||||
@ -139,8 +158,10 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="credit",
|
balance_type="credit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
asset_ca_accounts_payable.role_default = True
|
||||||
|
asset_ca_accounts_payable.save()
|
||||||
# Create Equity Account
|
# Create Equity Account
|
||||||
entity.create_account(
|
asset_ca_equity = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="3101",
|
code="3101",
|
||||||
role=roles.EQUITY_CAPITAL,
|
role=roles.EQUITY_CAPITAL,
|
||||||
@ -148,9 +169,11 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="credit",
|
balance_type="credit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
asset_ca_equity.role_default = True
|
||||||
|
asset_ca_equity.save()
|
||||||
|
|
||||||
# Create Sales Revenue Account
|
# Create Sales Revenue Account
|
||||||
entity.create_account(
|
asset_ca_revenue = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="4101",
|
code="4101",
|
||||||
role=roles.INCOME_OPERATIONAL,
|
role=roles.INCOME_OPERATIONAL,
|
||||||
@ -158,9 +181,11 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="credit",
|
balance_type="credit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
asset_ca_revenue.role_default = True
|
||||||
|
asset_ca_revenue.save()
|
||||||
|
|
||||||
# Create Cost of Goods Sold Account
|
# Create Cost of Goods Sold Account
|
||||||
entity.create_account(
|
asset_ca_cogs = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="5101",
|
code="5101",
|
||||||
role=roles.COGS,
|
role=roles.COGS,
|
||||||
@ -168,9 +193,11 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="debit",
|
balance_type="debit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
asset_ca_cogs.role_default = True
|
||||||
|
asset_ca_cogs.save()
|
||||||
|
|
||||||
# Create Rent Expense Account
|
# Create Rent Expense Account
|
||||||
entity.create_account(
|
expense = entity.create_account(
|
||||||
coa_model=coa,
|
coa_model=coa,
|
||||||
code="6101",
|
code="6101",
|
||||||
role=roles.EXPENSE_OPERATIONAL,
|
role=roles.EXPENSE_OPERATIONAL,
|
||||||
@ -178,6 +205,8 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="debit",
|
balance_type="debit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
expense.role_default = True
|
||||||
|
expense.save()
|
||||||
|
|
||||||
# Create Utilities Expense Account
|
# Create Utilities Expense Account
|
||||||
entity.create_account(
|
entity.create_account(
|
||||||
@ -188,7 +217,15 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
balance_type="debit",
|
balance_type="debit",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
|
#Create Deferred Revenue Account
|
||||||
|
entity.create_account(
|
||||||
|
coa_model=coa,
|
||||||
|
code="2060",
|
||||||
|
role=roles.LIABILITY_CL_DEFERRED_REVENUE,
|
||||||
|
name=_("Deferred Revenue"),
|
||||||
|
balance_type="credit",
|
||||||
|
active=True,
|
||||||
|
)
|
||||||
|
|
||||||
# Create Vendor
|
# Create Vendor
|
||||||
@receiver(post_save, sender=models.Vendor)
|
@receiver(post_save, sender=models.Vendor)
|
||||||
@ -241,95 +278,38 @@ def create_customer(sender, instance, created, **kwargs):
|
|||||||
|
|
||||||
# Create Item
|
# Create Item
|
||||||
@receiver(post_save, sender=models.Car)
|
@receiver(post_save, sender=models.Car)
|
||||||
def create_item_product(sender, instance, created, **kwargs):
|
def create_item_model(sender, instance, created, **kwargs):
|
||||||
|
name = instance.dealer.name
|
||||||
|
entity = EntityModel.objects.filter(name=name).first()
|
||||||
if created:
|
if created:
|
||||||
product_name = f"{instance.year} - {instance.id_car_make} - {instance.id_car_model}"
|
coa = entity.get_default_coa()
|
||||||
entity = EntityModel.objects.get(name=instance.dealer.name)
|
uom = entity.get_uom_all().get(name="Unit")
|
||||||
uom = entity.get_uom_all().first()
|
|
||||||
# coa_model = entity.get_default_coa()
|
if not entity.get_items_all().filter(name=instance.vin).first():
|
||||||
inventory_account = AccountModel.objects.first()
|
entity.create_item_product(
|
||||||
cogs_account = AccountModel.objects.first()
|
name=f"{instance.vin}",
|
||||||
earnings_account = AccountModel.objects.first()
|
item_type=ItemModel.ITEM_TYPE_MATERIAL,
|
||||||
|
uom_model=uom,
|
||||||
|
coa_model=coa
|
||||||
ItemModel.objects.create(
|
)
|
||||||
entity=entity,
|
entity.create_item_inventory(
|
||||||
uom=uom,
|
name=f"{instance.vin}",
|
||||||
name=product_name,
|
item_type=ItemModel.ITEM_TYPE_MATERIAL,
|
||||||
item_role=ItemModelAbstract.ITEM_ROLE_PRODUCT,
|
uom_model=uom,
|
||||||
item_type=ItemModelAbstract.ITEM_TYPE_MATERIAL,
|
coa_model=coa
|
||||||
item_id=instance.vin,
|
)
|
||||||
sold_as_unit=True,
|
|
||||||
for_inventory=True,
|
|
||||||
is_product_or_service=True,
|
|
||||||
inventory_received=1.00,
|
|
||||||
inventory_received_value=0.00,
|
|
||||||
inventory_account=inventory_account,
|
|
||||||
earnings_account=earnings_account,
|
|
||||||
cogs_account=cogs_account,
|
|
||||||
additional_info={
|
|
||||||
"remarks": instance.remarks,
|
|
||||||
"status": instance.status,
|
|
||||||
"stock_type": instance.stock_type,
|
|
||||||
"mileage": instance.mileage,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
print(f"Item created: {product_name}")
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=models.AdditionalServices)
|
|
||||||
def create_item_for_service(sender, instance, created, **kwargs):
|
|
||||||
"""
|
|
||||||
Signal to create an ItemModel of type SERVICE when a new AdditionalServices instance is created.
|
|
||||||
"""
|
|
||||||
if created: # Only run on creation, not update
|
|
||||||
|
|
||||||
entity = EntityModel.objects.get(name=instance.dealer.name)
|
|
||||||
uom_model = entity.get_uom_all().first()
|
|
||||||
|
|
||||||
entity.create_item_service(
|
|
||||||
name=instance.name,
|
|
||||||
uom_model=uom_model,
|
|
||||||
commit=True
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ItemModel.objects.create(
|
|
||||||
# entity=entity,
|
|
||||||
# uom=uom,
|
|
||||||
# name=instance.name,
|
|
||||||
# item_role=ItemModelAbstract.ITEM_ROLE_SERVICE,
|
|
||||||
# item_type=ItemModelAbstract.ITEM_TYPE_LABOR,
|
|
||||||
# # item_id=instance.vin,
|
|
||||||
# sold_as_unit=True,
|
|
||||||
# for_inventory=True,
|
|
||||||
# is_product_or_service=True,
|
|
||||||
# inventory_received=1.00,
|
|
||||||
# inventory_received_value=instance.price,
|
|
||||||
# inventory_account=inventory_account,
|
|
||||||
# earnings_account=earnings_account,
|
|
||||||
# cogs_account=cogs_account,
|
|
||||||
# additional_info={
|
|
||||||
# "remarks": instance.remarks,
|
|
||||||
# "status": instance.status,
|
|
||||||
# "stock_type": instance.stock_type,
|
|
||||||
# "mileage": instance.mileage,
|
|
||||||
# },
|
|
||||||
# )
|
|
||||||
print(f"Service Item created for AdditionalService: {instance.name}")
|
|
||||||
|
|
||||||
# # update price - CarFinance
|
# # update price - CarFinance
|
||||||
# @receiver(post_save, sender=models.CarFinance)
|
@receiver(post_save, sender=models.CarFinance)
|
||||||
# def update_item_model_cost(sender, instance, created, **kwargs):
|
def update_item_model_cost(sender, instance, created, **kwargs):
|
||||||
#
|
|
||||||
# ItemModel.objects.filter(item_id=instance.car.vin).update(
|
ItemModel.objects.filter(item_id=instance.car.vin).update(
|
||||||
# inventory_received_value=instance.cost_price,
|
inventory_received_value=instance.cost_price,
|
||||||
# default_amount=instance.selling_price,
|
default_amount=instance.cost_price,
|
||||||
# )
|
)
|
||||||
# print(f"Inventory item updated with CarFinance data for Car: {instance.car}")
|
print(f"Inventory item updated with CarFinance data for Car: {instance.car}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -71,6 +71,8 @@ from .utils import get_calculations, send_email, get_user_type
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from allauth.account import views
|
from allauth.account import views
|
||||||
from django.db.models import Count, F, Value
|
from django.db.models import Count, F, Value
|
||||||
|
from django.contrib.auth import authenticate
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
@ -118,6 +120,7 @@ def dealer_signup(request, *args, **kwargs):
|
|||||||
wf1 = data.get("wizardValidationForm1")
|
wf1 = data.get("wizardValidationForm1")
|
||||||
wf2 = data.get("wizardValidationForm2")
|
wf2 = data.get("wizardValidationForm2")
|
||||||
wf3 = data.get("wizardValidationForm3")
|
wf3 = data.get("wizardValidationForm3")
|
||||||
|
username = wf1.get("username")
|
||||||
email = wf1.get("email")
|
email = wf1.get("email")
|
||||||
password = wf1.get("password")
|
password = wf1.get("password")
|
||||||
password_confirm = wf1.get("confirm_password")
|
password_confirm = wf1.get("confirm_password")
|
||||||
@ -133,7 +136,9 @@ def dealer_signup(request, *args, **kwargs):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
user = User.objects.create(email=email, password=password)
|
user = User.objects.create(username=username, email=email)
|
||||||
|
user.set_password(password)
|
||||||
|
user.save()
|
||||||
|
|
||||||
models.Dealer.objects.create(
|
models.Dealer.objects.create(
|
||||||
user=user,
|
user=user,
|
||||||
@ -144,7 +149,14 @@ def dealer_signup(request, *args, **kwargs):
|
|||||||
phone_number=phone,
|
phone_number=phone,
|
||||||
address=address,
|
address=address,
|
||||||
)
|
)
|
||||||
return JsonResponse({"message": "User created successfully."}, status=200)
|
user = authenticate(request, username=username, password=password)
|
||||||
|
if user is not None:
|
||||||
|
return JsonResponse(
|
||||||
|
{"message": "User created successfully."}, status=200
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return JsonResponse({"error": "User creation failed."}, status=400)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return JsonResponse({"error": str(e)}, status=400)
|
return JsonResponse({"error": str(e)}, status=400)
|
||||||
|
|
||||||
@ -171,7 +183,6 @@ class TestView(TemplateView):
|
|||||||
template_name = "test.html"
|
template_name = "test.html"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AccountingDashboard(LoginRequiredMixin, TemplateView):
|
class AccountingDashboard(LoginRequiredMixin, TemplateView):
|
||||||
template_name = "dashboards/accounting.html"
|
template_name = "dashboards/accounting.html"
|
||||||
|
|
||||||
@ -256,7 +267,9 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
|||||||
return JsonResponse({"error": _("VIN number exists")}, status=400)
|
return JsonResponse({"error": _("VIN number exists")}, status=400)
|
||||||
|
|
||||||
if not vin_no or len(vin_no.strip()) != 17:
|
if not vin_no or len(vin_no.strip()) != 17:
|
||||||
return JsonResponse({"success": False, "error": "Invalid VIN number provided."}, status=400)
|
return JsonResponse(
|
||||||
|
{"success": False, "error": "Invalid VIN number provided."}, status=400
|
||||||
|
)
|
||||||
|
|
||||||
vin_no = vin_no.strip()
|
vin_no = vin_no.strip()
|
||||||
vin_data = {}
|
vin_data = {}
|
||||||
@ -481,26 +494,26 @@ def inventory_stats_view(request):
|
|||||||
]["total_cars"] += 1
|
]["total_cars"] += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
result = {
|
result = {
|
||||||
"total_cars": cars.count(),
|
"total_cars": cars.count(),
|
||||||
"makes": [
|
"makes": [
|
||||||
{
|
{
|
||||||
"make_id": make_data["make_id"],
|
"make_id": make_data["make_id"],
|
||||||
"make_name": make_data["make_name"],
|
"make_name": make_data["make_name"],
|
||||||
"total_cars": make_data["total_cars"],
|
"total_cars": make_data["total_cars"],
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"model_id": model_data["model_id"],
|
"model_id": model_data["model_id"],
|
||||||
"model_name": model_data["model_name"],
|
"model_name": model_data["model_name"],
|
||||||
"total_cars": model_data["total_cars"],
|
"total_cars": model_data["total_cars"],
|
||||||
"trims": list(model_data["trims"].values()),
|
"trims": list(model_data["trims"].values()),
|
||||||
}
|
}
|
||||||
for model_data in make_data["models"].values()
|
for model_data in make_data["models"].values()
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
for make_data in inventory.values()
|
for make_data in inventory.values()
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, "inventory/inventory_stats.html", {"inventory": result})
|
return render(request, "inventory/inventory_stats.html", {"inventory": result})
|
||||||
|
|
||||||
@ -634,6 +647,8 @@ def reserve_car_view(request, car_id):
|
|||||||
models.CarReservation.objects.create(
|
models.CarReservation.objects.create(
|
||||||
car=car, reserved_by=request.user, reserved_until=reserved_until
|
car=car, reserved_by=request.user, reserved_until=reserved_until
|
||||||
)
|
)
|
||||||
|
car.status = models.CarStatusChoices.RESERVED
|
||||||
|
car.save()
|
||||||
messages.success(request, _("Car reserved successfully."))
|
messages.success(request, _("Car reserved successfully."))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messages.error(request, f"Error reserving car: {e}")
|
messages.error(request, f"Error reserving car: {e}")
|
||||||
@ -659,7 +674,10 @@ def manage_reservation(request, reservation_id):
|
|||||||
return redirect("car_detail", pk=reservation.car.pk)
|
return redirect("car_detail", pk=reservation.car.pk)
|
||||||
|
|
||||||
elif action == "cancel":
|
elif action == "cancel":
|
||||||
|
car = reservation.car
|
||||||
reservation.delete()
|
reservation.delete()
|
||||||
|
car.status = models.CarStatusChoices.AVAILABLE
|
||||||
|
car.save()
|
||||||
messages.success(request, _("Reservation canceled successfully."))
|
messages.success(request, _("Reservation canceled successfully."))
|
||||||
return redirect("car_detail", pk=reservation.car.pk)
|
return redirect("car_detail", pk=reservation.car.pk)
|
||||||
|
|
||||||
@ -724,9 +742,9 @@ class CustomerListView(LoginRequiredMixin, ListView):
|
|||||||
|
|
||||||
if query:
|
if query:
|
||||||
customers = customers.filter(
|
customers = customers.filter(
|
||||||
Q(national_id__icontains=query) |
|
Q(national_id__icontains=query)
|
||||||
Q(first_name__icontains=query) |
|
| Q(first_name__icontains=query)
|
||||||
Q(last_name__icontains=query)
|
| Q(last_name__icontains=query)
|
||||||
)
|
)
|
||||||
return customers
|
return customers
|
||||||
|
|
||||||
@ -1691,6 +1709,10 @@ class EstimateListView(LoginRequiredMixin, ListView):
|
|||||||
template_name = "sales/estimates/estimate_list.html"
|
template_name = "sales/estimates/estimate_list.html"
|
||||||
context_object_name = "estimates"
|
context_object_name = "estimates"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
entity = self.request.user.dealer.entity
|
||||||
|
return entity.get_estimates()
|
||||||
|
|
||||||
|
|
||||||
# class EstimateCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
|
# class EstimateCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
# model = EstimateModel
|
# model = EstimateModel
|
||||||
@ -1727,98 +1749,143 @@ class EstimateListView(LoginRequiredMixin, ListView):
|
|||||||
def create_estimate(request):
|
def create_estimate(request):
|
||||||
dealer = get_user_type(request)
|
dealer = get_user_type(request)
|
||||||
entity = dealer.entity
|
entity = dealer.entity
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
try:
|
# try:
|
||||||
data = json.loads(request.body)
|
data = json.loads(request.body)
|
||||||
title = data.get("title")
|
title = data.get("title")
|
||||||
customer_id = data.get("customer")
|
customer_id = data.get("customer")
|
||||||
terms = data.get("terms")
|
terms = data.get("terms")
|
||||||
customer = entity.get_customers().filter(pk=customer_id).first()
|
customer = entity.get_customers().filter(pk=customer_id).first()
|
||||||
|
|
||||||
estimate = entity.create_estimate(
|
items = data.get("item", [])
|
||||||
estimate_title=title, customer_model=customer, contract_terms=terms
|
quantities = data.get("quantity", [])
|
||||||
)
|
|
||||||
|
|
||||||
items = data.get("item", [])
|
|
||||||
quantities = data.get("quantity", [])
|
|
||||||
|
|
||||||
if items and quantities:
|
|
||||||
if isinstance(items, list):
|
|
||||||
items_list = [
|
|
||||||
{"item_id": items[i], "quantity": quantities[i]}
|
|
||||||
for i in range(len(items))
|
|
||||||
]
|
|
||||||
items_txs = []
|
|
||||||
for item in items_list:
|
|
||||||
item_instance = ItemModel.objects.get(pk=item.get("item_id"))
|
|
||||||
car_instace = models.Car.objects.get(vin=item_instance.name)
|
|
||||||
items_txs.append({
|
|
||||||
"item_number": item_instance.item_number,
|
|
||||||
"quantity": float(item.get("quantity")),
|
|
||||||
"unit_cost": car_instace.finances.cost_price,
|
|
||||||
"unit_revenue": car_instace.finances.selling_price,
|
|
||||||
"total_amount": car_instace.finances.cost_price * int(item.get("quantity")),
|
|
||||||
})
|
|
||||||
|
|
||||||
estimate_itemtxs = {
|
|
||||||
item.get("item_number"): {
|
|
||||||
"unit_cost": item.get("unit_cost"),
|
|
||||||
"unit_revenue": item.get("unit_revenue"),
|
|
||||||
"quantity": item.get("quantity"),
|
|
||||||
"total_amount": item.get("total_amount"),
|
|
||||||
}
|
|
||||||
for item in items_txs
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
item = entity.get_items_all().filter(pk=items).first()
|
|
||||||
|
|
||||||
instance = models.Car.objects.get(vin=item.name)
|
|
||||||
estimate_itemtxs = {
|
|
||||||
item.item_number: {
|
|
||||||
"unit_cost": instance.finances.cost_price,
|
|
||||||
"unit_revenue": instance.finances.selling_price,
|
|
||||||
"quantity": float(quantities),
|
|
||||||
"total_amount": instance.finances.total * int(quantities),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
estimate.migrate_itemtxs(
|
|
||||||
itemtxs=estimate_itemtxs,
|
|
||||||
commit=True,
|
|
||||||
operation=EstimateModel.ITEMIZE_APPEND,
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(items, list):
|
|
||||||
for item in items:
|
|
||||||
instance = models.Car.objects.get(vin=item)
|
|
||||||
instance.status = models.CarStatusChoices.RESERVED
|
|
||||||
instance.save()
|
|
||||||
else:
|
|
||||||
instance = models.Car.objects.get(vin=items)
|
|
||||||
instance.status = models.CarStatusChoices.RESERVED
|
|
||||||
instance.save()
|
|
||||||
url = reverse("estimate_detail", kwargs={"pk": estimate.pk})
|
|
||||||
|
|
||||||
|
if not all([items, quantities]):
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
{
|
{"status": "error", "message": "Items and Quantities are required"},
|
||||||
"status": "success",
|
status=400,
|
||||||
"message": "Estimate created successfully!",
|
)
|
||||||
"url": url,
|
if isinstance(quantities, list):
|
||||||
},
|
if '0' in quantities:
|
||||||
status=200,
|
return JsonResponse(
|
||||||
)
|
{
|
||||||
except Exception as e:
|
"status": "error",
|
||||||
return JsonResponse(
|
"message": "Quantity must be greater than zero"
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
if int(quantities) <= 0:
|
||||||
|
return JsonResponse(
|
||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"message": f"An error occurred while processing the request.{e}",
|
"message": "Quantity must be greater than zero"
|
||||||
},
|
}
|
||||||
status=400,
|
)
|
||||||
)
|
|
||||||
|
estimate = entity.create_estimate(
|
||||||
|
estimate_title=title, customer_model=customer, contract_terms=terms
|
||||||
|
)
|
||||||
|
if isinstance(items, list):
|
||||||
|
item_quantity_map = {}
|
||||||
|
for item, quantity in zip(items, quantities):
|
||||||
|
if item in item_quantity_map:
|
||||||
|
item_quantity_map[item] += int(quantity)
|
||||||
|
else:
|
||||||
|
item_quantity_map[item] = int(quantity)
|
||||||
|
item_list = list(item_quantity_map.keys())
|
||||||
|
quantity_list = list(item_quantity_map.values())
|
||||||
|
|
||||||
|
items_list = [
|
||||||
|
{"item_id": item_list[i], "quantity": quantity_list[i]}
|
||||||
|
for i in range(len(item_list))
|
||||||
|
]
|
||||||
|
items_txs = []
|
||||||
|
for item in items_list:
|
||||||
|
item_instance = ItemModel.objects.get(pk=item.get("item_id"))
|
||||||
|
car_instance = models.Car.objects.get(vin=item_instance.name)
|
||||||
|
items_txs.append(
|
||||||
|
{
|
||||||
|
"item_number": item_instance.item_number,
|
||||||
|
"quantity": float(item.get("quantity")),
|
||||||
|
"unit_cost": car_instance.finances.cost_price,
|
||||||
|
"unit_revenue": car_instance.finances.selling_price,
|
||||||
|
"total_amount": car_instance.finances.cost_price
|
||||||
|
* int(item.get("quantity")),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
estimate_itemtxs = {
|
||||||
|
item.get("item_number"): {
|
||||||
|
"unit_cost": item.get("unit_cost"),
|
||||||
|
"unit_revenue": item.get("unit_revenue"),
|
||||||
|
"quantity": item.get("quantity"),
|
||||||
|
"total_amount": item.get("total_amount"),
|
||||||
|
}
|
||||||
|
for item in items_txs
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
item = entity.get_items_all().filter(pk=items).first()
|
||||||
|
instance = models.Car.objects.get(vin=item.name)
|
||||||
|
estimate_itemtxs = {
|
||||||
|
item.item_number: {
|
||||||
|
"unit_cost": instance.finances.cost_price,
|
||||||
|
"unit_revenue": instance.finances.selling_price,
|
||||||
|
"quantity": float(quantities),
|
||||||
|
"total_amount": instance.finances.total * int(quantities),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
estimate.migrate_itemtxs(
|
||||||
|
itemtxs=estimate_itemtxs,
|
||||||
|
commit=True,
|
||||||
|
operation=EstimateModel.ITEMIZE_APPEND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(items, list):
|
||||||
|
for item in items:
|
||||||
|
item_instance = ItemModel.objects.get(pk=item)
|
||||||
|
instance = models.Car.objects.get(vin=item_instance.name)
|
||||||
|
instance.status = models.CarStatusChoices.RESERVED
|
||||||
|
instance.save()
|
||||||
|
else:
|
||||||
|
item_instance = ItemModel.objects.get(pk=items)
|
||||||
|
instance = models.Car.objects.get(vin=item_instance.name)
|
||||||
|
instance.status = models.CarStatusChoices.RESERVED
|
||||||
|
instance.save()
|
||||||
|
|
||||||
|
url = reverse("estimate_detail", kwargs={"pk": estimate.pk})
|
||||||
|
return JsonResponse(
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"message": "Estimate created successfully!",
|
||||||
|
"url": f"{url}"
|
||||||
|
})
|
||||||
|
|
||||||
|
# except Exception as e:
|
||||||
|
# return JsonResponse(
|
||||||
|
# {
|
||||||
|
# "status": "error",
|
||||||
|
# "message": f"An error occurred while processing the request: {str(e)}",
|
||||||
|
# },
|
||||||
|
# status=400,
|
||||||
|
# )
|
||||||
|
|
||||||
form = EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
|
form = EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
|
||||||
|
car_list = models.Car.objects.filter(
|
||||||
|
dealer=dealer, finances__selling_price__gt=0
|
||||||
|
).exclude(status="reserved")
|
||||||
context = {
|
context = {
|
||||||
"form": form,
|
"form": form,
|
||||||
"items": entity.get_items_all().filter(item_role=ItemModel.ITEM_ROLE_PRODUCT),
|
"items": [
|
||||||
|
{
|
||||||
|
"car": x,
|
||||||
|
"product": entity.get_items_all()
|
||||||
|
.filter(item_role=ItemModel.ITEM_ROLE_PRODUCT, name=x.vin)
|
||||||
|
.first(),
|
||||||
|
}
|
||||||
|
for x in car_list
|
||||||
|
],
|
||||||
}
|
}
|
||||||
return render(request, "sales/estimates/estimate_form.html", context)
|
return render(request, "sales/estimates/estimate_form.html", context)
|
||||||
|
|
||||||
@ -1832,12 +1899,17 @@ class EstimateDetailView(LoginRequiredMixin, DetailView):
|
|||||||
estimate = kwargs.get("object")
|
estimate = kwargs.get("object")
|
||||||
if estimate.get_itemtxs_data():
|
if estimate.get_itemtxs_data():
|
||||||
total = sum(
|
total = sum(
|
||||||
x.ce_cost_estimate for x in estimate.get_itemtxs_data()[0].all()
|
(x.ce_revenue_estimate - models.Car.objects.get(vin=x.item_model.name).finances.discount_amount) for x in estimate.get_itemtxs_data()[0].all()
|
||||||
)
|
)
|
||||||
vat = models.VatRate.objects.filter(is_active=True).first()
|
vat = models.VatRate.objects.filter(is_active=True).first()
|
||||||
# vat = settings.VAT_RATE
|
|
||||||
kwargs["vat_amount"] = total * vat.vat_rate
|
# Calculate VAT and total with 2 decimal places
|
||||||
kwargs["total"] = (total * vat.vat_rate) + total
|
vat_amount = round(total * vat.vat_rate, 2) # Round to 2 decimal places
|
||||||
|
grand_total = round((total * vat.vat_rate) + total, 2) # Round to 2 decimal places
|
||||||
|
|
||||||
|
# Add values to the context
|
||||||
|
kwargs["vat_amount"] = vat_amount
|
||||||
|
kwargs["total"] = grand_total
|
||||||
kwargs["vat"] = vat.rate
|
kwargs["vat"] = vat.rate
|
||||||
kwargs["invoice"] = (
|
kwargs["invoice"] = (
|
||||||
InvoiceModel.objects.all().filter(ce_model=estimate).first()
|
InvoiceModel.objects.all().filter(ce_model=estimate).first()
|
||||||
@ -1893,11 +1965,22 @@ def estimate_mark_as(request, pk):
|
|||||||
messages.error(request, "Estimate is not ready for approval")
|
messages.error(request, "Estimate is not ready for approval")
|
||||||
return redirect("estimate_detail", pk=estimate.pk)
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
estimate.mark_as_approved()
|
estimate.mark_as_approved()
|
||||||
|
messages.success(request, "Estimate approved successfully.")
|
||||||
|
for i in estimate.get_itemtxs_data()[0]:
|
||||||
|
car = models.Car.objects.get(vin=i.item_model.name)
|
||||||
|
car.status = models.CarStatusChoices.SOLD
|
||||||
|
car.save()
|
||||||
elif mark == "rejected":
|
elif mark == "rejected":
|
||||||
if not estimate.can_cancel():
|
if not estimate.can_cancel():
|
||||||
messages.error(request, "Estimate is not ready for rejection")
|
messages.error(request, "Estimate is not ready for rejection")
|
||||||
return redirect("estimate_detail", pk=estimate.pk)
|
return redirect("estimate_detail", pk=estimate.pk)
|
||||||
estimate.mark_as_canceled()
|
estimate.mark_as_canceled()
|
||||||
|
messages.success(request, "Estimate canceled successfully.")
|
||||||
|
for i in estimate.get_itemtxs_data()[0]:
|
||||||
|
car = models.Car.objects.get(vin=i.item_model.name)
|
||||||
|
car.status = models.CarStatusChoices.AVAILABLE
|
||||||
|
car.save()
|
||||||
|
|
||||||
elif mark == "completed":
|
elif mark == "completed":
|
||||||
if not estimate.can_complete():
|
if not estimate.can_complete():
|
||||||
messages.error(request, "Estimate is not ready for completion")
|
messages.error(request, "Estimate is not ready for completion")
|
||||||
@ -2240,7 +2323,7 @@ def create_lead(request, pk):
|
|||||||
class LeadListView(ListView):
|
class LeadListView(ListView):
|
||||||
model = models.Customer
|
model = models.Customer
|
||||||
template_name = "crm/lead_list.html"
|
template_name = "crm/lead_list.html"
|
||||||
context_object_name ='customers'
|
context_object_name = "customers"
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
query = self.request.GET.get("q")
|
query = self.request.GET.get("q")
|
||||||
@ -2250,9 +2333,9 @@ class LeadListView(ListView):
|
|||||||
|
|
||||||
if query:
|
if query:
|
||||||
customers = customers.filter(
|
customers = customers.filter(
|
||||||
Q(national_id__icontains=query) |
|
Q(national_id__icontains=query)
|
||||||
Q(first_name__icontains=query) |
|
| Q(first_name__icontains=query)
|
||||||
Q(last_name__icontains=query)
|
| Q(last_name__icontains=query)
|
||||||
)
|
)
|
||||||
return customers
|
return customers
|
||||||
|
|
||||||
@ -2395,5 +2478,5 @@ class ItemServiceListView(ListView):
|
|||||||
|
|
||||||
class SubscriptionPlans(ListView):
|
class SubscriptionPlans(ListView):
|
||||||
model = models.SubscriptionPlan
|
model = models.SubscriptionPlan
|
||||||
template_name = 'subscriptions/subscription_plan.html'
|
template_name = "subscriptions/subscription_plan.html"
|
||||||
context_object_name = 'plans'
|
context_object_name = "plans"
|
||||||
|
|||||||
BIN
static/images/logos/users/tenhal_hero.png
Normal file
BIN
static/images/logos/users/tenhal_hero.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
@ -117,6 +117,9 @@ const url = "{% url 'account_signup' %}";
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
notify("success","Account created successfully");
|
notify("success","Account created successfully");
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "{% url 'account_login' %}";
|
||||||
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
notify("error",data.error);
|
notify("error",data.error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,12 +122,10 @@
|
|||||||
<div class="table-responsive scrollbar mb-3">
|
<div class="table-responsive scrollbar mb-3">
|
||||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||||
{% if car.finances %}
|
{% if car.finances %}
|
||||||
{% if perms.inventory.view_carfinance %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans "Cost Price"|capfirst %}</th>
|
<th>{% trans "Cost Price"|capfirst %}</th>
|
||||||
<td>{{ car.finances.cost_price }}</td>
|
<td>{{ car.finances.cost_price }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans "Selling Price"|capfirst %}</th>
|
<th>{% trans "Selling Price"|capfirst %}</th>
|
||||||
<td>{{ car.finances.selling_price }}</td>
|
<td>{{ car.finances.selling_price }}</td>
|
||||||
@ -154,15 +152,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans "Total"|capfirst %}</th>
|
<th>{% trans "Total"|capfirst %}</th>
|
||||||
<td>{{ car.finances.total }}</td>
|
<td>{{ car.finances.total_vat }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
{% if perms.inventory.change_carfinance %}
|
|
||||||
<a href="{% url 'car_finance_update' car.finances.pk %}" class="btn btn-phoenix-warning btn-sm mb-3">
|
<a href="{% url 'car_finance_update' car.finances.pk %}" class="btn btn-phoenix-warning btn-sm mb-3">
|
||||||
{% trans "Edit" %}
|
{% trans "Edit" %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>{% trans "No finance details available." %}</p>
|
<p>{% trans "No finance details available." %}</p>
|
||||||
<a href="{% url 'car_finance_create' car.pk %}" class="btn btn-phoenix-success btn-sm mb-3">
|
<a href="{% url 'car_finance_create' car.pk %}" class="btn btn-phoenix-success btn-sm mb-3">
|
||||||
|
|||||||
@ -131,8 +131,8 @@
|
|||||||
<td class="">{{forloop.counter}}</td>
|
<td class="">{{forloop.counter}}</td>
|
||||||
<td class="">{{item.item_model.name}}</td>
|
<td class="">{{item.item_model.name}}</td>
|
||||||
<td class="align-middle">{{item.ce_quantity}}</td>
|
<td class="align-middle">{{item.ce_quantity}}</td>
|
||||||
<td class="align-middle ps-5">{{item.ce_unit_cost_estimate}}</td>
|
<td class="align-middle ps-5">{{item.ce_unit_revenue_estimate}}</td>
|
||||||
<td class="align-middle text-body-tertiary fw-semibold">{{item.ce_total_amount}}</td>
|
<td class="align-middle text-body-tertiary fw-semibold">{{item.ce_revenue_estimate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
@ -187,7 +187,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// Run the function on page load
|
// Run the function on page load
|
||||||
window.onload = calculateTotals;
|
//window.onload = calculateTotals;
|
||||||
|
|
||||||
function setFormAction(action) {
|
function setFormAction(action) {
|
||||||
// Get the form element
|
// Get the form element
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
<div class="mb-2 col-sm-2">
|
<div class="mb-2 col-sm-2">
|
||||||
<select class="form-control item" name="item[]" required>
|
<select class="form-control item" name="item[]" required>
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<option value="{{ item.pk }}">{{ item.name }}</option>
|
<option value="{{ item.product.pk }}">{{ item.car.id_car_model }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<div class="mb-2 col-sm-2">
|
<div class="mb-2 col-sm-2">
|
||||||
<select class="form-control item" name="item[]" required>
|
<select class="form-control item" name="item[]" required>
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<option value="{{ item.pk }}">{{ item.name }}</option>
|
<option value="{{ item.product.pk }}">{{ item.car.id_car_model }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -335,14 +335,12 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('confirmAccept').addEventListener('click', function () {
|
document.getElementById('confirmAccept').addEventListener('click', function () {
|
||||||
// Handle the accept action here
|
// Handle the accept action here
|
||||||
alert('Estimate Accepted');
|
|
||||||
$('#acceptModal').modal('hide');
|
$('#acceptModal').modal('hide');
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('confirmReject').addEventListener('click', function () {
|
document.getElementById('confirmReject').addEventListener('click', function () {
|
||||||
// Handle the reject action here
|
// Handle the reject action here
|
||||||
alert('Estimate Rejected');
|
|
||||||
$('#rejectModal').modal('hide');
|
$('#rejectModal').modal('hide');
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user