latest update
This commit is contained in:
parent
5ef0d68f7c
commit
ecf1c375c1
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)
|
||||
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):
|
||||
if not self.formatted_order_id:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from django import template
|
||||
from calendar import month_abbr
|
||||
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()
|
||||
|
||||
@ -146,3 +146,35 @@ def balance_sheet_statement(context, io_model, to_date=None):
|
||||
'user_model': user_model,
|
||||
'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>/',
|
||||
views.DateBalanceSheetView.as_view(),
|
||||
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'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -284,15 +284,11 @@ def set_invoice_payment(dealer, entity, invoice, amount, payment_method):
|
||||
vat_amount = 0
|
||||
total_amount = 0
|
||||
|
||||
if invoice.terms == "on_receipt":
|
||||
for x in invoice.get_itemtxs_data()[0].all():
|
||||
# vat_amount += models.Car.objects.get(
|
||||
# vin=x.item_model.name
|
||||
# ).finances.vat_amount * Decimal(x.quantity)
|
||||
total_amount += Decimal(x.unit_cost) * Decimal(x.quantity)
|
||||
|
||||
# grand_total = total_amount - Decimal(vat_amount)
|
||||
total_amount
|
||||
calculator = CarFinanceCalculator(invoice)
|
||||
finance_data = calculator.get_finance_data()
|
||||
# if invoice.terms == "on_receipt":
|
||||
# for x in invoice.get_itemtxs_data()[0].all():
|
||||
# total_amount += Decimal(x.unit_cost) * Decimal(x.quantity)
|
||||
|
||||
ledger = LedgerModel.objects.filter(
|
||||
name__icontains=str(invoice.pk), entity=entity
|
||||
@ -323,28 +319,26 @@ def set_invoice_payment(dealer, entity, invoice, amount, payment_method):
|
||||
TransactionModel.objects.create(
|
||||
journal_entry=journal,
|
||||
account=debit_account, # Debit Cash
|
||||
amount=amount, # Payment amount
|
||||
amount=finance_data["grand_total"], # Payment amount
|
||||
tx_type="debit",
|
||||
description="Payment Received",
|
||||
)
|
||||
|
||||
# if total_amount + invoice.
|
||||
|
||||
TransactionModel.objects.create(
|
||||
journal_entry=journal,
|
||||
account=credit_account, # Credit Accounts Receivable
|
||||
amount=total_amount, # Payment amount
|
||||
amount=finance_data["total_price"], # Payment amount
|
||||
tx_type="credit",
|
||||
description="Payment Received",
|
||||
)
|
||||
|
||||
if vat_amount > 0:
|
||||
TransactionModel.objects.create(
|
||||
journal_entry=journal,
|
||||
account=vat_payable_account, # Credit VAT Payable
|
||||
amount=vat_amount,
|
||||
tx_type="credit",
|
||||
description="VAT Payable on Invoice",
|
||||
|
||||
TransactionModel.objects.create(
|
||||
journal_entry=journal,
|
||||
account=vat_payable_account, # Credit VAT Payable
|
||||
amount=finance_data["total_vat_amount"],
|
||||
tx_type="credit",
|
||||
description="VAT Payable on Invoice",
|
||||
)
|
||||
|
||||
invoice.make_payment(amount)
|
||||
@ -622,7 +616,8 @@ class CarFinanceCalculator:
|
||||
"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
|
||||
"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'),
|
||||
@ -657,7 +652,7 @@ class CarFinanceCalculator:
|
||||
"total_price": total_price,
|
||||
"total_vat_amount": total_vat_amount,
|
||||
"total_discount": total_discount,
|
||||
"grand_total": (total_price + total_vat_amount) - total_discount,
|
||||
"grand_total": (total_price + total_vat_amount) - total_discount ,
|
||||
}
|
||||
|
||||
def get_finance_data(self):
|
||||
@ -668,6 +663,7 @@ class CarFinanceCalculator:
|
||||
"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,
|
||||
|
||||
@ -2380,16 +2380,9 @@ class EstimateDetailView(LoginRequiredMixin, DetailView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
estimate = kwargs.get("object")
|
||||
if estimate.get_itemtxs_data():
|
||||
# data = get_financial_values(estimate)
|
||||
if estimate.get_itemtxs_data():
|
||||
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"]
|
||||
finance_data = calculator.get_finance_data()
|
||||
kwargs['data'] = finance_data
|
||||
print(finance_data)
|
||||
kwargs["invoice"] = (
|
||||
@ -2517,16 +2510,10 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
|
||||
def get_context_data(self, **kwargs):
|
||||
invoice = kwargs.get("object")
|
||||
|
||||
if invoice.get_itemtxs_data():
|
||||
# data = get_financial_values(invoice)
|
||||
if invoice.get_itemtxs_data():
|
||||
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"]
|
||||
print((finance_data["total_vat_amount"]+finance_data["total_price"]) == finance_data["grand_total"])
|
||||
kwargs["data"] = finance_data
|
||||
kwargs["payments"] = JournalEntryModel.objects.filter(
|
||||
ledger=invoice.ledger
|
||||
@ -2627,38 +2614,41 @@ def invoice_create(request, pk):
|
||||
ledger.save()
|
||||
invoice.save()
|
||||
|
||||
unit_items = estimate.get_itemtxs_data()[0]
|
||||
vat = models.VatRate.objects.filter(is_active=True).first()
|
||||
total = 0
|
||||
discount_amount = 0
|
||||
# unit_items = estimate.get_itemtxs_data()[0]
|
||||
# vat = models.VatRate.objects.filter(is_active=True).first()
|
||||
calculator = CarFinanceCalculator(estimate)
|
||||
finance_data = calculator.get_finance_data()
|
||||
|
||||
# total = 0
|
||||
# discount_amount = 0
|
||||
|
||||
itemtxs = []
|
||||
for item in unit_items:
|
||||
car = models.Car.objects.get(vin=item.item_model.name)
|
||||
# itemtxs = []
|
||||
# for item in unit_items:
|
||||
# car = models.Car.objects.get(vin=item.item_model.name)
|
||||
|
||||
total = Decimal(car.finances.total) * Decimal(item.ce_quantity)
|
||||
discount_amount = car.finances.discount_amount
|
||||
# total = Decimal(car.finances.total) * Decimal(item.ce_quantity)
|
||||
# discount_amount = car.finances.discount_amount
|
||||
|
||||
grand_total = Decimal(total) - Decimal(discount_amount)
|
||||
vat_amount = round(Decimal(grand_total) * Decimal(vat.rate), 2)
|
||||
grand_total += Decimal(vat_amount)
|
||||
unit_cost = grand_total / Decimal(item.ce_quantity)
|
||||
itemtxs.append(
|
||||
{
|
||||
"item_number": item.item_model.item_number,
|
||||
"unit_cost": unit_cost,
|
||||
"unit_revenue": unit_cost,
|
||||
"quantity": item.ce_quantity,
|
||||
"total_amount": grand_total,
|
||||
}
|
||||
)
|
||||
# grand_total = Decimal(total) - Decimal(discount_amount)
|
||||
# vat_amount = round(Decimal(grand_total) * Decimal(vat.rate), 2)
|
||||
# grand_total += Decimal(vat_amount)
|
||||
# unit_cost = grand_total / Decimal(item.ce_quantity)
|
||||
# itemtxs.append(
|
||||
# {
|
||||
# "item_number": item.item_model.item_number,
|
||||
# "unit_cost": unit_cost,
|
||||
# "unit_revenue": unit_cost,
|
||||
# "quantity": item.ce_quantity,
|
||||
# "total_amount": grand_total,
|
||||
# }
|
||||
# )
|
||||
invoice_itemtxs = {
|
||||
i.get("item_number"): {
|
||||
"unit_cost": i.get("unit_cost"),
|
||||
"unit_cost": i.get("total_vat"),
|
||||
"quantity": i.get("quantity"),
|
||||
"total_amount": i.get("total_amount"),
|
||||
"total_amount": i.get("total_vat"),
|
||||
}
|
||||
for i in itemtxs
|
||||
for i in finance_data.get("cars")
|
||||
}
|
||||
|
||||
invoice_itemtxs = invoice.migrate_itemtxs(
|
||||
@ -2705,14 +2695,16 @@ class InvoicePreviewView(LoginRequiredMixin, DetailView):
|
||||
def get_context_data(self, **kwargs):
|
||||
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["data"] = 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"]
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
@ -3433,7 +3425,8 @@ class SubscriptionPlans(ListView):
|
||||
class OrderListView(ListView):
|
||||
model = models.SaleOrder
|
||||
template_name = "sales/orders/order_list.html"
|
||||
context_object_name = "orders"
|
||||
context_object_name = "orders"
|
||||
|
||||
|
||||
# email
|
||||
def send_email_view(request, pk):
|
||||
@ -3509,7 +3502,7 @@ def custom_bad_request_view(request, exception=None):
|
||||
# from django_ledger.io.io_core import get_localdate
|
||||
# from django_ledger.views.mixins import (DjangoLedgerSecurityMixIn)
|
||||
# from django.views.generic import RedirectView
|
||||
from django_ledger.views.financial_statement import FiscalYearBalanceSheetView
|
||||
from django_ledger.views.financial_statement import FiscalYearBalanceSheetView,BaseIncomeStatementRedirectView,FiscalYearIncomeStatementView
|
||||
from django.views.generic import DetailView, RedirectView
|
||||
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
@ -3548,3 +3541,34 @@ class DateBalanceSheetView(FiscalYearBalanceSheetViewBase, DateReportMixIn):
|
||||
"""
|
||||
Date Balance Sheet View.
|
||||
"""
|
||||
|
||||
class BaseIncomeStatementRedirectViewBase(BaseIncomeStatementRedirectView):
|
||||
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
year = get_localdate().year
|
||||
dealer = get_user_type(self.request)
|
||||
return reverse('entity-ic-year',
|
||||
kwargs={
|
||||
'entity_slug': dealer.entity.slug,
|
||||
'year': year
|
||||
})
|
||||
|
||||
class FiscalYearIncomeStatementViewBase(FiscalYearIncomeStatementView):
|
||||
template_name = "ledger/reports/income_statement.html"
|
||||
|
||||
class QuarterlyIncomeStatementView(FiscalYearIncomeStatementView, QuarterlyReportMixIn):
|
||||
"""
|
||||
Quarter Income Statement View.
|
||||
"""
|
||||
|
||||
|
||||
class MonthlyIncomeStatementView(FiscalYearIncomeStatementView, MonthlyReportMixIn):
|
||||
"""
|
||||
Monthly Income Statement View.
|
||||
"""
|
||||
|
||||
|
||||
class DateModelIncomeStatementView(FiscalYearIncomeStatementView, DateReportMixIn):
|
||||
"""
|
||||
Date Income Statement View.
|
||||
"""
|
||||
|
||||
504
requirements.txt
504
requirements.txt
@ -1,252 +1,252 @@
|
||||
aiohappyeyeballs==2.4.4
|
||||
aiohttp==3.11.11
|
||||
aiohttp-retry==2.9.1
|
||||
aiosignal==1.3.2
|
||||
alabaster==1.0.0
|
||||
albucore==0.0.23
|
||||
albumentations==2.0.1
|
||||
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==2022.9.22
|
||||
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-next-url-mixin==0.4.0
|
||||
django-nine==0.2.7
|
||||
django-nonefield==0.4
|
||||
django-ordered-model==3.7.4
|
||||
django-phonenumber-field==8.0.0
|
||||
django-picklefield==3.2
|
||||
django-plans==1.2.0
|
||||
django-prometheus==2.3.1
|
||||
django-q2==1.7.6
|
||||
django-sekizai==4.1.0
|
||||
django-sequences==3.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
|
||||
emoji==2.14.1
|
||||
et_xmlfile==2.0.0
|
||||
Faker==35.0.0
|
||||
filelock==3.17.0
|
||||
fire==0.7.0
|
||||
Flask==3.1.0
|
||||
fonttools==4.55.6
|
||||
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.1.0
|
||||
hstspreload==2025.1.1
|
||||
httpcore==1.0.7
|
||||
httpx==0.28.1
|
||||
hyperframe==6.1.0
|
||||
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.26.0
|
||||
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
|
||||
numpy==2.2.2
|
||||
oauthlib==3.2.2
|
||||
ofxtools==0.9.5
|
||||
openai==1.60.0
|
||||
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.42
|
||||
pillow==10.4.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.2
|
||||
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
|
||||
python-stdnum==1.20
|
||||
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==1.6.1
|
||||
scipy==1.15.1
|
||||
selenium==4.28.1
|
||||
sentencepiece==0.2.0
|
||||
shapely==2.0.6
|
||||
simsimd==6.2.1
|
||||
six==1.17.0
|
||||
sniffio==1.3.1
|
||||
snowballstemmer==2.2.0
|
||||
sortedcontainers==2.4.0
|
||||
soupsieve==2.6
|
||||
SQLAlchemy==2.0.37
|
||||
sqlparse==0.5.3
|
||||
stanza==1.10.1
|
||||
stringzilla==3.11.3
|
||||
suds==1.2.0
|
||||
swapper==1.3.0
|
||||
sympy==1.13.1
|
||||
tablib==3.8.0
|
||||
termcolor==2.5.0
|
||||
threadpoolctl==3.5.0
|
||||
tifffile==2025.1.10
|
||||
tinycss2==1.4.0
|
||||
tinyhtml5==2.0.0
|
||||
tomli==2.2.1
|
||||
tomlkit==0.13.2
|
||||
torch==2.5.1
|
||||
tqdm==4.67.1
|
||||
trio==0.28.0
|
||||
trio-websocket==0.11.1
|
||||
twilio==9.4.3
|
||||
typing-inspect==0.9.0
|
||||
typing_extensions==4.12.2
|
||||
tzdata==2025.1
|
||||
Unidecode==1.3.8
|
||||
upgrade-requirements==1.7.0
|
||||
urllib3==2.3.0
|
||||
vin==0.6.2
|
||||
vininfo==1.8.0
|
||||
vishap==0.1.5
|
||||
vpic-api==0.7.4
|
||||
weasyprint==63.1
|
||||
webencodings==0.5.1
|
||||
websocket-client==1.8.0
|
||||
Werkzeug==3.1.3
|
||||
wikipedia==1.4.0
|
||||
wsproto==1.2.0
|
||||
xmlsec==1.3.14
|
||||
yarl==1.18.3
|
||||
zopfli==0.2.3.post1
|
||||
aiohappyeyeballs
|
||||
aiohttp
|
||||
aiohttp-retry
|
||||
aiosignal
|
||||
alabaster
|
||||
albucore
|
||||
albumentations
|
||||
annotated-types
|
||||
anyio
|
||||
arabic-reshaper
|
||||
asgiref
|
||||
astor
|
||||
astroid
|
||||
attrs
|
||||
autopep8
|
||||
Babel
|
||||
beautifulsoup4
|
||||
bleach
|
||||
blinker
|
||||
Brotli
|
||||
certifi
|
||||
cffi
|
||||
chardet
|
||||
charset-normalizer
|
||||
click
|
||||
colorama
|
||||
commonmark
|
||||
contourpy
|
||||
crispy-bootstrap5
|
||||
cryptography
|
||||
cssselect2
|
||||
ctranslate2
|
||||
cycler
|
||||
Cython
|
||||
decorator
|
||||
desert
|
||||
dill
|
||||
distro
|
||||
dj-rest-auth
|
||||
dj-shop-cart
|
||||
Django
|
||||
django-allauth
|
||||
django-appointment
|
||||
django-autoslug
|
||||
django-bootstrap5
|
||||
django-classy-tags
|
||||
django-cors-headers
|
||||
django-countries
|
||||
django-crispy-forms
|
||||
django-debug-toolbar
|
||||
django-extensions
|
||||
django-filter
|
||||
django-formtools
|
||||
django-ledger
|
||||
django-money
|
||||
django-next-url-mixin
|
||||
django-nine
|
||||
django-nonefield
|
||||
django-ordered-model
|
||||
django-phonenumber-field
|
||||
django-picklefield
|
||||
django-plans
|
||||
django-prometheus
|
||||
django-q2
|
||||
django-sekizai
|
||||
django-sequences
|
||||
django-silk
|
||||
django-sms
|
||||
django-sslserver
|
||||
django-tables2
|
||||
django-treebeard
|
||||
django-view-breadcrumbs
|
||||
djangocms-admin-style
|
||||
djangorestframework
|
||||
djangorestframework_simplejwt
|
||||
djangoviz
|
||||
docutils
|
||||
easy-thumbnails
|
||||
emoji
|
||||
et_xmlfile
|
||||
Faker
|
||||
filelock
|
||||
fire
|
||||
Flask
|
||||
fonttools
|
||||
frozenlist
|
||||
fsspec
|
||||
gprof2dot
|
||||
graphqlclient
|
||||
greenlet
|
||||
h11
|
||||
h2
|
||||
hpack
|
||||
hstspreload
|
||||
httpcore
|
||||
httpx
|
||||
hyperframe
|
||||
idna
|
||||
imageio
|
||||
imagesize
|
||||
imgaug
|
||||
iso4217
|
||||
isodate
|
||||
isort
|
||||
itsdangerous
|
||||
Jinja2
|
||||
jiter
|
||||
joblib
|
||||
kiwisolver
|
||||
lazy_loader
|
||||
ledger
|
||||
libretranslatepy
|
||||
lmdb
|
||||
lxml
|
||||
Markdown
|
||||
markdown-it-py
|
||||
MarkupSafe
|
||||
marshmallow
|
||||
matplotlib
|
||||
mccabe
|
||||
mdurl
|
||||
MouseInfo
|
||||
mpmath
|
||||
multidict
|
||||
mypy-extensions
|
||||
networkx
|
||||
newrelic
|
||||
nltk
|
||||
numpy
|
||||
oauthlib
|
||||
ofxtools
|
||||
openai
|
||||
opencv-contrib-python
|
||||
opencv-python
|
||||
opencv-python-headless
|
||||
openpyxl
|
||||
opt_einsum
|
||||
outcome
|
||||
packaging
|
||||
pandas
|
||||
pango
|
||||
pdfkit
|
||||
phonenumbers
|
||||
pillow
|
||||
platformdirs
|
||||
prometheus_client
|
||||
propcache
|
||||
protobuf
|
||||
psycopg
|
||||
psycopg-binary
|
||||
psycopg-c
|
||||
py-moneyed
|
||||
PyAutoGUI
|
||||
pyclipper
|
||||
pycodestyle
|
||||
pycparser
|
||||
pydantic
|
||||
pydantic_core
|
||||
pydotplus
|
||||
pydyf
|
||||
PyGetWindow
|
||||
Pygments
|
||||
PyJWT
|
||||
pylint
|
||||
PyMsgBox
|
||||
PyMySQL
|
||||
pyobjc-core
|
||||
pyobjc-framework-Cocoa
|
||||
pyobjc-framework-Quartz
|
||||
pyparsing
|
||||
pyperclip
|
||||
pyphen
|
||||
pypng
|
||||
PyRect
|
||||
PyScreeze
|
||||
pyserial
|
||||
PySocks
|
||||
python-bidi
|
||||
python-dateutil
|
||||
python-docx
|
||||
python-openid
|
||||
python-stdnum
|
||||
python3-saml
|
||||
pytweening
|
||||
pytz
|
||||
pyvin
|
||||
pywa
|
||||
pywhat
|
||||
pywhatkit
|
||||
PyYAML
|
||||
pyzbar
|
||||
qrcode
|
||||
RapidFuzz
|
||||
regex
|
||||
reportlab
|
||||
requests
|
||||
requests-oauthlib
|
||||
rfc3986
|
||||
rich
|
||||
rubicon-objc
|
||||
sacremoses
|
||||
scikit-image
|
||||
scikit-learn
|
||||
scipy
|
||||
selenium
|
||||
sentencepiece
|
||||
shapely
|
||||
simsimd
|
||||
six
|
||||
sniffio
|
||||
snowballstemmer
|
||||
sortedcontainers
|
||||
soupsieve
|
||||
SQLAlchemy
|
||||
sqlparse
|
||||
stanza
|
||||
stringzilla
|
||||
suds
|
||||
swapper
|
||||
sympy
|
||||
tablib
|
||||
termcolor
|
||||
threadpoolctl
|
||||
tifffile
|
||||
tinycss2
|
||||
tinyhtml5
|
||||
tomli
|
||||
tomlkit
|
||||
torch
|
||||
tqdm
|
||||
trio
|
||||
trio-websocket
|
||||
twilio
|
||||
typing-inspect
|
||||
typing_extensions
|
||||
tzdata
|
||||
Unidecode
|
||||
upgrade-requirements
|
||||
urllib3
|
||||
vin
|
||||
vininfo
|
||||
vishap
|
||||
vpic-api
|
||||
weasyprint
|
||||
webencodings
|
||||
websocket-client
|
||||
Werkzeug
|
||||
wikipedia
|
||||
wsproto
|
||||
xmlsec
|
||||
yarl
|
||||
zopfli
|
||||
|
||||
@ -35,11 +35,11 @@ def run():
|
||||
|
||||
invoice_itemtxs = {
|
||||
i.get("item_number"): {
|
||||
"unit_cost": i.get("total"),
|
||||
"unit_cost": i.get("total_price"),
|
||||
"quantity": i.get("quantity"),
|
||||
"total_amount": i.get("total_vat"),
|
||||
}
|
||||
for i in finance_data.get("cars")
|
||||
}
|
||||
|
||||
print(invoice_itemtxs)
|
||||
print(finance_data)
|
||||
@ -235,6 +235,29 @@
|
||||
<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>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</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">
|
||||
<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 %}">
|
||||
@ -242,7 +265,7 @@
|
||||
<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 'Reports'|capfirst %}</span>
|
||||
<span class="nav-link-icon"><span data-feather="package"></span></span><span class="nav-link-text">{% trans 'Balance Sheet'|capfirst %}</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@ -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,9 +45,12 @@
|
||||
{% 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>
|
||||
{% if estimate.sale_orders.first %}
|
||||
<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>
|
||||
{% endif %}
|
||||
{% 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>
|
||||
{% endif %}
|
||||
@ -137,15 +140,15 @@
|
||||
</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 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">- {{data.total_discount}}</span>
|
||||
<span id="grand-total">+ {{data.total_vat_amount}}</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" %} ({{data.vat}}%)</td>
|
||||
<td class="align-middle text-start fw-semibold">
|
||||
<span id="grand-total"></span>
|
||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="4">{% trans "Discount Amount" %}</td>
|
||||
<td class="align-middle text-start text-danger fw-semibold ">
|
||||
<span id="grand-total">- {{data.total_discount}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="bg-body-secondary total-sum">
|
||||
|
||||
@ -84,6 +84,20 @@
|
||||
<p class="ps-6 ps-sm-0 fw-semibold mb-0">{{ estimate.customer.address_1 }}</p>
|
||||
</td>
|
||||
</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>
|
||||
<td class="py-2">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</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="last_activity align-middle text-center py-2">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -237,7 +237,7 @@
|
||||
<tr class="bg-body-secondary total-sum">
|
||||
<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">+ {{data.total_vat_amount}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="bg-body-secondary total-sum">
|
||||
|
||||
@ -208,11 +208,11 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in car_and_item_info %}
|
||||
{% for item in data.cars %}
|
||||
<tr>
|
||||
<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 %}
|
||||
@ -222,10 +222,10 @@
|
||||
|
||||
<!-- Additional Charges (VAT and Services) -->
|
||||
<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>
|
||||
<br>
|
||||
{% for service in additional_services %}
|
||||
{% for service in data.additional_services %}
|
||||
<span class="highlight">{{service.name}} - {{service.price}} {{ _("SAR") }}</span><br>
|
||||
{% endfor %}
|
||||
</p>
|
||||
@ -233,7 +233,7 @@
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- Footer Note -->
|
||||
|
||||
@ -21,8 +21,11 @@
|
||||
<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.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">
|
||||
{% comment %} <a href="{% url 'estimate_detail' estimate.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user