add payment_link and banks
This commit is contained in:
1 parent
2ae79b1ca4
commit
de3135b588
100 files changed
+6167
-47
No files matched your search
@@ -0,0 +1,30 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% block title %}این لینک مربوط به حساب دیگری است | {{ site_branding.site_title }}{% endblock %}
|
||||
{% block extra_head %}
|
||||
<meta name="referrer" content="same-origin">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="{% static 'css/magic-link-confirmation.css' %}?v={{ static_asset_version }}">
|
||||
<script defer src="{% static 'js/magic-link-confirmation.js' %}?v={{ static_asset_version }}"></script>
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<main class="magic-confirmation magic-confirmation-shell">
|
||||
<div class="magic-confirmation-brand">{% include 'includes/auth_brand.html' with hide_copy=True %}</div>
|
||||
<section class="magic-confirmation-card" aria-labelledby="confirmation-title" aria-describedby="confirmation-description">
|
||||
<div class="magic-confirmation-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M10 17l5-5-5-5M15 12H3M14 3h5a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-5"/></svg>
|
||||
</div>
|
||||
<h1 id="confirmation-title">این لینک مربوط به حساب دیگری است</h1>
|
||||
<p id="confirmation-description">شما با حساب دیگری وارد سامانه شدهاید. برای مشاهده تیکت مرتبط با این لینک، از حساب فعلی خارج شوید. پس از خروج، تیکت بهصورت خودکار باز میشود و نیازی به ورود مجدد ندارید.</p>
|
||||
<form method="post" action="{{ request.path }}" class="magic-confirmation-actions" data-magic-confirmation>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="logout_and_open">
|
||||
<input type="hidden" name="account_id" value="{{ user.pk }}">
|
||||
<button type="submit" class="magic-confirmation-primary">خروج از حساب و مشاهده تیکت</button>
|
||||
<a class="magic-confirmation-cancel" href="{% url 'accounts:home' %}">انصراف از مشاهده این تیکت/پیام</a>
|
||||
<span class="magic-confirmation-status" role="status" aria-live="polite"></span>
|
||||
</form>
|
||||
</section>
|
||||
{% include 'includes/auth_footer.html' %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
+11
-4
@@ -13,8 +13,10 @@
|
||||
<link rel="stylesheet" href="{% static 'css/operations.css' %}?v={{ static_asset_version }}">
|
||||
<link rel="stylesheet" href="{% static 'css/dispatches.css' %}?v={{ static_asset_version }}">
|
||||
<script defer src="{% static 'vendor/htmx-2.0.3.min.js' %}?v={{ static_asset_version }}"></script><script defer src="{% static 'vendor/alpine-3.14.8.min.js' %}?v={{ static_asset_version }}"></script>
|
||||
{% block extra_head %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}
|
||||
{% if user.is_authenticated and user.account_type == 'STAFF' %}
|
||||
<div class="staff-shell">
|
||||
<aside class="staff-sidebar">
|
||||
@@ -33,6 +35,8 @@
|
||||
{% if staff_operations_access.contacts %}<a class="{% if active_staff_section == 'contacts' %}active{% endif %}" href="{% url 'staff_tickets:contacts' %}" {% if active_staff_section == 'contacts' %}aria-current="page"{% endif %}><span>♧</span><b>مخاطبان</b></a>{% endif %}
|
||||
{% if staff_operations_access.dispatches %}<a class="{% if active_staff_section == 'dispatches' %}active{% endif %}" href="{% url 'staff_tickets:dispatch_create' %}" {% if active_staff_section == 'dispatches' %}aria-current="page"{% endif %}><span>⇶</span><b>ارسال گروهی</b></a>{% endif %}
|
||||
{% if staff_operations_access.audit %}<a class="{% if active_staff_section == 'audit' %}active{% endif %}" href="{% url 'staff_tickets:magic_audit' %}" {% if active_staff_section == 'audit' %}aria-current="page"{% endif %}><span>⌁</span><b>ممیزی لینکها</b></a>{% endif %}
|
||||
{% if payment_can_view %}<a class="{% if active_staff_section == 'payments' %}active{% endif %}" href="{% url 'staff_payments:desk' %}" {% if active_staff_section == 'payments' %}aria-current="page"{% endif %}><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3h12v18l-3-2-3 2-3-2-3 2V3Zm3 5h6m-6 4h6m-6 4h3"/></svg><b>اعلامیه واریز</b><em data-payment-count data-count-url="{% url 'staff_payments:count' %}" aria-label="فیشهای در انتظار بررسی">{{ payment_pending_count }}</em></a>{% endif %}
|
||||
{% if payment_can_manage_banks %}<a class="{% if active_staff_section == 'banks' %}active{% endif %}" href="{% url 'staff_payments:banks' %}" {% if active_staff_section == 'banks' %}aria-current="page"{% endif %}><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="m3 8 9-5 9 5H3Zm3 3v7m6-7v7m6-7v7M3 21h18"/></svg><b>بانکها</b></a>{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
<div><div class="staff-profile"><span class="staff-profile-avatar">{{ user.staff_profile.display_name|default:user.username|slice:':1' }}</span><div><strong>{{ user.staff_profile.display_name|default:user.username }}</strong><span>{{ user.staff_profile.job_title|default:'کارشناس فروش' }}</span></div></div><div class="staff-developer-credit">{{ staff_sidebar_credit }}</div></div>
|
||||
@@ -40,7 +44,7 @@
|
||||
<div class="staff-main">
|
||||
<header class="staff-topbar"><div><small>{{ site_branding.staff_panel_label }}</small><h2>{% if active_tab_title %}{{ active_tab_title }}{% else %}{{ site_branding.staff_brand_subtitle }}{% endif %}</h2></div><div class="staff-topbar-actions"><span class="hidden text-xs text-ink/40 sm:block">{{ user.username }}</span><form method="post" action="{% url 'accounts:staff_logout' %}">{% csrf_token %}<button class="logout-button" type="submit">خروج</button></form></div></header>
|
||||
{% else %}
|
||||
<header class="site-header"><div class="header-inner"><a class="logo" href="{% if user.is_authenticated %}{% url 'tickets:list' %}{% else %}{% url 'accounts:login' %}{% endif %}">{% block header_logo %}<img class="header-company-logo" src="{{ company_logo_url }}?v={{ static_asset_version }}-{{ branding_version }}" alt="لوگوی شرکت" width="300" height="130">{% endblock %}<span class="logo-copy">{{ site_branding.header_title }}<small>{{ site_branding.header_subtitle }}</small></span></a>{% if user.is_authenticated %}<nav class="desktop-nav"><a href="{% url 'tickets:list' %}">درخواستهای من</a><a href="{% url 'accounts:profile' %}">پروفایل</a><form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button class="logout-button" type="submit">خروج</button></form></nav>{% endif %}</div></header>
|
||||
{% block customer_header %}<header class="site-header"><div class="header-inner"><a class="logo" href="{% if user.is_authenticated %}{% url 'payments:home' %}{% else %}{% url 'accounts:login' %}{% endif %}">{% block header_logo %}<img class="header-company-logo" src="{{ company_logo_url }}?v={{ static_asset_version }}-{{ branding_version }}" alt="لوگوی شرکت" width="300" height="130">{% endblock %}<span class="logo-copy">{{ site_branding.header_title }}<small>{{ site_branding.header_subtitle }}</small></span></a>{% if user.is_authenticated %}<nav class="desktop-nav"><a href="{% url 'tickets:list' %}">درخواستهای من</a><a href="{% url 'accounts:profile' %}">پروفایل</a><form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button class="logout-button" type="submit">خروج</button></form></nav>{% endif %}</div></header>{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
<main class="{% if user.is_authenticated and user.account_type == 'STAFF' %}staff-content{% else %}customer-main{% endif %}">{% for message in messages %}<div class="flash {{ message.tags }}" role="status">{{ message }}</div>{% endfor %}{% block content %}{% endblock %}</main>
|
||||
@@ -48,7 +52,7 @@
|
||||
|
||||
{% if user.is_authenticated and user.account_type == 'STAFF' %}
|
||||
</div>
|
||||
<nav class="staff-mobile-dock" aria-label="دسترسی سریع کارشناسان">
|
||||
{% block staff_mobile_navigation %}<nav class="staff-mobile-dock" aria-label="دسترسی سریع کارشناسان">
|
||||
<a class="{% if request.resolver_match.url_name == 'list' and active_tab == '' %}active{% endif %}" href="{% url 'staff_tickets:list' %}" {% if request.resolver_match.url_name == 'list' and active_tab == '' %}aria-current="page"{% endif %}><span class="dock-icon">⌂</span>میز کار</a>
|
||||
<a class="{% if request.resolver_match.url_name == 'list' and active_tab == 'new' %}active{% endif %}" href="{% url 'staff_tickets:list' %}?tab=new" {% if request.resolver_match.url_name == 'list' and active_tab == 'new' %}aria-current="page"{% endif %}><span class="dock-icon">◌</span>صف جدید</a>
|
||||
<a class="{% if request.resolver_match.url_name == 'list' and active_tab == 'waiting_staff' %}active{% endif %}" href="{% url 'staff_tickets:list' %}?tab=waiting_staff" {% if request.resolver_match.url_name == 'list' and active_tab == 'waiting_staff' %}aria-current="page"{% endif %}><span class="dock-icon">↺</span>پاسخ من</a>
|
||||
@@ -56,10 +60,12 @@
|
||||
<a class="{% if request.resolver_match.url_name == 'list' and active_tab == 'shared' %}active{% endif %}" href="{% url 'staff_tickets:list' %}?tab=shared" {% if request.resolver_match.url_name == 'list' and active_tab == 'shared' %}aria-current="page"{% endif %}><span class="dock-icon">◇</span>اشتراکها<em data-share-unread-count data-count-url="{% url 'staff_tickets:shares_count' %}"{% if not staff_unread_shares %} hidden{% endif %}>{{ staff_unread_shares }}</em></a>
|
||||
{% if staff_operations_access.contacts %}<a class="{% if active_staff_section == 'contacts' %}active{% endif %}" href="{% url 'staff_tickets:contacts' %}" {% if active_staff_section == 'contacts' %}aria-current="page"{% endif %}><span class="dock-icon">♧</span>مخاطبان</a>{% endif %}
|
||||
{% if staff_operations_access.dispatches %}<a class="{% if active_staff_section == 'dispatches' %}active{% endif %}" href="{% url 'staff_tickets:dispatch_create' %}" {% if active_staff_section == 'dispatches' %}aria-current="page"{% endif %}><span class="dock-icon">⇶</span>گروهی</a>{% endif %}
|
||||
</nav>
|
||||
{% if payment_can_view %}<a class="{% if active_staff_section == 'payments' %}active{% endif %}" href="{% url 'staff_payments:desk' %}" {% if active_staff_section == 'payments' %}aria-current="page"{% endif %}><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3h12v18l-3-2-3 2-3-2-3 2V3Zm3 5h6m-6 4h6m-6 4h3"/></svg><b>اعلامیه واریز</b><em data-payment-count data-count-url="{% url 'staff_payments:count' %}" aria-label="فیشهای در انتظار بررسی">{{ payment_pending_count }}</em></a>{% endif %}
|
||||
{% if payment_can_manage_banks %}<a class="{% if active_staff_section == 'banks' %}active{% endif %}" href="{% url 'staff_payments:banks' %}" {% if active_staff_section == 'banks' %}aria-current="page"{% endif %}><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="m3 8 9-5 9 5H3Zm3 3v7m6-7v7m6-7v7M3 21h18"/></svg><b>بانکها</b></a>{% endif %}
|
||||
</nav>{% endblock %}
|
||||
</div>
|
||||
{% elif user.is_authenticated %}
|
||||
<nav class="mobile-dock customer-mobile-dock" aria-label="دسترسی سریع مشتری"><a class="{% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}active{% endif %}" href="{% url 'tickets:list' %}" {% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}aria-current="page"{% endif %}><span class="dock-icon">◎</span>درخواستها</a><a class="{% if request.resolver_match.url_name == 'new' %}active{% endif %}" href="{% url 'tickets:new' %}" {% if request.resolver_match.url_name == 'new' %}aria-current="page"{% endif %}><span class="dock-icon">+</span>درخواست جدید</a><a class="{% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}active{% endif %}" href="{% url 'accounts:profile' %}" {% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}aria-current="page"{% endif %}><span class="dock-icon">○</span>پروفایل</a><form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button type="submit"><span class="dock-icon">←</span>خروج</button></form></nav>
|
||||
{% if financial_page %}<nav class="mobile-dock customer-mobile-dock chaharsu-dock" aria-label="دسترسی سریع مشتری"><a href="{% url 'payments:home' %}" {% if request.resolver_match.url_name == 'home' %}class="active" aria-current="page"{% endif %}><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h7v7H3V3Zm11 0h7v7h-7V3ZM3 14h7v7H3v-7Zm11 0h7v7h-7v-7Z"/></svg>خدمات</a><a href="{% url 'tickets:list' %}"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h16v12H9l-5 4V5Zm4 4h8m-8 4h5"/></svg>درخواستها</a><a href="{% url 'accounts:profile' %}"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M16 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0ZM4 21v-2a8 8 0 0 1 16 0v2"/></svg>پروفایل</a></nav>{% else %} <nav class="mobile-dock customer-mobile-dock" aria-label="دسترسی سریع مشتری"><a class="{% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}active{% endif %}" href="{% url 'tickets:list' %}" {% if request.resolver_match.namespace == 'tickets' and request.resolver_match.url_name != 'new' %}aria-current="page"{% endif %}><span class="dock-icon">◎</span>درخواستها</a><a class="{% if request.resolver_match.url_name == 'new' %}active{% endif %}" href="{% url 'tickets:new' %}" {% if request.resolver_match.url_name == 'new' %}aria-current="page"{% endif %}><span class="dock-icon">+</span>درخواست جدید</a><a class="{% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}active{% endif %}" href="{% url 'accounts:profile' %}" {% if request.resolver_match.namespace == 'accounts' and request.resolver_match.url_name == 'profile' %}aria-current="page"{% endif %}><span class="dock-icon">○</span>پروفایل</a><form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button type="submit"><span class="dock-icon">←</span>خروج</button></form></nav>{% endif %}
|
||||
{% endif %}
|
||||
{% block pwa_install_prompt %}{% endblock %}
|
||||
<script src="{% static 'js/voice-recorder.js' %}?v={{ static_asset_version }}"></script><script src="{% static 'js/ui.js' %}?v={{ static_asset_version }}"></script><script src="{% static 'js/chat-coach.js' %}?v={{ static_asset_version }}"></script>
|
||||
@@ -67,4 +73,5 @@
|
||||
{% if user.is_authenticated and user.account_type == 'STAFF' %}<link rel="stylesheet" href="{% static 'css/staff-sharing.css' %}?v={{ static_asset_version }}"><script defer src="{% static 'js/staff-sharing.js' %}?v={{ static_asset_version }}"></script>{% endif %}
|
||||
{% block extra_scripts %}{% endblock %}
|
||||
{% block otp_script %}{% endblock %}
|
||||
{% endblock %}
|
||||
</body></html>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div class="pay-customer-summary">
|
||||
<strong>{% if customer.customer_profile.first_name or customer.customer_profile.last_name %}{{ customer.customer_profile.first_name }} {{ customer.customer_profile.last_name }}{% else %}{{ customer.get_full_name|default:'نام ثبت نشده' }}{% endif %}</strong>
|
||||
<span><bdi>{{ customer.local_mobile }}</bdi>{% if customer.customer_profile.province %} · {{ customer.customer_profile.province }}{% endif %}{% if customer.customer_profile.city %} · {{ customer.customer_profile.city }}{% endif %}</span>
|
||||
</div>
|
||||
@@ -0,0 +1,12 @@
|
||||
<section class="pay-customer-picker pay-field-wide" data-payment-customer-picker data-search-url="{% url 'staff_payments:customer_search' %}" aria-label="انتخاب مشتری">
|
||||
{{ form.customer }}
|
||||
<label for="payment-customer-search">جستوجو و انتخاب مشتری <span class="pay-required">الزامی</span></label>
|
||||
<div class="pay-search-input">{% include 'payments/_icon.html' with name='search' %}<input id="payment-customer-search" type="search" autocomplete="off" placeholder="نام، موبایل، سازمان یا شماره و موضوع تیکت" aria-describedby="payment-customer-help payment-customer-status"></div>
|
||||
<p id="payment-customer-help" class="pay-field-hint">نام و شماره تماس را تطبیق دهید؛ هیچ نتیجهای خودکار انتخاب نمیشود.</p>
|
||||
{% if form.customer.errors %}<div class="field-error" role="alert">{{ form.customer.errors }}</div>{% endif %}
|
||||
<p id="payment-customer-status" class="pay-field-hint" role="status" aria-live="polite">برای جستوجو حداقل دو حرف یا رقم وارد کنید.</p>
|
||||
<div class="pay-customer-results" data-customer-results aria-label="نتایج جستوجوی مشتری" hidden></div>
|
||||
<div class="pay-selected-customer" data-selected-customer hidden></div>
|
||||
{{ customer_selection|json_script:'payment-selected-customer' }}
|
||||
<noscript>{% if customer_selection %}<p class="pay-inline-note">مشتری انتخابشده: {{ customer_selection.name }} · <bdi>{{ customer_selection.mobile }}</bdi></p>{% else %}<p class="pay-inline-note">برای جستوجوی مشتری JavaScript مرورگر را فعال کنید. میتوانید از صفحه مخاطبان یا تیکت مشتری، فرم اعلامیه را با مشتری انتخابشده باز کنید.</p>{% endif %}</noscript>
|
||||
</section>
|
||||
@@ -0,0 +1,39 @@
|
||||
<section class="chaharsu customer-finance customer-receipt {% if staff_form %}pay-workspace pay-form-workspace staff-receipt-workspace{% endif %}">
|
||||
{% include 'payments/_link_status.html' %}
|
||||
<nav class="pay-breadcrumb" aria-label="مسیر صفحه">{% if staff_form %}<a href="{% url 'staff_payments:desk' %}">اعلامیهها و فیشها</a>{% elif payment_link_access.notice_id %}<a href="{% url 'payments:notice_detail' payment_link_access.notice.public_id %}">اعلامیه واریز</a>{% elif not payment_link_access %}<a href="{% url 'payments:home' %}">خدمات چهارسو</a>{% endif %}<span aria-hidden="true">/</span><span aria-current="page">ارسال فیش واریزی</span></nav>
|
||||
<header class="customer-finance-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='receipt' %}</span><div><h1>{% if staff_form %}ثبت فیش برای مشتری{% elif revision_version %}اصلاح فیش واریزی{% else %}ارسال فیش واریزی{% endif %}</h1><p>فیش را مستقل یا برای یکی از واریزهای اعلامشده ارسال کنید.</p>{% if staff_form %}{% include 'payments/_customer_identity.html' with customer=customer %}{% endif %}</div></header>
|
||||
<form id="receipt-form" class="customer-receipt-form pay-form" method="post" enctype="multipart/form-data" data-max-bytes="{{ max_bytes }}" novalidate>
|
||||
{% csrf_token %}{{ form.submission_key }}{% if revision_version %}<input type="hidden" name="version" value="{{ revision_version }}">{% endif %}
|
||||
<div id="receipt-errors" class="pay-errors" role="alert" {% if not form.errors %}hidden{% endif %}><strong>لطفاً این موارد را اصلاح کنید</strong><ul>{% for field in form %}{% for error in field.errors %}<li><a href="#{{ field.id_for_label }}">{{ error }}</a></li>{% endfor %}{% endfor %}{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
|
||||
<section class="pay-card" aria-labelledby="association-title">
|
||||
<h2 id="association-title">این فیش مربوط به کدام واریز است؟</h2>
|
||||
<fieldset class="pay-field receipt-mode-field" data-field="receipt_mode"><legend class="sr-only">نوع واریز</legend>
|
||||
<div class="customer-receipt-modes">{% for radio in form.receipt_mode %}<div class="customer-mode {% if radio.data.value == 'linked' %}recommended-mode{% endif %}"><label for="{{ radio.id_for_label }}">{{ radio.tag }}<strong>{{ radio.choice_label }}</strong></label><small>{% if radio.data.value == 'linked' %}با اعلامیه واریز کارشناس{% else %}بدون اعلامیه واریز{% endif %}</small></div>{% endfor %}</div>
|
||||
<p class="field-error" id="error-receipt_mode" {% if not form.receipt_mode.errors %}hidden{% endif %}>{% for error in form.receipt_mode.errors %}{{ error }}{% endfor %}</p>
|
||||
</fieldset>
|
||||
<p class="finance-guidance">{% if staff_form %}اعلامیه مشتری را انتخاب کنید تا مبلغ و حساب مقصد قابل تطبیق باشد؛ ثبت واریز مستقل نیز امکانپذیر است.{% else %}برای ثبت دقیقتر، از کارشناس بخواهید اعلامیه واریز ایجاد کند؛ این کار توصیه میشود و اجباری نیست.{% endif %}</p>
|
||||
{% if staff_form %}{% include 'payments/_receipt_field.html' with field=form.notice_id hint='موضوع، مبلغ و شماره فاکتور را با فیش مشتری تطبیق دهید.' %}{% elif payment_link_access %}{% include 'payments/_receipt_field.html' with field=form.notice_id hint='این لینک به اعلامیه مربوط به خودش دسترسی دارد؛ ارسال واریز مستقل نیز ممکن است.' %}{% else %}{% include 'payments/_receipt_field.html' with field=form.notice_id hint='۱۰ واریز اخیرِ تسویهنشده؛ برای واریزهای قدیمیتر، از صفحه شماره حسابها وارد شوید.' %}{% endif %}
|
||||
<div id="selected-payment" class="pay-supplement" hidden><h3 data-selected-notice-title></h3><p data-selected-notice-summary></p><p class="pay-deposit-warning" data-selected-deposit-warning hidden>هنگام واریز، حتماً شناسه واریز ارائهشده را در فرم بانکی، موبایلبانک یا اینترنتبانک وارد کنید؛ واریز بدون این شناسه معتبر نخواهد بود.</p><a class="pay-text-link" data-selected-notice-link>مشاهده اطلاعات و کپی شمارهها {% include 'payments/_icon.html' with name='arrow' %}</a></div>
|
||||
</section>
|
||||
<section class="pay-card" aria-labelledby="receipt-title">
|
||||
<h2 id="receipt-title">اطلاعات فیش پرداخت</h2><p class="pay-section-help">مبلغ، حساب مقصد، تاریخ کامل و تصویر فیش الزامیاند.</p>
|
||||
<div class="customer-field-grid">
|
||||
{% include 'payments/_receipt_field.html' with field=form.paid_amount hint='مبلغی که واقعاً پرداخت کردهاید؛ ممکن است با مبلغ اعلامشده متفاوت باشد.' %}
|
||||
{% include 'payments/_receipt_field.html' with field=form.tracking_number hint='شماره درجشده روی فیش بانکی' %}
|
||||
{% include 'payments/_receipt_field.html' with field=form.origin_bank %}
|
||||
{% include 'payments/_receipt_field.html' with field=form.destination_account hint='نام حسابی را که وجه به آن واریز کردهاید انتخاب کنید.' %}
|
||||
{% include 'payments/_receipt_field.html' with field=form.origin_other %}
|
||||
{% include 'payments/_receipt_field.html' with field=form.deposit_id hint='در صورت تمایل، شناسهای را که هنگام پرداخت وارد کردهاید بنویسید؛ ارسال فیش بدون تکمیل این فیلد نیز امکانپذیر است.' %}
|
||||
</div>
|
||||
<fieldset class="customer-date"><legend>تاریخ واریز <span class="pay-optional">شمسی · الزامی</span></legend><div class="customer-date-selects">{% include 'payments/_receipt_field.html' with field=form.paid_day %}{% include 'payments/_receipt_field.html' with field=form.paid_month %}{% include 'payments/_receipt_field.html' with field=form.paid_year %}</div><div class="customer-date-tools"><p class="pay-field-hint">تاریخ درجشده روی فیش را کامل انتخاب کنید.</p><button id="date-today" type="button" class="pay-today">امروز</button></div><p id="date-preview" aria-live="polite"></p><input id="paid-date-iso" type="hidden" name="paid_date" value=""></fieldset>
|
||||
<div class="pay-field customer-upload-field" data-field="receipt_image"><div class="customer-upload-zone">{% include 'payments/_icon.html' with name='upload' %}<label class="customer-file-button" for="{{ form.receipt_image.id_for_label }}">انتخاب تصویر فیش <span>الزامی</span></label>{{ form.receipt_image }}<p>تصویر JPG، PNG، GIF یا WEBP؛ حداکثر {{ max_bytes|filesizeformat }}.</p></div><p class="field-error" id="error-receipt_image" {% if not form.receipt_image.errors %}hidden{% endif %}>{% for error in form.receipt_image.errors %}{{ error }}{% endfor %}</p><div class="customer-file-selection" id="receipt-file-selection" hidden><p id="receipt-file-status" role="status" aria-live="polite"></p><button type="button" id="receipt-clear-file">حذف انتخاب</button></div><img id="receipt-file-preview" alt="پیشنمایش تصویر فیش" hidden></div>
|
||||
{% include 'payments/_receipt_field.html' with field=form.description %}
|
||||
<p id="receipt-summary" class="finance-guidance" role="status"></p><p role="status" id="form-status"></p>
|
||||
<div class="customer-receipt-actions"><button class="pay-button" id="submit-receipt" type="submit">ثبت و ارسال فیش</button>{% if staff_form %}<a class="pay-text-link" href="{% url 'staff_payments:desk' %}">انصراف و بازگشت</a>{% elif payment_link_access.notice_id %}<a class="pay-text-link" href="{% url 'payments:notice_detail' payment_link_access.notice.public_id %}">مشاهده اعلامیه واریز</a>{% elif not payment_link_access %}<a class="pay-text-link" href="{% url 'payments:notices' %}">مشاهده واریزهای اعلامشده {% include 'payments/_icon.html' with name='arrow' %}</a>{% endif %}</div>
|
||||
</section>
|
||||
</form>
|
||||
{% if not staff_form %}
|
||||
<div class="customer-service-footer">{% if not payment_link_access %}<a class="pay-text-link" href="{% url 'payments:home' %}">بازگشت به خدمات چهارسو</a>{% endif %}<a class="pay-text-link" href="{% url 'payments:receipt_list' %}">فیشهای من و وضعیت بررسی</a></div>
|
||||
{% endif %}
|
||||
{{ notice_data|json_script:'notice-data' }}{{ account_requirements|json_script:'account-requirements' }}
|
||||
</section>
|
||||
@@ -0,0 +1,7 @@
|
||||
<div class="pay-field {% if field.errors %}has-error{% endif %} {% if wide %}pay-field-wide{% endif %}">
|
||||
<label for="{{ field.id_for_label }}">{{ label|default:field.label }}{% if field.field.required %}<span class="pay-required">الزامی</span>{% else %}<span class="pay-optional">اختیاری</span>{% endif %}</label>
|
||||
{{ field }}
|
||||
{% if hint %}<p class="pay-field-hint">{{ hint }}</p>{% endif %}
|
||||
{% if field.help_text %}<p class="pay-field-hint">{{ field.help_text }}</p>{% endif %}
|
||||
{% if field.errors %}<div class="field-error" role="alert">{{ field.errors }}</div>{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
{# Local inline SVG paths: no icon font, CDN or external request. #}
|
||||
<svg class="cs-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
|
||||
{% if name == 'chat' %}<path d="M5 4h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H9l-6 3V6a2 2 0 0 1 2-2Z M7 9h10M7 13h6"/>
|
||||
{% elif name == 'receipt' %}<path d="M5 3h14v18l-3-2-4 2-4-2-3 2V3ZM9 8h6M9 12h6"/>
|
||||
{% elif name == 'bank' %}<path d="m3 7 9-4 9 4v3H3ZM5 10v7M10 10v7M14 10v7M19 10v7M3 17h18v4H3"/>
|
||||
{% elif name == 'plus' %}<path d="M12 5v14M5 12h14"/>
|
||||
{% elif name == 'upload' %}<path d="M12 16V3m-5 5 5-5 5 5M4 16v5h16v-5"/>
|
||||
{% elif name == 'copy' %}<rect x="8" y="8" width="12" height="13" rx="2"/><path d="M16 8V3H3v13h5"/>
|
||||
{% elif name == 'chevron-down' %}<path d="m6 9 6 6 6-6"/>
|
||||
{% elif name == 'history' %}<path d="M3 11a9 9 0 1 1 2 7M3 5v6h6M12 7v5l3 2"/>
|
||||
{% elif name == 'search' %}<circle cx="10" cy="10" r="6"/><path d="m15 15 6 6"/>
|
||||
{% elif name == 'filter' %}<path d="M4 7h16M7 12h10M10 17h4"/>
|
||||
{% elif name == 'user' %}<circle cx="12" cy="8" r="4"/><path d="M4 21v-2a8 8 0 0 1 16 0v2"/>
|
||||
{% elif name == 'edit' %}<path d="m15 4 5 5M4 20l5-1L21 7l-4-4L5 15l-1 5Z"/>
|
||||
{% elif name == 'chevron' %}<path d="m9 5 7 7-7 7"/>
|
||||
{% else %}<path d="M20 12H4m6-6-6 6 6 6"/>{% endif %}
|
||||
</svg>
|
||||
@@ -0,0 +1,2 @@
|
||||
{% load jalali %}
|
||||
{% if payment_link_access %}<div class="pay-link-status" role="note"><span>{% include 'payments/_icon.html' with name='receipt' %}مشاهده و ارسال فیش بدون نیاز به ورود</span><small>اعتبار دسترسی تا <time datetime="{{ payment_link_access.expires_at|date:'c' }}">{{ payment_link_access.expires_at|jalali_datetime }}</time></small></div>{% endif %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% load jalali humanize %}
|
||||
<section class="pay-linked-receipts" aria-label="فیشهای این واریز"><h3>فیشهای این واریز</h3>
|
||||
{% for linked_receipt in notice.related_receipts %}<article class="pay-linked-receipt">
|
||||
<div class="pay-linked-receipt-head"><a class="pay-text-link" href="{% url 'payments:receipt_detail' linked_receipt.public_id %}"><bdi>{{ linked_receipt.number }}</bdi>{% include 'payments/_icon.html' with name='arrow' %}</a><span class="pay-status {{ linked_receipt.status|lower }}">{{ linked_receipt.get_status_display }}</span></div>
|
||||
<p class="pay-linked-receipt-meta">{{ linked_receipt.current_amount|intcomma:False }} ریال · واریز {{ linked_receipt.current_paid_date|jalali_date }}</p>
|
||||
{% for vote in linked_receipt.review_decisions %}<p class="pay-linked-decision"><strong>{{ vote.get_action_display }} · {{ vote.actor_name }}</strong><time>{{ vote.created_at|jalali_datetime }}</time>{% if vote.reason %}<span>{{ vote.reason|truncatechars:160 }}</span>{% endif %}</p>{% empty %}<p class="pay-field-hint">فیش در انتظار بررسی است.</p>{% endfor %}
|
||||
<a class="pay-text-link" href="{% url 'payments:receipt_detail' linked_receipt.public_id %}">جزئیات فیش و سوابق بررسی</a>
|
||||
</article>{% empty %}<p class="pay-field-hint">هنوز فیشی برای این واریز ارسال نکردهاید.</p>{% endfor %}</section>
|
||||
@@ -0,0 +1,19 @@
|
||||
{% load jalali humanize %}
|
||||
{% if not staff_notice and not notice_page %}<article class="pay-notice-entry">{% endif %}
|
||||
<details class="pay-card payment-notice" {% if open_notice == notice.public_id|stringformat:'s' or staff_notice %}open{% endif %}>
|
||||
<summary><strong>{{ notice.subject }}</strong><b>{{ notice.amount|intcomma:False }} <span>ریال</span></b><small>{{ notice.number }} · {{ notice.created_at|jalali_date }}</small><span class="notice-state">{{ notice.settlement_label }}{% if notice.cancelled_at %} · لغو شده{% endif %}</span>{% include 'payments/_icon.html' with name='chevron-down' %}</summary>
|
||||
<div class="pay-details"><p class="notice-bank">{% if notice.account_snapshot.name %}{{ notice.account_snapshot.name }} · {% endif %}{{ notice.account_snapshot.bank }} · {{ notice.account_snapshot.holder }}</p>
|
||||
<dl class="payment-values">
|
||||
<div><dt>مبلغ (ریال)</dt><dd dir="ltr">{{ notice.amount|intcomma:False }}</dd><button type="button" data-copy="{{ notice.amount }}" class="pay-copy" aria-label="کپی مبلغ">{% include 'payments/_icon.html' with name='copy' %} کپی</button></div>
|
||||
{% if notice.account_snapshot.account_number %}<div><dt>شماره حساب</dt><dd dir="ltr">{{ notice.account_snapshot.account_number }}</dd><button type="button" data-copy="{{ notice.account_snapshot.account_number }}" class="pay-copy" aria-label="کپی شماره حساب">{% include 'payments/_icon.html' with name='copy' %} کپی</button></div>{% endif %}
|
||||
{% if notice.account_snapshot.iban %}<div><dt>شبا</dt><dd dir="ltr">{{ notice.account_snapshot.iban }}</dd><button type="button" data-copy="{{ notice.account_snapshot.iban }}" class="pay-copy" aria-label="کپی شبا">{% include 'payments/_icon.html' with name='copy' %} کپی</button></div>{% endif %}
|
||||
{% if notice.account_snapshot.card_number %}<div><dt>شماره کارت</dt><dd dir="ltr">{{ notice.account_snapshot.card_number }}</dd><button type="button" data-copy="{{ notice.account_snapshot.card_number }}" class="pay-copy" aria-label="کپی کارت">{% include 'payments/_icon.html' with name='copy' %} کپی</button></div>{% endif %}
|
||||
{% if notice.deposit_id %}<div class="pay-deposit-required"><dt>شناسه واریز · ضروری</dt><dd dir="ltr">{{ notice.deposit_id }}</dd><button type="button" data-copy="{{ notice.deposit_id }}" class="pay-copy" aria-label="کپی شناسه واریز">{% include 'payments/_icon.html' with name='copy' %} کپی</button></div>{% endif %}
|
||||
</dl>
|
||||
{% if notice.deposit_id %}<p class="pay-deposit-warning" role="note">هنگام واریز، حتماً شناسه واریز ارائهشده را در فرم بانکی، موبایلبانک یا اینترنتبانک وارد کنید؛ واریز بدون این شناسه معتبر نخواهد بود.</p>{% endif %}
|
||||
<!-- Supplementary details stay visible within the expanded notice. Complete copy uses ALL snapshot fields. -->
|
||||
<p>تأییدشده: {{ notice.approved_amount|intcomma:False }} ریال · باقیمانده: {{ notice.remaining_amount|intcomma:False }} ریال</p><section class="pay-supplement"><h3>اطلاعات تکمیلی و توضیحات</h3>{% if notice.invoice_number %}<p>فاکتور: {{ notice.invoice_number }}</p>{% endif %}<p>{{ notice.description|default:'توضیح دیگری اعلام نشده است.'|linebreaksbr }}</p></section>
|
||||
<div class="pay-actions">{% if not notice.cancelled_at and not staff_notice and notice.remaining_amount > 0 %}<a class="pay-button" href="{% url 'payments:receipt_new' %}?notice={{ notice.public_id }}">ارسال فیش این واریز</a>{% endif %}<button type="button" class="pay-button secondary" data-copy="{{ notice.copy_text }}">کپی کامل اطلاعات</button></div>
|
||||
{% if not staff_notice %}{% include 'payments/_linked_receipts.html' %}{% endif %}
|
||||
</div></details>
|
||||
{% if not staff_notice and not notice_page %}<a class="pay-notice-permalink pay-text-link" href="{% url 'payments:notice_detail' notice.public_id %}">جزئیات واریز و فیشها {% include 'payments/_icon.html' with name='arrow' %}</a></article>{% endif %}
|
||||
@@ -0,0 +1 @@
|
||||
{% if payment_can_create and customer.is_active %}<a class="payment-notice-shortcut" href="{% url 'staff_payments:notice_new' %}?customer={{ customer.public_id }}"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M5 3h14v18l-3-2-4 2-4-2-3 2V3ZM9 8h6M9 12h6"/></svg><span>ایجاد اعلامیه واریز</span></a>{% endif %}
|
||||
@@ -0,0 +1 @@
|
||||
{% if page_obj.paginator.num_pages > 1 %}<nav class="pay-pagination" aria-label="صفحهبندی">{% if page_obj.has_previous %}<a href="?{{ query_string }}&page={{ page_obj.previous_page_number }}">قبلی</a>{% endif %}<span>{{ page_obj.number }} از {{ page_obj.paginator.num_pages }}</span>{% if page_obj.has_next %}<a href="?{{ query_string }}&page={{ page_obj.next_page_number }}">بعدی</a>{% endif %}</nav>{% endif %}
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="pay-field" data-field="{{ field.name }}">
|
||||
<label for="{{ field.id_for_label }}">{{ field.label }}{% if field.field.required %}<span class="pay-optional">الزامی</span>{% endif %}</label>{{ field }}
|
||||
{% if field.name == 'paid_amount' %}<p id="amount-words" aria-live="polite"></p>{% endif %}
|
||||
{% if hint %}<p class="pay-field-hint">{{ hint }}</p>{% endif %}
|
||||
<p class="field-error" id="error-{{ field.name }}" {% if not field.errors %}hidden{% endif %}>{% for error in field.errors %}{{ error }}{% endfor %}</p>
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
{% load jalali humanize %}
|
||||
{% if payment_can_create or customer_notices %}
|
||||
<details class="ticket-notices">
|
||||
<summary><span class="ticket-notices-title"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M5 3h14v18l-3-2-4 2-4-2-3 2V3ZM9 8h6M9 12h6"/></svg>اعلامیه واریز</span><span class="ticket-notices-chevron" aria-hidden="true">⌄</span></summary>
|
||||
<div class="ticket-notices-content">
|
||||
{% include 'payments/_notice_shortcut.html' %}
|
||||
<p class="ticket-notices-caption">آخرین اعلامیههای این مشتری</p>
|
||||
<ul class="ticket-notices-list" aria-label="اعلامیههای اخیر مشتری">
|
||||
{% for notice in customer_notices %}
|
||||
<li><a class="ticket-notice-item" href="{% url 'staff_payments:notice_detail' notice.public_id %}">
|
||||
<strong>{{ notice.subject }}</strong>
|
||||
<span class="ticket-notice-meta"><bdi>{{ notice.number }}</bdi><time datetime="{{ notice.created_at|date:'c' }}">{{ notice.created_at|jalali_date }}</time></span>
|
||||
<span class="ticket-notice-meta"><span>{{ notice.amount|intcomma }} ریال</span><span class="ticket-notice-status {% if notice.cancelled_at %}is-cancelled{% elif notice.approved_total >= notice.amount %}is-settled{% endif %}">{% if notice.cancelled_at %}لغو شده{% elif notice.approved_total >= notice.amount %}تسویه شده{% elif notice.approved_total %}پرداخت جزئی{% else %}در انتظار واریز{% endif %}</span></span>
|
||||
</a></li>
|
||||
{% empty %}<li class="ticket-notices-empty">اعلامیه واریزی برای نمایش وجود ندارد.</li>{% endfor %}
|
||||
</ul>
|
||||
<a class="ticket-notices-more" href="{% url 'staff_payments:desk' %}?tab=notices&customer={{ customer.pk }}"><span>بیشتر</span><small>همه اعلامیههای این مشتری</small><span aria-hidden="true">←</span></a>
|
||||
</div>
|
||||
</details>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,45 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% load static %}
|
||||
{% block title %}بانکها و حسابهای شرکت{% endblock %}
|
||||
{% block content %}
|
||||
<section class="chaharsu pay-workspace">
|
||||
<header class="pay-page-head">
|
||||
<div class="pay-page-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='bank' %}</span><div><h1>بانکها و حسابهای شرکت</h1><p>حسابهای قابل انتخاب برای کارشناسان و مشتریان را مدیریت کنید.</p></div></div>
|
||||
<a class="pay-button" href="{% url 'staff_payments:bank_new' %}">{% include 'payments/_icon.html' with name='plus' %}ایجاد حساب</a>
|
||||
</header>
|
||||
<form class="pay-card pay-filter-panel" method="get">
|
||||
<div class="pay-filter-grid pay-bank-filters">
|
||||
<label class="pay-search-field">جستوجوی حساب<span class="pay-search-input">{% include 'payments/_icon.html' with name='search' %}<input type="search" name="q" value="{{ request.GET.q }}" placeholder="نام حساب، بانک یا صاحب حساب"></span></label>
|
||||
{% for flag in bank_flags %}<label>{{ flag.label }}<select name="{{ flag.key }}"><option value="">همه</option><option value="1" {% if flag.value == '1' %}selected{% endif %}>فعال</option><option value="0" {% if flag.value == '0' %}selected{% endif %}>غیرفعال</option></select></label>{% endfor %}
|
||||
<button class="pay-button" type="submit">جستوجو</button>
|
||||
</div>
|
||||
{% if request.GET.q or request.GET.is_active or request.GET.available_to_staff or request.GET.available_to_customers %}<div class="pay-filter-bottom"><a class="pay-reset" href="{% url 'staff_payments:banks' %}">پاک کردن فیلترها</a></div>{% endif %}
|
||||
</form>
|
||||
<form class="pay-bank-panel" method="post" action="{% url 'staff_payments:bank_bulk' %}" data-bank-selection>
|
||||
{% csrf_token %}
|
||||
<div class="pay-list-head"><h2>حسابهای شرکت</h2><span>{{ page_obj.paginator.count }} حساب</span></div>
|
||||
{% if page_obj %}
|
||||
<div class="pay-bank-table-head"><label class="pay-select-all"><input type="checkbox" data-select-all aria-label="انتخاب همه حسابهای این صفحه"><span>انتخاب همه</span></label><span>حساب و بانک</span><span>وضعیت کلی</span><span>کارشناسان</span><span>مشتریان</span><span>مدیریت</span></div>
|
||||
{% for account in page_obj %}
|
||||
<article class="pay-bank-row">
|
||||
<label class="pay-bank-select"><input type="checkbox" name="accounts" value="{{ account.pk }}" aria-label="انتخاب {{ account.name }}"></label>
|
||||
<div class="pay-bank-identity"><span class="pay-record-icon">{% include 'payments/_icon.html' with name='bank' %}</span><div><h3><a href="{% url 'staff_payments:bank_edit' account.public_id %}">{{ account.name }}</a></h3><p>{{ account.bank.name }} · {{ account.holder }}</p>{% if account.requires_deposit_id %}<span class="pay-identifier-badge">شناسه واریز الزامی</span>{% endif %}</div></div>
|
||||
<div class="pay-bank-flag"><span class="pay-mobile-label">وضعیت کلی</span><span class="pay-status {% if account.is_active %}approved{% else %}neutral{% endif %}">{{ account.is_active|yesno:'فعال,غیرفعال' }}</span></div>
|
||||
<div class="pay-bank-flag"><span class="pay-mobile-label">کارشناسان</span><span class="pay-status {% if account.is_active and account.available_to_staff %}approved{% else %}neutral{% endif %}">{% if not account.is_active %}غیرفعال{% else %}{{ account.available_to_staff|yesno:'فعال,غیرفعال' }}{% endif %}</span></div>
|
||||
<div class="pay-bank-flag"><span class="pay-mobile-label">مشتریان</span><span class="pay-status {% if account.is_active and account.available_to_customers %}approved{% else %}neutral{% endif %}">{% if not account.is_active %}غیرفعال{% else %}{{ account.available_to_customers|yesno:'فعال,غیرفعال' }}{% endif %}</span></div>
|
||||
<a class="pay-bank-edit" href="{% url 'staff_payments:bank_edit' account.public_id %}">{% include 'payments/_icon.html' with name='edit' %}ویرایش</a>
|
||||
</article>
|
||||
{% endfor %}
|
||||
<div class="pay-bulk-bar">
|
||||
<div class="pay-bulk-label"><strong>تغییر گروهی وضعیت</strong><span data-selection-count role="status" aria-live="polite">حسابهای موردنظر را انتخاب کنید.</span></div>
|
||||
<label>بخش موردنظر<select name="field"><option value="is_active">وضعیت کلی حساب</option><option value="available_to_staff">پنل کارشناسان</option><option value="available_to_customers">پنل مشتریان</option></select></label>
|
||||
<label>وضعیت جدید<select name="value"><option value="1">فعال</option><option value="0">غیرفعال</option></select></label>
|
||||
<button class="pay-button" type="submit" data-bulk-submit>اعمال بر انتخابشدهها</button>
|
||||
</div>
|
||||
<p class="pay-bank-hint">حساب غیرفعال کلی در هیچ پنلی قابل انتخاب نیست؛ تنظیم هر پنل جداگانه حفظ میشود.</p>
|
||||
{% else %}<div class="pay-empty"><span class="pay-empty-icon">{% include 'payments/_icon.html' with name='bank' %}</span><h3>{% if request.GET %}حسابی با این فیلترها پیدا نشد{% else %}هنوز حسابی تعریف نشده است{% endif %}</h3><p>{% if request.GET %}فیلترها را تغییر دهید یا پاک کنید.{% else %}برای شروع، اولین حساب شرکت را ایجاد کنید.{% endif %}</p></div>{% endif %}
|
||||
</form>
|
||||
{% include 'payments/_pagination.html' %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% block extra_scripts %}{{ block.super }}<script defer src="{% static 'js/chaharsu/bank-selection.js' %}?v={{ static_asset_version }}"></script>{% endblock %}
|
||||
@@ -0,0 +1,36 @@
|
||||
{% extends 'base.html' %}{% load static %}
|
||||
{% block extra_head %}<link rel="stylesheet" href="{% static 'css/chaharsu.css' %}?v={{ static_asset_version }}"><link rel="stylesheet" href="{% static 'css/payment-link.css' %}?v={{ static_asset_version }}">{% if payment_link_access %}<meta name="robots" content="noindex, nofollow"><meta name="referrer" content="same-origin">{% endif %}{% endblock %}
|
||||
{% block customer_header %}
|
||||
<header class="cs-header">
|
||||
<div class="cs-header-inner">
|
||||
<a class="cs-brand" href="{% if payment_link_access.notice_id %}{% url 'payments:notice_detail' payment_link_access.notice.public_id %}{% elif payment_link_access.receipt_id %}{% url 'payments:receipt_detail' payment_link_access.receipt.public_id %}{% else %}{% url 'payments:home' %}{% endif %}" aria-label="چهارسو، خدمات پرداخت">
|
||||
<img src="{{ company_logo_url }}?v={{ static_asset_version }}-{{ branding_version }}" alt="لوگوی شرکت" width="300" height="130">
|
||||
<span class="cs-brand-divider" aria-hidden="true"></span>
|
||||
<span><b>چهارسو</b><small>مرکز خدمات مشتریان</small></span>
|
||||
</a>
|
||||
<nav class="cs-nav" aria-label="منوی اصلی">
|
||||
{% if payment_link_access %}
|
||||
<a href="{% url 'payments:receipt_new' %}">ارسال فیش واریزی</a><a href="{% url 'payments:receipt_list' %}">فیشها و وضعیت بررسی</a>
|
||||
{% else %}
|
||||
<a href="{% url 'payments:home' %}" {% if request.resolver_match.url_name == 'home' %}aria-current="page"{% endif %}>خدمات چهارسو</a>
|
||||
<a href="{% url 'tickets:list' %}">درخواستهای من</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
<div class="cs-header-actions">
|
||||
{% if payment_link_access %}<span class="pay-link-session-label">دسترسی موقت پرداخت</span>{% else %}
|
||||
<a class="cs-profile" href="{% url 'accounts:profile' %}" aria-label="پروفایل من">{% include 'payments/_icon.html' with name='user' %}<span>پروفایل من</span></a>
|
||||
<form method="post" action="{% url 'accounts:logout' %}">{% csrf_token %}<button class="cs-logout" type="submit">خروج</button></form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{% endblock %}
|
||||
{% block staff_mobile_navigation %}
|
||||
<nav class="staff-mobile-dock pay-staff-dock {% if payment_can_manage_banks %}has-banks{% endif %}" aria-label="دسترسی سریع پرداختها">
|
||||
<a href="{% url 'staff_tickets:list' %}">{% include 'payments/_icon.html' with name='chat' %}میز کار</a>
|
||||
<a href="{% url 'staff_payments:desk' %}" {% if active_staff_section == 'payments' %}class="active" aria-current="page"{% endif %}>{% include 'payments/_icon.html' with name='receipt' %}واریزها</a>
|
||||
{% if payment_can_manage_banks %}<a href="{% url 'staff_payments:banks' %}" {% if active_staff_section == 'banks' %}class="active" aria-current="page"{% endif %}>{% include 'payments/_icon.html' with name='bank' %}بانکها</a>{% endif %}
|
||||
</nav>
|
||||
{% endblock %}
|
||||
{% block footer %}<footer class="cs-footer">{% if payment_link_access %}{{ site_branding.developer_credit_text }}{% else %}{{ developer_credit }}{% endif %}</footer>{% endblock %}
|
||||
{% block extra_scripts %}<script defer src="{% static 'js/chaharsu/payments.js' %}?v={{ static_asset_version }}"></script>{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% block title %}جزئیات واریز {{ notice.number }}{% endblock %}
|
||||
{% block content %}<section class="chaharsu customer-finance customer-accounts customer-notice-detail">
|
||||
{% include 'payments/_link_status.html' %}
|
||||
{% if not payment_link_access %}<nav class="pay-breadcrumb" aria-label="مسیر صفحه"><a href="{% url 'payments:notices' %}">شماره حسابها</a><span aria-hidden="true">/</span><span aria-current="page">جزئیات واریز</span></nav>{% endif %}
|
||||
<header class="customer-finance-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='bank' %}</span><div><h1>جزئیات واریز</h1><p>اطلاعات حساب، فیشهای ارسالی و سوابق بررسی این واریز</p></div></header>
|
||||
{% include 'payments/_notice.html' with notice_page=True %}
|
||||
<div class="customer-service-footer">{% if payment_link_access %}<a class="pay-text-link" href="{% url 'payments:receipt_new' %}?mode=independent">ارسال فیش واریز مستقل</a>{% else %}<a class="pay-text-link" href="{% url 'payments:notices' %}">بازگشت به واریزهای شما</a>{% endif %}<a class="pay-text-link" href="{% url 'payments:receipt_list' %}">فیشهای من و وضعیت بررسی</a></div>
|
||||
</section>{% endblock %}
|
||||
@@ -0,0 +1,59 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% load jalali humanize %}
|
||||
{% block title %}اعلامیهها و فیشهای واریزی{% endblock %}
|
||||
{% block content %}
|
||||
<section class="chaharsu pay-workspace">
|
||||
<header class="pay-page-head">
|
||||
<div class="pay-page-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='receipt' %}</span><div><h1>اعلامیهها و فیشهای واریزی</h1><p>اعلام اطلاعات واریز به مشتریان و بررسی فیشهای پرداخت</p></div></div>
|
||||
{% if can_create %}<div class="pay-head-actions"><a class="pay-button" href="{% url 'staff_payments:notice_new' %}">{% include 'payments/_icon.html' with name='plus' %}ایجاد اعلامیه واریز</a><a class="pay-button secondary" href="{% url 'staff_payments:receipt_customer' %}">ثبت فیش برای مشتری</a></div>{% endif %}
|
||||
</header>
|
||||
<nav class="pay-tabs pay-desk-tabs" aria-label="نمای پرداختها">
|
||||
<a href="?tab=receipts" {% if tab != 'notices' and not request.GET.mine %}aria-current="page"{% endif %}>فیشهای واریزی</a>
|
||||
<a href="?tab=notices" {% if tab == 'notices' %}aria-current="page"{% endif %}>اعلامیههای واریز</a>
|
||||
<a href="?tab=receipts&mine=1" {% if tab != 'notices' and request.GET.mine %}aria-current="page"{% endif %}>نیازمند اقدام من</a>
|
||||
</nav>
|
||||
<form method="get" class="pay-card pay-filter-panel">
|
||||
<input type="hidden" name="tab" value="{{ tab }}">
|
||||
{% if request.GET.mine %}<input type="hidden" name="mine" value="1">{% endif %}
|
||||
<div class="pay-filter-grid">
|
||||
<label class="pay-search-field">جستوجو<span class="pay-search-input">{% include 'payments/_icon.html' with name='search' %}<input type="search" name="q" value="{{ request.GET.q }}" placeholder="نام، موبایل، استان، شهر یا فاکتور"></span></label>
|
||||
<label>حساب مقصد<select name="account"><option value="">همه حسابها</option>{% for bank in banks %}<option value="{{ bank.pk }}" {% if request.GET.account == bank.pk|stringformat:'s' %}selected{% endif %}>{{ bank.name }}</option>{% endfor %}</select></label>
|
||||
{% if tab != 'notices' %}<label>وضعیت فیش<select name="status"><option value="">همه وضعیتها</option>{% for value,label in statuses %}<option value="{{ value }}" {% if request.GET.status == value %}selected{% endif %}>{{ label }}</option>{% endfor %}</select></label>{% else %}<label>وضعیت واریز<select name="notice_state"><option value="">همه واریزها</option><option value="pending" {% if request.GET.notice_state == 'pending' %}selected{% endif %}>تسویهنشده</option><option value="settled" {% if request.GET.notice_state == 'settled' %}selected{% endif %}>تسویه شده</option><option value="cancelled" {% if request.GET.notice_state == 'cancelled' %}selected{% endif %}>لغو شده</option></select></label>{% endif %}
|
||||
<button class="pay-button" type="submit">جستوجو</button>
|
||||
</div>
|
||||
<div class="pay-filter-bottom">
|
||||
<details class="pay-more-filters" {% if request.GET.kind or request.GET.from or request.GET.to %}open{% endif %}>
|
||||
<summary>{% include 'payments/_icon.html' with name='filter' %}فیلترهای بیشتر</summary>
|
||||
<div class="pay-extra-filters">
|
||||
{% if tab != 'notices' %}<label>نوع واریز<select name="kind"><option value="">همه فیشها</option><option value="independent" {% if request.GET.kind == 'independent' %}selected{% endif %}>واریز مستقل</option><option value="linked" {% if request.GET.kind == 'linked' %}selected{% endif %}>واریز مرتبط</option></select></label>{% endif %}
|
||||
<label>از تاریخ <small>(میلادی)</small><input type="date" name="from" value="{{ request.GET.from }}"></label>
|
||||
<label>تا تاریخ <small>(میلادی)</small><input type="date" name="to" value="{{ request.GET.to }}"></label>
|
||||
</div>
|
||||
</details>
|
||||
<a class="pay-reset" href="?tab={{ tab }}{% if request.GET.mine %}&mine=1{% endif %}">پاک کردن فیلترها</a>
|
||||
</div>
|
||||
</form>
|
||||
<section class="pay-records" aria-labelledby="pay-results-title">
|
||||
<div class="pay-list-head"><h2 id="pay-results-title">{% if tab == 'notices' %}اعلامیههای واریز{% elif request.GET.mine %}فیشهای نیازمند اقدام شما{% else %}فیشهای واریزی{% endif %}</h2><span>{{ page_obj.paginator.count }} مورد</span></div>
|
||||
{% for item in page_obj %}
|
||||
<article class="pay-record">
|
||||
<span class="pay-record-icon">{% include 'payments/_icon.html' with name='receipt' %}</span>
|
||||
<div class="pay-record-main">
|
||||
{% if tab == 'notices' %}<h3><a href="{% url 'staff_payments:notice_detail' item.public_id %}">{{ item.subject }}</a></h3><span class="pay-record-meta"><bdi>{{ item.number }}</bdi>{% if item.invoice_number %} · فاکتور {{ item.invoice_number }}{% endif %}</span>
|
||||
{% else %}<h3><a href="{% url 'staff_payments:receipt_detail' item.public_id %}"><bdi>{{ item.number }}</bdi></a></h3><span class="pay-record-meta">{% if item.notice %}مرتبط با {{ item.notice.subject }}{% else %}واریز مستقل{% endif %}</span>{% endif %}
|
||||
{% include 'payments/_customer_identity.html' with customer=item.customer %}
|
||||
<div class="pay-record-review">{% if tab == 'notices' %}<span>ایجادکننده: {{ item.created_by.staff_profile.display_name|default:item.created_by.get_full_name|default:item.created_by.username }}</span>{% for linked in item.related_receipts %}{% if linked.status == 'APPROVED' %}{% for vote in linked.review_decisions %}<span>تأیید فیش {{ linked.number }}: {{ vote.actor_name }}</span>{% endfor %}{% endif %}{% endfor %}{% else %}{% if item.notice %}<span>ایجادکننده اعلامیه: {{ item.notice.created_by.staff_profile.display_name|default:item.notice.created_by.get_full_name|default:item.notice.created_by.username }}</span>{% endif %}{% if item.status == 'APPROVED' %}{% for vote in item.review_decisions %}<span>تأییدکننده: {{ vote.actor_name }}</span>{% endfor %}{% endif %}{% endif %}</div>
|
||||
</div>
|
||||
<div class="pay-record-amount"><strong>{% if tab == 'notices' %}{{ item.amount|intcomma:False }}{% else %}{{ item.current_amount|intcomma:False }}{% endif %} <small>ریال</small></strong><time>{% if tab == 'notices' %}{{ item.created_at|jalali_datetime }}{% else %}واریز {{ item.current_paid_date|jalali_date }}{% endif %}</time></div>
|
||||
<div class="pay-record-side">
|
||||
{% if tab == 'notices' %}<span class="pay-status {% if item.cancelled_at %}neutral{% elif item.approved_amount >= item.amount %}approved{% else %}info{% endif %}">{% if item.cancelled_at %}لغو شده{% else %}{{ item.settlement_label }}{% endif %}</span><a class="pay-open" href="{% url 'staff_payments:notice_detail' item.public_id %}">مشاهده اعلامیه{% include 'payments/_icon.html' with name='arrow' %}</a>
|
||||
{% else %}<span class="pay-status {{ item.status|lower }}">{{ item.get_status_display }}</span><a class="pay-open" href="{% url 'staff_payments:receipt_detail' item.public_id %}">مشاهده و بررسی{% include 'payments/_icon.html' with name='arrow' %}</a>{% endif %}
|
||||
</div>
|
||||
</article>
|
||||
{% empty %}
|
||||
<div class="pay-empty"><span class="pay-empty-icon">{% include 'payments/_icon.html' with name='search' %}</span><h3>موردی پیدا نشد</h3><p>{% if request.GET.q or request.GET.status or request.GET.notice_state or request.GET.account or request.GET.kind or request.GET.from or request.GET.to %}فیلترها را تغییر دهید یا پاک کنید.{% elif request.GET.mine %}در حال حاضر فیشی برای اقدام شما وجود ندارد.{% elif tab == 'notices' %}اعلامیههای صادرشده برای مشتریان اینجا نمایش داده میشوند.{% else %}فیشهای ارسالی مشتریان برای بررسی اینجا نمایش داده میشوند.{% endif %}</p></div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% include 'payments/_pagination.html' %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,25 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% block title %}چهارسو · مرکز خدمات مشتریان{% endblock %}
|
||||
{% block content %}
|
||||
<section class="chaharsu chaharsu-home" aria-labelledby="services-title">
|
||||
<header class="chaharsu-heading"><h1 id="services-title">چهارسو</h1><p>خدمت موردنیازتان را انتخاب کنید.</p></header>
|
||||
<div class="service-grid">
|
||||
<section class="expert-service" aria-labelledby="expert-title">
|
||||
<div class="expert-service-head"><span class="service-icon">{% include 'payments/_icon.html' with name='chat' %}</span><h2 id="expert-title">ارتباط با کارشناسان</h2><p>سؤال بپرسید، درخواست ثبت کنید یا برای پیگیری و هماهنگی با کارشناسان در ارتباط باشید.</p></div>
|
||||
<div class="service-actions">
|
||||
<a class="pay-button light" href="{% url 'tickets:new' %}">{% include 'payments/_icon.html' with name='plus' %}ثبت درخواست</a>
|
||||
<a class="pay-button outline-light" href="{% url 'tickets:list' %}">{% include 'payments/_icon.html' with name='history' %}درخواستهای من</a>
|
||||
</div>
|
||||
</section>
|
||||
<a class="financial-service" href="{% url 'payments:receipt_new' %}">
|
||||
<span class="service-icon">{% include 'payments/_icon.html' with name='receipt' %}</span>
|
||||
<h2>ارسال فیش واریزی</h2><p>ثبت تصویر پرداخت برای بررسی و تأیید</p>
|
||||
<span class="service-link">صفحه ارسال فیش{% include 'payments/_icon.html' with name='arrow' %}</span>
|
||||
</a>
|
||||
<a class="financial-service" href="{% url 'payments:notices' %}">
|
||||
<span class="service-icon">{% include 'payments/_icon.html' with name='bank' %}</span>
|
||||
<h2>شماره حسابها</h2><p>حساب، شبا و شناسه واریز اعلامشده به شما</p>
|
||||
<span class="service-link">مشاهده حسابها{% include 'payments/_icon.html' with name='arrow' %}</span>
|
||||
</a>
|
||||
</div></section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,4 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% block title %}این لینک پرداخت مربوط به حساب دیگری است{% endblock %}
|
||||
{% block extra_head %}{{ block.super }}<meta name="robots" content="noindex, nofollow"><meta name="referrer" content="same-origin">{% endblock %}
|
||||
{% block body %}<main class="customer-main"><section class="chaharsu pay-link-message"><article class="pay-card"><h1>این لینک پرداخت مربوط به حساب دیگری است</h1><p>شما با حساب دیگری وارد شدهاید. برای مشاهده این اعلامیه و ارسال فیش بدون ورود، ابتدا از حساب فعلی خارج شوید.</p><form method="post" action="{{ request.path }}" class="pay-actions">{% csrf_token %}<input type="hidden" name="action" value="logout_and_open"><input type="hidden" name="account_id" value="{{ user.pk }}"><button class="pay-button" type="submit">خروج از حساب و مشاهده پرداخت</button><a class="pay-text-link" href="{% url 'accounts:home' %}">انصراف</a></form></article></section></main><footer class="cs-footer">{{ site_branding.developer_credit_text }}</footer>{% endblock %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% block title %}لینک پرداخت معتبر نیست{% endblock %}
|
||||
{% block customer_header %}<header class="cs-header"><div class="cs-header-inner"><div class="cs-brand"><img src="{{ company_logo_url }}?v={{ static_asset_version }}-{{ branding_version }}" alt="لوگوی شرکت" width="300" height="130"><span><b>چهارسو</b><small>مرکز خدمات مشتریان</small></span></div></div></header>{% endblock %}
|
||||
{% block content %}<section class="chaharsu pay-link-message"><article class="pay-card"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='bank' %}</span><h1>این لینک پرداخت معتبر نیست</h1><p>ممکن است زمان اعتبار لینک تمام شده باشد یا لینک ابطال شده باشد. برای دریافت لینک تازه با کارشناس تماس بگیرید، یا با حساب خود وارد شوید.</p><a class="pay-button" href="{% url 'accounts:login' %}?next={% url 'payments:notices' %}">ورود با شماره موبایل</a></article></section>{% endblock %}
|
||||
{% block footer %}<footer class="cs-footer">{{ site_branding.developer_credit_text }}</footer>{% endblock %}
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% load jalali %}
|
||||
{% block title %}اعلامیه {{ notice.number }}{% endblock %}
|
||||
{% block content %}
|
||||
<section class="chaharsu pay-workspace pay-detail-workspace">
|
||||
<a class="pay-back" href="{% url 'staff_payments:desk' %}?tab=notices">{% include 'payments/_icon.html' with name='chevron' %}اعلامیههای واریز</a>
|
||||
<header class="pay-page-head"><div class="pay-page-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='receipt' %}</span><div><h1>اعلامیه <bdi>{{ notice.number }}</bdi></h1><p>مشتری: <bdi>{{ notice.customer.local_mobile }}</bdi> · {{ notice.created_at|jalali_datetime }}</p></div></div><a class="pay-button" href="{% url 'staff_payments:receipt_new' notice.customer.public_id %}?notice={{ notice.public_id }}">{% include 'payments/_icon.html' with name='plus' %}ثبت فیش برای مشتری</a></header>
|
||||
<div class="pay-detail-grid">
|
||||
<div class="pay-notice-main">{% include 'payments/_notice.html' with staff_notice=True %}</div>
|
||||
<aside class="pay-detail-aside">
|
||||
{% if can_share_payment_link %}<section class="pay-card"><h2>لینک موقت پرداخت</h2><p class="pay-section-help">برای مشاهده اعلامیه و ارسال فیش، مشتری نیازی به ورود ندارد. پس از پایان اعتبار، میتوانید لینک تازه بسازید.</p>{% if payment_share_url %}<p class="pay-share-url" dir="ltr">{{ payment_share_url }}</p><button type="button" class="pay-button secondary" data-copy="{{ payment_share_url }}">کپی لینک پرداخت</button>{% endif %}<form method="post" action="{% url 'staff_payments:notice_payment_link' notice.public_id %}">{% csrf_token %}<button class="pay-button" type="submit">ساخت لینک تازه پرداخت</button></form></section>{% endif %}
|
||||
<section class="pay-card"><h2>فیشهای این اعلامیه</h2>{% for receipt in receipts %}<a class="pay-linked-record" href="{% url 'staff_payments:receipt_detail' receipt.public_id %}"><bdi>{{ receipt.number }}</bdi><span class="pay-status {{ receipt.status|lower }}">{{ receipt.get_status_display }}</span>{% include 'payments/_icon.html' with name='arrow' %}</a>{% empty %}<p class="pay-section-help">هنوز فیشی برای این اعلامیه ثبت نشده است.</p>{% endfor %}</section>
|
||||
<section class="pay-card"><h2>اطلاعرسانی پیامک</h2>{% for notification in notifications %}<div class="pay-notification-row"><strong>{{ notification.job.get_status_display }}</strong><span>وضعیت دریافت: {{ notification.job.get_delivery_status_display }}</span></div>{% empty %}<p class="pay-section-help">اطلاعرسانی ثبتشدهای وجود ندارد.</p>{% endfor %}</section>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends 'payments/base.html' %}{% block title %}شماره حسابها{% endblock %}
|
||||
{% block content %}<section class="chaharsu customer-finance customer-accounts">
|
||||
<nav class="pay-breadcrumb" aria-label="مسیر صفحه"><a href="{% url 'payments:home' %}">خدمات چهارسو</a><span aria-hidden="true">/</span><span aria-current="page">شماره حسابها</span></nav>
|
||||
<header class="customer-finance-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='bank' %}</span><div><h1>شماره حسابها</h1><p>اطلاعات هر واریز را ببینید، کپی کنید و فیش آن را ارسال کنید.</p></div></header>
|
||||
<p class="finance-guidance">از کارشناس بخواهید شماره حساب و شناسه واریز مرتبط را برای شما ارسال کند.</p>
|
||||
<div class="customer-list-heading"><h2>واریزهای شما</h2><span>{{ page_obj.paginator.count }} مورد</span></div>
|
||||
<form class="pay-search customer-notice-search" method="get"><label class="customer-search-box">{% include 'payments/_icon.html' with name='search' %}<input name="q" value="{{ query }}" placeholder="موضوع یا شماره فاکتور" aria-label="جستوجوی اعلامیه"></label><button class="pay-button">جستوجو</button>{% if query %}<a class="pay-text-link" href="{% url 'payments:notices' %}">حذف جستوجو</a>{% endif %}</form>
|
||||
{% for notice in page_obj %}{% include 'payments/_notice.html' %}{% empty %}<div class="pay-card customer-empty">{% include 'payments/_icon.html' with name='bank' %}<h2>{% if query %}واریزی پیدا نشد{% else %}هنوز اعلامیهای ندارید{% endif %}</h2><p>{% if query %}عبارت جستوجو را تغییر دهید.{% else %}پس از اعلام کارشناس، اطلاعات هر واریز اینجا نمایش داده میشود.{% endif %}</p></div>{% endfor %}
|
||||
{% include 'payments/_pagination.html' %}<div class="customer-service-footer"><a class="pay-text-link" href="{% url 'payments:home' %}">بازگشت به خدمات چهارسو</a><a class="pay-text-link" href="{% url 'payments:receipt_list' %}">فیشهای من و وضعیت بررسی</a></div></section>{% endblock %}
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends 'payments/base.html' %}
|
||||
{% load jalali humanize %}
|
||||
{% block title %}فیش {{ receipt.number }}{% endblock %}
|
||||
{% block content %}
|
||||
<section class="chaharsu {% if staff_detail %}pay-workspace pay-detail-workspace{% else %}customer-finance customer-receipt-detail{% endif %}">
|
||||
{% include 'payments/_link_status.html' %}
|
||||
{% if not staff_detail %}<nav class="pay-breadcrumb" aria-label="مسیر صفحه"><a href="{% if payment_link_access %}{% url 'payments:receipt_list' %}{% else %}{% url 'payments:notices' %}{% endif %}">{% if payment_link_access %}فیشهای این لینک{% else %}واریزهای شما{% endif %}</a><span>/</span><span aria-current="page">جزئیات فیش</span></nav>{% endif %}
|
||||
{% if staff_detail %}<a class="pay-back" href="{% url 'staff_payments:desk' %}">{% include 'payments/_icon.html' with name='chevron' %}فیشهای واریزی</a>{% endif %}
|
||||
<header class="pay-page-head"><div class="pay-page-title"><span class="pay-page-icon">{% include 'payments/_icon.html' with name='receipt' %}</span><div><h1>فیش <bdi>{{ receipt.number }}</bdi></h1>{% if staff_detail %}{% include 'payments/_customer_identity.html' with customer=receipt.customer %}<p class="pay-field-hint">نسخه {{ revision.version }}</p>{% endif %}</div></div><span class="pay-status {{ receipt.status|lower }}">{{ receipt.get_status_display }}</span></header>
|
||||
{% if revision.destination_mismatch %}<p class="pay-warning">حساب مقصد با اعلامیه متفاوت است؛ بررسی مغایرت لازم است.</p>{% endif %}
|
||||
{% if duplicate_image %}<p class="pay-warning">تصویر مشابه روی فیش دیگری ثبت شده است؛ پیش از تصمیم بررسی کنید.</p>{% endif %}
|
||||
<div class="{% if staff_detail %}pay-detail-grid{% endif %}">
|
||||
<div>
|
||||
<article class="pay-card"><div class="pay-receipt-total"><span>مبلغ پرداختشده</span><h2>{{ revision.amount|intcomma:False }} <small>ریال</small></h2><p>تاریخ پرداخت: {{ revision.paid_date|jalali_date }}</p></div>
|
||||
<dl class="pay-facts"><div><dt>حساب مقصد</dt><dd>{{ revision.account_snapshot.name }}</dd></div><div><dt>بانک مقصد</dt><dd>{{ revision.account_snapshot.bank }}</dd></div><div><dt>صاحب حساب</dt><dd>{{ revision.account_snapshot.holder }}</dd></div><div><dt>شناسه واریز</dt><dd><bdi>{{ revision.deposit_id|default:'اعلام نشده' }}</bdi></dd></div>{% if revision.origin_bank %}<div><dt>بانک مبدأ</dt><dd>{{ revision.origin_bank.name }}{% if revision.origin_other %} · {{ revision.origin_other }}{% endif %}</dd></div>{% endif %}{% if revision.tracking_number %}<div><dt>شماره پیگیری</dt><dd><bdi>{{ revision.tracking_number }}</bdi></dd></div>{% endif %}</dl>
|
||||
{% if staff_detail %}<h3 class="pay-section-title">اطلاعات مقصد ثبتشده</h3><dl class="pay-facts">{% if revision.account_snapshot.account_number %}<div><dt>شماره حساب مقصد ثبتشده</dt><dd dir="ltr">{{ revision.account_snapshot.account_number }}</dd></div>{% endif %}{% if revision.account_snapshot.iban %}<div><dt>شبای مقصد ثبتشده</dt><dd dir="ltr">{{ revision.account_snapshot.iban }}</dd></div>{% endif %}{% if revision.account_snapshot.card_number %}<div><dt>کارت مقصد ثبتشده</dt><dd dir="ltr">{{ revision.account_snapshot.card_number }}</dd></div>{% endif %}</dl><p class="pay-section-help">شمارههای ثبتشده را با تصویر فیش تطبیق دهید.</p>{% endif %}
|
||||
<section class="pay-supplement">{% if receipt.notice %}<h3>اعلامیه مرتبط</h3><p>{% if staff_detail %}<a href="{% url 'staff_payments:notice_detail' receipt.notice.public_id %}">{{ receipt.notice.number }}</a>{% else %}<a href="{% url 'payments:notice_detail' receipt.notice.public_id %}">{{ receipt.notice.number }}</a>{% endif %} · مبلغ اعلامشده: {{ receipt.notice.amount|intcomma:False }} ریال{% if receipt.notice.invoice_number %} · فاکتور {{ receipt.notice.invoice_number }}{% endif %}</p>{% else %}<p>واریز مستقل</p>{% endif %}{% if revision.description %}<h3>توضیحات پرداخت</h3><p>{{ revision.description|linebreaksbr }}</p>{% endif %}</section>
|
||||
</article>
|
||||
<article class="pay-card pay-image-card"><div class="pay-card-title"><h2>تصویر فیش واریز</h2><a class="pay-button secondary" href="{% url 'payments:receipt_image' receipt.public_id %}?version={{ revision.version }}&download=1">دریافت تصویر</a></div><a href="{% url 'payments:receipt_image' receipt.public_id %}?version={{ revision.version }}" target="_blank" rel="noopener"><img class="receipt-preview" src="{% url 'payments:receipt_image' receipt.public_id %}?version={{ revision.version }}" alt="تصویر فیش واریز"></a><p class="pay-section-help">برای مشاهده تصویر در اندازه اصلی، روی آن بزنید.</p></article>
|
||||
</div>
|
||||
<aside class="pay-detail-aside">
|
||||
{% if can_assign %}<form method="post" action="{% url 'staff_payments:assign_policy' receipt.public_id %}" class="pay-card">{% csrf_token %}<h2>تعیین تأییدکنندگان</h2><p class="pay-section-help">سیاست فعال تأیید را به این فیش اختصاص دهید.</p><button class="pay-button">اعمال سیاست فعال تأیید</button></form>{% endif %}
|
||||
{% if receipt.status == 'PENDING' or receipt.status == 'PARTIAL' %}{% if can_approve or can_senior %}<form class="pay-card pay-form pay-decision-form" method="post" action="{% url 'staff_payments:decision' receipt.public_id %}">{% csrf_token %}<input type="hidden" name="version" value="{{ revision.version }}"><h2>ثبت نتیجه بررسی</h2><p class="pay-section-help">پس از تطبیق مبلغ، حساب و تصویر فیش، تصمیم خود را ثبت کنید.</p><div class="pay-field"><label for="decision-reason">توضیحات و دلیل تأیید یا رد</label><textarea name="reason" id="decision-reason" aria-describedby="decision-help"></textarea><p id="decision-help" class="pay-field-hint">برای تأیید میتوانید توضیح بنویسید؛ برای رد، تأیید ارشد و مغایرت حساب، دلیل الزامی است.</p></div><p class="pay-inline-note">تأیید من تا پایان بررسیهای لازم، تأیید نهایی نیست.</p><div class="pay-decision-actions">{% if can_approve %}<button class="pay-button" name="action" value="APPROVE">ثبت تأیید من</button>{% endif %}{% if can_approve or can_senior %}<button class="pay-button pay-danger secondary" name="action" value="REJECT">رد فیش</button>{% endif %}{% if can_senior %}<button class="pay-button" name="action" value="SENIOR_APPROVE">تأیید نهایی ارشد</button>{% endif %}</div></form>{% endif %}{% endif %}
|
||||
{% if receipt.status == 'REJECTED' and not staff_detail %}<a class="pay-button" href="{% url 'payments:receipt_revise' receipt.public_id %}">اصلاح و ارسال دوباره فیش</a>{% endif %}
|
||||
<article class="pay-card"><h2>سوابق بررسی</h2><div class="pay-timeline">{% for vote in decisions %}<div class="pay-timeline-item"><strong>{{ vote.actor_name }}</strong><span>{{ vote.get_action_display }} · نسخه {{ vote.cycle.revision.version }}</span><time>{{ vote.created_at|jalali_datetime }}</time>{% if vote.reason %}<p>{{ vote.reason|linebreaksbr }}</p>{% else %}<p class="pay-field-hint">توضیحی ثبت نشده است.</p>{% endif %}</div>{% empty %}<p class="pay-section-help">هنوز تصمیمی ثبت نشده است.</p>{% endfor %}</div><h3 class="pay-section-title">نسخههای مدرک</h3>{% for item in versions %}<div class="pay-version-row"><a href="{% url 'payments:receipt_image' receipt.public_id %}?version={{ item.version }}">نسخه {{ item.version }}</a><div><time>{{ item.created_at|jalali_datetime }}</time><p class="pay-field-hint">{{ item.amount|intcomma:False }} ریال · واریز {{ item.paid_date|jalali_date }} · {{ item.cycle.get_status_display }}</p></div></div>{% endfor %}{% if revision_events %}<h3 class="pay-section-title">سوابق ارسال و اصلاح</h3>{% for event in revision_events %}<div class="pay-timeline-item"><strong>{{ event.actor_name }}</strong><span>{% if event.action == 'RECEIPT_REVISED' %}اصلاح و ارسال نسخه {{ event.details.version }}{% else %}ارسال فیش{% endif %}</span><time>{{ event.created_at|jalali_datetime }}</time></div>{% endfor %}{% endif %}{% if cycle.finalized_at %}<div class="pay-supplement"><h3>نهاییکننده</h3><p>{{ cycle.finalized_by.username }}</p><time>{{ cycle.finalized_at|jalali_datetime }}</time></div>{% endif %}</article>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'payments/base.html' %}{% load static %}{% block title %}{% if staff_form %}ثبت فیش برای مشتری{% else %}ارسال فیش واریزی{% endif %}{% endblock %}
|
||||
{% block content %}{% include 'payments/_customer_receipt_form.html' %}{% endblock %}
|
||||
{% block extra_scripts %}{{ block.super }}<script defer src="{% static 'js/chaharsu/receipt-amount.js' %}?v={{ static_asset_version }}"></script><script defer src="{% static 'js/chaharsu/receipt-form.js' %}?v={{ static_asset_version }}"></script><script defer src="{% static 'js/chaharsu/customer-receipt.js' %}?v={{ static_asset_version }}"></script>{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'payments/base.html' %}{% load jalali humanize %}
|
||||
{% block content %}<section class="chaharsu">{% include 'payments/_link_status.html' %}<div class="pay-actions"><h1>{% if payment_link_access %}فیشهای این لینک{% else %}فیشهای من{% endif %}</h1><a class="pay-button" href="{% url 'payments:receipt_new' %}">ارسال فیش جدید</a></div>
|
||||
{% for receipt in page_obj %}<article class="pay-card"><h2><a href="{% url 'payments:receipt_detail' receipt.public_id %}">{{ receipt.number }}</a></h2><p>{{ receipt.current_amount|intcomma:False }} ریال · {{ receipt.current_paid_date|jalali_date }}</p><p>{{ receipt.get_status_display }} · {% if receipt.notice %}{{ receipt.notice.subject }}{% else %}واریز مستقل{% endif %}</p><a href="{% url 'payments:receipt_detail' receipt.public_id %}">مشاهده فیش و سوابق بررسی</a></article>{% empty %}<p class="pay-card">هنوز فیشی ارسال نکردهاید.</p>{% endfor %}{% include 'payments/_pagination.html' %}</section>{% endblock %}
|
||||
@@ -0,0 +1,38 @@
|
||||
{% extends 'payments/base.html' %}{% load static %}
|
||||
{% block title %}{{ heading }}{% endblock %}
|
||||
{% block content %}
|
||||
<section class="chaharsu pay-workspace pay-form-workspace">
|
||||
<a class="pay-back" href="{% if form.bank %}{% url 'staff_payments:banks' %}{% else %}{% url 'staff_payments:desk' %}{% endif %}">{% include 'payments/_icon.html' with name='chevron' %}{% if form.bank %}بانکها و حسابها{% else %}اعلامیهها و فیشها{% endif %}</a>
|
||||
<header class="pay-page-head"><div class="pay-page-title"><span class="pay-page-icon">{% if form.bank %}{% include 'payments/_icon.html' with name='bank' %}{% else %}{% include 'payments/_icon.html' with name='receipt' %}{% endif %}</span><div><h1>{{ heading }}</h1><p>{% if form.bank %}اطلاعات حساب و دسترسی هر پنل را مشخص کنید.{% elif form.subject %}حساب مقصد و جزئیات واریز را برای مشتری اعلام کنید.{% else %}ابتدا مشتری را انتخاب کنید؛ در مرحله بعد اطلاعات فیش را وارد میکنید.{% endif %}</p></div></div></header>
|
||||
<form method="post" class="pay-card pay-form pay-staff-form">
|
||||
{% csrf_token %}
|
||||
{% if form.non_field_errors %}<div class="pay-errors" role="alert"><strong>اطلاعات را دوباره بررسی کنید</strong>{{ form.non_field_errors }}</div>{% endif %}
|
||||
{% for field in form.hidden_fields %}{% if field.name != 'customer' %}{{ field }}{% if field.errors %}<div class="field-error" role="alert">{{ field.errors }}</div>{% endif %}{% endif %}{% endfor %}
|
||||
{% if form.bank %}
|
||||
<fieldset class="pay-form-section"><legend>مشخصات حساب</legend><p class="pay-section-help">نام نمایشی، همان نامی است که کارشناسان و مشتریان هنگام انتخاب حساب میبینند.</p><div class="pay-form-grid">
|
||||
{% include 'payments/_field.html' with field=form.name %}{% include 'payments/_field.html' with field=form.bank %}
|
||||
{% include 'payments/_field.html' with field=form.holder wide=True %}
|
||||
{% include 'payments/_field.html' with field=form.account_number %}{% include 'payments/_field.html' with field=form.card_number %}
|
||||
{% include 'payments/_field.html' with field=form.iban wide=True hint='شبا را با IR و بدون فاصله وارد کنید.' %}
|
||||
</div><p class="pay-inline-note">حداقل یکی از شماره حساب، شبا یا شماره کارت را وارد کنید.</p></fieldset>
|
||||
<fieldset class="pay-form-section"><legend>تنظیمات و دسترسیها</legend><p class="pay-section-help">فعالبودن کلی حساب، شرط استفاده از آن در هر دو پنل است.</p><div class="pay-check-grid">
|
||||
<label class="pay-check-card">{{ form.is_active }}<span><strong>فعالبودن کلی حساب</strong><small>با غیرفعالکردن، حساب در هیچ پنلی قابل انتخاب نیست.</small>{{ form.is_active.errors }}</span></label>
|
||||
<label class="pay-check-card">{{ form.requires_deposit_id }}<span><strong>شناسه واریز الزامی است</strong><small>کارشناس باید شناسه واریز مشتری را هنگام صدور اعلامیه وارد کند.</small>{{ form.requires_deposit_id.errors }}</span></label>
|
||||
<label class="pay-check-card">{{ form.available_to_staff }}<span><strong>قابل انتخاب کارشناسان</strong><small>این حساب برای ایجاد اعلامیه واریز نمایش داده شود.</small>{{ form.available_to_staff.errors }}</span></label>
|
||||
<label class="pay-check-card">{{ form.available_to_customers }}<span><strong>قابل انتخاب مشتریان</strong><small>این حساب برای ثبت واریز مستقل در چهارسو نمایش داده شود.</small>{{ form.available_to_customers.errors }}</span></label>
|
||||
</div><div class="pay-sort-field">{% include 'payments/_field.html' with field=form.sort_order label='ترتیب نمایش' hint='عدد کوچکتر، حساب را بالاتر در فهرست قرار میدهد.' %}</div></fieldset>
|
||||
{% elif form.subject %}
|
||||
<fieldset class="pay-form-section"><legend>مشتری و حساب مقصد</legend><div class="pay-form-grid">{% include 'payments/_customer_picker.html' %}{% include 'payments/_field.html' with field=form.account wide=True %}</div></fieldset>
|
||||
<fieldset class="pay-form-section"><legend>جزئیات واریز</legend><div class="pay-form-grid">
|
||||
{% include 'payments/_field.html' with field=form.subject wide=True %}{% include 'payments/_field.html' with field=form.amount %}{% include 'payments/_field.html' with field=form.invoice_number %}
|
||||
<div class="pay-field pay-field-wide {% if form.deposit_id.errors %}has-error{% endif %}"><label for="{{ form.deposit_id.id_for_label }}">{{ form.deposit_id.label }}</label><div class="pay-identifier-control">{{ form.deposit_id }}<button type="button" class="pay-button secondary" id="generate-deposit-identifier" data-url="{% url 'staff_payments:generate_identifier' %}" aria-describedby="identifier-generation-status" disabled>{% include 'payments/_icon.html' with name='plus' %}تولید خودکار شناسه</button></div><p id="identifier-generation-status" class="pay-field-hint" role="status" aria-live="polite">ابتدا مشتری را انتخاب کنید؛ شناسه بر اساس شماره موبایل او تولید میشود.</p><div id="identifier-replacement" class="pay-supplement" hidden><p>شناسه پیشنهادی: <bdi id="identifier-candidate"></bdi></p><p class="pay-field-hint">شناسه فعلی حفظ شده است. برای جایگزینی، تأیید کنید.</p><div class="pay-actions"><button type="button" class="pay-button secondary" id="apply-deposit-identifier">جایگزینی شناسه</button><button type="button" class="pay-text-link" id="cancel-deposit-identifier">انصراف</button></div></div><p id="identifier-help" class="pay-field-hint" role="status">برای حسابهای شناسهدار، شناسه واریز مشتری الزامی است.</p>{% if form.deposit_id.errors %}<div class="field-error" role="alert">{{ form.deposit_id.errors }}</div>{% endif %}</div>
|
||||
{% include 'payments/_field.html' with field=form.description wide=True hint='توضیحات این بخش برای مشتری قابل مشاهده است.' %}
|
||||
</div><p class="pay-inline-note">پس از صدور اعلامیه، پیامک اطلاعرسانی برای مشتری در صف ارسال قرار میگیرد.</p></fieldset>
|
||||
{% else %}<fieldset class="pay-form-section"><legend>انتخاب مشتری</legend><div class="pay-form-grid">{% include 'payments/_customer_picker.html' %}</div></fieldset>{% endif %}
|
||||
<div class="pay-form-footer"><button class="pay-button" type="submit">{{ submit_label }}</button><a class="pay-button secondary" href="{% if form.bank %}{% url 'staff_payments:banks' %}{% else %}{% url 'staff_payments:desk' %}{% endif %}">انصراف</a></div>
|
||||
</form>
|
||||
{% if bank_account %}<details class="pay-delete-panel"><summary>حذف حساب</summary><form method="post" action="{% url 'staff_payments:bank_delete' bank_account.public_id %}">{% csrf_token %}<p>حساب «{{ bank_account.name }}» فقط در صورت نداشتن سابقه مالی حذف میشود. برای توقف استفاده، آن را غیرفعال کنید.</p><button class="pay-button pay-danger" type="submit">حذف حساب بدون سابقه</button></form></details>{% endif %}
|
||||
{% if identifier_accounts %}{{ identifier_accounts|json_script:'identifier-accounts' }}{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% block extra_scripts %}{{ block.super }}{% if form.subject %}<script defer src="{% static 'js/chaharsu/deposit-identifier.js' %}?v={{ static_asset_version }}"></script>{% endif %}{% if form.amount %}<script defer src="{% static 'js/chaharsu/receipt-amount.js' %}?v={{ static_asset_version }}"></script>{% endif %}{% if form.customer %}<script defer src="{% static 'js/chaharsu/customer-picker.js' %}?v={{ static_asset_version }}"></script>{% endif %}{% endblock %}
|
||||
@@ -4,5 +4,5 @@
|
||||
<section class="operations-hero"><div><p class="eyebrow">مرکز یکپارچه ارتباطات</p><h1>مخاطبان و مشتریان</h1><p>پرونده ارتباطی مشتریان، تأمینکنندگان و باربریها همراه با گروهها و وضعیت تیکتهای قابل مشاهده در یک نما.</p></div><div class="operations-hero-actions">{% if staff_operations_access.contact_groups %}<a class="button button-secondary" href="{% url 'staff_tickets:groups' %}">مدیریت گروهها</a>{% endif %}{% if can_add_contact %}<a class="button" href="{% url 'staff_tickets:contact_create' %}">+ مخاطب جدید</a>{% endif %}</div></section>
|
||||
<section class="operations-kpis" aria-label="آمار مخاطبان"><article><span class="kpi-icon">◎</span><div><b>{{ metrics.total }}</b><small>نتیجه قابل مشاهده</small></div></article><article><span class="kpi-icon is-blue">♙</span><div><b>{{ metrics.customers }}</b><small>مشتری</small></div></article><article><span class="kpi-icon is-amber">▣</span><div><b>{{ metrics.suppliers }}</b><small>تأمینکننده</small></div></article><article><span class="kpi-icon is-violet">⇄</span><div><b>{{ metrics.carriers }}</b><small>باربری</small></div></article><article><span class="kpi-icon is-coral">!</span><div><b>{{ metrics.needs_action }}</b><small>تیکت نیازمند اقدام</small></div></article></section>
|
||||
<section class="operations-panel"><form method="get" class="contact-filter-bar"><label class="contact-search"><span>⌕</span><input type="search" name="q" value="{{ request.GET.q }}" placeholder="جستوجو با نام، سازمان یا شماره همراه"></label><label><span>نوع مخاطب</span><select name="stakeholder_type"><option value="">همه انواع</option>{% for value,label in stakeholder_types %}<option value="{{ value }}" {% if request.GET.stakeholder_type == value %}selected{% endif %}>{{ label }}</option>{% endfor %}</select></label><label><span>گروه</span><select name="group"><option value="">همه گروهها</option>{% for group in groups %}<option value="{{ group.pk }}" {% if request.GET.group == group.pk|stringformat:'s' %}selected{% endif %}>{{ group.name }} ({{ group.contact_count }})</option>{% endfor %}</select></label><label><span>استان</span><select name="province"><option value="">همه استانها</option>{% for province in provinces %}<option value="{{ province }}" {% if request.GET.province == province %}selected{% endif %}>{{ province }}</option>{% endfor %}</select></label><button type="submit">اعمال فیلتر</button>{% if request.GET %}<a class="filter-reset" href="{% url 'staff_tickets:contacts' %}">پاککردن</a>{% endif %}</form>
|
||||
<div class="contact-result-meta"><div><b>{{ contacts|length }} مخاطب</b><small>مرتبشده بر اساس تیکتهای قابل مشاهده و آخرین ثبت</small></div>{% if staff_operations_access.contact_groups %}<a href="{% url 'staff_tickets:groups' %}">{{ groups|length }} گروه قابل دسترس ←</a>{% endif %}</div><div class="contact-card-grid">{% for contact in contacts %}{% with profile=contact.customer_profile %}<article class="contact-card"><header><span class="contact-avatar">{{ profile.first_name|default:contact.local_mobile|slice:':1' }}</span><div class="contact-identity"><h2>{{ profile|default:contact.local_mobile }}</h2><p>{% if profile %}{{ profile.organization_name|default:profile.get_stakeholder_type_display }}{% else %}مشتری{% endif %}</p></div><span class="contact-type type-{{ profile.stakeholder_type|lower }}">{{ profile.get_stakeholder_type_display }}</span></header><div class="contact-meta"><span dir="ltr">☎ {{ contact.local_mobile }}</span><span>⌖ {% if profile.city or profile.province %}{{ profile.city }}{% if profile.city and profile.province %}، {% endif %}{{ profile.province }}{% else %}موقعیت ثبت نشده{% endif %}</span></div><div class="contact-groups">{% for group in profile.visible_groups %}<span>{{ group.name }}</span>{% empty %}<small>بدون گروه قابل مشاهده</small>{% endfor %}</div><div class="contact-ticket-stats"><span><b>{{ contact.ticket_count }}</b>تیکت قابل مشاهده</span><span><b>{{ contact.active_count }}</b>فعال</span><span class="needs-action"><b>{{ contact.waiting_staff_count }}</b>نیازمند اقدام</span><span><b>{{ contact.resolved_count }}</b>مختومه</span></div><footer><a href="{% url 'staff_tickets:contact_edit' contact.public_id %}">ویرایش پرونده</a>{% include 'tickets/_voip_call_button.html' with customer=contact %}{% if staff_operations_access.create_ticket %}<a class="primary-action" href="{% url 'staff_tickets:create' %}?customer={{ contact.public_id }}">+ ثبت تیکت</a>{% endif %}</footer></article>{% endwith %}{% empty %}<div class="empty-state contact-empty"><span>⌕</span><h2>مخاطبی پیدا نشد</h2><p>فیلترها را تغییر دهید یا مخاطب جدیدی ثبت کنید.</p>{% if can_add_contact %}<a class="button" href="{% url 'staff_tickets:contact_create' %}">ثبت مخاطب جدید</a>{% endif %}</div>{% endfor %}</div></section></div>{% endblock %}
|
||||
<div class="contact-result-meta"><div><b>{{ contacts|length }} مخاطب</b><small>مرتبشده بر اساس تیکتهای قابل مشاهده و آخرین ثبت</small></div>{% if staff_operations_access.contact_groups %}<a href="{% url 'staff_tickets:groups' %}">{{ groups|length }} گروه قابل دسترس ←</a>{% endif %}</div><div class="contact-card-grid">{% for contact in contacts %}{% with profile=contact.customer_profile %}<article class="contact-card"><header><span class="contact-avatar">{{ profile.first_name|default:contact.local_mobile|slice:':1' }}</span><div class="contact-identity"><h2>{{ profile|default:contact.local_mobile }}</h2><p>{% if profile %}{{ profile.organization_name|default:profile.get_stakeholder_type_display }}{% else %}مشتری{% endif %}</p></div><span class="contact-type type-{{ profile.stakeholder_type|lower }}">{{ profile.get_stakeholder_type_display }}</span></header><div class="contact-meta"><span dir="ltr">☎ {{ contact.local_mobile }}</span><span>⌖ {% if profile.city or profile.province %}{{ profile.city }}{% if profile.city and profile.province %}، {% endif %}{{ profile.province }}{% else %}موقعیت ثبت نشده{% endif %}</span></div><div class="contact-groups">{% for group in profile.visible_groups %}<span>{{ group.name }}</span>{% empty %}<small>بدون گروه قابل مشاهده</small>{% endfor %}</div><div class="contact-ticket-stats"><span><b>{{ contact.ticket_count }}</b>تیکت قابل مشاهده</span><span><b>{{ contact.active_count }}</b>فعال</span><span class="needs-action"><b>{{ contact.waiting_staff_count }}</b>نیازمند اقدام</span><span><b>{{ contact.resolved_count }}</b>مختومه</span></div><footer><a href="{% url 'staff_tickets:contact_edit' contact.public_id %}">ویرایش پرونده</a>{% include 'tickets/_voip_call_button.html' with customer=contact %}{% if staff_operations_access.create_ticket %}<a class="primary-action" href="{% url 'staff_tickets:create' %}?customer={{ contact.public_id }}">+ ثبت تیکت</a>{% endif %}{% include 'payments/_notice_shortcut.html' with customer=contact %}</footer></article>{% endwith %}{% empty %}<div class="empty-state contact-empty"><span>⌕</span><h2>مخاطبی پیدا نشد</h2><p>فیلترها را تغییر دهید یا مخاطب جدیدی ثبت کنید.</p>{% if can_add_contact %}<a class="button" href="{% url 'staff_tickets:contact_create' %}">ثبت مخاطب جدید</a>{% endif %}</div>{% endfor %}</div></section></div>{% endblock %}
|
||||
{% block extra_scripts %}<script defer src="{% static 'js/voip-call.js' %}?v={{ static_asset_version }}"></script>{% endblock %}
|
||||
@@ -42,7 +42,7 @@
|
||||
</section>
|
||||
{% endif %}
|
||||
</main>
|
||||
<aside class="workspace-side customer-side" id="customer-info" data-workspace-panel><button type="button" class="panel-close" data-close-panel>×</button><section class="info-card"><p class="panel-index">مشتری</p><h3>{{ ticket.customer.customer_profile|default:'بدون نام' }}</h3><p class="mt-1 text-sm font-bold" dir="ltr">{{ ticket.customer.mobile }}</p><div class="info-list"><div class="info-row"><span>نوع مشتری</span><b>{{ ticket.customer.customer_profile.get_customer_type_display|default:'ثبت نشده' }}</b></div><div class="info-row"><span>موقعیت تیکت</span><b>{% if ticket.city %}{{ ticket.city }}، {{ ticket.province }}{% elif ticket.province %}{{ ticket.province }}{% else %}ثبت نشده{% endif %}</b></div><div class="info-row"><span>تعداد تیکت</span><b>{{ ticket.customer.customer_tickets.count }}</b></div></div></section><section class="info-card"><h3>سابقه اخیر</h3>{% for old in customer_history %}<div class="history-item"><b>{{ old.subject }}</b><span class="ticket-number">{{ old.ticket_number }}</span>{% if perms.tickets.view_all_tickets or old.owner == user or old.selected_expert == user %}<a class="back-link" href="{% url 'staff_tickets:detail' old.public_id %}">مشاهده ←</a>{% else %}<small class="muted">محتوای خصوصی</small>{% endif %}</div>{% empty %}<p class="muted mt-3">تیکت دیگری ثبت نشده است.</p>{% endfor %}</section></aside>
|
||||
<aside class="workspace-side customer-side" id="customer-info" data-workspace-panel><button type="button" class="panel-close" data-close-panel>×</button><section class="info-card"><p class="panel-index">مشتری</p><h3>{{ ticket.customer.customer_profile|default:'بدون نام' }}</h3><p class="mt-1 text-sm font-bold" dir="ltr">{{ ticket.customer.mobile }}</p><div class="info-list"><div class="info-row"><span>نوع مشتری</span><b>{{ ticket.customer.customer_profile.get_customer_type_display|default:'ثبت نشده' }}</b></div><div class="info-row"><span>موقعیت تیکت</span><b>{% if ticket.city %}{{ ticket.city }}، {{ ticket.province }}{% elif ticket.province %}{{ ticket.province }}{% else %}ثبت نشده{% endif %}</b></div><div class="info-row"><span>تعداد تیکت</span><b>{{ ticket.customer.customer_tickets.count }}</b></div></div>{% include 'payments/_ticket_notices.html' with customer=ticket.customer %}</section><section class="info-card"><h3>سابقه اخیر</h3>{% for old in customer_history %}<div class="history-item"><b>{{ old.subject }}</b><span class="ticket-number">{{ old.ticket_number }}</span>{% if perms.tickets.view_all_tickets or old.owner == user or old.selected_expert == user %}<a class="back-link" href="{% url 'staff_tickets:detail' old.public_id %}">مشاهده ←</a>{% else %}<small class="muted">محتوای خصوصی</small>{% endif %}</div>{% empty %}<p class="muted mt-3">تیکت دیگری ثبت نشده است.</p>{% endfor %}</section></aside>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'tickets/_image_viewer.html' %}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'base.html' %}{% load static %}
|
||||
{% block title %}{{ page_title }}{% endblock %}
|
||||
{% block content %}<div class="operations-page operations-templates">
|
||||
<section class="operations-hero"><div><p class="eyebrow">پیامرسانی استاندارد</p><h1>الگوهای پیامک واحدها</h1><p>متنهای تاییدشده دیتابیس را برای هر رویداد مدیریت و با متغیرهای امن شخصیسازی کنید.</p></div><div class="template-guide"><span>✦</span><div><b>متغیرهای کنترلشده</b><small>از ورود تگ نامعتبر جلوگیری میشود</small></div></div></section>
|
||||
<div class="template-layout"><section class="operations-panel"><header class="panel-heading"><div><small>کتابخانه واحدهای شما و fallback سیستم</small><h2>الگوهای موجود در دیتابیس</h2></div><span>{{ templates|length }} الگو</span></header><div class="template-card-list">{% for item in templates %}<article class="template-card"><span class="template-icon">✉</span><div><h3>{{ item.title }}</h3><p>{{ item.get_event_type_display }}</p><small>{% if item.unit %}{{ item.unit }}{% else %}الگوی عمومی سیستم{% endif %} · بروزرسانی {{ item.updated_at|date:'Y/m/d' }}</small></div><span class="status-pill {% if item.is_active %}is-success{% else %}is-muted{% endif %}">{% if item.is_active %}فعال{% else %}غیرفعال{% endif %}</span>{% if item.unit %}<a href="{% url 'staff_tickets:sms_template_edit' item.pk %}">ویرایش</a>{% else %}<span class="status-pill is-muted">Fallback</span>{% endif %}</article>{% empty %}<div class="empty-state"><span>✉</span><h3>هیچ الگویی در دیتابیس وجود ندارد</h3><p>migration دادههای پیشفرض را ایجاد میکند؛ وضعیت migration را بررسی کنید.</p></div>{% endfor %}</div></section>
|
||||
<aside class="operations-form-side template-editor"><header><span>{% if form.instance.pk %}✎{% else %}+{% endif %}</span><div><small>{% if form.instance.pk %}ویرایش الگو{% else %}ساخت الگو{% endif %}</small><h2>{% if form.instance.pk %}{{ form.instance.title }}{% else %}الگوی اختصاصی جدید{% endif %}</h2></div></header><form method="post" class="operations-form">{% csrf_token %}{% if form.non_field_errors %}<div class="create-form-errors">{{ form.non_field_errors }}</div>{% endif %}{% for field in form %}<label><span>{{ field.label }}</span>{{ field }}{{ field.errors }}</label>{% endfor %}<div class="variable-box"><b>متغیرهای قابل استفاده</b><div dir="ltr">{% for tag in allowed_tags %}<code>{% templatetag openvariable %}{{ tag }}{% templatetag closevariable %}</code>{% endfor %}</div></div><button type="submit">ذخیره الگوی پیامک</button>{% if form.instance.pk %}<a href="{% url 'staff_tickets:sms_templates' %}">انصراف از ویرایش</a>{% endif %}</form></aside></div>
|
||||
<aside class="operations-form-side template-editor"><header><span>{% if form.instance.pk %}✎{% else %}+{% endif %}</span><div><small>{% if form.instance.pk %}ویرایش الگو{% else %}ساخت الگو{% endif %}</small><h2>{% if form.instance.pk %}{{ form.instance.title }}{% else %}الگوی اختصاصی جدید{% endif %}</h2></div></header><form method="post" class="operations-form">{% csrf_token %}{% if form.non_field_errors %}<div class="create-form-errors">{{ form.non_field_errors }}</div>{% endif %}{% for field in form %}<label><span>{{ field.label }}</span>{{ field }}{{ field.errors }}</label>{% endfor %}<div class="variable-box"><b>متغیرهای قابل استفاده</b><div id="sms-allowed-tags" dir="ltr">{% for tag in allowed_tags %}<code>{% templatetag openbrace %}{{ tag }}{% templatetag closebrace %}</code>{% endfor %}</div></div><div class="variable-box"><b>متغیرهای رویدادهای مالی</b><div dir="ltr"><code>{recipient_name}</code> <code>{company_name}</code> <code>{notice_number}</code> <code>{receipt_number}</code> <code>{amount_rial}</code> <code>{invoice_number}</code> <code>{payment_link}</code></div></div><button type="submit">ذخیره الگوی پیامک</button>{% if form.instance.pk %}<a href="{% url 'staff_tickets:sms_templates' %}">انصراف از ویرایش</a>{% endif %}</form></aside></div>
|
||||
</div>{% endblock %}
|
||||
{% block extra_scripts %}{{ block.super }}{{ sms_tag_map|json_script:'sms-tag-map' }}<script defer src="{% static 'js/sms-template-tags.js' %}?v={{ static_asset_version }}"></script>{% endblock %}
|
||||
Reference in new issue
Block a user