fix counter nazar, improve check, call button
This commit is contained in:
1 parent
36364447c7
commit
04ddc701a3
6 files changed
+538
-183
No files matched your search
@@ -1,24 +1,43 @@
|
|||||||
from django.db.models import Count, Sum
|
from django.db.models import Count, Sum, Q
|
||||||
from django.db.models import Q
|
|
||||||
import os
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
from .models import *
|
from .models import *
|
||||||
|
|
||||||
def dashBoxData(request):
|
def dashBoxData(request):
|
||||||
|
|
||||||
|
|
||||||
bazdid = os.environ.get('bazdid', 9)
|
bazdid = os.environ.get('bazdid', 9)
|
||||||
|
|
||||||
debit = Article.objects.filter().aggregate(Sum('debit'))['debit__sum']
|
debit = Article.objects.filter().aggregate(Sum('debit'))['debit__sum']
|
||||||
credit = Article.objects.filter().aggregate(Sum('credit'))['credit__sum']
|
credit = Article.objects.filter().aggregate(Sum('credit'))['credit__sum']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mandehesab = debit - credit
|
mandehesab = debit - credit
|
||||||
except:
|
except:
|
||||||
mandehesab = 0
|
mandehesab = 0
|
||||||
|
|
||||||
countCustomers = Customer.objects.all().count()
|
countCustomers = Customer.objects.all().count()
|
||||||
allUsers = User.objects.filter().exclude(username='admin').exclude(username='fesahat')
|
allUsers = User.objects.filter().exclude(username='admin').exclude(username='fesahat')
|
||||||
ActionCount = Action.objects.filter(forUser=request.user.id, status='waite').count()
|
ActionCount = Action.objects.filter(forUser=request.user.id, status='waite').count()
|
||||||
rezayatCount = Action.objects.exclude(actionType='vosol').filter(Q(nazar='') | Q(nazar=None) & Q(status='finish')).count()
|
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# بخش اصلاح شده برای شمارش دقیق نظرسنجیهای در انتظار
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
dt_30_days_ago = now - datetime.timedelta(days=30)
|
||||||
|
dt_60_days_ago = now - datetime.timedelta(days=60)
|
||||||
|
|
||||||
|
rezayatCount = Action.objects.exclude(actionType='vosol').filter(
|
||||||
|
status='finish',
|
||||||
|
nazarDT__isnull=True, # نظرسنجی هنوز نهایی نشده
|
||||||
|
createdDT__gte=dt_60_days_ago # حداکثر ۶۰ روز از ایجاد گذشته باشد
|
||||||
|
).filter(
|
||||||
|
Q(finishDateTime__isnull=True) | Q(finishDateTime__gte=dt_30_days_ago) # حداکثر ۳۰ روز از اتمام گذشته باشد
|
||||||
|
).filter(
|
||||||
|
Q(nextNazarDT__isnull=True) | Q(nextNazarDT__lte=now) # موعد پیگیری رسیده یا تعویقی نداشته باشد
|
||||||
|
).count()
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
try:
|
try:
|
||||||
entezarbazdid = CacheTable.objects.get(key='9mahbazdid').value
|
entezarbazdid = CacheTable.objects.get(key='9mahbazdid').value
|
||||||
except Exception as exp:
|
except Exception as exp:
|
||||||
@@ -33,4 +52,5 @@ def dashBoxData(request):
|
|||||||
'entezarbazdid': entezarbazdid,
|
'entezarbazdid': entezarbazdid,
|
||||||
'bazdid': bazdid
|
'bazdid': bazdid
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 3.2.25 on 2026-07-31 14:54
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('admin_panel', '0055_action_nextnazardt'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sarresid',
|
||||||
|
name='check_owner_name',
|
||||||
|
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='نام مالک چک'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sarresid',
|
||||||
|
name='check_owner_phone',
|
||||||
|
field=models.CharField(blank=True, max_length=11, null=True, validators=[django.core.validators.RegexValidator(message='شماره تلفن باید ۱۱ رقم و فقط شامل اعداد باشد.', regex='^\\d{11}$')], verbose_name='تلفن مالک چک'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sarresid',
|
||||||
|
name='check_row_number',
|
||||||
|
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='شماره ردیف چک'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sarresid',
|
||||||
|
name='check_sayyad_id',
|
||||||
|
field=models.CharField(blank=True, max_length=16, null=True, validators=[django.core.validators.RegexValidator(message='شناسه صیادی باید دقیقاً ۱۶ رقم عدد باشد.', regex='^\\d{16}$')], verbose_name='شناسه صیادی'),
|
||||||
|
),
|
||||||
|
]
|
||||||
+30
-2
@@ -6,6 +6,7 @@ from django.dispatch import receiver
|
|||||||
from django.db import transaction, connection # اصلاح فیکس خطای تراکنش
|
from django.db import transaction, connection # اصلاح فیکس خطای تراکنش
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.validators import RegexValidator
|
||||||
|
|
||||||
userModel = get_user_model()
|
userModel = get_user_model()
|
||||||
|
|
||||||
@@ -467,17 +468,44 @@ class Action(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class Sarresid(models.Model):
|
class Sarresid(models.Model):
|
||||||
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True, blank=True)
|
customer = models.ForeignKey('Customer', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
createdDT = models.DateTimeField(auto_now_add=True)
|
createdDT = models.DateTimeField(auto_now_add=True)
|
||||||
changeDT = models.DateTimeField(auto_now=True)
|
changeDT = models.DateTimeField(auto_now=True)
|
||||||
price = models.IntegerField(null=False, blank=False)
|
price = models.IntegerField(null=False, blank=False)
|
||||||
payStatus = models.CharField(max_length=50, null=True, blank=True)
|
payStatus = models.CharField(max_length=50, null=True, blank=True)
|
||||||
type = models.CharField(max_length=50, null=True, blank=True)
|
type = models.CharField(max_length=50, null=True, blank=True)
|
||||||
factor = models.ForeignKey(Factor, on_delete=models.CASCADE, null=True, blank=True)
|
factor = models.ForeignKey('Factor', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
sarresidDT = models.DateTimeField(null=True, blank=True)
|
sarresidDT = models.DateTimeField(null=True, blank=True)
|
||||||
user = models.ForeignKey(userModel, on_delete=models.SET_NULL, null=True, blank=True)
|
user = models.ForeignKey(userModel, on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
desc = models.TextField(null=True, blank=True)
|
desc = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
|
# ---------------- فیلدهای استاندارد و ایمنشده چک ----------------
|
||||||
|
check_row_number = models.CharField(
|
||||||
|
max_length=50,
|
||||||
|
null=True, blank=True,
|
||||||
|
verbose_name="شماره ردیف چک"
|
||||||
|
)
|
||||||
|
check_sayyad_id = models.CharField(
|
||||||
|
max_length=16,
|
||||||
|
validators=[
|
||||||
|
RegexValidator(regex=r'^\d{16}$', message='شناسه صیادی باید دقیقاً ۱۶ رقم عدد باشد.')
|
||||||
|
],
|
||||||
|
null=True, blank=True,
|
||||||
|
verbose_name="شناسه صیادی"
|
||||||
|
)
|
||||||
|
check_owner_name = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
null=True, blank=True,
|
||||||
|
verbose_name="نام مالک چک"
|
||||||
|
)
|
||||||
|
check_owner_phone = models.CharField(
|
||||||
|
max_length=11,
|
||||||
|
validators=[
|
||||||
|
RegexValidator(regex=r'^\d{11}$', message='شماره تلفن باید ۱۱ رقم و فقط شامل اعداد باشد.')
|
||||||
|
],
|
||||||
|
null=True, blank=True,
|
||||||
|
verbose_name="تلفن مالک چک"
|
||||||
|
)
|
||||||
|
|
||||||
class CacheTable(models.Model):
|
class CacheTable(models.Model):
|
||||||
key = models.CharField(max_length=50, unique=True)
|
key = models.CharField(max_length=50, unique=True)
|
||||||
|
|||||||
@@ -45,38 +45,42 @@
|
|||||||
<div class="field column is-12-desktop is-12-mobile m-0">
|
<div class="field column is-12-desktop is-12-mobile m-0">
|
||||||
<label class="label">شمارههای تماس</label>
|
<label class="label">شمارههای تماس</label>
|
||||||
<div id="dynamic-phones-edit">
|
<div id="dynamic-phones-edit">
|
||||||
|
|
||||||
{% if customer.phones.all %}
|
{% if customer.phones.all %}
|
||||||
{% for phone_obj in customer.phones.all %}
|
{% for phone_obj in customer.phones.all %}
|
||||||
<div class="field has-addons mt-2 ss02">
|
<div class="field has-addons mt-2 ss02">
|
||||||
<div class="control" style="width: 35%;">
|
<div class="control" style="width: 30%;">
|
||||||
<input disabled value="{{ phone_obj.title }}" name="phone_titles" class="input" type="text" placeholder="عنوان">
|
<input disabled value="{{ phone_obj.title }}" name="phone_titles" class="input" type="text" placeholder="عنوان">
|
||||||
</div>
|
</div>
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<input disabled value="{{ phone_obj.phone_number }}" name="phones" class="input an_phone" type="text" placeholder="تلفن">
|
<input disabled value="{{ phone_obj.phone_number }}" name="phones" class="input an_phone" type="text" placeholder="تلفن">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<a href="tel:{{ phone_obj.phone_number }}" class="button is-success" title="تماس با {{ phone_obj.phone_number }}">
|
||||||
|
📞
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
{% if perms.admin_panel.ViewStore %}
|
{% if perms.admin_panel.ViewStore %}
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button type="button" disabled class="button is-danger remove-phone-btn">-</button>
|
<button type="button" disabled class="button is-danger remove-phone-btn">-</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if not perms.admin_panel.ViewStore %}
|
|
||||||
<p class="pb-1 ss02">
|
|
||||||
<small class="has-text-grey">{{ phone_obj.title }}:</small> <a href="tel:{{ phone_obj.phone_number }}">{{ phone_obj.phone_number }}</a>
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if customer.phone1 %}
|
{% if customer.phone1 %}
|
||||||
<div class="field has-addons ss02 mt-2">
|
<div class="field has-addons ss02 mt-2">
|
||||||
<div class="control" style="width: 35%;">
|
<div class="control" style="width: 30%;">
|
||||||
<input disabled value="تلفن 1" name="phone_titles" class="input" type="text" placeholder="عنوان">
|
<input disabled value="تلفن 1" name="phone_titles" class="input" type="text" placeholder="عنوان">
|
||||||
</div>
|
</div>
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<input disabled value="{{ customer.phone1 }}" name="phones" class="input an_phone" type="text" placeholder="تلفن">
|
<input disabled value="{{ customer.phone1 }}" name="phones" class="input an_phone" type="text" placeholder="تلفن">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<a href="tel:{{ customer.phone1 }}" class="button is-success" title="تماس">
|
||||||
|
📞
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
{% if perms.admin_panel.ViewStore %}
|
{% if perms.admin_panel.ViewStore %}
|
||||||
<div class="control"><button type="button" disabled class="button is-danger remove-phone-btn">-</button></div>
|
<div class="control"><button type="button" disabled class="button is-danger remove-phone-btn">-</button></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -85,12 +89,17 @@
|
|||||||
|
|
||||||
{% if customer.phone2 %}
|
{% if customer.phone2 %}
|
||||||
<div class="field has-addons ss02 mt-2">
|
<div class="field has-addons ss02 mt-2">
|
||||||
<div class="control" style="width: 35%;">
|
<div class="control" style="width: 30%;">
|
||||||
<input disabled value="تلفن 2" name="phone_titles" class="input" type="text">
|
<input disabled value="تلفن 2" name="phone_titles" class="input" type="text">
|
||||||
</div>
|
</div>
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<input disabled value="{{ customer.phone2 }}" name="phones" class="input an_phone" type="text">
|
<input disabled value="{{ customer.phone2 }}" name="phones" class="input an_phone" type="text">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<a href="tel:{{ customer.phone2 }}" class="button is-success" title="تماس">
|
||||||
|
📞
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
{% if perms.admin_panel.ViewStore %}
|
{% if perms.admin_panel.ViewStore %}
|
||||||
<div class="control"><button type="button" disabled class="button is-danger remove-phone-btn">-</button></div>
|
<div class="control"><button type="button" disabled class="button is-danger remove-phone-btn">-</button></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -99,21 +108,24 @@
|
|||||||
|
|
||||||
{% if customer.phone3 %}
|
{% if customer.phone3 %}
|
||||||
<div class="field has-addons ss02 mt-2">
|
<div class="field has-addons ss02 mt-2">
|
||||||
<div class="control" style="width: 35%;">
|
<div class="control" style="width: 30%;">
|
||||||
<input disabled value="تلفن 3" name="phone_titles" class="input" type="text">
|
<input disabled value="تلفن 3" name="phone_titles" class="input" type="text">
|
||||||
</div>
|
</div>
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<input disabled value="{{ customer.phone3 }}" name="phones" class="input an_phone" type="text">
|
<input disabled value="{{ customer.phone3 }}" name="phones" class="input an_phone" type="text">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<a href="tel:{{ customer.phone3 }}" class="button is-success" title="تماس">
|
||||||
|
📞
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
{% if perms.admin_panel.ViewStore %}
|
{% if perms.admin_panel.ViewStore %}
|
||||||
<div class="control"><button type="button" disabled class="button is-danger remove-phone-btn">-</button></div>
|
<div class="control"><button type="button" disabled class="button is-danger remove-phone-btn">-</button></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if perms.admin_panel.ViewStore %}
|
{% if perms.admin_panel.ViewStore %}
|
||||||
<button type="button" disabled id="add-more-phone-edit" class="button is-small is-info mt-2 w-100 add-phone-btn">
|
<button type="button" disabled id="add-more-phone-edit" class="button is-small is-info mt-2 w-100 add-phone-btn">
|
||||||
+ افزودن شماره دیگر
|
+ افزودن شماره دیگر
|
||||||
|
|||||||
@@ -4,109 +4,204 @@
|
|||||||
|
|
||||||
{% block BodyCustomer1 %}
|
{% block BodyCustomer1 %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* استایلهای اختصاصی جدول و جستجوگر */
|
||||||
|
.sayyad-code {
|
||||||
|
font-family: monospace, monospace;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1e293b;
|
||||||
|
background-color: #f1f5f9;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.table th {
|
||||||
|
vertical-align: middle !important;
|
||||||
|
background-color: #f8fafc;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.table td {
|
||||||
|
vertical-align: middle !important;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.price-preview {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #2563eb;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 4px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* تنظیمات پاسخگویی هدر */
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.search-box {
|
||||||
|
flex-grow: 1;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.header-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch !important;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.header-actions {
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.search-box {
|
||||||
|
max-width: 100% !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.header-actions .button {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.table th, .table td {
|
||||||
|
padding: 0.5em 0.6em !important;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-responsive-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<div id="hesabdari" class="column is-12-mobile is-12-desktop">
|
<div id="hesabdari" class="column is-12-mobile is-12-desktop">
|
||||||
<h1 class="has-text-centered has-text-weight-bold toCurrency">
|
|
||||||
مانده چک و نسیه:
|
<div class="is-flex is-justify-content-space-between is-align-items-center mb-4 header-container">
|
||||||
|
<div>
|
||||||
|
<h1 class="title is-5 has-text-weight-bold mb-0">
|
||||||
|
مدیریت چکها و نسیهها
|
||||||
</h1>
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if perms.admin_panel.ViewStore %}
|
<div class="header-actions">
|
||||||
<!--<form method="post" action="{% url 'admin_panel:customerHesabdariAdd' customer.id %}" class="columns is-mobile is-multiline is-gapless mt-5 is-centered">
|
<div class="field mb-0 search-box">
|
||||||
{% csrf_token %}
|
<p class="control has-icons-left">
|
||||||
<div class="column is-12-mobile is-3-desktop">
|
<input class="input is-rounded is-small" type="text" id="checkSearchInput" placeholder="جستجو: ردیف چک یا صیادی...">
|
||||||
<span class="select is-fullwidth">
|
<span class="icon is-small is-left has-text-grey">
|
||||||
<select required name="typePy" >
|
<i class="fas fa-search"></i>
|
||||||
<option value="">خدمات یا نصب</option>
|
|
||||||
<option value="">هیچکدام</option>
|
|
||||||
<option value="khadamat">خدمات</option>
|
|
||||||
<option value="nasb">نصب</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-12-mobile is-3-desktop">
|
|
||||||
<span class="select is-fullwidth">
|
<button class="button is-primary is-rounded is-small" id="newSarresid">
|
||||||
<select required name="type" >
|
<span class="icon"><i class="fas fa-plus"></i></span>
|
||||||
<option value="">انتخاب کنید</option>
|
<span>افزودن سند جدید</span>
|
||||||
<option value="credit">تسویه بدهی قبلی</option>
|
</button>
|
||||||
<option value="debit">ایجاد بدهی جدید</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-12-mobile is-3-desktop ">
|
|
||||||
<input required name="price" class="input" type="number" placeholder="مبلغ را به تومان وارد کنید">
|
|
||||||
</div>
|
</div>
|
||||||
<div class=" column is-12-mobile is-4-desktop ">
|
|
||||||
<input required name="desc" class="input " type="text" placeholder="توضیحات">
|
{% if messages %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="notification is-{{ message.tags }} is-light mt-3 py-2">
|
||||||
|
<button class="delete"></button>
|
||||||
|
{{ message }}
|
||||||
</div>
|
</div>
|
||||||
<div class=" column is-12-mobile is-2-desktop">
|
{% endfor %}
|
||||||
<input type="submit" class="button is-primary" value="ثبت" />
|
|
||||||
</div>
|
|
||||||
</form>!-->
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<span class="button is-success mb-4" id="newSarresid">افزودن</span>
|
|
||||||
|
|
||||||
{% if all_sarresid %}
|
{% if all_sarresid %}
|
||||||
<div class="table-container column is-12-desktop is-12-mobile m-0">
|
<div class="table-responsive-wrapper">
|
||||||
<table class="table m-auto has-text-centered table is-bordered is-striped is-narrow is-fullwidth mojodiTB ">
|
<table class="table is-bordered is-striped is-hoverable is-fullwidth has-text-centered mb-0" id="sarresidTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="min-width: 150px;">مبلغ</th>
|
<th style="width: 50px;">#</th>
|
||||||
<th style="min-width: 100px;">نوع</th>
|
<th>مبلغ (تومان)</th>
|
||||||
<th style="min-width: 100px;">سررسید</th>
|
<th>نوع</th>
|
||||||
<th style="min-width: 100px;">ثبت</th>
|
<th>وضعیت</th>
|
||||||
<th style="min-width: 400px;">توضیحات</th>
|
<th>عملیات</th>
|
||||||
<th style="min-width: 100;">وضعیت</th>
|
<th>تاریخ سررسید</th>
|
||||||
<th style="min-width: 100;">وصول شد</th>
|
<th>ردیف چک</th>
|
||||||
|
<th>شناسه صیادی</th>
|
||||||
|
<th>صاحب حساب (تلفن)</th>
|
||||||
|
<th>توضیحات / فاکتور</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tfoot>
|
<tbody>
|
||||||
<tr>
|
|
||||||
<th class="toCurrency" style="min-width: 150px;">مبلغ</th>
|
|
||||||
<th style="min-width: 100px;">نوع</th>
|
|
||||||
<th style="min-width: 100px;">سررسید</th>
|
|
||||||
<th style="min-width: 100px;">ثبت</th>
|
|
||||||
<th style="min-width: 400px;">توضیحات</th>
|
|
||||||
<th style="min-width: 100;">وضعیت</th>
|
|
||||||
<th style="min-width: 100;">وصول شد</th>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody id="listPrds">
|
|
||||||
|
|
||||||
{% for sarresid in all_sarresid %}
|
{% for sarresid in all_sarresid %}
|
||||||
<tr class="IteamPrd">
|
<tr class="sarresid-row">
|
||||||
<td>
|
<td>{{ forloop.counter }}</td>
|
||||||
<span class="bedehkar toCurrency">{{ sarresid.price }}</span>
|
|
||||||
<span class=" is-hidden"></span>
|
|
||||||
</td>
|
|
||||||
<td class="">
|
|
||||||
{% if sarresid.type == 'check' %}چک{% endif %}
|
|
||||||
{% if sarresid.type == 'nesiye' %}نسیه{% endif %}
|
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<span class="has-text-weight-bold is-size-6 bedehkar toCurrency">{{ sarresid.price }}</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="">{{ sarresid.sarresidDT | toJalali }}</td>
|
|
||||||
<td class="">{{ sarresid.createdDT | toJalali }}</td>
|
<td>
|
||||||
<td class="desc">
|
{% if sarresid.type == 'check' %}
|
||||||
|
<span class="tag is-info is-light has-text-weight-bold">چک</span>
|
||||||
|
{% elif sarresid.type == 'nesiye' %}
|
||||||
|
<span class="tag is-warning is-light has-text-weight-bold">نسیه</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{% if sarresid.payStatus == "true" %}
|
||||||
|
<span class="has-text-success has-text-weight-bold is-size-7">
|
||||||
|
<i class="fas fa-check-circle"></i> وصول شد
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="has-text-danger has-text-weight-bold is-size-7">
|
||||||
|
<i class="fas fa-clock"></i> در انتظار
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{% if sarresid.payStatus == "false" %}
|
||||||
|
<button class="button is-danger is-small is-outlined VosolButton"
|
||||||
|
price="{{ sarresid.price }}"
|
||||||
|
type="{{ sarresid.type }}"
|
||||||
|
articlID="{{ sarresid.id }}">
|
||||||
|
وصول شد
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<span class="has-text-grey-light is-size-7">تسویه شده</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>{{ sarresid.sarresidDT | toJalali }}</td>
|
||||||
|
|
||||||
|
<td class="search-row-num has-text-weight-semibold">
|
||||||
|
{{ sarresid.check_row_number|default:"-" }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="search-sayyad-id">
|
||||||
|
{% if sarresid.check_sayyad_id %}
|
||||||
|
<span class="sayyad-code">{{ sarresid.check_sayyad_id }}</span>
|
||||||
|
{% else %}
|
||||||
|
-
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{% if sarresid.check_owner_name %}
|
||||||
|
<div class="has-text-dark has-text-weight-semibold is-size-7">{{ sarresid.check_owner_name }}</div>
|
||||||
|
{% if sarresid.check_owner_phone %}
|
||||||
|
<div class="has-text-grey is-size-7 mt-1" dir="ltr">{{ sarresid.check_owner_phone }}</div>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
-
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="has-text-right is-size-7">
|
||||||
{% if sarresid.desc %}
|
{% if sarresid.desc %}
|
||||||
{{ sarresid.desc }}
|
<p class="has-text-grey-dark">{{ sarresid.desc }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if sarresid.factor.id %}
|
{% if sarresid.factor.id %}
|
||||||
فاکتور شماره {{ sarresid.factor.id }}
|
<span class="tag is-small is-link is-light mt-1">فاکتور: {{ sarresid.factor.id }}</span>
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="">
|
|
||||||
{% if sarresid.payStatus == "true" %}پرداخت شده{% endif %}
|
|
||||||
{% if sarresid.payStatus == "false" %}پرداخت نشده{% endif %}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="">
|
|
||||||
{% if sarresid.payStatus == "false" %}
|
|
||||||
<span class="button is-danger VosolButton" price={{ sarresid.price }} type={{ sarresid.type }} articlID={{ sarresid.id }}>وصول شد</span>
|
|
||||||
{% else %}
|
|
||||||
<span>بله</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@@ -115,96 +210,131 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="notification is-warning is-light has-text-centered my-5">
|
||||||
|
هیچ سابقه چک یا نسیهای برای این مشتری ثبت نشده است.
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="modal modalAddNew" method="post" action="{% url 'admin_panel:addSarresid' customer.id %}">
|
<form class="modal modalAddNew" method="post" action="{% url 'admin_panel:addSarresid' customer.id %}" id="addSarresidForm">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">سررسید جدید</p>
|
<p class="modal-card-title">ثبت سررسید / چک جدید</p>
|
||||||
<button class="delete" aria-label="close"></button>
|
<button type="button" class="delete" aria-label="close"></button>
|
||||||
</header>
|
</header>
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
|
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">نوع</label>
|
<label class="label">نوع سند <span class="has-text-danger">*</span></label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select required class="reset_input" name="n_sarresidType">
|
<select required class="reset_input" name="n_sarresidType" id="sarresidTypeSelect">
|
||||||
<option></option>
|
<option value="">انتخاب کنید...</option>
|
||||||
<option value="check">چک</option>
|
<option value="check">چک بانکی</option>
|
||||||
<option value="nesiye">نسیه</option>
|
<option value="nesiye">نسیه / حساب دفتری</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">مبلغ</label>
|
<label class="label">مبلغ (تومان) <span class="has-text-danger">*</span></label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input name="n_sarresidPrice" required class="input reset_input" type="text" placeholder="واحد تومان">
|
<input id="formattedPriceInput" required class="input reset_input comma-separator" type="text" inputmode="numeric" placeholder="مثال: ۱,۰۰۰,۰۰۰">
|
||||||
|
<input type="hidden" name="n_sarresidPrice" id="realPriceInput" class="reset_input">
|
||||||
|
<span class="price-preview" id="priceInWords"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">تاریخ</label>
|
<label class="label">تاریخ سررسید <span class="has-text-danger">*</span></label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input name="xxxxxaaaa" required class="input reset_input" id="NewSarResid" type="text">
|
<input required class="input reset_input" id="NewSarResid" type="text" autocomplete="off" readonly style="cursor: pointer;" placeholder="برای انتخاب تاریخ کلیک کنید">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input required type="text" class="is-hidden reset_input" name="n_sarresidDateTime" id="NewSarResidVal">
|
<input type="hidden" name="n_sarresidDateTime" id="NewSarResidVal" class="reset_input">
|
||||||
|
|
||||||
|
<div id="check_extra_fields" style="display: none; background-color: #f8fafc; padding: 15px; border-radius: 8px; margin-top: 15px; border: 1px solid #cbd5e1;">
|
||||||
|
<p class="has-text-weight-bold mb-3 has-text-info">اطلاعات چک صیادی</p>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">شماره ردیف / سریال چک <span class="has-text-danger">*</span></label>
|
||||||
|
<div class="control">
|
||||||
|
<input name="check_row_number" class="input reset_input is-required-check" type="text" placeholder="مثال: 123456">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">شناسه صیادی (۱۶ رقم) <span class="has-text-danger">*</span></label>
|
||||||
|
<div class="control">
|
||||||
|
<input name="check_sayyad_id" class="input reset_input is-required-check" type="text" inputmode="numeric" pattern="[0-9]{16}" minlength="16" maxlength="16" placeholder="فقط اعداد ۱۶ رقمی" title="لطفاً دقیقاً ۱۶ رقم وارد کنید">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">نام و نامخانوادگی صاحب حساب <span class="has-text-danger">*</span></label>
|
||||||
|
<div class="control">
|
||||||
|
<input name="check_owner_name" class="input reset_input is-required-check" type="text" placeholder="نام مالک چک">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">تلفن مالک چک (اختیاری)</label>
|
||||||
|
<div class="control">
|
||||||
|
<input name="check_owner_phone" class="input reset_input" type="text" inputmode="numeric" pattern="[0-9]*" maxlength="11" placeholder="مثال: 09123456789">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
<input type="submit" class="button is-success" value="ثبت">
|
<button type="submit" class="button is-success">
|
||||||
|
<i class="fas fa-save ml-1"></i> ثبت اطلاعات
|
||||||
|
</button>
|
||||||
<span class="button cancellBTNSR">لغو</span>
|
<span class="button cancellBTNSR">لغو</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<form class="modal nesiyeModal" method="post" action="{% url 'admin_panel:pardakhtNesiye' customer.id %}" id="pardakhtNesiyeForm">
|
||||||
<form class="modal nesiyeModal" method="post" action="{% url 'admin_panel:pardakhtNesiye' customer.id %}">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">نسیه</p>
|
<p class="modal-card-title">پرداخت و تسویه نسیه</p>
|
||||||
<button class="delete" aria-label="close"></button>
|
<button type="button" class="delete" aria-label="close"></button>
|
||||||
</header>
|
</header>
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
|
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">مانده از این نسیه</label>
|
<label class="label">مانده فعلی از این نسیه (تومان)</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input id="priceBedehi" disabled class="input reset_input" type="text" placeholder="واحد تومان">
|
<input id="priceBedehi" disabled class="input reset_input has-text-weight-bold" type="text">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input name="sr_articlID" id="sr_articlID" class="input reset_input is-hidden" type="text">
|
<input name="sr_articlID" id="sr_articlID" class="input reset_input is-hidden" type="text">
|
||||||
|
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">مبلغ پرداختی فعلی</label>
|
<label class="label">مبلغ پرداختی فعلی (تومان) <span class="has-text-danger">*</span></label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input name="next_sarresidPrice" required class="input reset_input" type="text" placeholder="واحد تومان">
|
<input id="formattedNextPriceInput" required class="input reset_input comma-separator" type="text" inputmode="numeric" placeholder="مبلغ واریزی">
|
||||||
|
<input type="hidden" name="next_sarresidPrice" id="realNextPriceInput" class="reset_input">
|
||||||
|
<span class="price-preview" id="nextPriceInWords"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">نحوه پرداخت</label>
|
<label class="label">نحوه پرداخت <span class="has-text-danger">*</span></label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select required class="reset_input" name="nahvePardakht">
|
<select required class="reset_input" name="nahvePardakht">
|
||||||
<option></option>
|
<option value="">انتخاب کنید...</option>
|
||||||
<option value="naghd">نقد</option>
|
<option value="naghd">نقد</option>
|
||||||
<option value="kartbekart">کارت به کارت</option>
|
<option value="kartbekart">کارت به کارت</option>
|
||||||
<option value="kartkhan">کارت خوان</option>
|
<option value="kartkhan">کارت خوان</option>
|
||||||
@@ -215,26 +345,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">سررسید بعدی</label>
|
<label class="label">سررسید بعدی (برای مابقی حساب) <span class="has-text-danger">*</span></label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input name="xxxxxaaaa" required class="input reset_input" id="NextSarResid" type="text">
|
<input required class="input reset_input" id="NextSarResid" type="text" autocomplete="off" readonly style="cursor: pointer;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">توضیحات</label>
|
<label class="label">توضیحات</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<textarea name="desc_sar" class="input"></textarea>
|
<textarea name="desc_sar" class="input reset_input" rows="2" placeholder="توضیحات اختیاری..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input required type="text" class="is-hidden reset_input" name="next_sarresidDateTime" id="NextSarResidVal">
|
<input type="hidden" name="next_sarresidDateTime" id="NextSarResidVal" class="reset_input">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
<input type="submit" class="button is-success" value="ثبت">
|
<button type="submit" class="button is-success">ثبت و بروزرسانی</button>
|
||||||
<span class="button cancellBTNSR">لغو</span>
|
<span class="button cancellBTNSR">لغو</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
@@ -243,31 +371,94 @@
|
|||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
$("#newSarresid").click(function(){
|
// ----------------------------------------------------
|
||||||
$(".modalAddNew").addClass("is-active")
|
// جستجوگر زنده (Real-time Search)
|
||||||
|
// ----------------------------------------------------
|
||||||
|
$("#checkSearchInput").on("keyup", function() {
|
||||||
|
var value = $(this).val().toLowerCase();
|
||||||
|
$("#sarresidTable tbody tr").filter(function() {
|
||||||
|
var searchData = $(this).find('.search-row-num, .search-sayyad-id').text().toLowerCase();
|
||||||
|
$(this).toggle(searchData.indexOf(value) > -1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".modal-background").click(function(){
|
// ----------------------------------------------------
|
||||||
$(".modal").removeClass("is-active");
|
// فرمتبندی اعداد (۳ رقم ۳ رقم)
|
||||||
$('.reset_input').val('');
|
// ----------------------------------------------------
|
||||||
})
|
function formatNumber(num) {
|
||||||
$(".cancellBTNSR").click(function(){
|
return num.toString().replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
$(".modal").removeClass("is-active");
|
}
|
||||||
$('.reset_input').val('');
|
|
||||||
})
|
|
||||||
|
|
||||||
|
$(document).on('input', '.comma-separator', function() {
|
||||||
|
let val = $(this).val();
|
||||||
|
let rawVal = val.replace(/,/g, '');
|
||||||
|
|
||||||
|
if (rawVal && !isNaN(rawVal)) {
|
||||||
|
$(this).val(formatNumber(rawVal));
|
||||||
|
if ($(this).attr('id') === 'formattedPriceInput') {
|
||||||
|
$('#realPriceInput').val(rawVal);
|
||||||
|
$('#priceInWords').text(formatNumber(rawVal) + ' تومان');
|
||||||
|
} else if ($(this).attr('id') === 'formattedNextPriceInput') {
|
||||||
|
$('#realNextPriceInput').val(rawVal);
|
||||||
|
$('#nextPriceInWords').text(formatNumber(rawVal) + ' تومان');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(this).val('');
|
||||||
|
$('#realPriceInput, #realNextPriceInput').val('');
|
||||||
|
$('#priceInWords, #nextPriceInWords').text('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// مدیریت فرم و نمایش دینامیک چک
|
||||||
|
// ----------------------------------------------------
|
||||||
|
$("#sarresidTypeSelect").change(function(){
|
||||||
|
let selectedType = $(this).val();
|
||||||
|
if(selectedType === "check") {
|
||||||
|
$("#check_extra_fields").slideDown(250);
|
||||||
|
$(".is-required-check").prop('required', true);
|
||||||
|
} else {
|
||||||
|
$("#check_extra_fields").slideUp(250);
|
||||||
|
$(".is-required-check").prop('required', false);
|
||||||
|
$("#check_extra_fields input").val('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// حذف پیامهای سیستم
|
||||||
|
// ----------------------------------------------------
|
||||||
|
$('.notification .delete').click(function() {
|
||||||
|
$(this).parent().fadeOut();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// مودالها
|
||||||
|
// ----------------------------------------------------
|
||||||
|
$("#newSarresid").click(function(){
|
||||||
|
$(".modalAddNew").addClass("is-active");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".modal-background, .delete, .cancellBTNSR").click(function(){
|
||||||
|
$(".modal").removeClass("is-active");
|
||||||
|
$('.reset_input').val('');
|
||||||
|
$('#priceInWords, #nextPriceInWords').text('');
|
||||||
|
$("#check_extra_fields").hide();
|
||||||
|
$(".is-required-check").prop('required', false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// تقویم شمسی (اصلاح شده)
|
||||||
|
// ----------------------------------------------------
|
||||||
$("#NewSarResid").pDatepicker({
|
$("#NewSarResid").pDatepicker({
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
initialValueType: 'en',
|
initialValueType: 'en',
|
||||||
format: 'YYYY/MM/DD',
|
format: 'YYYY/MM/DD',
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
calendar: {
|
calendar: {
|
||||||
persian: {
|
persian: { locale: 'fa' }
|
||||||
locale: 'fa'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onSelect: (unix)=>{
|
onSelect: function(unix){
|
||||||
$("#NewSarResidVal").val(unix)
|
$("#NewSarResidVal").val(unix);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -277,31 +468,50 @@
|
|||||||
format: 'YYYY/MM/DD',
|
format: 'YYYY/MM/DD',
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
calendar: {
|
calendar: {
|
||||||
persian: {
|
persian: { locale: 'fa' }
|
||||||
locale: 'fa'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onSelect: (unix)=>{
|
onSelect: function(unix){
|
||||||
$("#NextSarResidVal").val(unix)
|
$("#NextSarResidVal").val(unix);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// اعتبارپردازی و اطمینان از مقداردهی قبل از Submit
|
||||||
|
// ----------------------------------------------------
|
||||||
|
$("#addSarresidForm").on("submit", function(e) {
|
||||||
|
if(!$("#NewSarResidVal").val()){
|
||||||
|
alert("لطفاً تاریخ سررسید را انتخاب کنید.");
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#pardakhtNesiyeForm").on("submit", function(e) {
|
||||||
|
if(!$("#NextSarResidVal").val()){
|
||||||
|
alert("لطفاً تاریخ سررسید بعدی را انتخاب کنید.");
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// عملیات وصول شد
|
||||||
|
// ----------------------------------------------------
|
||||||
$(".VosolButton").click(function(){
|
$(".VosolButton").click(function(){
|
||||||
|
var articlID = $(this).attr("articlID");
|
||||||
|
var type = $(this).attr("type");
|
||||||
|
var price = $(this).attr("price");
|
||||||
|
|
||||||
var articlID = $(this).attr("articlID")
|
if(type === "check"){
|
||||||
var type = $(this).attr("type")
|
if( confirm('آیا از وصول شدن این چک بانکی اطمینان دارید؟') ){
|
||||||
var price = $(this).attr("price")
|
if( confirm('با تایید شما، سند حسابداری تسویه این چک ثبت خواهد شد.') ){
|
||||||
|
|
||||||
if(type=="check"){
|
|
||||||
if( confirm('چک وصول شده؟') ){
|
|
||||||
if( confirm('در صورتی که از پاس شدن چک اطمینان دارید تایید کنید') ){
|
|
||||||
window.location.href = '/panel/passCheck/' + articlID;
|
window.location.href = '/panel/passCheck/' + articlID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$(".nesiyeModal").addClass("is-active");
|
$(".nesiyeModal").addClass("is-active");
|
||||||
$("#priceBedehi").val(price);
|
$("#priceBedehi").val(formatNumber(price));
|
||||||
$("#sr_articlID").val(articlID)
|
$("#sr_articlID").val(articlID);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+70
-19
@@ -2273,42 +2273,93 @@ def passCheck(request, articl_id):
|
|||||||
@login_required(login_url='/panel/p_login/')
|
@login_required(login_url='/panel/p_login/')
|
||||||
@permission_required('admin_panel.ViewStore', raise_exception=True)
|
@permission_required('admin_panel.ViewStore', raise_exception=True)
|
||||||
def addSarresid(request, cs_id):
|
def addSarresid(request, cs_id):
|
||||||
|
if request.method != 'POST':
|
||||||
|
return HttpResponseBadRequest("متد ارسالی نامعتبر است.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
customerObj = Customer.objects.get(id=cs_id)
|
customerObj = get_object_or_404(Customer, id=cs_id)
|
||||||
|
|
||||||
sarrresidUNIX = request.POST.get('n_sarresidDateTime', None)
|
# دریافت فیلدهای اصلی
|
||||||
sarresidPrice = request.POST.get('n_sarresidPrice', None)
|
sarrresidUNIX = request.POST.get('n_sarresidDateTime')
|
||||||
sarresidType = request.POST.get('n_sarresidType', None)
|
sarresidPrice = request.POST.get('n_sarresidPrice')
|
||||||
|
sarresidType = request.POST.get('n_sarresidType')
|
||||||
|
|
||||||
sarResidDateTime01 = datetime.datetime.fromtimestamp(int(sarrresidUNIX)/1000.0)
|
# دریافت و پاکسازی فیلدهای چک (جلوگیری از باگ فاصلههای خالی)
|
||||||
|
check_row_number = request.POST.get('check_row_number', '').strip()
|
||||||
|
check_sayyad_id = request.POST.get('check_sayyad_id', '').strip()
|
||||||
|
check_owner_name = request.POST.get('check_owner_name', '').strip()
|
||||||
|
check_owner_phone = request.POST.get('check_owner_phone', '').strip()
|
||||||
|
|
||||||
articleHesabDariObj = Article()
|
# --- لایه اول: اعتبارسنجی فیلدهای پایه ---
|
||||||
articleHesabDariObj.debit = int(sarresidPrice)
|
if not sarrresidUNIX or not sarresidPrice or not sarresidType:
|
||||||
articleHesabDariObj.credit = 0
|
messages.error(request, "لطفا فیلدهای اصلی (مبلغ، نوع و تاریخ) را پر کنید.")
|
||||||
articleHesabDariObj.desc = "بدهی بابت ثبت "
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
|
# --- لایه دوم: اعتبارسنجی دقیق و امنیتی فیلدهای چک ---
|
||||||
if sarresidType == "check":
|
if sarresidType == "check":
|
||||||
articleHesabDariObj.desc += " چک به صورت دستی "
|
if not check_row_number or not check_sayyad_id or not check_owner_name:
|
||||||
elif sarresidType == "nesiye":
|
messages.error(request, "برای ثبت چک، وارد کردن شماره ردیف، شناسه صیادی و نام مالک اجباری است.")
|
||||||
articleHesabDariObj.desc += " نسیه به صورت دستی "
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
|
# بررسی ۱۶ رقمی و عددی بودن شناسه صیادی
|
||||||
|
if not check_sayyad_id.isdigit() or len(check_sayyad_id) != 16:
|
||||||
|
messages.error(request, "شناسه صیادی باید دقیقاً ۱۶ رقم عدد باشد.")
|
||||||
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
|
# بررسی عددی بودن شماره تلفن (در صورت وارد شدن)
|
||||||
|
if check_owner_phone and not check_owner_phone.isdigit():
|
||||||
|
messages.error(request, "شماره تلفن مالک چک باید فقط شامل اعداد باشد.")
|
||||||
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
|
# تبدیل نوع دادهها با مدیریت خطا (جلوگیری از کرش سرور 500)
|
||||||
|
try:
|
||||||
|
sarResidDateTime01 = datetime.datetime.fromtimestamp(int(sarrresidUNIX) / 1000.0)
|
||||||
|
price_int = int(sarresidPrice.replace(',', ''))
|
||||||
|
except ValueError:
|
||||||
|
messages.error(request, "مقادیر تاریخ یا مبلغ نامعتبر است.")
|
||||||
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
|
# --- لایه سوم: ذخیرهسازی اتمیک (تضمین جامعیت دادهها) ---
|
||||||
|
with transaction.atomic():
|
||||||
|
# ۱. ثبت سند حسابداری
|
||||||
|
articleHesabDariObj = Article()
|
||||||
|
articleHesabDariObj.debit = price_int
|
||||||
|
articleHesabDariObj.credit = 0
|
||||||
articleHesabDariObj.customer = customerObj
|
articleHesabDariObj.customer = customerObj
|
||||||
|
articleHesabDariObj.user = request.user
|
||||||
|
|
||||||
|
if sarresidType == "check":
|
||||||
|
articleHesabDariObj.desc = f"بدهی بابت ثبت چک دستی (صیادی: {check_sayyad_id})"
|
||||||
|
elif sarresidType == "nesiye":
|
||||||
|
articleHesabDariObj.desc = "بدهی بابت ثبت نسیه دستی"
|
||||||
|
|
||||||
articleHesabDariObj.save()
|
articleHesabDariObj.save()
|
||||||
|
|
||||||
|
# ۲. ثبت سررسید / چک
|
||||||
sarresidINC = Sarresid()
|
sarresidINC = Sarresid()
|
||||||
sarresidINC.customer = customerObj
|
sarresidINC.customer = customerObj
|
||||||
sarresidINC.price = int(sarresidPrice)
|
sarresidINC.price = price_int
|
||||||
sarresidINC.payStatus = "false"
|
sarresidINC.payStatus = "false"
|
||||||
#check ya nesiye
|
|
||||||
sarresidINC.type = sarresidType
|
sarresidINC.type = sarresidType
|
||||||
sarresidINC.user = request.user
|
sarresidINC.user = request.user
|
||||||
sarresidINC.sarresidDT = sarResidDateTime01
|
sarresidINC.sarresidDT = sarResidDateTime01
|
||||||
|
|
||||||
|
if sarresidType == "check":
|
||||||
|
sarresidINC.check_row_number = check_row_number
|
||||||
|
sarresidINC.check_sayyad_id = check_sayyad_id
|
||||||
|
sarresidINC.check_owner_name = check_owner_name
|
||||||
|
sarresidINC.check_owner_phone = check_owner_phone
|
||||||
|
sarresidINC.desc = f"صیادی: {check_sayyad_id} | مالک: {check_owner_name} | تلفن: {check_owner_phone or 'ندارد'}"
|
||||||
|
|
||||||
sarresidINC.save()
|
sarresidINC.save()
|
||||||
|
|
||||||
return redirect(request.META.get('HTTP_REFERER'))
|
messages.success(request, "اطلاعات با موفقیت ثبت شد.")
|
||||||
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
except:
|
except Exception as e:
|
||||||
return HttpResponse("خطا در ثبت ")
|
logger.error(f"Error in addSarresid: {str(e)}", exc_info=True)
|
||||||
|
messages.error(request, "خطای سیستمی رخ داد. لطفا مجددا تلاش کنید.")
|
||||||
#return HttpResponse(customerObj.id)
|
return redirect(request.META.get('HTTP_REFERER', '/'))
|
||||||
|
|
||||||
@login_required(login_url='/panel/p_login/')
|
@login_required(login_url='/panel/p_login/')
|
||||||
@permission_required('admin_panel.ViewStore', raise_exception=True)
|
@permission_required('admin_panel.ViewStore', raise_exception=True)
|
||||||
|
|||||||
Reference in new issue
Block a user