diff --git a/.gitignore b/.gitignore
index 16c1bd8a..e656dd72 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,7 +18,7 @@ car_inventory/settings.py
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
-
+Makefile
# AWS User-specific
.idea/**/aws.xml
diff --git a/inventory/forms.py b/inventory/forms.py
index b15d7cf1..fee214e9 100644
--- a/inventory/forms.py
+++ b/inventory/forms.py
@@ -34,7 +34,7 @@ from django_ledger.io import roles, DEBIT, CREDIT
class AdditionalServiceForm(forms.ModelForm):
class Meta:
model = AdditionalServices
- fields = ['name', 'price','description','vatable', 'uom']
+ fields = ['name', 'price','description','taxable', 'uom']
class PaymentForm(forms.ModelForm):
class Meta:
diff --git a/inventory/migrations/0031_remove_salequotation_entity.py b/inventory/migrations/0031_remove_salequotation_entity.py
new file mode 100644
index 00000000..715069b0
--- /dev/null
+++ b/inventory/migrations/0031_remove_salequotation_entity.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.17 on 2024-12-26 07:58
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('inventory', '0030_account'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='salequotation',
+ name='entity',
+ ),
+ ]
diff --git a/inventory/migrations/0032_remove_additionalservices_vatable_and_more.py b/inventory/migrations/0032_remove_additionalservices_vatable_and_more.py
new file mode 100644
index 00000000..e97bfde8
--- /dev/null
+++ b/inventory/migrations/0032_remove_additionalservices_vatable_and_more.py
@@ -0,0 +1,22 @@
+# Generated by Django 4.2.17 on 2024-12-26 08:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('inventory', '0031_remove_salequotation_entity'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='additionalservices',
+ name='vatable',
+ ),
+ migrations.AddField(
+ model_name='additionalservices',
+ name='taxable',
+ field=models.BooleanField(default=False, verbose_name='taxable'),
+ ),
+ ]
diff --git a/inventory/models.py b/inventory/models.py
index 5662aacf..92df4595 100644
--- a/inventory/models.py
+++ b/inventory/models.py
@@ -237,7 +237,7 @@ class AdditionalServices(models.Model, LocalizedNameMixin):
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
description = models.TextField(verbose_name=_("Description"))
price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Price"))
- vatable = models.BooleanField(default=False, verbose_name=_("Vatable"))
+ taxable = models.BooleanField(default=False, verbose_name=_("taxable"))
uom = models.CharField(max_length=10, choices=UNIT_CHOICES, verbose_name=_("Unit of Measurement"))
dealer = models.ForeignKey("Dealer", on_delete=models.CASCADE, verbose_name=_("Dealer"))
@@ -767,8 +767,7 @@ class SaleQuotation(models.Model):
]
dealer = models.ForeignKey(
Dealer, on_delete=models.CASCADE, related_name="sales", null=True
- )
- entity = models.ForeignKey(EntityModel, on_delete=models.CASCADE)
+ )
customer = models.ForeignKey(
Customer,
on_delete=models.CASCADE,
diff --git a/inventory/signals.py b/inventory/signals.py
index 5bf6f486..22c81d21 100644
--- a/inventory/signals.py
+++ b/inventory/signals.py
@@ -5,10 +5,12 @@ from django.dispatch import receiver
from django.utils import timezone
from django_ledger.models import EntityModel
from django.utils.translation import gettext_lazy as _
-
-
+from django.contrib.auth import get_user_model
+from django_ledger.io import roles
+from django_ledger.models import EntityModel,AccountModel,ItemModel,ItemModelAbstract,UnitOfMeasureModel
from . import models
+User = get_user_model()
# @receiver(post_save, sender=models.SaleQuotation)
# def link_quotation_to_entity(sender, instance, created, **kwargs):
@@ -22,6 +24,25 @@ from . import models
# user = instance.user
# if user:
# user.delete()
+
+@receiver(post_save, sender=User)
+def create_dealer(instance, created, *args, **kwargs):
+ if created:
+ models.Dealer.objects.create(user=instance,name=instance.username,email=instance.email)
+
+@receiver(post_save, sender=models.Dealer)
+def create_user_account(sender, instance, created, **kwargs):
+ if created:
+ if instance.dealer_type != "Owner":
+ user = User.objects.create_user(
+ username=instance.name,
+ email=instance.email,
+ )
+ user.set_password("Tenhal@123")
+ user.save()
+ instance.user = user
+ instance.save()
+
@receiver(post_save, sender=models.Car)
def create_car_location(sender, instance, created, **kwargs):
"""
@@ -67,11 +88,11 @@ def create_ledger_entity(sender, instance, created, **kwargs):
if created:
root_dealer = instance.get_root_dealer
if not root_dealer.entity:
- entity_name = f"{root_dealer.name}-{root_dealer.pk}-{root_dealer.joined_at.date()}"
+ entity_name = f"{root_dealer.name}-{root_dealer.joined_at.date()}"
entity = EntityModel.create_entity(
name=entity_name,
admin=root_dealer.user,
- use_accrual_method=True,
+ use_accrual_method=False,
fy_start_month=1,
)
@@ -82,60 +103,88 @@ def create_ledger_entity(sender, instance, created, **kwargs):
assign_as_default=True, commit=True, coa_name=_(f"{entity_name}-COA")
)
if coa:
- 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}")
- entity.create_account(
- coa_model=coa,
- code="10100",
- role="asset_ca_cash",
- name=_("Cash"),
- balance_type="debit",
- active=True,
- )
- entity.create_account(
- coa_model=coa,
- code="11000",
- role="asset_ca_recv",
- name=_("Accounts Receivable"),
- balance_type="debit",
- active=True,
- )
- entity.create_account(
- coa_model=coa,
- code="12000",
- role="asset_ca_inv",
- name=_("Inventory"),
- balance_type="debit",
- active=True,
- )
+ # Create Cash Account
+ entity.create_account(
+ coa_model=coa,
+ code="1010",
+ role=roles.ASSET_CA_CASH,
+ name=_("Cash"),
+ balance_type="debit",
+ active=True,
+ )
- entity.create_account(
- coa_model=coa,
- code="20100",
- role="lia_cl_acc_payable",
- name=_("Accounts Payable"),
- balance_type="credit",
- active=True,
- )
+ # Create Accounts Receivable Account
+ entity.create_account(
+ coa_model=coa,
+ code="1020",
+ role=roles.ASSET_CA_RECEIVABLES,
+ name=_("Accounts Receivable"),
+ balance_type="debit",
+ active=True,
+ )
+
+ # Create Inventory Account
+ entity.create_account(
+ coa_model=coa,
+ code="1030",
+ role=roles.ASSET_CA_INVENTORY,
+ name=_("Inventory"),
+ balance_type="debit",
+ active=True,
+ )
- entity.create_account(
- coa_model=coa,
- code="40100",
- role="in_operational",
- name=_("Sales Income"),
- balance_type="credit",
- active=True,
- )
+ # Create Accounts Payable Account
+ entity.create_account(
+ coa_model=coa,
+ code="2010",
+ role=roles.LIABILITY_CL_ACC_PAYABLE,
+ name=_("Accounts Payable"),
+ balance_type="credit",
+ active=True,
+ )
- entity.create_account(
- coa_model=coa,
- code="50100",
- role="cogs_regular",
- name=_("Cost of Goods Sold"),
- balance_type="debit",
- active=True,
- )
+ # Create Sales Revenue Account
+ entity.create_account(
+ coa_model=coa,
+ code="4010",
+ role=roles.INCOME_OPERATIONAL,
+ name=_("Sales Revenue"),
+ balance_type="credit",
+ active=True,
+ )
+
+ # Create Cost of Goods Sold Account
+ entity.create_account(
+ coa_model=coa,
+ code="5010",
+ role=roles.COGS,
+ name=_("Cost of Goods Sold"),
+ balance_type="debit",
+ active=True,
+ )
+
+ # Create Rent Expense Account
+ entity.create_account(
+ coa_model=coa,
+ code="6010",
+ role=roles.EXPENSE_OPERATIONAL,
+ name=_("Rent Expense"),
+ balance_type="debit",
+ active=True,
+ )
+
+ # Create Utilities Expense Account
+ entity.create_account(
+ coa_model=coa,
+ code="6020",
+ role=roles.EXPENSE_OPERATIONAL,
+ name=_("Utilities Expense"),
+ balance_type="debit",
+ active=True,
+ )
# uom_name = _("Unit")
# unit_abbr = _("U")
@@ -169,87 +218,52 @@ def create_ledger_vendor(sender, instance, created, **kwargs):
@receiver(post_save, sender=models.Customer)
def create_customer(sender, instance, created, **kwargs):
if created:
- entity = EntityModel.objects.filter(
- name=instance.dealer.get_root_dealer.name
- ).first()
+ dealer = instance.dealer.get_root_dealer
+ entity = dealer.entity
name = f"{instance.first_name} {instance.middle_name} {instance.last_name}"
+ if entity:
+ entity.create_customer(
+ customer_model_kwargs={
+ "customer_name": name,
+ "address_1": instance.address,
+ "phone": instance.phone_number,
+ "email": instance.email,
+ "sales_tax_rate": 0.15,
+ "active": True,
+ "hidden": False,
+ "additional_info": {},
+ }
+ )
- entity.create_customer(
- customer_model_kwargs={
- "customer_name": name,
- "address_1": instance.address,
- "phone": instance.phone_number,
- "email": instance.email,
- "sales_tax_rate": 0.15,
- "active": True,
- "hidden": False,
- "additional_info": {},
- }
- )
-
- print(f"Customer created: {name}")
+ print(f"Customer created: {name}")
# Create Item
-# @receiver(post_save, sender=models.Car)
-# def create_item_model(sender, instance, created, **kwargs):
-# item_name = f"{instance.year} - {instance.id_car_make} - {instance.id_car_model} - {instance.id_car_trim}"
-# uom_name = _("Car")
-# unit_abbr = _("C")
-#
-# uom, uom_created = UnitOfMeasureModel.objects.get_or_create(
-# name=uom_name,
-# unit_abbr=unit_abbr
-# )
-#
-# if uom_created:
-# print(f"UOM created: {uom_name}")
-# else:
-# print(f"Using existing UOM: {uom_name}")
-#
-# entity = EntityModel.objects.filter(name=instance.dealer.name).first()
-#
-# inventory_account = AccountModel.objects.first()
-# cogs_account = AccountModel.objects.first()
-# earnings_account = AccountModel.objects.first()
-#
-# entity.create_item_product(
-# item_name=item_name,
-# item_role=ItemModelAbstract.ITEM_ROLE_PRODUCT,
-# item_type=ItemModelAbstract.ITEM_TYPE_MATERIAL,
-# item_id=instance.vin,
-# sold_as_unit=True,
-# inventory_received=1.00,
-# inventory_received_value=0.00,
-# inventory_account=inventory_account,
-# for_inventory=True,)
-#
-# item = ItemModel.objects.create(
-# entity=entity,
-# uom=uom,
-# name=item_name,
-# item_role=ItemModelAbstract.ITEM_ROLE_INVENTORY,
-# item_type=ItemModelAbstract.ITEM_TYPE_MATERIAL,
-# item_id=instance.vin,
-# sold_as_unit=True,
-# inventory_received=1.00,
-# inventory_received_value=0.00,
-# inventory_account=inventory_account,
-# for_inventory=True,
-# is_product_or_service=True,
-# cogs_account=cogs_account,
-# earnings_account=earnings_account,
-# is_active=True,
-# additional_info={
-# "remarks": instance.remarks,
-# "status": instance.status,
-# "stock_type": instance.stock_type,
-# "mileage": instance.mileage,
-# },
-# )
-#
-# print(f"ItemModel {'created' if created else 'updated'} for Car: {item.name}")
-#
+@receiver(post_save, sender=models.Car)
+def create_item_model(sender, instance, created, **kwargs):
+ item_name = f"{instance.year} - {instance.id_car_make} - {instance.id_car_model} - {instance.id_car_trim}"
+ dealer = instance.dealer
+ entity = dealer.entity
+
+ if not entity:
+ return
+
+ uom_name = _("Car")
+ unit_abbr = _("C")
+ uom = entity.get_uom_all().filter(name=uom_name, unit_abbr=unit_abbr).first()
+ if not uom:
+ uom = entity.create_uom(
+ name=uom_name,
+ unit_abbr=unit_abbr
+ )
+
+ entity.create_item_product(
+ name=item_name,
+ uom_model=uom,
+ item_type=ItemModel.ITEM_TYPE_MATERIAL)
+
+ print(f"ItemModel for Car:")
+
#
# # update price - CarFinance
# @receiver(post_save, sender=CarFinance)
diff --git a/inventory/utilities/financials.py b/inventory/utilities/financials.py
index 068f8661..ffbb56de 100644
--- a/inventory/utilities/financials.py
+++ b/inventory/utilities/financials.py
@@ -22,17 +22,13 @@ def get_financial_value(name,vat=False):
def get_total_financials(instance,vat=False):
- # price_after_discount = get_financial_value(instance,"selling_price",vat) - get_financial_value(instance,"discount_amount",vat)
- # subtotal = (
- # price_after_discount +
- # get_financial_value("registration_fee") +
- # get_financial_value("administration_fee",vat) +
- # get_financial_value("transportation_fee",vat) +
- # get_financial_value("custom_card_fee",vat))
-
- return 1000
-
+ total = 0
+ if instance.additional_services.count() != 0:
+ total = sum(x.price for x in instance.additional_services) + instance.selling_price
+ if vat:
+ total = (total * settings.VAT_RATE).quantize(Decimal('0.01')) + total
+ return total
+
def get_total(instance):
- total = get_total_financials(instance)
- total_vat = get_total_financials(instance,vat=True)
- return total + total_vat
\ No newline at end of file
+ total = get_total_financials(instance,vat=True)
+ return total
\ No newline at end of file
diff --git a/inventory/views.py b/inventory/views.py
index 349f8ce3..277f440b 100644
--- a/inventory/views.py
+++ b/inventory/views.py
@@ -761,10 +761,8 @@ class QuotationCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateVie
permission_required = ("inventory.add_salequotation",)
def form_valid(self, form):
- dealer = self.request.user.dealer.get_root_dealer
- entity = EntityModel.objects.get(name=dealer.get_root_dealer.name)
- form.instance.dealer = dealer
- form.instance.entity = entity
+ dealer = self.request.user.dealer.get_root_dealer
+ form.instance.dealer = dealer
quotation = form.save()
selected_cars = form.cleaned_data.get("cars")
for car in selected_cars:
@@ -815,12 +813,13 @@ class QuotationDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailVie
@login_required
def generate_invoice(request, pk):
quotation = get_object_or_404(models.SaleQuotation, pk=pk)
+ dealer = request.user.dealer.get_root_dealer
+ entity = dealer.entity
if not quotation.is_approved:
messages.error(
request, "Quotation must be approved before converting to an invoice."
)
else:
- entity = quotation.entity
coa_qs, coa_map = entity.get_all_coa_accounts()
cash_account = coa_qs.first().get_coa_accounts().filter(name="Cash")
recivable_account = coa_qs.first().get_coa_accounts().filter(name="Accounts Receivable")
@@ -961,10 +960,11 @@ def generate_invoice(request, pk):
@login_required
def post_quotation(request, pk):
qoutation = get_object_or_404(models.SaleQuotation, pk=pk)
+ dealer = request.user.dealer.get_root_dealer
+ entity = dealer.entity
if qoutation.posted:
messages.error(request, "Quotation is already posted")
- return redirect("quotation_detail", pk=pk)
- entity = qoutation.entity
+ return redirect("quotation_detail", pk=pk)
coa_qs, coa_map = entity.get_all_coa_accounts()
cash_account = coa_qs.first().get_coa_accounts().filter(name="Cash")
recivable_account = coa_qs.first().get_coa_accounts().filter(name="Accounts Receivable")
@@ -1016,7 +1016,8 @@ def post_quotation(request, pk):
def mark_quotation(request, pk):
qoutation = get_object_or_404(models.SaleQuotation, pk=pk)
status = request.GET.get("status")
- entity = qoutation.entity
+ dealer = request.user.dealer.get_root_dealer
+ entity = dealer.entity
date = datetime.datetime.now()
customer = entity.get_customers().filter(customer_name=qoutation.customer.get_full_name).first()
invoice_model = entity.get_invoices().filter(customer=customer)
@@ -1361,7 +1362,8 @@ def download_quotation_pdf(request, quotation_id):
@login_required
def invoice_detail(request,pk):
quotation = get_object_or_404(models.SaleQuotation, pk=pk)
- entity = quotation.entity
+ dealer = request.user.dealer.get_root_dealer
+ entity = dealer.entity
customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first()
invoice_model = entity.get_invoices()
@@ -1371,7 +1373,8 @@ def invoice_detail(request,pk):
@login_required
def payment_invoice(request,pk):
quotation = get_object_or_404(models.SaleQuotation, pk=pk)
- entity = quotation.entity
+ dealer = request.user.dealer.get_root_dealer
+ entity = dealer.entity
customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first()
invoice_model = entity.get_invoices()
invoice = invoice_model.filter(customer=customer,date_draft=quotation.date_draft).first()
@@ -1406,7 +1409,8 @@ def payment_create(request, pk):
form.instance.quotation = quotation
insatnce = form.save()
- entity = quotation.entity
+ dealer = request.user.dealer.get_root_dealer
+ entity = dealer.entity
customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first()
coa_qs, coa_map = entity.get_all_coa_accounts()
cash_account = coa_qs.first().get_coa_accounts().filter(name="Cash")
diff --git a/templates/base.html b/templates/base.html
index 5f8a86fe..798ae8d2 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -41,6 +41,7 @@
+
{% if LANGUAGE_CODE == 'ar' %}
@@ -724,6 +725,7 @@
+