update
This commit is contained in:
commit
e3c1810b4a
20
inventory/migrations/0012_saleorder_created.py
Normal file
20
inventory/migrations/0012_saleorder_created.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 4.2.17 on 2025-01-29 12:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0011_alter_saleorder_estimate'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='saleorder',
|
||||||
|
name='created',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
17
inventory/migrations/0013_alter_saleorder_options.py
Normal file
17
inventory/migrations/0013_alter_saleorder_options.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 4.2.17 on 2025-01-29 13:02
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0012_saleorder_created'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='saleorder',
|
||||||
|
options={'ordering': ['created']},
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -1562,6 +1562,10 @@ class SaleOrder(models.Model):
|
|||||||
])
|
])
|
||||||
comments = models.TextField(blank=True, null=True)
|
comments = models.TextField(blank=True, null=True)
|
||||||
formatted_order_id = models.CharField(max_length=10, unique=True, editable=False)
|
formatted_order_id = models.CharField(max_length=10, unique=True, editable=False)
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['-created']
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.formatted_order_id:
|
if not self.formatted_order_id:
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
from django import template
|
from django import template
|
||||||
from calendar import month_abbr
|
from calendar import month_abbr
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django_ledger.io.io_core import get_localdate
|
from django_ledger.io.io_core import get_localdate,validate_activity
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@ -146,3 +146,35 @@ def balance_sheet_statement(context, io_model, to_date=None):
|
|||||||
'user_model': user_model,
|
'user_model': user_model,
|
||||||
'tx_digest': io_digest.get_io_data(),
|
'tx_digest': io_digest.get_io_data(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@register.inclusion_tag('django_ledger/financial_statements/tags/income_statement.html', takes_context=True)
|
||||||
|
def income_statement_table(context, io_model, from_date=None, to_date=None):
|
||||||
|
user_model = context['user']
|
||||||
|
activity = context['request'].GET.get('activity')
|
||||||
|
activity = validate_activity(activity, raise_404=True)
|
||||||
|
entity_slug = context['view'].kwargs.get('entity_slug')
|
||||||
|
|
||||||
|
if not from_date:
|
||||||
|
from_date = context['from_date']
|
||||||
|
if not to_date:
|
||||||
|
to_date = context['to_date']
|
||||||
|
|
||||||
|
io_digest = io_model.digest(
|
||||||
|
activity=activity,
|
||||||
|
user_model=user_model,
|
||||||
|
entity_slug=entity_slug,
|
||||||
|
unit_slug=context['unit_slug'],
|
||||||
|
by_unit=context['by_unit'],
|
||||||
|
from_date=from_date,
|
||||||
|
to_date=to_date,
|
||||||
|
equity_only=True,
|
||||||
|
process_groups=True,
|
||||||
|
income_statement=True,
|
||||||
|
signs=True
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'entity_slug': entity_slug,
|
||||||
|
'user_model': user_model,
|
||||||
|
'tx_digest': io_digest.get_io_data()
|
||||||
|
}
|
||||||
|
|||||||
@ -546,7 +546,23 @@ urlpatterns = [
|
|||||||
path('entity/<slug:entity_slug>/balance-sheet/date/<int:year>/<int:month>/<int:day>/',
|
path('entity/<slug:entity_slug>/balance-sheet/date/<int:year>/<int:month>/<int:day>/',
|
||||||
views.DateBalanceSheetView.as_view(),
|
views.DateBalanceSheetView.as_view(),
|
||||||
name='entity-bs-date'),
|
name='entity-bs-date'),
|
||||||
|
# INCOME STATEMENT Reports ----
|
||||||
|
# Entity .....
|
||||||
|
path('entity/<slug:entity_slug>/income-statement/',
|
||||||
|
views.BaseIncomeStatementRedirectViewBase.as_view(),
|
||||||
|
name='entity-ic'),
|
||||||
|
path('entity/<slug:entity_slug>/income-statement/year/<int:year>/',
|
||||||
|
views.FiscalYearIncomeStatementViewBase.as_view(),
|
||||||
|
name='entity-ic-year'),
|
||||||
|
# path('entity/<slug:entity_slug>/income-statement/quarter/<int:year>/<int:quarter>/',
|
||||||
|
# views.QuarterlyIncomeStatementView.as_view(),
|
||||||
|
# name='entity-ic-quarter'),
|
||||||
|
# path('entity/<slug:entity_slug>/income-statement/month/<int:year>/<int:month>/',
|
||||||
|
# views.MonthlyIncomeStatementView.as_view(),
|
||||||
|
# name='entity-ic-month'),
|
||||||
|
# path('entity/<slug:entity_slug>/income-statement/date/<int:year>/<int:month>/<int:day>/',
|
||||||
|
# views.MonthlyIncomeStatementView.as_view(),
|
||||||
|
# name='entity-ic-date'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import datetime
|
import datetime
|
||||||
@ -283,15 +284,11 @@ def set_invoice_payment(dealer, entity, invoice, amount, payment_method):
|
|||||||
vat_amount = 0
|
vat_amount = 0
|
||||||
total_amount = 0
|
total_amount = 0
|
||||||
|
|
||||||
if invoice.terms == "on_receipt":
|
calculator = CarFinanceCalculator(invoice)
|
||||||
for x in invoice.get_itemtxs_data()[0].all():
|
finance_data = calculator.get_finance_data()
|
||||||
# vat_amount += models.Car.objects.get(
|
# if invoice.terms == "on_receipt":
|
||||||
# vin=x.item_model.name
|
# for x in invoice.get_itemtxs_data()[0].all():
|
||||||
# ).finances.vat_amount * Decimal(x.quantity)
|
# total_amount += Decimal(x.unit_cost) * Decimal(x.quantity)
|
||||||
total_amount += Decimal(x.unit_cost) * Decimal(x.quantity)
|
|
||||||
|
|
||||||
# grand_total = total_amount - Decimal(vat_amount)
|
|
||||||
total_amount
|
|
||||||
|
|
||||||
ledger = LedgerModel.objects.filter(
|
ledger = LedgerModel.objects.filter(
|
||||||
name__icontains=str(invoice.pk), entity=entity
|
name__icontains=str(invoice.pk), entity=entity
|
||||||
@ -322,28 +319,26 @@ def set_invoice_payment(dealer, entity, invoice, amount, payment_method):
|
|||||||
TransactionModel.objects.create(
|
TransactionModel.objects.create(
|
||||||
journal_entry=journal,
|
journal_entry=journal,
|
||||||
account=debit_account, # Debit Cash
|
account=debit_account, # Debit Cash
|
||||||
amount=amount, # Payment amount
|
amount=finance_data["grand_total"], # Payment amount
|
||||||
tx_type="debit",
|
tx_type="debit",
|
||||||
description="Payment Received",
|
description="Payment Received",
|
||||||
)
|
)
|
||||||
|
|
||||||
# if total_amount + invoice.
|
|
||||||
|
|
||||||
TransactionModel.objects.create(
|
TransactionModel.objects.create(
|
||||||
journal_entry=journal,
|
journal_entry=journal,
|
||||||
account=credit_account, # Credit Accounts Receivable
|
account=credit_account, # Credit Accounts Receivable
|
||||||
amount=total_amount, # Payment amount
|
amount=finance_data["total_price"], # Payment amount
|
||||||
tx_type="credit",
|
tx_type="credit",
|
||||||
description="Payment Received",
|
description="Payment Received",
|
||||||
)
|
)
|
||||||
|
|
||||||
if vat_amount > 0:
|
|
||||||
TransactionModel.objects.create(
|
TransactionModel.objects.create(
|
||||||
journal_entry=journal,
|
journal_entry=journal,
|
||||||
account=vat_payable_account, # Credit VAT Payable
|
account=vat_payable_account, # Credit VAT Payable
|
||||||
amount=vat_amount,
|
amount=finance_data["total_vat_amount"],
|
||||||
tx_type="credit",
|
tx_type="credit",
|
||||||
description="VAT Payable on Invoice",
|
description="VAT Payable on Invoice",
|
||||||
)
|
)
|
||||||
|
|
||||||
invoice.make_payment(amount)
|
invoice.make_payment(amount)
|
||||||
@ -578,5 +573,99 @@ def to_dict(obj):
|
|||||||
obj_dict[key] = str(value)
|
obj_dict[key] = str(value)
|
||||||
return obj_dict
|
return obj_dict
|
||||||
|
|
||||||
|
class CarFinanceCalculator:
|
||||||
|
VAT_OBJ_NAME = 'vat_rate'
|
||||||
|
CAR_FINANCE_KEY = 'car_finance'
|
||||||
|
CAR_INFO_KEY = 'car_info'
|
||||||
|
ADDITIONAL_SERVICES_KEY = 'additional_services'
|
||||||
|
|
||||||
|
def __init__(self, model):
|
||||||
|
self.model = model
|
||||||
|
self.vat_rate = self._get_vat_rate()
|
||||||
|
self.item_transactions = self._get_item_transactions()
|
||||||
|
self.additional_services = self._get_additional_services()
|
||||||
|
|
||||||
|
def _get_vat_rate(self):
|
||||||
|
vat = models.VatRate.objects.filter(is_active=True).first()
|
||||||
|
if not vat:
|
||||||
|
raise ObjectDoesNotExist("No active VAT rate found")
|
||||||
|
return vat.rate
|
||||||
|
|
||||||
|
def _get_item_transactions(self):
|
||||||
|
return self.model.get_itemtxs_data()[0].all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_quantity(item):
|
||||||
|
return item.ce_quantity or item.quantity
|
||||||
|
|
||||||
|
def _get_nested_value(self, item, *keys):
|
||||||
|
current = item.item_model.additional_info
|
||||||
|
for key in keys:
|
||||||
|
current = current.get(key, {})
|
||||||
|
return current
|
||||||
|
|
||||||
|
def _get_car_data(self, item):
|
||||||
|
quantity = self._get_quantity(item)
|
||||||
|
car_finance = self._get_nested_value(item, self.CAR_FINANCE_KEY)
|
||||||
|
car_info = self._get_nested_value(item, self.CAR_INFO_KEY)
|
||||||
|
unit_price = Decimal(car_finance.get('selling_price', 0))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"item_number": item.item_model.item_number,
|
||||||
|
"vin": car_info.get('vin'),
|
||||||
|
"make": car_info.get('make'),
|
||||||
|
"model": car_info.get('model'),
|
||||||
|
"year": car_info.get('year'),
|
||||||
|
"trim": car_info.get('trim'),
|
||||||
|
"mileage": car_info.get('mileage'),
|
||||||
|
"cost_price": car_finance.get('cost_price'),
|
||||||
|
"selling_price": car_finance.get('selling_price'),
|
||||||
|
"discount": car_finance.get('discount_amount'),
|
||||||
|
"quantity": quantity,
|
||||||
|
"unit_price": unit_price,
|
||||||
|
"total": unit_price * Decimal(quantity),
|
||||||
|
"total_vat": car_finance.get('total_vat'),
|
||||||
|
"additional_services": self._get_nested_value(item, self.ADDITIONAL_SERVICES_KEY),
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_additional_services(self):
|
||||||
|
return [
|
||||||
|
{"name": service.name, "price": service.price}
|
||||||
|
for item in self.item_transactions
|
||||||
|
for service in self._get_nested_value(item, self.ADDITIONAL_SERVICES_KEY) or []
|
||||||
|
]
|
||||||
|
|
||||||
|
def calculate_totals(self):
|
||||||
|
total_price = sum(
|
||||||
|
Decimal(self._get_nested_value(item, self.CAR_FINANCE_KEY, 'selling_price')) *
|
||||||
|
Decimal(self._get_quantity(item))
|
||||||
|
for item in self.item_transactions
|
||||||
|
)
|
||||||
|
|
||||||
|
total_vat_amount = total_price * self.vat_rate
|
||||||
|
total_discount = sum(
|
||||||
|
Decimal(self._get_nested_value(item, self.CAR_FINANCE_KEY, 'discount_amount'))
|
||||||
|
for item in self.item_transactions
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"total_price": total_price,
|
||||||
|
"total_vat_amount": total_vat_amount,
|
||||||
|
"total_discount": total_discount,
|
||||||
|
"grand_total": (total_price + total_vat_amount) - total_discount ,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_finance_data(self):
|
||||||
|
totals = self.calculate_totals()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"cars": [self._get_car_data(item) for item in self.item_transactions],
|
||||||
|
"quantity": sum(self._get_quantity(item) for item in self.item_transactions),
|
||||||
|
"total_price": totals['total_price'],
|
||||||
|
"total_vat": totals['total_vat_amount'] + totals['total_price'],
|
||||||
|
"total_vat_amount": totals['total_vat_amount'],
|
||||||
|
"total_discount": totals['total_discount'],
|
||||||
|
"grand_total": totals['grand_total'],
|
||||||
|
"additionals": self.additional_services,
|
||||||
|
"vat": self.vat_rate,
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -184,6 +184,9 @@ python3-saml
|
|||||||
pytweening
|
pytweening
|
||||||
pytz
|
pytz
|
||||||
pyvin
|
pyvin
|
||||||
|
pywa
|
||||||
|
pywhat
|
||||||
|
pywhatkit
|
||||||
PyYAML
|
PyYAML
|
||||||
pyzbar
|
pyzbar
|
||||||
qrcode
|
qrcode
|
||||||
|
|||||||
101
scripts/run.py
101
scripts/run.py
@ -1,70 +1,45 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from django_ledger.models import EstimateModel
|
from django_ledger.models import EstimateModel,EntityModel
|
||||||
from rich import print
|
from rich import print
|
||||||
|
from datetime import date
|
||||||
from inventory.models import VatRate
|
from inventory.models import VatRate
|
||||||
|
from inventory.utils import CarFinanceCalculator
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
|
# estimate = EstimateModel.objects.first()
|
||||||
|
# calculator = CarFinanceCalculator(estimate)
|
||||||
|
# finance_data = calculator.get_finance_data()
|
||||||
|
|
||||||
|
# print(finance_data)
|
||||||
|
# entity = EntityModel.objects.get(name="ismail")
|
||||||
|
# bs_report = entity.get_balance_sheet_statement(
|
||||||
|
# to_date=date(2025, 1, 1),
|
||||||
|
# save_pdf=False,
|
||||||
|
# filepath='./'
|
||||||
|
# )
|
||||||
|
|
||||||
|
# ic_report = entity.get_income_statement(
|
||||||
|
# from_date=date(2022, 1, 1),
|
||||||
|
# to_date=date(2022, 12, 31),
|
||||||
|
# save_pdf=False,
|
||||||
|
# filepath='./'
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # print(bs_report)
|
||||||
|
# print(ic_report.get_report_data())
|
||||||
estimate = EstimateModel.objects.first()
|
estimate = EstimateModel.objects.first()
|
||||||
vat = VatRate.objects.filter(is_active=True).first()
|
calculator = CarFinanceCalculator(estimate)
|
||||||
data = estimate.get_itemtxs_data()[0].all()
|
finance_data = calculator.get_finance_data()
|
||||||
total = sum(
|
|
||||||
[
|
|
||||||
Decimal(item.item_model.additional_info["car_finance"]["selling_price"])
|
invoice_itemtxs = {
|
||||||
* Decimal(item.ce_quantity or item.quantity)
|
i.get("item_number"): {
|
||||||
for item in data
|
"unit_cost": i.get("total_price"),
|
||||||
]
|
"quantity": i.get("quantity"),
|
||||||
)
|
"total_amount": i.get("total_vat"),
|
||||||
|
}
|
||||||
additional_services = []
|
for i in finance_data.get("cars")
|
||||||
|
}
|
||||||
for i in data:
|
|
||||||
if i.item_model.additional_info["additional_services"]:
|
print(finance_data)
|
||||||
additional_services.extend(
|
|
||||||
[
|
|
||||||
{"name": x.name, "price": x.price}
|
|
||||||
for x in i.item_model.additional_info["additional_services"]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
cars_info = {
|
|
||||||
"cars": [
|
|
||||||
{
|
|
||||||
"vin": x.item_model.additional_info["car_info"]["vin"],
|
|
||||||
"make": x.item_model.additional_info["car_info"]["make"],
|
|
||||||
"model": x.item_model.additional_info["car_info"]["model"],
|
|
||||||
"year": x.item_model.additional_info["car_info"]["year"],
|
|
||||||
"trim": x.item_model.additional_info["car_info"]["mileage"],
|
|
||||||
"cost_price": x.item_model.additional_info["car_finance"]["cost_price"],
|
|
||||||
"selling_price": x.item_model.additional_info["car_finance"][
|
|
||||||
"selling_price"
|
|
||||||
],
|
|
||||||
"discount": x.item_model.additional_info["car_finance"][
|
|
||||||
"discount_amount"
|
|
||||||
],
|
|
||||||
"total": x.item_model.additional_info["car_finance"]["total"],
|
|
||||||
"additional_services": x.item_model.additional_info[
|
|
||||||
"additional_services"
|
|
||||||
],
|
|
||||||
}
|
|
||||||
for x in data
|
|
||||||
],
|
|
||||||
"quantity": data.count(),
|
|
||||||
"total_price": total,
|
|
||||||
"total__vat": (total * vat.rate) + total,
|
|
||||||
"total_discount": sum(
|
|
||||||
Decimal(x.item_model.additional_info["car_finance"]["discount_amount"])
|
|
||||||
for x in data
|
|
||||||
),
|
|
||||||
"grand_total": Decimal(total * vat.rate)
|
|
||||||
+ total
|
|
||||||
- Decimal(
|
|
||||||
sum(
|
|
||||||
Decimal(x.item_model.additional_info["car_finance"]["discount_amount"])
|
|
||||||
for x in data
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"additionals": additional_services,
|
|
||||||
}
|
|
||||||
|
|
||||||
print(cars_info)
|
|
||||||
@ -235,14 +235,39 @@
|
|||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'bills'|capfirst %}</span>
|
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'bills'|capfirst %}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{% if request.user.dealer.entity.slug %}
|
</li>
|
||||||
<a class="nav-link" href="{% url 'entity-bs' request.user.dealer.entity.slug %}">
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="nav-item-wrapper">
|
||||||
|
<a class="nav-link dropdown-indicator label-1" href="#nv-reports" role="button" data-bs-toggle="collapse" aria-expanded="false" aria-controls="nv-reports">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="dropdown-indicator-icon-wrapper"><span class="fas fa-caret-right dropdown-indicator-icon"></span></div>
|
||||||
|
<span class="nav-link-icon"><span class="fas fa-money-check-alt"></span></span><span class="nav-link-text">{% trans 'Reports' %}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="parent-wrapper label-1">
|
||||||
|
<ul class="nav collapse parent" data-bs-parent="#navbarVerticalCollapse" id="nv-reports">
|
||||||
|
<li class="nav-item">
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<a class="nav-link" href="{% url 'entity-ic' request.user.dealer.entity.slug %}">
|
||||||
|
{% else %}
|
||||||
|
<a class="nav-link" href="#">
|
||||||
|
{% endif %}
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span class="nav-link-icon"><span class="fas fa-newspaper"></span></span><span class="nav-link-text">{% trans 'Balance Sheet' %}</span>
|
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'Income Statement'|capfirst %}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<a class="nav-link" href="{% url 'entity-bs' request.user.dealer.entity.slug %}">
|
||||||
|
{% else %}
|
||||||
|
<a class="nav-link" href="#">
|
||||||
|
{% endif %}
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'Balance Sheet'|capfirst %}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,63 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
{% load custom_filters %}
|
||||||
|
|
||||||
|
{% block period_navigation %}
|
||||||
|
{% if unit_model %}
|
||||||
|
<div class="column is-12">{% period_navigation 'unit-ic' %}</div>
|
||||||
|
{% elif entity %}
|
||||||
|
<div class="column is-12">{% period_navigation 'entity-ic' %}</div>
|
||||||
|
{% elif ledger %}
|
||||||
|
<div class="column is-12">{% period_navigation 'ledger-ic' %}</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content has-text-centered">
|
||||||
|
<div class="container mb-4">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
{% if entity %}
|
||||||
|
<h1 class="is-size-2 has-text-weight-light">{{ entity.name }}</h1>
|
||||||
|
{% elif ledger %}
|
||||||
|
<h1 class="is-size-2 has-text-weight-light">{{ ledger.name }}</h1>
|
||||||
|
{% endif %}
|
||||||
|
{% if unit_model %}
|
||||||
|
<h3 class="is-size-4 has-text-weight-medium is-italic">{{ unit_model.name }} {% trans 'Unit' %}</h3>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h1 class="is-size-2 has-text-weight-bold">{% trans 'Income Statement' %}</h1>
|
||||||
|
<h2 class="is-size-2 has-text-weight-light">
|
||||||
|
{% if quarter %}{{ year }} | Q{{ quarter }}
|
||||||
|
{% elif month %}{{ start_date | date:'F, Y' }}
|
||||||
|
{% else %}Fiscal Year {{ year }}
|
||||||
|
{% endif %}</h2>
|
||||||
|
<h3 class="is-size-4 is-italic has-font-weight-light">
|
||||||
|
{{ from_date | date:'m/d/Y' }} - {{ to_date | date:'m/d/Y' }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% income_statement_table io_model=object %}
|
||||||
|
|
||||||
|
{% if ledger %}
|
||||||
|
<a class="button is-fullwidth is-dark my-2"
|
||||||
|
href="{% url 'django_ledger:ledger-list' entity_slug=view.kwargs.entity_slug %}">Go
|
||||||
|
Back</a>
|
||||||
|
{% elif entity %}
|
||||||
|
<a class="button is-fullwidth is-dark my-2"
|
||||||
|
href="{% url 'django_ledger:entity-dashboard' entity_slug=view.kwargs.entity_slug %}">Go
|
||||||
|
Back</a>
|
||||||
|
{% endif %}
|
||||||
|
<a class="button is-fullwidth is-light my-2"
|
||||||
|
href="?by_unit=1">{% trans 'By Unit' %}</a>
|
||||||
|
|
||||||
|
<a class="button is-fullwidth is-link my-2"
|
||||||
|
href="{{ request.path }}?format=pdf">{% trans 'Download PDF' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -45,10 +45,12 @@
|
|||||||
{% elif estimate.status == 'in_review' %}
|
{% elif estimate.status == 'in_review' %}
|
||||||
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block">{% trans 'Mark As Accept' %}</span></button>
|
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block">{% trans 'Mark As Accept' %}</span></button>
|
||||||
{% elif estimate.status == 'approved' %}
|
{% elif estimate.status == 'approved' %}
|
||||||
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Sale Order' %}</span></a>
|
{% if estimate.sale_orders.first %}
|
||||||
{% elif estimate.status == 'completed' %}
|
|
||||||
<a href="{% url 'invoice_create' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Invoice' %}</span></a>
|
<a href="{% url 'invoice_create' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Invoice' %}</span></a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Create Sale Order' %}</span></a>
|
||||||
<a href="{% url 'preview_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview Sale Order' %}</span></a>
|
<a href="{% url 'preview_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview Sale Order' %}</span></a>
|
||||||
|
{% endif %}
|
||||||
{% elif estimate.status == 'in_review' %}
|
{% elif estimate.status == 'in_review' %}
|
||||||
<a href="{% url 'estimate_preview' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview' %}</span></a>
|
<a href="{% url 'estimate_preview' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview' %}</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -128,31 +130,31 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in car_and_item_info %}
|
{% for item in data.cars %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="">{{forloop.counter}}</td>
|
<td class="">{{forloop.counter}}</td>
|
||||||
<td class="">{{item.info.make}}</td>
|
<td class="">{{item.make}}</td>
|
||||||
<td class="align-middle">{{item.quantity}}</td>
|
<td class="align-middle">{{item.quantity}}</td>
|
||||||
<td class="align-middle ps-5">{{item.finances.selling_price}}</td>
|
<td class="align-middle ps-5">{{item.unit_price}}</td>
|
||||||
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
|
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
|
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Vat" %} ({{data.vat}}%)</td>
|
||||||
<td class="align-middle text-start fw-semibold">
|
<td class="align-middle text-start fw-semibold">
|
||||||
<span id="grand-total">- {{discount_amount}}</span>
|
<span id="grand-total">+ {{data.total_vat_amount}}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Vat" %} ({{vat}}%)</td>
|
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
|
||||||
<td class="align-middle text-start fw-semibold">
|
<td class="align-middle text-start text-danger fw-semibold ">
|
||||||
<span id="grand-total">+ {{vat_amount}}</span>
|
<span id="grand-total">- {{data.total_discount}}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Additional Services" %}</td>
|
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Additional Services" %}</td>
|
||||||
<td class="align-middle text-start fw-semibold">
|
<td class="align-middle text-start fw-semibold">
|
||||||
{% for service in additional_services %}
|
{% for service in data.additional_services %}
|
||||||
<small><span class="fw-semibold">+ {{service.name}} - {{service.price}}</span></small><br>
|
<small><span class="fw-semibold">+ {{service.name}} - {{service.price}}</span></small><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
@ -160,7 +162,7 @@
|
|||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-bolder text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
|
<td class="align-middle ps-4 fw-bolder text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
|
||||||
<td class="align-middle text-start fw-bolder">
|
<td class="align-middle text-start fw-bolder">
|
||||||
<span id="grand-total">{{total}}</span>
|
<span id="grand-total">{{data.grand_total}}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -84,6 +84,20 @@
|
|||||||
<p class="ps-6 ps-sm-0 fw-semibold mb-0">{{ estimate.customer.address_1 }}</p>
|
<p class="ps-6 ps-sm-0 fw-semibold mb-0">{{ estimate.customer.address_1 }}</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="py-2">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="d-flex bg-info-subtle rounded-circle flex-center me-3" style="width:24px; height:24px">
|
||||||
|
<span class="text-info-dark" data-feather="trending-up" style="width:16px; height:16px"></span>
|
||||||
|
</div>
|
||||||
|
<p class="fw-bold mb-0">Total Discount</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="py-2 d-none d-sm-block pe-sm-2">:</td>
|
||||||
|
<td class="py-2">
|
||||||
|
<p class="ps-6 ps-sm-0 fw-semibold mb-0">${{ data.total_discount }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="py-2">
|
<td class="py-2">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
@ -98,6 +112,7 @@
|
|||||||
<p class="ps-6 ps-sm-0 fw-semibold mb-0">${{ data.grand_total }}</p>
|
<p class="ps-6 ps-sm-0 fw-semibold mb-0">${{ data.grand_total }}</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -143,7 +158,7 @@
|
|||||||
<td class="create_by align-middle white-space-nowrap fw-semibold text-body-highlight">{{car.year}}</td>
|
<td class="create_by align-middle white-space-nowrap fw-semibold text-body-highlight">{{car.year}}</td>
|
||||||
<td class="last_activity align-middle text-center py-2">
|
<td class="last_activity align-middle text-center py-2">
|
||||||
<div class="d-flex align-items-center flex-1">
|
<div class="d-flex align-items-center flex-1">
|
||||||
<span class="fw-bold fs-9 text-body">${{car.total_vat}}</span>
|
<span class="fw-bold fs-9 text-body">${{car.total}}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -237,7 +237,7 @@
|
|||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "VAT" %} ({{vat}}%)</td>
|
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "VAT" %} ({{vat}}%)</td>
|
||||||
<td class="align-middle text-start fw-semibold">
|
<td class="align-middle text-start fw-semibold">
|
||||||
<span id="grand-total">+ {{vat_amount}}</span>
|
<span id="grand-total">+ {{data.total_vat_amount}}</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
|
|||||||
@ -208,11 +208,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in car_and_item_info %}
|
{% for item in data.cars %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="">{{item.info.make}}</td>
|
<td class="">{{item.make}}</td>
|
||||||
<td class="align-middle">{{item.quantity}}</td>
|
<td class="align-middle">{{item.quantity}}</td>
|
||||||
<td class="align-middle ps-5">{{item.finances.selling_price}}</td>
|
<td class="align-middle ps-5">{{item.selling_price}}</td>
|
||||||
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
|
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -222,10 +222,10 @@
|
|||||||
|
|
||||||
<!-- Additional Charges (VAT and Services) -->
|
<!-- Additional Charges (VAT and Services) -->
|
||||||
<div class="additional-charges">
|
<div class="additional-charges">
|
||||||
<p><strong>VAT/ضريبة القيمة المضافة ({{vat}}%):</strong> <span class="highlight">{{vat_amount}} {{ _("SAR") }}</span></p>
|
<p><strong>VAT/ضريبة القيمة المضافة ({{vat}}%):</strong> <span class="highlight">{{data.vat}} {{ _("SAR") }}</span></p>
|
||||||
<p><strong>Additional Services/ الخدمات الإضافية</strong>
|
<p><strong>Additional Services/ الخدمات الإضافية</strong>
|
||||||
<br>
|
<br>
|
||||||
{% for service in additional_services %}
|
{% for service in data.additional_services %}
|
||||||
<span class="highlight">{{service.name}} - {{service.price}} {{ _("SAR") }}</span><br>
|
<span class="highlight">{{service.name}} - {{service.price}} {{ _("SAR") }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
@ -233,7 +233,7 @@
|
|||||||
|
|
||||||
<!-- Total -->
|
<!-- Total -->
|
||||||
<div class="invoice-total">
|
<div class="invoice-total">
|
||||||
<p><strong>Total/الإجمالي</strong> <span class="highlight">{{total}} {{ _("SAR") }}</span></p>
|
<p><strong>Total/الإجمالي</strong> <span class="highlight">{{data.grand_total}} {{ _("SAR") }}</span></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Footer Note -->
|
<!-- Footer Note -->
|
||||||
|
|||||||
@ -21,8 +21,11 @@
|
|||||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||||
<td class="align-middle product white-space-nowrap py-0">{{ order.formatted_order_id }}</td>
|
<td class="align-middle product white-space-nowrap py-0">{{ order.formatted_order_id }}</td>
|
||||||
<td class="align-middle product white-space-nowrap py-0">{{ order.estimate.customer.customer_name }}</td>
|
<td class="align-middle product white-space-nowrap py-0">{{ order.estimate.customer.customer_name }}</td>
|
||||||
<td class="align-middle product white-space-nowrap">{{ order.estimate }}</td>
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
<a href="{% url 'estimate_detail' order.estimate.pk %}">
|
||||||
|
{{ order.estimate }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
{% comment %} <a href="{% url 'estimate_detail' estimate.pk %}"
|
{% comment %} <a href="{% url 'estimate_detail' estimate.pk %}"
|
||||||
class="btn btn-sm btn-phoenix-success">
|
class="btn btn-sm btn-phoenix-success">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user