fix prints

This commit is contained in:
aminhashemi92 2025-10-09 16:17:01 +03:30
parent 6367d34f0c
commit 10810f8700
15 changed files with 423 additions and 245 deletions

View file

@ -157,15 +157,15 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
JAZZMIN_SETTINGS = {
# title of the window (Will default to current_admin_site.site_title if absent or None)
"site_title": "سامانه شفافیت",
"site_title": "کنتور پلاس",
# Title on the login screen (19 chars max) (defaults to current_admin_site.site_header if absent or None)
"site_header": "سامانه شفافیت",
"site_header": "کنتور پلاس",
# Title on the brand (19 chars max) (defaults to current_admin_site.site_header if absent or None)
"site_brand": "سامانه شفافیت",
"site_brand": "کنتور پلاس",
# Welcome text on the login screen
"welcome_sign": "به سامانه شفافیت خوش آمدید",
"welcome_sign": "به کنتور پلاس خوش آمدید",
# Copyright on the footer
"copyright": "سامانه شفافیت",
"copyright": "کنتور پلاس",
# Logo to use for your site, must be present in static files, used for brand on top left
# "site_logo": "../static/dist/img/iconlogo.png",
# Relative paths to custom CSS/JS scripts (must be present in static files)

View file

@ -192,4 +192,122 @@ def normalize_size(size: int) -> str:
return f"{int(size_mb)} MB" if size_mb.is_integer() else f"{size_mb:.1f} MB"
else:
size_gb = size / (1024 * 1024 * 1024)
return f"{int(size_gb)} GB" if size_gb.is_integer() else f"{size_gb:.1f} GB"
return f"{int(size_gb)} GB" if size_gb.is_integer() else f"{size_gb:.1f} GB"
def number_to_persian_words(number):
"""
تبدیل عدد به حروف فارسی
مثال: 12345 -> دوازده هزار و سیصد و چهل و پنج
"""
try:
# تبدیل به عدد صحیح (در صورت نیاز)
from decimal import Decimal
if isinstance(number, Decimal):
number = int(number)
elif isinstance(number, float):
number = int(number)
elif isinstance(number, str):
number = int(float(number.replace(',', '')))
if number == 0:
return "صفر"
if number < 0:
return "منفی " + number_to_persian_words(abs(number))
# اعداد یک رقمی
ones = [
"", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", "نه"
]
# اعداد ده تا نوزده
teens = [
"ده", "یازده", "دوازده", "سیزده", "چهارده", "پانزده",
"شانزده", "هفده", "هجده", "نوزده"
]
# اعداد بیست تا نود
tens = [
"", "", "بیست", "سی", "چهل", "پنجاه", "شصت", "هفتاد", "هشتاد", "نود"
]
# اعداد صد تا نهصد
hundreds = [
"", "یکصد", "دویست", "سیصد", "چهارصد", "پانصد",
"ششصد", "هفتصد", "هشتصد", "نهصد"
]
# مراتب بزرگتر
scale = [
"", "هزار", "میلیون", "میلیارد", "بیلیون", "بیلیارد"
]
def convert_group(num):
"""تبدیل گروه سه رقمی به حروف"""
if num == 0:
return ""
result = []
# صدها
h = num // 100
if h > 0:
result.append(hundreds[h])
# دهگان و یکان
remainder = num % 100
if remainder >= 10 and remainder < 20:
# اعداد 10 تا 19
result.append(teens[remainder - 10])
else:
# دهگان
t = remainder // 10
if t > 0:
result.append(tens[t])
# یکان
o = remainder % 10
if o > 0:
result.append(ones[o])
return " و ".join(result)
# تقسیم عدد به گروه‌های سه رقمی
groups = []
scale_index = 0
while number > 0:
group = number % 1000
if group != 0:
group_text = convert_group(group)
if scale_index > 0:
group_text += " " + scale[scale_index]
groups.append(group_text)
number //= 1000
scale_index += 1
# معکوس کردن و ترکیب گروه‌ها
groups.reverse()
result = " و ".join(groups)
return result
except Exception:
return ""
def amount_to_persian_words(amount):
"""
تبدیل مبلغ به حروف فارسی با واحد ریال
مثال: 12345 -> دوازده هزار و سیصد و چهل و پنج ریال
"""
try:
words = number_to_persian_words(amount)
if words:
return words + " ریال"
return ""
except Exception:
return ""

View file

@ -64,7 +64,7 @@ layout-wide customizer-hide
</svg>
</span>
<span class="app-brand-text demo text-body fw-bold">سامانه شفافیت</span>
<span class="app-brand-text demo text-body fw-bold">کنتور پلاس</span>
</a>
</div>

View file

@ -1,7 +1,23 @@
from django import template
from _helpers.utils import jalali_converter2
from _helpers.utils import jalali_converter2, amount_to_persian_words
register = template.Library()
@register.filter(name='to_jalali')
def to_jalali(value):
return jalali_converter2(value)
return jalali_converter2(value)
@register.filter(name='amount_to_words')
def amount_to_words(value):
"""تبدیل مبلغ به حروف فارسی"""
try:
if value is None or value == '':
return ""
# تبدیل Decimal به int
from decimal import Decimal
if isinstance(value, Decimal):
value = int(value)
result = amount_to_persian_words(value)
return result if result else "صفر ریال"
except Exception as e:
return f"خطا: {str(e)}"

Binary file not shown.

View file

@ -66,12 +66,11 @@ class InstallationReportForm(forms.ModelForm):
'class': 'form-select'
}, choices=[
('', 'انتخاب کنید'),
('A', 'A'),
('B', 'B')
('direct', 'مستقیم'),
('indirect', 'غیرمستقیم')
]),
'discharge_pipe_diameter': forms.NumberInput(attrs={
'class': 'form-control',
'min': '0',
'required': True
}),
'usage_type': forms.Select(attrs={
@ -89,7 +88,6 @@ class InstallationReportForm(forms.ModelForm):
}),
'motor_power': forms.NumberInput(attrs={
'class': 'form-control',
'min': '0',
'required': True
}),
'pre_calibration_flow_rate': forms.NumberInput(attrs={

View file

@ -0,0 +1,30 @@
# Generated by Django 5.2.4 on 2025-10-09 12:28
import django.core.validators
from decimal import Decimal
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('installations', '0008_alter_installationreport_post_calibration_flow_rate_and_more'),
]
operations = [
migrations.AlterField(
model_name='installationreport',
name='meter_model',
field=models.CharField(blank=True, choices=[('direct', 'مستقیم'), ('indirect', 'غیرمستقیم')], max_length=20, null=True, verbose_name='مدل کنتور'),
),
migrations.AlterField(
model_name='installationreport',
name='post_calibration_flow_rate',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(Decimal('0.0001'))], verbose_name='(لیتر بر ثانیه)دبی بعد از کالیبراسیون'),
),
migrations.AlterField(
model_name='installationreport',
name='pre_calibration_flow_rate',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(Decimal('0.0001'))], verbose_name='(لیتر بر ثانیه)دبی قبل از کالیبراسیون'),
),
]

