This commit is contained in:
= 2025-03-23 21:03:13 +03:00
parent 3f89935d1b
commit e5d09b6e0d
6 changed files with 209 additions and 137 deletions

View File

@ -592,6 +592,10 @@ class CarFinance(models.Model):
def total(self): def total(self):
return self.selling_price return self.selling_price
@property
def total_additionals_no_vat(self):
return sum(x.price for x in self.additional_services.all())
@property @property
def total_additionals(self): def total_additionals(self):
return sum(x.price_ for x in self.additional_services.all()) return sum(x.price_ for x in self.additional_services.all())

View File

@ -19,7 +19,9 @@ from django_ledger.models import (
CustomerModel, CustomerModel,
JournalEntryModel, JournalEntryModel,
TransactionModel, TransactionModel,
LedgerModel LedgerModel,
BillModel,
ItemTransactionModel
) )
from . import models from . import models
from django.utils.timezone import now from django.utils.timezone import now
@ -642,20 +644,18 @@ def create_dealer_groups(sender, instance, created, **kwargs):
def create_ledger_vendor(sender, instance, created, **kwargs): def create_ledger_vendor(sender, instance, created, **kwargs):
if created: if created:
entity = EntityModel.objects.filter(name=instance.dealer.name).first() entity = EntityModel.objects.filter(name=instance.dealer.name).first()
additionals = to_dict(instance)
entity.create_vendor( entity.create_vendor(
vendor_model_kwargs={ vendor_model_kwargs={
"vendor_name": instance.name, "vendor_name": instance.name,
"vendor_number": instance.crn, "vendor_number": instance.crn,
"address_1": instance.address, "address_1": instance.address,
"phone": instance.phone_number, "phone": instance.phone_number,
"email": instance.email,
"tax_id_number": instance.vrn, "tax_id_number": instance.vrn,
"active": True, "active": True,
"hidden": False, "hidden": False,
"additional_info": { "additional_info": additionals,
"arabic_name": instance.arabic_name,
"contact_person": instance.contact_person,
},
} }
) )
@ -676,25 +676,37 @@ def create_ledger_vendor(sender, instance, created, **kwargs):
active=True active=True
) )
print(f"VendorModel created for Vendor: {instance.name}") print(f"VendorModel created for Vendor: {instance.name}")
else:
additionals = to_dict(instance)
entity.get_vendors().filter(email=instance.email).first().update(
vendor_name= instance.name,
vendor_number= instance.crn,
address_1= instance.address,
phone= instance.phone_number,
email= instance.email,
tax_id_number= instance.vrn,
additional_info= additionals,
)
@receiver(post_save, sender=models.CustomerModel) @receiver(post_save, sender=models.CustomerModel)
def create_customer_user(sender, instance, created, **kwargs): def create_customer_user(sender, instance, created, **kwargs):
if created: if created:
first_name = instance.additional_info.get("customer_info").get("first_name") try:
last_name = instance.additional_info.get("customer_info").get("last_name") first_name = instance.additional_info.get("customer_info").get("first_name")
user = User.objects.create( last_name = instance.additional_info.get("customer_info").get("last_name")
username=instance.email, user = User.objects.create(
email=instance.email, username=instance.email,
first_name=first_name if first_name else '', email=instance.email,
last_name=last_name if last_name else '', first_name=first_name if first_name else '',
) last_name=last_name if last_name else '',
instance.additional_info.update({"user_info": to_dict(user)}) )
user.set_unusable_password() instance.additional_info.update({"user_info": to_dict(user)})
user.save() user.set_unusable_password()
instance.user = user user.save()
instance.save() instance.user = user
instance.save()
except Exception as e:
print(e)
# Create Item # Create Item
@receiver(post_save, sender=models.Car) @receiver(post_save, sender=models.Car)
@ -929,98 +941,106 @@ def create_dealer_settings(sender, instance, created, **kwargs):
@receiver(post_save, sender=models.Dealer) @receiver(post_save, sender=models.Dealer)
def create_make_ledger_accounts(sender, instance, created, **kwargs): def create_make_ledger_accounts(sender, instance, created, **kwargs):
if created: if created:
entity_name = instance.user.dealer.name entity = instance.entity
entity = EntityModel.objects.get(name=entity_name) coa = entity.get_default_coa()
last_account = entity.get_all_accounts().filter(role=roles.ASSET_CA_RECEIVABLES).order_by('-created').first()
if len(last_account.code) == 4:
code = f"{int(last_account.code)}{1:03d}"
elif len(last_account.code) > 4:
code = f"{int(last_account.code)+1}"
for make in models.CarMake.objects.all():
entity.create_account(
name=make.name,
code=code,
role=roles.ASSET_CA_RECEIVABLES,
coa_model=coa,
balance_type="credit",
active=True
)
# @receiver(post_save, sender=VendorModel) # @receiver(post_save, sender=VendorModel)
# def create_vendor_accounts(sender, instance, created, **kwargs): # def create_vendor_accounts(sender, instance, created, **kwargs):
# if created: # if created:
# entity = instance.entity_model # entity = instance.entity_model
# coa = entity.get_default_coa()
# last_account = entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).order_by('-created').first() # last_account = entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).order_by('-created').first()
# code = str(int(last_account.code) + 1) # if len(last_account.code) == 4:
# account = entity.create_account( # code = f"{int(last_account.path)}{1:03d}"
# elif len(last_account.code) > 4:
# code = f"{int(last_account.path)+1}"
# entity.create_account(
# name=instance.vendor_name, # name=instance.vendor_name,
# code=code, # code=code,
# role=roles.LIABILITY_CL_ACC_PAYABLE, # role=roles.LIABILITY_CL_ACC_PAYABLE,
# coa_model=entity.get_default_coa(), # coa_model=coa,
# balance_type="credit", # balance_type="credit",
# active=True # active=True
# ) # )
def save_journal(car_finance,ledger,vendor):
entity = ledger.entity
journal = JournalEntryModel.objects.create(
posted=False,
description=f"Finances of Car:{car_finance.car.vin} for Vendor:{car_finance.car.vendor.vendor_name}",
ledger=ledger,
locked=False,
origin="Payment",
)
ledger.additional_info["je_number"] = journal.je_number
ledger.save()
inventory_account = entity.get_default_coa_accounts().filter(role=roles.ASSET_CA_INVENTORY).first()
vendor_account = entity.get_default_coa_accounts().get(name=vendor.vendor_name)
additional_services_account = entity.get_default_coa_accounts().filter(name="Additional Services",role=roles.COGS).first()
# Debit Inventory Account
TransactionModel.objects.create(
journal_entry=journal,
account=inventory_account,
amount=car_finance.cost_price,
tx_type='debit'
)
# Credit Vendor Account
TransactionModel.objects.create(
journal_entry=journal,
account=vendor_account,
amount=car_finance.cost_price,
tx_type='credit',
)
@receiver(post_save, sender=models.CarFinance) @receiver(post_save, sender=models.CarFinance)
def update_finance_cost(sender, instance, created, **kwargs): def update_finance_cost(sender, instance, created, **kwargs):
entity = instance.car.dealer.entity
ledger,created = LedgerModel.objects.get_or_create(name=instance.car.vin, entity=entity)
vendor = instance.car.vendor
if created: if created:
journal = JournalEntryModel.objects.create( entity = instance.car.dealer.entity
posted=False, vendor = instance.car.vendor
description=f"Finances of Car:{instance.car.vin} for Vendor:{instance.car.vendor.vendor_name}", name = f"{instance.car.vin}-{instance.car.id_car_make.name}-{instance.car.id_car_model.name}-{instance.car.year}-{vendor.vendor_name}"
ledger=ledger, ledger,_ = LedgerModel.objects.get_or_create(name=name, entity=entity)
locked=False, save_journal(instance,ledger,vendor)
origin="Payment",
)
ledger.additional_info["je_number"] = journal.je_number
ledger.save()
inventory_account = entity.get_default_coa_accounts().filter(role=roles.ASSET_CA_INVENTORY).first() # if not created:
vendor_account = entity.get_default_coa_accounts().get(name=vendor.vendor_name) # if ledger.additional_info.get("je_number"):
# journal = JournalEntryModel.objects.filter(je_number=ledger.additional_info.get("je_number")).first()
# Debit Inventory Account # journal.description = f"Finances of Car:{instance.car.vin} for Vendor:{instance.car.vendor.vendor_name}"
TransactionModel.objects.create( # journal.save()
journal_entry=journal, # debit = journal.get_transaction_queryset().filter(tx_type='debit').first()
account=inventory_account, # credit = journal.get_transaction_queryset().filter(tx_type='credit').first()
amount=instance.total + instance.total_additionals, # if debit and credit:
tx_type='debit' # if journal.is_locked():
) # journal.mark_as_unlocked()
# journal.save()
# Credit Vendor Account # debit.amount = instance.cost_price
TransactionModel.objects.create( # credit.amount = instance.cost_price
journal_entry=journal, # debit.save()
account=vendor_account, # credit.save()
amount=instance.cost_price, # else:
tx_type='credit' # save_journal(instance,ledger,vendor,journal=journal)
) # else:
else: # save_journal(instance,ledger,vendor)
if not ledger.additional_info.get("je_number"): # else:
journal = JournalEntryModel.objects.create( # save_journal(instance,ledger,vendor)
posted=False,
description=f"Finances of Car:{instance.car.vin} for Vendor:{instance.car.vendor.vendor_name}",
ledger=ledger,
locked=False,
origin="Payment",
)
ledger.additional_info["je_number"] = journal.je_number
ledger.save()
inventory_account = entity.get_default_coa_accounts().filter(role=roles.ASSET_CA_INVENTORY).first()
vendor_account = entity.get_default_coa_accounts().get(name=vendor.vendor_name, active=True)
# Debit Inventory Account
TransactionModel.objects.create(
journal_entry=journal,
account=inventory_account,
amount=instance.cost_price,
tx_type='debit'
)
# Credit Vendor Account
TransactionModel.objects.create(
journal_entry=journal,
account=vendor_account,
amount=instance.cost_price,
tx_type='credit'
)
else:
journal = JournalEntryModel.objects.filter(je_number=ledger.additional_info.get("je_number")).first()
debit = journal.get_transaction_queryset().filter(tx_type='debit').first()
credit = journal.get_transaction_queryset().filter(tx_type='credit').first()
debit.amount = instance.cost_price
credit.amount = instance.cost_price
debit.save()
credit.save()

