update
This commit is contained in:
parent
7142975004
commit
a3cb3c5f55
208
Pipfile
Normal file
208
Pipfile
Normal file
@ -0,0 +1,208 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
aiohappyeyeballs = "==2.4.4"
|
||||
aiohttp = "==3.11.11"
|
||||
aiohttp-retry = "==2.8.3"
|
||||
aiosignal = "==1.3.2"
|
||||
alabaster = "==1.0.0"
|
||||
albucore = "==0.0.23"
|
||||
albumentations = "==2.0.0"
|
||||
annotated-types = "==0.7.0"
|
||||
anyio = "==4.8.0"
|
||||
arabic-reshaper = "==3.0.0"
|
||||
asgiref = "==3.8.1"
|
||||
astor = "==0.8.1"
|
||||
astroid = "==3.3.8"
|
||||
attrs = "==23.2.0"
|
||||
autopep8 = "==2.3.2"
|
||||
babel = "==2.15.0"
|
||||
beautifulsoup4 = "==4.12.3"
|
||||
bleach = "==6.2.0"
|
||||
blinker = "==1.9.0"
|
||||
brotli = "==1.1.0"
|
||||
certifi = "==2024.12.14"
|
||||
cffi = "==1.17.1"
|
||||
chardet = "==5.2.0"
|
||||
charset-normalizer = "==3.4.1"
|
||||
click = "==8.1.8"
|
||||
colorama = "==0.4.6"
|
||||
commonmark = "==0.9.1"
|
||||
contourpy = "==1.3.1"
|
||||
crispy-bootstrap5 = "==2024.10"
|
||||
cryptography = "==44.0.0"
|
||||
cssselect2 = "==0.7.0"
|
||||
ctranslate2 = "==4.5.0"
|
||||
cycler = "==0.12.1"
|
||||
cython = "==3.0.11"
|
||||
decorator = "==5.1.1"
|
||||
desert = "==2020.11.18"
|
||||
dill = "==0.3.9"
|
||||
distro = "==1.9.0"
|
||||
dj-rest-auth = "==7.0.1"
|
||||
dj-shop-cart = "==7.1.1"
|
||||
django = "==5.1.5"
|
||||
django-allauth = "==65.3.1"
|
||||
django-appointment = "==3.7.4"
|
||||
django-autoslug = "==1.9.9"
|
||||
django-bootstrap5 = "==24.3"
|
||||
django-classy-tags = "==4.1.0"
|
||||
django-cors-headers = "==4.6.0"
|
||||
django-countries = "==7.6.1"
|
||||
django-crispy-forms = "==2.3"
|
||||
django-debug-toolbar = "==5.0.1"
|
||||
django-extensions = "==3.2.3"
|
||||
django-filter = "==24.3"
|
||||
django-formtools = "==2.5.1"
|
||||
django-ledger = "==0.7.3"
|
||||
django-money = "==3.5.3"
|
||||
django-nine = "==0.2.7"
|
||||
django-nonefield = "==0.4"
|
||||
django-phonenumber-field = "==8.0.0"
|
||||
django-picklefield = "==3.2"
|
||||
django-prometheus = "==2.3.1"
|
||||
django-q2 = "==1.7.6"
|
||||
django-sekizai = "==4.1.0"
|
||||
django-silk = "==5.3.2"
|
||||
django-sms = "==0.7.0"
|
||||
django-sslserver = "==0.22"
|
||||
django-tables2 = "==2.7.5"
|
||||
django-treebeard = "==4.7.1"
|
||||
django-view-breadcrumbs = "==2.5.1"
|
||||
djangocms-admin-style = "==3.3.1"
|
||||
djangorestframework = "==3.15.2"
|
||||
djangorestframework-simplejwt = "==5.4.0"
|
||||
djangoviz = "==0.1.1"
|
||||
docutils = "==0.21.2"
|
||||
easy-thumbnails = "==2.10"
|
||||
et-xmlfile = "==2.0.0"
|
||||
faker = "==33.3.1"
|
||||
filelock = "==3.16.1"
|
||||
fire = "==0.7.0"
|
||||
flask = "==3.1.0"
|
||||
fonttools = "==4.55.3"
|
||||
frozenlist = "==1.5.0"
|
||||
fsspec = "==2024.12.0"
|
||||
gprof2dot = "==2024.6.6"
|
||||
graphqlclient = "==0.2.4"
|
||||
greenlet = "==3.1.1"
|
||||
h11 = "==0.14.0"
|
||||
h2 = "==4.1.0"
|
||||
hpack = "==4.0.0"
|
||||
hstspreload = "==2025.1.1"
|
||||
httpcore = "==1.0.7"
|
||||
httpx = "==0.28.1"
|
||||
hyperframe = "==6.0.1"
|
||||
idna = "==3.10"
|
||||
imageio = "==2.37.0"
|
||||
imagesize = "==1.4.1"
|
||||
imgaug = "==0.4.0"
|
||||
iso4217 = "==1.12.20240625"
|
||||
isodate = "==0.7.2"
|
||||
isort = "==5.13.2"
|
||||
itsdangerous = "==2.2.0"
|
||||
jinja2 = "==3.1.5"
|
||||
jiter = "==0.8.2"
|
||||
joblib = "==1.4.2"
|
||||
kiwisolver = "==1.4.8"
|
||||
lazy-loader = "==0.4"
|
||||
ledger = "==1.0.1"
|
||||
libretranslatepy = "==2.1.4"
|
||||
lmdb = "==1.6.2"
|
||||
lxml = "==5.3.0"
|
||||
markdown = "==3.7"
|
||||
markdown-it-py = "==3.0.0"
|
||||
markupsafe = "==3.0.2"
|
||||
marshmallow = "==3.25.1"
|
||||
matplotlib = "==3.10.0"
|
||||
mccabe = "==0.7.0"
|
||||
mdurl = "==0.1.2"
|
||||
mouseinfo = "==0.1.3"
|
||||
mpmath = "==1.3.0"
|
||||
multidict = "==6.1.0"
|
||||
mypy-extensions = "==1.0.0"
|
||||
networkx = "==3.4.2"
|
||||
newrelic = "==10.4.0"
|
||||
nltk = "==3.9.1"
|
||||
libquadmath = "==2.2.2"
|
||||
oauthlib = "==3.2.2"
|
||||
ofxtools = "==0.9.5"
|
||||
openai = "==1.59.8"
|
||||
opencv-contrib-python = "==4.11.0.86"
|
||||
opencv-python = "==4.11.0.86"
|
||||
opencv-python-headless = "==4.11.0.86"
|
||||
openpyxl = "==3.1.5"
|
||||
opt-einsum = "==3.4.0"
|
||||
outcome = "==1.3.0.post0"
|
||||
packaging = "==24.2"
|
||||
pandas = "==2.2.3"
|
||||
pango = "==0.0.1"
|
||||
pdfkit = "==1.0.0"
|
||||
phonenumbers = "==8.13.53"
|
||||
pillow = "==11.1.0"
|
||||
platformdirs = "==4.3.6"
|
||||
prometheus-client = "==0.21.1"
|
||||
propcache = "==0.2.1"
|
||||
protobuf = "==5.29.3"
|
||||
psycopg = "==3.2.4"
|
||||
psycopg-binary = "==3.2.4"
|
||||
psycopg-c = "==3.2.4"
|
||||
py-moneyed = "==3.0"
|
||||
pyautogui = "==0.9.54"
|
||||
pyclipper = "==1.3.0.post6"
|
||||
pycodestyle = "==2.12.1"
|
||||
pycparser = "==2.22"
|
||||
pydantic = "==2.10.5"
|
||||
pydantic-core = "==2.27.2"
|
||||
pydotplus = "==2.0.2"
|
||||
pydyf = "==0.11.0"
|
||||
pygetwindow = "==0.0.9"
|
||||
pygments = "==2.19.1"
|
||||
pyjwt = "==2.10.1"
|
||||
pylint = "==3.3.3"
|
||||
pymsgbox = "==1.0.9"
|
||||
pymysql = "==1.1.1"
|
||||
pyobjc-core = "==11.0"
|
||||
pyobjc-framework-cocoa = "==11.0"
|
||||
pyobjc-framework-quartz = "==11.0"
|
||||
pyparsing = "==3.2.1"
|
||||
pyperclip = "==1.9.0"
|
||||
pyphen = "==0.17.0"
|
||||
pypng = "==0.20220715.0"
|
||||
pyrect = "==0.2.0"
|
||||
pyscreeze = "==1.0.1"
|
||||
pyserial = "==3.5"
|
||||
pysocks = "==1.7.1"
|
||||
python-bidi = "==0.6.3"
|
||||
python-dateutil = "==2.9.0.post0"
|
||||
python-docx = "==1.1.2"
|
||||
python-openid = "==2.2.5"
|
||||
python3-saml = "==1.16.0"
|
||||
pytweening = "==1.2.0"
|
||||
pytz = "==2024.2"
|
||||
pyvin = "==0.0.2"
|
||||
pywa = "==2.7.0"
|
||||
pywhat = "==5.1.0"
|
||||
pywhatkit = "==5.4"
|
||||
pyyaml = "==6.0.2"
|
||||
pyzbar = "==0.1.9"
|
||||
qrcode = "==8.0"
|
||||
rapidfuzz = "==3.11.0"
|
||||
regex = "==2024.11.6"
|
||||
reportlab = "==4.2.5"
|
||||
requests = "==2.32.3"
|
||||
requests-oauthlib = "==2.0.0"
|
||||
rfc3986 = "==2.0.0"
|
||||
rich = "==13.9.4"
|
||||
rubicon-objc = "==0.5.0"
|
||||
sacremoses = "==0.1.1"
|
||||
scikit-image = "==0.25.0"
|
||||
scikit-learn = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.12"
|
||||
BIN
i.mosa_BalanceSheetStatement_20250101.pdf
Normal file
BIN
i.mosa_BalanceSheetStatement_20250101.pdf
Normal file
Binary file not shown.
@ -9,6 +9,8 @@ from phonenumber_field.phonenumber import PhoneNumber
|
||||
from .mixins import AddClassMixin
|
||||
from django.forms.models import inlineformset_factory
|
||||
from django_ledger.forms.invoice import InvoiceModelCreateForm as InvoiceModelCreateFormBase
|
||||
from django_ledger.forms.estimate import EstimateModelCreateForm as EstimateModelCreateFormBase
|
||||
|
||||
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
|
||||
from django_ledger.forms.vendor import VendorModelForm
|
||||
from .models import (
|
||||
@ -675,7 +677,10 @@ class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
|
||||
self.fields['prepaid_account'].widget = forms.HiddenInput()
|
||||
self.fields['unearned_account'].widget = forms.HiddenInput()
|
||||
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
|
||||
|
||||
|
||||
def get_customer_queryset(self):
|
||||
if 'customer' in self.fields:
|
||||
self.fields['customer'].queryset = self.USER_MODEL.dealer.entity.get_customers()
|
||||
|
||||
class BillModelCreateForm(BillModelCreateFormBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -692,4 +697,15 @@ class SaleOrderForm(forms.ModelForm):
|
||||
fields = ['estimate','payment_method', 'comments']
|
||||
widgets = {
|
||||
'comments': forms.Textarea(attrs={'rows': 3}),
|
||||
}
|
||||
}
|
||||
|
||||
class EstimateModelCreateForm(EstimateModelCreateFormBase):
|
||||
def __init__(self, *args, entity_slug, user_model, **kwargs):
|
||||
super(EstimateModelCreateForm, self).__init__(*args, entity_slug=entity_slug, user_model=user_model, **kwargs)
|
||||
self.ENTITY_SLUG = entity_slug
|
||||
self.USER_MODEL = user_model
|
||||
self.fields['customer'].queryset = self.get_customer_queryset()
|
||||
|
||||
def get_customer_queryset(self):
|
||||
return self.USER_MODEL.dealer.entity.get_customers()
|
||||
|
||||
|
||||
@ -87,13 +87,13 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
||||
use_accrual_method=False,
|
||||
fy_start_month=1,
|
||||
)
|
||||
|
||||
if entity:
|
||||
|
||||
if entity:
|
||||
instance.entity = entity
|
||||
instance.save()
|
||||
coa = entity.create_chart_of_accounts(
|
||||
assign_as_default=True, commit=True, coa_name=_(f"{entity_name}-COA")
|
||||
)
|
||||
)
|
||||
if coa:
|
||||
# Create unit of measures
|
||||
entity.create_uom(name="Unit", unit_abbr="unit")
|
||||
@ -688,9 +688,10 @@ def create_item_model(sender, instance, created, **kwargs):
|
||||
name=instance.vin,
|
||||
item_type=ItemModel.ITEM_TYPE_MATERIAL,
|
||||
uom_model=uom,
|
||||
coa_model=coa,
|
||||
additional_info={}
|
||||
coa_model=coa,
|
||||
)
|
||||
product.additional_info = {}
|
||||
product.save()
|
||||
|
||||
product = entity.get_items_all().filter(name=instance.vin).first()
|
||||
product.additional_info.update({'car_info': instance.to_dict()})
|
||||
@ -702,6 +703,7 @@ def update_item_model_cost(sender, instance, created, **kwargs):
|
||||
entity = instance.car.dealer.entity
|
||||
|
||||
product = entity.get_items_all().filter(name=instance.car.vin).first()
|
||||
|
||||
product.default_amount = instance.selling_price
|
||||
product.additional_info = {}
|
||||
product.additional_info.update({"car_finance":instance.to_dict()})
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
import json
|
||||
import random
|
||||
import datetime
|
||||
@ -577,3 +578,98 @@ def to_dict(obj):
|
||||
else:
|
||||
obj_dict[key] = str(value)
|
||||
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('mileage'), # Verify if this should actually be 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_discount": totals['total_discount'],
|
||||
"grand_total": totals['grand_total'],
|
||||
"additionals": self.additional_services,
|
||||
"vat": self.vat_rate,
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
from rich import print
|
||||
from decimal import Decimal
|
||||
from django.core.paginator import Paginator
|
||||
from django.forms import DateField, DateInput, HiddenInput, TextInput
|
||||
@ -34,7 +35,8 @@ from django_ledger.forms.invoice import (
|
||||
PaidInvoiceModelUpdateForm,
|
||||
)
|
||||
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
|
||||
from django_ledger.forms.estimate import EstimateModelCreateForm
|
||||
# from django_ledger.forms.estimate import EstimateModelCreateForm
|
||||
|
||||
from django_ledger.forms.invoice import InvoiceModelCreateForm
|
||||
from django_ledger.forms.item import (
|
||||
ServiceCreateForm,
|
||||
@ -82,6 +84,7 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.contrib.auth.models import Group
|
||||
from .utils import (
|
||||
CarFinanceCalculator,
|
||||
calculate_vat_amount,
|
||||
get_calculations,
|
||||
get_car_finance_data,
|
||||
@ -2349,7 +2352,7 @@ def create_estimate(request):
|
||||
}
|
||||
)
|
||||
|
||||
form = EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
|
||||
form = forms.EstimateModelCreateForm(entity_slug=entity.slug, user_model=entity.admin)
|
||||
form.fields["customer"].queryset = entity.get_customers().filter(active=True)
|
||||
car_list = models.Car.objects.filter(
|
||||
dealer=dealer, finances__selling_price__gt=0
|
||||
@ -2378,14 +2381,17 @@ class EstimateDetailView(LoginRequiredMixin, DetailView):
|
||||
def get_context_data(self, **kwargs):
|
||||
estimate = kwargs.get("object")
|
||||
if estimate.get_itemtxs_data():
|
||||
data = get_financial_values(estimate)
|
||||
|
||||
kwargs["vat_amount"] = data["vat_amount"]
|
||||
kwargs["total"] = data["grand_total"]
|
||||
kwargs["discount_amount"] = data["discount_amount"]
|
||||
kwargs["vat"] = data["vat"]
|
||||
kwargs["car_and_item_info"] = data["car_and_item_info"]
|
||||
kwargs["additional_services"] = data["additional_services"]
|
||||
# data = get_financial_values(estimate)
|
||||
calculator = CarFinanceCalculator(estimate)
|
||||
finance_data = calculator.get_finance_data()
|
||||
# kwargs["vat_amount"] = data["vat_amount"]
|
||||
# kwargs["total"] = data["grand_total"]
|
||||
# kwargs["discount_amount"] = data["discount_amount"]
|
||||
# kwargs["vat"] = data["vat"]
|
||||
# kwargs["car_and_item_info"] = data["car_and_item_info"]
|
||||
# kwargs["additional_services"] = data["additional_services"]
|
||||
kwargs['data'] = finance_data
|
||||
print(finance_data)
|
||||
kwargs["invoice"] = (
|
||||
InvoiceModel.objects.all().filter(ce_model=estimate).first()
|
||||
)
|
||||
@ -2400,8 +2406,8 @@ def create_sale_order(request, pk):
|
||||
form = forms.SaleOrderForm(request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
if not estimate.is_completed():
|
||||
estimate.mark_as_completed()
|
||||
if not estimate.is_approved():
|
||||
estimate.mark_as_approved()
|
||||
estimate.save()
|
||||
messages.success(request, "Sale Order created successfully")
|
||||
return redirect("estimate_detail", pk=pk)
|
||||
@ -2409,11 +2415,13 @@ def create_sale_order(request, pk):
|
||||
form = forms.SaleOrderForm()
|
||||
form.fields["estimate"].queryset = EstimateModel.objects.filter(pk=pk)
|
||||
form.initial['estimate'] = estimate
|
||||
data = get_car_finance_data(estimate)
|
||||
# data = get_car_finance_data(estimate)
|
||||
calculator = CarFinanceCalculator(estimate)
|
||||
finance_data = calculator.get_finance_data()
|
||||
return render(
|
||||
request,
|
||||
"sales/estimates/sale_order_form.html",
|
||||
{"form": form, "estimate": estimate, "items": items,"data": data},
|
||||
{"form": form, "estimate": estimate, "items": items,"data": finance_data},
|
||||
)
|
||||
|
||||
def preview_sale_order(request,pk):
|
||||
@ -2510,14 +2518,16 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
|
||||
invoice = kwargs.get("object")
|
||||
|
||||
if invoice.get_itemtxs_data():
|
||||
data = get_financial_values(invoice)
|
||||
|
||||
kwargs["vat_amount"] = data["vat_amount"]
|
||||
kwargs["total"] = data["grand_total"]
|
||||
kwargs["discount_amount"] = data["discount_amount"]
|
||||
kwargs["vat"] = data["vat"]
|
||||
kwargs["car_and_item_info"] = data["car_and_item_info"]
|
||||
kwargs["additional_services"] = data["additional_services"]
|
||||
# data = get_financial_values(invoice)
|
||||
calculator = CarFinanceCalculator(invoice)
|
||||
finance_data = calculator.get_finance_data()
|
||||
# kwargs["vat_amount"] = data["vat_amount"]
|
||||
# kwargs["total"] = data["grand_total"]
|
||||
# kwargs["discount_amount"] = data["discount_amount"]
|
||||
# kwargs["vat"] = data["vat"]
|
||||
# kwargs["car_and_item_info"] = data["car_and_item_info"]
|
||||
# kwargs["additional_services"] = data["additional_services"]
|
||||
kwargs["data"] = finance_data
|
||||
kwargs["payments"] = JournalEntryModel.objects.filter(
|
||||
ledger=invoice.ledger
|
||||
).all()
|
||||
|
||||
BIN
ismail_BalanceSheetStatement_20250101.pdf
Normal file
BIN
ismail_BalanceSheetStatement_20250101.pdf
Normal file
Binary file not shown.
101
scripts/run.py
101
scripts/run.py
@ -1,70 +1,45 @@
|
||||
from decimal import Decimal
|
||||
from django_ledger.models import EstimateModel
|
||||
from django_ledger.models import EstimateModel,EntityModel
|
||||
from rich import print
|
||||
|
||||
from datetime import date
|
||||
from inventory.models import VatRate
|
||||
from inventory.utils import CarFinanceCalculator
|
||||
|
||||
|
||||
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()
|
||||
vat = VatRate.objects.filter(is_active=True).first()
|
||||
data = estimate.get_itemtxs_data()[0].all()
|
||||
total = sum(
|
||||
[
|
||||
Decimal(item.item_model.additional_info["car_finance"]["selling_price"])
|
||||
* Decimal(item.ce_quantity or item.quantity)
|
||||
for item in data
|
||||
]
|
||||
)
|
||||
|
||||
additional_services = []
|
||||
|
||||
for i in data:
|
||||
if i.item_model.additional_info["additional_services"]:
|
||||
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)
|
||||
calculator = CarFinanceCalculator(estimate)
|
||||
finance_data = calculator.get_finance_data()
|
||||
|
||||
|
||||
invoice_itemtxs = {
|
||||
i.get("item_number"): {
|
||||
"unit_cost": i.get("total"),
|
||||
"quantity": i.get("quantity"),
|
||||
"total_amount": i.get("total_vat"),
|
||||
}
|
||||
for i in finance_data.get("cars")
|
||||
}
|
||||
|
||||
print(invoice_itemtxs)
|
||||
@ -236,9 +236,13 @@
|
||||
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'bills'|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 'bills'|capfirst %}</span>
|
||||
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'Reports'|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
{% block content %}
|
||||
<div class="card shadow-sm border-0 p-6">
|
||||
<div class="card-body">
|
||||
<div class="text-center mb-5">
|
||||
@ -44,6 +44,7 @@
|
||||
</h2>
|
||||
<p class="h5 fst-italic fw-light">As of {{ to_date | date:'m/d/Y' }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Balance Sheet Statement -->
|
||||
<div class="table-responsive">
|
||||
|
||||
@ -58,14 +58,14 @@
|
||||
<span class="icon is-small">{% icon 'bi:arrow-down' 24 %}</span>
|
||||
</button>
|
||||
</div>
|
||||
{% comment %} <div class="dropdown-menu" id="dropdown-menu-{{ acc.uuid }}" role="menu">
|
||||
<div class="dropdown-menu" id="dropdown-menu-{{ acc.uuid }}" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<a href="{% url 'django_ledger:account-detail' entity_slug=entity_slug coa_slug=acc.coa_slug account_pk=acc.account_uuid %}"
|
||||
class="dropdown-item has-text-success">{% trans 'Detail' %}</a>
|
||||
<a href="{% url 'django_ledger:account-update' entity_slug=entity_slug coa_slug=acc.coa_slug account_pk=acc.account_uuid %}"
|
||||
class="dropdown-item has-text-warning">{% trans 'Update' %}</a>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -45,8 +45,7 @@
|
||||
{% 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>
|
||||
{% 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>
|
||||
{% elif estimate.status == 'completed' %}
|
||||
<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 '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 'preview_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview Sale Order' %}</span></a>
|
||||
{% elif estimate.status == 'in_review' %}
|
||||
@ -128,31 +127,31 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in car_and_item_info %}
|
||||
{% for item in data.cars %}
|
||||
<tr>
|
||||
<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 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>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<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 text-start fw-semibold">
|
||||
<span id="grand-total">- {{discount_amount}}</span>
|
||||
<span id="grand-total">- {{data.total_discount}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<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" %} ({{data.vat}}%)</td>
|
||||
<td class="align-middle text-start fw-semibold">
|
||||
<span id="grand-total">+ {{vat_amount}}</span>
|
||||
<span id="grand-total"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<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 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>
|
||||
{% endfor %}
|
||||
</td>
|
||||
@ -160,7 +159,7 @@
|
||||
<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 text-start fw-bolder">
|
||||
<span id="grand-total">{{total}}</span>
|
||||
<span id="grand-total">{{data.grand_total}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@ -219,23 +219,23 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in car_and_item_info %}
|
||||
{% for item in data.cars %}
|
||||
<tr>
|
||||
<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 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>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<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 text-start fw-semibold">
|
||||
<span id="grand-total">- {{discount_amount}}</span>
|
||||
<span id="grand-total">- {{data.total_discount}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<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" %} ({{data.vat}}%)</td>
|
||||
<td class="align-middle text-start fw-semibold">
|
||||
<span id="grand-total">+ {{vat_amount}}</span>
|
||||
</td>
|
||||
@ -243,7 +243,7 @@
|
||||
<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 text-start fw-bold">
|
||||
{% for service in additional_services %}
|
||||
{% for service in data.additional_services %}
|
||||
<small><span class="fw-bold">+ {{service.name}} - {{service.price}}</span></small><br>
|
||||
{% endfor %}
|
||||
</td>
|
||||
@ -251,7 +251,7 @@
|
||||
<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 text-start fw-bolder">
|
||||
<span id="grand-total">{{total}}</span>
|
||||
<span id="grand-total">{{data.grand_total}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user