View file

@ -0,0 +1,28 @@
# Generated by Django 5.2.4 on 2025-10-09 12:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('installations', '0009_alter_installationreport_meter_model_and_more'),
]
operations = [
migrations.AlterField(
model_name='installationreport',
name='motor_power',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, verbose_name='(کیلووات ساعت) قدرت موتور'),
),
migrations.AlterField(
model_name='installationreport',
name='post_calibration_flow_rate',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, verbose_name='(لیتر بر ثانیه)دبی بعد از کالیبراسیون'),
),
migrations.AlterField(
model_name='installationreport',
name='pre_calibration_flow_rate',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, verbose_name='(لیتر بر ثانیه)دبی قبل از کالیبراسیون'),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-10-09 12:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('installations', '0010_alter_installationreport_motor_power_and_more'),
]
operations = [
migrations.AlterField(
model_name='installationreport',
name='discharge_pipe_diameter',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, verbose_name='قطر لوله آبده (اینچ)'),
),
]

View file

@ -1,6 +1,8 @@
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.core.validators import MinValueValidator
from decimal import Decimal
from common.models import BaseModel
User = get_user_model()
@ -48,12 +50,12 @@ class InstallationReport(BaseModel):
]
meter_type = models.CharField(max_length=20, choices=METER_TYPE_CHOICES, null=True, blank=True, verbose_name='نوع کنتور')
METER_MODEL_CHOICES = [
('A', 'A'),
('B', 'B'),
('direct', 'مستقیم'),
('indirect', 'غیرمستقیم'),
]
meter_model = models.CharField(max_length=20, choices=METER_MODEL_CHOICES, null=True, blank=True, verbose_name='مدل کنتور')
meter_size = models.CharField(max_length=50, null=True, blank=True, verbose_name='سایز کنتور')
discharge_pipe_diameter = models.PositiveIntegerField(null=True, blank=True, verbose_name='قطر لوله آبده (اینچ)')
discharge_pipe_diameter = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='قطر لوله آبده (اینچ)')
USAGE_TYPE_CHOICES = [
('domestic', 'شرب و خدمات'),
('agriculture', 'کشاورزی'),
@ -61,7 +63,7 @@ class InstallationReport(BaseModel):
]
usage_type = models.CharField(max_length=20, choices=USAGE_TYPE_CHOICES, null=True, verbose_name='نوع مصرف')
exploitation_license_number = models.CharField(max_length=50, verbose_name='شماره پروانه بهره‌برداری چاه')
motor_power = models.PositiveIntegerField(null=True, blank=True, verbose_name='(کیلووات ساعت) قدرت موتور')
motor_power = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(کیلووات ساعت) قدرت موتور')
pre_calibration_flow_rate = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(لیتر بر ثانیه)دبی قبل از کالیبراسیون')
post_calibration_flow_rate = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(لیتر بر ثانیه)دبی بعد از کالیبراسیون')
water_meter_manufacturer = models.ForeignKey('wells.WaterMeterManufacturer', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='شرکت سازنده کنتور آب')