View File

@ -935,3 +935,29 @@ def handle_account_process(invoice,amount,finance_data):
tx_type="credit", tx_type="credit",
description="VAT Payable on Invoice", description="VAT Payable on Invoice",
) )
def create_make_accounts(dealer):
entity = dealer.entity
coa = entity.get_default_coa()
# Create a unique account name for the dealer and car make combination
makes = models.DealersMake.objects.filter(dealer=dealer).all()
for make in makes:
account_name = f"{make.car_make.name} Inventory Account"
account = entity.get_all_accounts().filter(coa_model=coa,name=account_name).first()
if not account:
last_account = entity.get_all_accounts().filter(role=roles.ASSET_CA_INVENTORY).order_by('-created').first()
if len(last_account.code) == 4:
code = f"{int(last_account.code)}{1:03d}"
elif len(last_account.code) > 4:
code = f"{int(last_account.code)+1}"
account = entity.create_account(
name=account_name,
code=code,
role=roles.ASSET_CA_INVENTORY,
coa_model=coa,
balance_type="credit",
active=True
)

View File

@ -127,6 +127,7 @@ from .services import (
) )
from .utils import ( from .utils import (
CarFinanceCalculator, CarFinanceCalculator,
create_make_accounts,
get_car_finance_data, get_car_finance_data,
get_financial_values, get_financial_values,
get_item_transactions, get_item_transactions,
@ -136,6 +137,7 @@ from .utils import (
set_bill_payment, set_bill_payment,
set_invoice_payment, set_invoice_payment,
CarTransfer, CarTransfer,
to_dict,
) )
##################################################################### #####################################################################
@ -1504,13 +1506,31 @@ class VendorUpdateView(
SuccessMessageMixin, SuccessMessageMixin,
UpdateView, UpdateView,
): ):
model = models.Vendor model = VendorModel
form_class = forms.VendorForm form_class = forms.VendorForm
template_name = "vendors/vendor_form.html" template_name = "vendors/vendor_form.html"
success_url = reverse_lazy("vendor_list") success_url = reverse_lazy("vendor_list")
success_message = _("Vendor updated successfully.") success_message = _("Vendor updated successfully.")
def get_initial(self):
initial = super().get_initial()
initial = self.object.additional_info
return initial
def form_valid(self, form):
instance = form.save(commit=False)
instance.vendor_name = self.request.POST["name"]
instance.vendor_number = self.request.POST["crn"]
instance.address_1 = self.request.POST["address"]
instance.phone = self.request.POST["phone_number"]
instance.email = self.request.POST["email"]
instance.tax_id_number = self.request.POST["vrn"]
additionals = form.cleaned_data
additionals['phone_number'] = str(additionals['phone_number'])
instance.additional_info = additionals
instance.save()
return super().form_valid(form)
@login_required @login_required
def delete_vendor(request, pk): def delete_vendor(request, pk):
vendor = get_object_or_404(models.Vendor, pk=pk) vendor = get_object_or_404(models.Vendor, pk=pk)
@ -4052,6 +4072,7 @@ def assign_car_makes(request):
form = forms.DealersMakeForm(request.POST, dealer=dealer) form = forms.DealersMakeForm(request.POST, dealer=dealer)
if form.is_valid(): if form.is_valid():
form.save() form.save()
create_make_accounts(dealer)
return redirect("dealer_detail", pk=dealer.pk) return redirect("dealer_detail", pk=dealer.pk)
else: else:
# Pre-fill the form with existing selections # Pre-fill the form with existing selections

View File

@ -130,7 +130,8 @@
<td class="align-middle white-space-nowrap text-end pe-0 ps-4"> <td class="align-middle white-space-nowrap text-end pe-0 ps-4">
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button> <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2"><a href="" class="dropdown-item text-success-dark"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'vendor_update' vendor.pk %}" class="dropdown-item text-success-dark">
{% trans "Edit" %} {% trans "Edit" %}
</a> </a>
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button> <div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button>