View file

@ -7,6 +7,7 @@
{% load static %}
{% load humanize %}
{% load common_tags %}
<!-- Fonts (match base) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
@ -48,71 +49,38 @@
</head>
<body>
<div class="container-fluid">
<!-- Header -->
<!-- Invoice Header (compact, matches preview) -->
<div class="invoice-header">
<div class="row align-items-center">
<div class="col-6 d-flex align-items-center">
<div class="me-3" style="width:64px;height:64px;display:flex;align-items:center;justify-content:center;background:#eef2ff;border-radius:8px;">
{% if instance.broker.company and instance.broker.company.logo %}
<img src="{{ instance.broker.company.logo.url }}" alt="لوگو" style="max-height:58px;max-width:120px;">
{% else %}
<span class="company-logo">شرکت</span>
{% endif %}
</div>
<div>
{% if instance.broker.company %}
{{ instance.broker.company.name }}
{% endif %}
{% if instance.broker.company %}
<div class="text-muted small">
{% if instance.broker.company.address %}
<div>{{ instance.broker.company.address }}</div>
{% endif %}
{% if instance.broker.affairs.county.city.name %}
<div>{{ instance.broker.affairs.county.city.name }}، ایران</div>
{% endif %}
{% if instance.broker.company.phone %}
<div>تلفن: {{ instance.broker.company.phone }}</div>
{% endif %}
<div class="row align-items-start justify-content-end">
<h5 class="mb-0 text-center fw-bold">فاکتور</h5>
<div class="col-3 text-start">
<div class="mt-2">
<div>شماره : {{ instance.code }}</div>
<div class="small">تاریخ صدور: {{ invoice.jcreated_date }}</div>
</div>
{% endif %}
</div>
</div>
<div class="col-6 text-end">
<div class="mt-2">
<div><strong>#فاکتور نهایی {{ instance.code }}</strong></div>
<div class="text-muted small">تاریخ صدور: {{ invoice.jcreated_date }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- Customer & Well Info -->
<div class="row mb-3">
<div class="col-6">
<h6 class="fw-bold mb-2">اطلاعات مشترک {% if instance.representative.profile and instance.representative.profile.user_type == 'legal' %}(حقوقی){% else %}(حقیقی){% endif %}</h6>
<div class="col-4 small mb-1"><span class="text-muted">شماره اشتراک آب:</span> {{ instance.well.water_subscription_number }}</div>
{% if instance.representative.profile and instance.representative.profile.user_type == 'legal' %}
<div class="small mb-1"><span class="text-muted">نام شرکت:</span> {{ instance.representative.profile.company_name|default:"-" }}</div>
<div class="small mb-1"><span class="text-muted">شناسه ملی:</span> {{ instance.representative.profile.company_national_id|default:"-" }}</div>
<div class="col-4 small mb-1"><span class="text-muted">نام شرکت:</span> {{ instance.representative.profile.company_name|default:"-" }}</div>
<div class="col-4 small mb-1"><span class="text-muted">شناسه ملی:</span> {{ instance.representative.profile.company_national_id|default:"-" }}</div>
{% endif %}
<div class="small mb-1"><span class="text-muted">نام:</span> {{ invoice.customer.get_full_name|default:instance.representative.get_full_name }}</div>
<div class="col-4 small mb-1"><span class="text-muted">نام و نام خانوادگی:</span> {{ invoice.customer.get_full_name|default:instance.representative.get_full_name }}</div>
{% if instance.representative.profile and instance.representative.profile.national_code %}
<div class="small mb-1"><span class="text-muted">کد ملی:</span> {{ instance.representative.profile.national_code }}</div>
<div class="col-4 small mb-1"><span class="text-muted">کد ملی:</span> {{ instance.representative.profile.national_code }}</div>
{% endif %}
{% if instance.representative.profile and instance.representative.profile.phone_number_1 %}
<div class="small mb-1"><span class="text-muted">تلفن:</span> {{ instance.representative.profile.phone_number_1 }}</div>
<div class="col-4 small mb-1"><span class="text-muted">تلفن:</span> {{ instance.representative.profile.phone_number_1 }}</div>
{% endif %}
{% if instance.representative.profile and instance.representative.profile.address %}
<div class="small"><span class="text-muted">آدرس:</span> {{ instance.representative.profile.address }}</div>
<div class="col-12 small"><span class="text-muted">آدرس:</span> {{ instance.representative.profile.address }}</div>
{% endif %}
</div>
<div class="col-6">
<h6 class="fw-bold mb-2">اطلاعات چاه</h6>
<div class="small mb-1"><span class="text-muted">شماره اشتراک آب:</span> {{ instance.well.water_subscription_number }}</div>
<div class="small mb-1"><span class="text-muted">شماره اشتراک برق:</span> {{ instance.well.electricity_subscription_number|default:"-" }}</div>
<div class="small mb-1"><span class="text-muted">سریال کنتور:</span> {{ instance.well.water_meter_serial_number|default:"-" }}</div>
<div class="small"><span class="text-muted">قدرت چاه:</span> {{ instance.well.well_power|default:"-" }}</div>
</div>
</div>
<!-- Items Table -->
@ -144,47 +112,43 @@
</tbody>
<tfoot>
<tr class="total-section">
<td colspan="5" class="text-end"><strong>جمع کل(ریال):</strong></td>
<td><strong>{{ invoice.total_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>جمع کل(ریال):</strong></td>
<td colspan="6" class="text-end"><strong>{{ invoice.total_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
{% if invoice.discount_amount > 0 %}
<tr class="total-section">
<td colspan="5" class="text-end"><strong>تخفیف(ریال):</strong></td>
<td><strong>{{ invoice.discount_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>تخفیف(ریال):</strong></td>
<td colspan="6" class="text-end"><strong>{{ invoice.discount_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
{% endif %}
<tr class="total-section">
<td colspan="5" class="text-end"><strong>مالیات بر ارزش افزوده(ریال):</strong></td>
<td><strong>{{ invoice.get_vat_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>مالیات بر ارزش افزوده(ریال):</strong></td>
<td colspan="6" class="text-end"><strong>{{ invoice.get_vat_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
<tr class="total-section border-top border-2">
<td colspan="5" class="text-end"><strong>مبلغ نهایی (شامل مالیات)(ریال):</strong></td>
<td><strong>{{ invoice.final_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>مبلغ نهایی (شامل مالیات)(ریال):</strong></td>
<td colspan="6" class="text-end"><strong>{{ invoice.final_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
<tr class="total-section">
<td colspan="5" class="text-end"><strong>پرداختی‌ها(ریال):</strong></td>
<td><strong">{{ invoice.get_paid_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>پرداختی‌ها(ریال):</strong></td>
<td colspan="6" class="text-end"><strong">{{ invoice.get_paid_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
<tr class="total-section">
<td colspan="5" class="text-end"><strong>مانده(ریال):</strong></td>
<td><strong>{{ invoice.get_remaining_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>مانده(ریال):</strong></td>
<td colspan="6" class="text-end"><strong>{{ invoice.get_remaining_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
<tr class="total-section small border-top border-2">
<td colspan="2" class="text-start"><strong>مبلغ نهایی به حروف:</strong></td>
<td colspan="6" class="text-end"><strong>{{ invoice.final_amount|amount_to_words }}</strong></td>
</tr>
</tfoot>
</table>
</div>
<!-- Conditions & Payment -->
<div class="row">
<div class="col-8">
<h6 class="fw-bold">مهر و امضا:</h6>
<ul class="small mb-0">
{% if instance.broker.company and instance.broker.company.signature %}
<li class="mt-3" style="list-style:none;"><img src="{{ instance.broker.company.signature.url }}" alt="امضا" style="height: 200px;"></li>
{% endif %}
</ul>
</div>
{% if instance.broker.company %}
<div class="col-4">
<div class="col-8">
<h6 class="fw-bold mb-2">اطلاعات پرداخت</h6>
{% if instance.broker.company.card_number %}
<div class="small mb-1"><span class="text-muted">شماره کارت:</span> {{ instance.broker.company.card_number }}</div>
@ -200,6 +164,18 @@
{% endif %}
</div>
{% endif %}
<div class="col-4">
{% if instance.broker.company and instance.broker.company.signature %}
<div class="row d-flex justify-content-center">
<h6 class="mb-3 text-center">مهر و امضا</h6>
{% if instance.broker.company.signature %}
<img class="img-fluid" src="{{ instance.broker.company.signature.url }}" alt="امضای شرکت" style="">
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>

View file

@ -2,6 +2,7 @@
{% load static %}
{% load processes_tags %}
{% load humanize %}
{% load common_tags %}
{% block sidebar %}
{% include 'sidebars/admin.html' %}
@ -56,8 +57,9 @@
<!-- Invoice Preview Card -->
<div class="card invoice-preview-card mt-4 border">
<div class="card-body">
<div class="d-flex justify-content-between flex-xl-row flex-md-column flex-sm-row flex-column p-sm-3 p-0 align-items-center">
<div class="mb-xl-0 mb-4">
<h5 class="mb-0 text-center fw-bold">پیش‌فاکتور</h5>
<div class="d-flex justify-content-end flex-xl-row flex-md-column flex-sm-row flex-column p-0 align-items-center">
<div class="mb-xl-0 mb-4 d-none">
<!-- Company Logo & Info -->
<div class="d-flex align-items-center">
<div class="avatar avatar-lg me-3">
@ -94,13 +96,13 @@
</div>
</div>
<!-- Invoice Details -->
<div class="text-center">
<div class="mb-3">
<h5 class="text-body">#{{ quote.name }}</h5>
<div class="text-start">
<div class="">
<h6 class="text-body">شماره : {{ quote.name }}</h6>
</div>
<div class="invoice-details">
<div class="d-flex justify-content-end align-items-center mb-2">
<span class="text-muted me-2">تاریخ صدور:</span>
<span class="me-2">تاریخ صدور:</span>
<span class="fw-medium text-body">{{ quote.jcreated_date }}</span>
</div>
</div>
@ -110,7 +112,7 @@
<hr class="my-0">
<div class="card-body py-1">
<div class="row">
<div class="col-xl-6 col-md-12 col-sm-6 col-12 mb-3">
<div class="col-xl-12 col-md-12 col-sm-12 col-12 mb-3">
<div class="">
<div class="card-body p-3">
<h6 class="card-title text-primary mb-2">
@ -121,43 +123,48 @@
اطلاعات مشترک (حقیقی)
{% endif %}
</h6>
{% if instance.representative.profile.user_type == 'legal' %}
<div class="d-flex gap-2 mb-1">
<span class="text-muted small">نام شرکت:</span>
<span class="fw-medium small">{{ instance.representative.profile.company_name|default:"-" }}</span>
<div class="row">
<div class="col-md-3 d-flex gap-2 mb-1">
<span class="text-muted small">شماره اشتراک آب:</span>
<span class="fw-medium small">{{ instance.well.water_subscription_number }}</span>
</div>
{% if instance.representative.profile.user_type == 'legal' %}
<div class="col-md-3 d-flex gap-2 mb-1">
<span class="text-muted small">نام شرکت:</span>
<span class="fw-medium small">{{ instance.representative.profile.company_name|default:"-" }}</span>
</div>
<div class="col-md-3 d-flex gap-2 mb-1">
<span class="text-muted small">شناسه ملی:</span>
<span class="fw-medium small">{{ instance.representative.profile.company_national_id|default:"-" }}</span>
</div>
{% endif %}
<div class="col-md-3 d-flex gap-2 mb-1">
<span class="text-muted small">نام:</span>
<span class="fw-medium small">{{ quote.customer.get_full_name }}</span>
</div>
{% if instance.representative.profile.national_code %}
<div class="col-md-3 d-flex gap-2 mb-1">
<span class="text-muted small">کد ملی:</span>
<span class="fw-medium small">{{ instance.representative.profile.national_code }}</span>
</div>
{% endif %}
{% if instance.representative.profile.phone_number_1 %}
<div class="col-md-3 d-flex gap-2 mb-1">
<span class="text-muted small">تلفن:</span>
<span class="fw-medium small">{{ instance.representative.profile.phone_number_1 }}</span>
</div>
{% endif %}
{% if instance.representative.profile.address %}
<div class="col-md-12 d-flex gap-2">
<span class="text-muted small">آدرس:</span>
<span class="fw-medium small">{{ instance.representative.profile.address }}</span>
</div>
{% endif %}
</div>
<div class="d-flex gap-2 mb-1">
<span class="text-muted small">شناسه ملی:</span>
<span class="fw-medium small">{{ instance.representative.profile.company_national_id|default:"-" }}</span>
</div>
{% endif %}
<div class="d-flex gap-2 mb-1">
<span class="text-muted small">نام:</span>
<span class="fw-medium small">{{ quote.customer.get_full_name }}</span>
</div>
{% if instance.representative.profile.national_code %}
<div class="d-flex gap-2 mb-1">
<span class="text-muted small">کد ملی:</span>
<span class="fw-medium small">{{ instance.representative.profile.national_code }}</span>
</div>
{% endif %}
{% if instance.representative.profile.phone_number_1 %}
<div class="d-flex gap-2 mb-1">
<span class="text-muted small">تلفن:</span>
<span class="fw-medium small">{{ instance.representative.profile.phone_number_1 }}</span>
</div>
{% endif %}
{% if instance.representative.profile.address %}
<div class="d-flex gap-2">
<span class="text-muted small">آدرس:</span>
<span class="fw-medium small">{{ instance.representative.profile.address }}</span>
</div>
{% endif %}
</div>
</div>
</div>
<div class="col-xl-6 col-md-12 col-sm-6 col-12 mb-3">
<div class="col-xl-6 col-md-12 col-sm-6 col-12 mb-3 d-none">
<div class="border-0 bg-light">
<div class="card-body p-3">
<h6 class="card-title text-primary mb-2">
@ -214,7 +221,8 @@
<p class="mb-2">تخفیف:</p>
{% endif %}
<p class="mb-2">مالیات بر ارزش افزوده:</p>
<p class="mb-0 fw-bold">مبلغ نهایی (شامل مالیات):</p>
<p class="mb-2 fw-bold">مبلغ نهایی (شامل مالیات):</p>
<p class="mb-0 small text-muted">مبلغ نهایی به حروف:</p>
</td>
<td class="px-4 py-5">
<p class="fw-medium mb-2">{{ quote.total_amount|floatformat:0|intcomma:False }} ریال</p>
@ -222,7 +230,8 @@
<p class="fw-medium mb-2">{{ quote.discount_amount|floatformat:0|intcomma:False }} ریال</p>
{% endif %}
<p class="fw-medium mb-2">{{ quote.get_vat_amount|floatformat:0|intcomma:False }} ریال</p>
<p class="fw-bold mb-0">{{ quote.final_amount|floatformat:0|intcomma:False }} ریال</p>
<p class="fw-bold mb-2">{{ quote.final_amount|floatformat:0|intcomma:False }} ریال</p>
<p class="mb-0 small text-muted">{{ quote.final_amount|amount_to_words }}</p>
</td>
</tr>
</tbody>
@ -245,50 +254,53 @@
<i class="bx bx-info-circle text-muted me-2"></i>
این برگه صرفاً جهت اعلام قیمت بوده و ارزش قانونی دیگری ندارد
</li>
{% if instance.broker.company.signature %}
<li class="mb-0 text-start mt-4 ms-5">
<img src="{{ instance.broker.company.signature.url }}" alt="امضای شرکت" style="height: 200px;">
</li>
{% endif %}
</ul>
{% if instance.broker.company %}
<div class="col-md-4 mt-4">
<h6 class="mb-1">اطلاعات پرداخت:</h6>
<div class="d-flex flex-column gap-1">
{% if instance.broker.company.card_number %}
<div>
<small class="text-muted">شماره کارت:</small>
<div class="fw-medium">{{ instance.broker.company.card_number }}</div>
</div>
{% endif %}
{% if instance.broker.company.account_number %}
<div>
<small class="text-muted">شماره حساب:</small>
<div class="fw-medium">{{ instance.broker.company.account_number }}</div>
</div>
{% endif %}
{% if instance.broker.company.sheba_number %}
<div>
<small class="text-muted">شماره شبا:</small>
<div class="fw-medium">{{ instance.broker.company.sheba_number }}</div>
</div>
{% endif %}
{% if instance.broker.company.bank_name %}
<div>
<small class="text-muted">بانک:</small>
<div class="fw-medium">{{ instance.broker.company.get_bank_name_display }}</div>
</div>
{% endif %}
{% if instance.broker.company.branch_name %}
<div>
<small class="text-muted">شعبه:</small>
<div class="fw-medium">{{ instance.broker.company.branch_name }}</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% if instance.broker.company %}
<div class="col-md-4">
<h6 class="mb-3">اطلاعات پرداخت:</h6>
<div class="d-flex flex-column gap-2">
{% if instance.broker.company.card_number %}
<div>
<small class="text-muted">شماره کارت:</small>
<div class="fw-medium">{{ instance.broker.company.card_number }}</div>
</div>
<div class="col-md-4 mt-5">
<div class="row d-flex justify-content-center">
<h6 class="mb-3 text-center">مهر و امضا</h6>
{% if instance.broker.company.signature %}
<img class="img-fluid" src="{{ instance.broker.company.signature.url }}" alt="امضای شرکت" style="">
{% endif %}
{% if instance.broker.company.account_number %}
<div>
<small class="text-muted">شماره حساب:</small>
<div class="fw-medium">{{ instance.broker.company.account_number }}</div>
</div>
{% endif %}
{% if instance.broker.company.sheba_number %}
<div>
<small class="text-muted">شماره شبا:</small>
<div class="fw-medium">{{ instance.broker.company.sheba_number }}</div>
</div>
{% endif %}
{% if instance.broker.company.bank_name %}
<div>
<small class="text-muted">بانک:</small>
<div class="fw-medium">{{ instance.broker.company.get_bank_name_display }}</div>
</div>
{% endif %}
{% if instance.broker.company.branch_name %}
<div>
<small class="text-muted">شعبه:</small>
<div class="fw-medium">{{ instance.broker.company.branch_name }}</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
</div>

View file

@ -7,6 +7,7 @@
{% load static %}
{% load humanize %}
{% load common_tags %}
<!-- Fonts (match base) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
@ -105,38 +106,12 @@
<!-- Invoice Header (compact, matches preview) -->
<div class="invoice-header">
<div class="row align-items-center">
<div class="col-6 d-flex align-items-center">
<div class="me-3" style="width:64px;height:64px;display:flex;align-items:center;justify-content:center;background:#eef2ff;border-radius:8px;">
{% if instance.broker.company and instance.broker.company.logo %}
<img src="{{ instance.broker.company.logo.url }}" alt="لوگو" style="max-height:58px;max-width:120px;">
{% else %}
<span class="company-logo">شرکت</span>
{% endif %}
</div>
<div>
{% if instance.broker.company %}
{{ instance.broker.company.name }}
{% endif %}
{% if instance.broker.company %}
<div class="text-muted small">
{% if instance.broker.company.address %}
<div>{{ instance.broker.company.address }}</div>
{% endif %}
{% if instance.broker.affairs.county.city.name %}
<div>{{ instance.broker.affairs.county.city.name }}، ایران</div>
{% endif %}
{% if instance.broker.company.phone %}
<div>تلفن: {{ instance.broker.company.phone }}</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
<div class="col-6 text-end">
<div class="row align-items-start justify-content-end">
<h5 class="mb-3 text-center fw-bold">پیش‌فاکتور</h5>
<div class="col-3 text-start">
<div class="mt-2">
<div><strong>#{{ quote.name }}</strong></div>
<div class="text-muted small">تاریخ صدور: {{ quote.jcreated_date }}</div>
<div>شماره : {{ quote.name }}</div>
<div class="small">تاریخ صدور: {{ quote.jcreated_date }}</div>
</div>
</div>
</div>
@ -144,37 +119,29 @@
<!-- Customer & Well Info (compact to match preview) -->
<div class="row mb-3">
<div class="col-6">
<h6 class="fw-bold mb-2">
{% if instance.representative.profile.user_type == 'legal' %}
اطلاعات مشترک (حقوقی)
{% else %}
اطلاعات مشترک (حقیقی)
{% endif %}
</h6>
<h6 class="fw-bold mb-2">
{% if instance.representative.profile.user_type == 'legal' %}
<div class="small mb-1"><span class="text-muted">نام شرکت:</span> {{ instance.representative.profile.company_name|default:"-" }}</div>
<div class="small mb-1"><span class="text-muted">شناسه ملی:</span> {{ instance.representative.profile.company_national_id|default:"-" }}</div>
{% endif %}
<div class="small mb-1"><span class="text-muted">نام:</span> {{ quote.customer.get_full_name }}</div>
{% if instance.representative.profile and instance.representative.profile.national_code %}
<div class="small mb-1"><span class="text-muted">کد ملی:</span> {{ instance.representative.profile.national_code }}</div>
{% endif %}
{% if instance.representative.profile and instance.representative.profile.phone_number_1 %}
<div class="small mb-1"><span class="text-muted">تلفن:</span> {{ instance.representative.profile.phone_number_1 }}</div>
{% endif %}
{% if instance.representative.profile and instance.representative.profile.address %}
<div class="small"><span class="text-muted">آدرس:</span> {{ instance.representative.profile.address }}</div>
اطلاعات مشترک (حقوقی)
{% else %}
اطلاعات مشترک (حقیقی)
{% endif %}
</h6>
<div class="col-4 small mb-1"><span class="text-muted">شماره اشتراک آب:</span> {{ instance.well.water_subscription_number }}</div>
{% if instance.representative.profile.user_type == 'legal' %}
<div class="col-4 small mb-1"><span class="text-muted">نام شرکت:</span> {{ instance.representative.profile.company_name|default:"-" }}</div>
<div class="col-4 small mb-1"><span class="text-muted">شناسه ملی:</span> {{ instance.representative.profile.company_national_id|default:"-" }}</div>
{% endif %}
<div class="col-4 small mb-1"><span class="text-muted">نام و نام خانوادگی:</span> {{ quote.customer.get_full_name }}</div>
{% if instance.representative.profile and instance.representative.profile.national_code %}
<div class="col-4 small mb-1"><span class="text-muted">کد ملی:</span> {{ instance.representative.profile.national_code }}</div>
{% endif %}
{% if instance.representative.profile and instance.representative.profile.phone_number_1 %}
<div class="col-4 small mb-1"><span class="text-muted">تلفن:</span> {{ instance.representative.profile.phone_number_1 }}</div>
{% endif %}
{% if instance.representative.profile and instance.representative.profile.address %}
<div class="col-12 small"><span class="text-muted">آدرس:</span> {{ instance.representative.profile.address }}</div>
{% endif %}
</div>
<div class="col-6">
<h6 class="fw-bold mb-2">اطلاعات چاه</h6>
<div class="small mb-1"><span class="text-muted">شماره اشتراک آب:</span> {{ instance.well.water_subscription_number }}</div>
<div class="small mb-1"><span class="text-muted">شماره اشتراک برق:</span> {{ instance.well.electricity_subscription_number|default:"-" }}</div>
<div class="small mb-1"><span class="text-muted">سریال کنتور:</span> {{ instance.well.water_meter_serial_number|default:"-" }}</div>
<div class="small"><span class="text-muted">قدرت چاه:</span> {{ instance.well.well_power|default:"-" }}</div>
</div>
</div>
<!-- Items Table -->
<div class="mb-4">
@ -203,22 +170,26 @@
</tbody>
<tfoot>
<tr class="total-section">
<td colspan="5" class="text-end"><strong>جمع کل(ریال):</strong></td>
<td><strong>{{ quote.total_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>جمع کل(ریال):</strong></td>
<td colspan="5" class="text-end"><strong>{{ quote.total_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
{% if quote.discount_amount > 0 %}
<tr class="total-section">
<td colspan="5" class="text-end"><strong>تخفیف(ریال):</strong></td>
<td><strong>{{ quote.discount_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>تخفیف(ریال):</strong></td>
<td colspan="5" class="text-end"><strong>{{ quote.discount_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
{% endif %}
<tr class="total-section">
<td colspan="5" class="text-end"><strong>مالیات بر ارزش افزوده(ریال):</strong></td>
<td><strong>{{ quote.get_vat_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>مالیات بر ارزش افزوده(ریال):</strong></td>
<td colspan="5" class="text-end"><strong>{{ quote.get_vat_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
<tr class="total-section border-top border-2">
<td colspan="5" class="text-end"><strong>مبلغ نهایی (با مالیات)(ریال):</strong></td>
<td><strong>{{ quote.final_amount|floatformat:0|intcomma:False }}</strong></td>
<td colspan="3" class="text-start"><strong>مبلغ نهایی (با مالیات)(ریال):</strong></td>
<td colspan="5" class="text-end"><strong>{{ quote.final_amount|floatformat:0|intcomma:False }}</strong></td>
</tr>
<tr class="total-section small border-top border-2">
<td colspan="2" class="text-start"><strong>مبلغ نهایی به حروف:</strong></td>
<td colspan="6" class="text-end"><strong>{{ quote.final_amount|amount_to_words }}</strong></td>
</tr>
</tfoot>
</table>
@ -232,14 +203,11 @@
<li class="mb-1">اعتبار پیش‌فاکتور صادر شده ۴۸ ساعت پس از تاریخ صدور می‌باشد</li>
<li class="mb-1">مبلغ فوق به صورت علی‌الحساب دریافت می‌گردد</li>
<li class="mb-1">این برگه صرفاً جهت اعلام قیمت بوده و ارزش قانونی دیگری ندارد</li>
{% if instance.broker.company and instance.broker.company.signature %}
<li class="mt-3" style="list-style:none;"><img src="{{ instance.broker.company.signature.url }}" alt="امضا" style="height: 200px;"></li>
{% endif %}
</ul>
</div>
{% if instance.broker.company %}
<div class="col-4">
<h6 class="fw-bold mb-2">اطلاعات پرداخت</h6>
{% if instance.broker.company %}
<h6 class="fw-bold mt-3">اطلاعات پرداخت</h6>
{% if instance.broker.company.card_number %}
<div class="small mb-1"><span class="text-muted">شماره کارت:</span> {{ instance.broker.company.card_number }}</div>
{% endif %}
@ -252,8 +220,20 @@
{% if instance.broker.company.bank_name %}
<div class="small"><span class="text-muted">بانک:</span> {{ instance.broker.company.get_bank_name_display }}</div>
{% endif %}
{% endif %}
</div>
<div class="col-4">
{% if instance.broker.company and instance.broker.company.signature %}
<div class="row d-flex justify-content-center">
<h6 class="mb-3 text-center">مهر و امضا</h6>
{% if instance.broker.company.signature %}
<img class="img-fluid" src="{{ instance.broker.company.signature.url }}" alt="امضای شرکت" style="">
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
</div>
<!-- Signature Section (optional, compact) -->

View file

@ -115,7 +115,7 @@ def create_quote(request, instance_id, step_id):
quote, created_q = Quote.objects.get_or_create(
process_instance=instance,
defaults={
'name': f"پیش‌فاکتور {instance.code}",
'name': f"{instance.code}",
'customer': instance.representative or request.user,
'valid_until': timezone.now().date(),
'created_by': request.user,

View file

@ -51,7 +51,7 @@
</svg>
</span>
<span class="app-brand-text demo menu-text fw-bold ms-2 fs-4">سامانه شفافیت</span>
<span class="app-brand-text demo menu-text fw-bold ms-2 fs-4">کنتور پلاس</span>
</a>
<a href="#" class="layout-menu-toggle menu-link text-large ms-auto">