1074 lines
		
	
	
	
		
			46 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			1074 lines
		
	
	
	
		
			46 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
{% extends '_base.html' %}
 | 
						|
{% load static %}
 | 
						|
{% load accounts_tags %}
 | 
						|
{% load common_tags %}
 | 
						|
 | 
						|
{% block sidebar %}
 | 
						|
    {% include 'sidebars/admin.html' %}
 | 
						|
{% endblock sidebar %}
 | 
						|
 | 
						|
{% block navbar %}
 | 
						|
    {% include 'navbars/admin.html' %}
 | 
						|
{% endblock navbar %}
 | 
						|
 | 
						|
 | 
						|
{% block title %}درخواستها{% endblock %}
 | 
						|
 | 
						|
{% block style %}
 | 
						|
<!-- DataTables CSS -->
 | 
						|
<link rel="stylesheet" href="{% static 'assets/vendor/libs/datatables-bs5/datatables.bootstrap5.css' %}">
 | 
						|
<link rel="stylesheet" href="{% static 'assets/vendor/libs/datatables-responsive-bs5/responsive.bootstrap5.css' %}">
 | 
						|
<link rel="stylesheet" href="{% static 'assets/vendor/libs/datatables-buttons-bs5/buttons.bootstrap5.css' %}">
 | 
						|
<!-- Persian Date Picker CSS -->
 | 
						|
<link rel="stylesheet" href="https://unpkg.com/persian-datepicker@latest/dist/css/persian-datepicker.min.css">
 | 
						|
 | 
						|
{% endblock style %}
 | 
						|
 | 
						|
 | 
						|
{% block content %}
 | 
						|
{% include '_toasts.html' %}
 | 
						|
 | 
						|
<div class="container-xxl flex-grow-1 container-p-y">
 | 
						|
 | 
						|
  <div class="row py-3 mb-4 card-header flex-column flex-md-row pb-0">
 | 
						|
    <div class="d-md-flex justify-content-between align-items-center dt-layout-start col-md-auto me-auto mt-0">
 | 
						|
      <h5 class="card-title mb-0 text-md-start text-center fw-bold">لیست درخواستها</h5>
 | 
						|
    </div>
 | 
						|
    <div class="d-md-flex justify-content-between align-items-center dt-layout-end col-md-auto ms-auto mt-0">
 | 
						|
      <div class="dt-buttons btn-group flex-wrap mb-0">
 | 
						|
        <div class="btn-group">
 | 
						|
          {% if not request.user|is_installer %}
 | 
						|
          <button class="btn btn-label-success me-2" type="button" onclick="exportToExcel()">
 | 
						|
            <span class="d-flex align-items-center gap-2">
 | 
						|
              <i class="bx bx-export me-sm-1"></i>
 | 
						|
              <span class="d-none d-sm-inline-block">خروجی اکسل</span>
 | 
						|
            </span>
 | 
						|
          </button>
 | 
						|
          {% endif %}
 | 
						|
          {% if request.user|is_broker %}
 | 
						|
          <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#requestModal">
 | 
						|
            <i class="bx bx-plus me-1"></i>
 | 
						|
            درخواست جدید
 | 
						|
          </button>
 | 
						|
          {% endif %}
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
 | 
						|
  <!-- Summary Cards -->
 | 
						|
  <div class="row g-4 mb-4">
 | 
						|
    <div class="col-sm-6 col-xl-3">
 | 
						|
      <div class="card">
 | 
						|
        <div class="card-body">
 | 
						|
          <div class="d-flex align-items-start justify-content-between">
 | 
						|
            <div class="content-left">
 | 
						|
              <span>کل درخواستها</span>
 | 
						|
              <div class="d-flex align-items-end mt-2">
 | 
						|
                <h4 class="mb-0 me-2">{{ total_count }}</h4>
 | 
						|
              </div>
 | 
						|
            </div>
 | 
						|
            <div class="avatar">
 | 
						|
              <span class="avatar-initial rounded bg-label-primary">
 | 
						|
                <i class="bx bx-list-ul bx-sm"></i>
 | 
						|
              </span>
 | 
						|
            </div>
 | 
						|
          </div>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <div class="col-sm-6 col-xl-3">
 | 
						|
      <div class="card">
 | 
						|
        <div class="card-body">
 | 
						|
          <div class="d-flex align-items-start justify-content-between">
 | 
						|
            <div class="content-left">
 | 
						|
              <span>تکمیلشده</span>
 | 
						|
              <div class="d-flex align-items-end mt-2">
 | 
						|
                <h4 class="mb-0 me-2">{{ completed_count }}</h4>
 | 
						|
              </div>
 | 
						|
            </div>
 | 
						|
            <div class="avatar">
 | 
						|
              <span class="avatar-initial rounded bg-label-success">
 | 
						|
                <i class="bx bx-badge-check bx-sm"></i>
 | 
						|
              </span>
 | 
						|
            </div>
 | 
						|
          </div>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <div class="col-sm-6 col-xl-3">
 | 
						|
      <div class="card">
 | 
						|
        <div class="card-body">
 | 
						|
          <div class="d-flex align-items-start justify-content-between">
 | 
						|
            <div class="content-left">
 | 
						|
              <span>در حال انجام</span>
 | 
						|
              <div class="d-flex align-items-end mt-2">
 | 
						|
                <h4 class="mb-0 me-2">{{ in_progress_count }}</h4>
 | 
						|
              </div>
 | 
						|
            </div>
 | 
						|
            <div class="avatar">
 | 
						|
              <span class="avatar-initial rounded bg-label-info">
 | 
						|
                <i class="bx bx-loader-circle bx-sm"></i>
 | 
						|
              </span>
 | 
						|
            </div>
 | 
						|
          </div>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
    <div class="col-sm-6 col-xl-3">
 | 
						|
      <div class="card">
 | 
						|
        <div class="card-body">
 | 
						|
          <div class="d-flex align-items-start justify-content-between">
 | 
						|
            <div class="content-left">
 | 
						|
              <span>در انتظار</span>
 | 
						|
              <div class="d-flex align-items-end mt-2">
 | 
						|
                <h4 class="mb-0 me-2">{{ pending_count }}</h4>
 | 
						|
              </div>
 | 
						|
            </div>
 | 
						|
            <div class="avatar">
 | 
						|
              <span class="avatar-initial rounded bg-label-warning">
 | 
						|
                <i class="bx bx-time bx-sm"></i>
 | 
						|
              </span>
 | 
						|
            </div>
 | 
						|
          </div>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
 | 
						|
  {% if access_denied %}
 | 
						|
  <div class="alert alert-warning d-flex align-items-center mb-3" role="alert">
 | 
						|
    <i class="bx bx-info-circle me-2"></i>
 | 
						|
    <div>شما به این بخش دسترسی ندارید.</div>
 | 
						|
  </div>
 | 
						|
  {% endif %}
 | 
						|
 | 
						|
  <div class="card mb-3">
 | 
						|
    <div class="card-body">
 | 
						|
      <form method="get" class="row g-2 align-items-end">
 | 
						|
        <div class="col-sm-6 col-md-3">
 | 
						|
          <label class="form-label">وضعیت درخواست</label>
 | 
						|
          <select class="form-select" name="status">
 | 
						|
            <option value="">همه</option>
 | 
						|
            {% for val, label in status_choices %}
 | 
						|
              <option value="{{ val }}" {% if filter_status == val %}selected{% endif %}>{{ label }}</option>
 | 
						|
            {% endfor %}
 | 
						|
          </select>
 | 
						|
        </div>
 | 
						|
        {% if request.user|is_admin or request.user|is_manager or request.user|is_accountant %}
 | 
						|
        <div class="col-sm-6 col-md-3">
 | 
						|
          <label class="form-label">امور</label>
 | 
						|
          <select class="form-select" name="affairs">
 | 
						|
            <option value="">همه</option>
 | 
						|
            {% for a in affairs_list %}
 | 
						|
              <option value="{{ a.id }}" {% if filter_affairs|default:''|stringformat:'s' == a.id|stringformat:'s' %}selected{% endif %}>{{ a.name }}</option>
 | 
						|
            {% endfor %}
 | 
						|
          </select>
 | 
						|
        </div>
 | 
						|
        {% endif %}
 | 
						|
        {% if request.user|is_admin or request.user|is_manager or request.user|is_accountant %}
 | 
						|
        <div class="col-sm-6 col-md-3">
 | 
						|
          <label class="form-label">کارگزار</label>
 | 
						|
          <select class="form-select" name="broker">
 | 
						|
            <option value="">همه</option>
 | 
						|
            {% for b in brokers_list %}
 | 
						|
              <option value="{{ b.id }}" {% if filter_broker|default:''|stringformat:'s' == b.id|stringformat:'s' %}selected{% endif %}>{{ b.name }}</option>
 | 
						|
            {% endfor %}
 | 
						|
          </select>
 | 
						|
        </div>
 | 
						|
        {% endif %}
 | 
						|
        <div class="col-sm-6 col-md-3">
 | 
						|
          <label class="form-label">مرحله فعلی</label>
 | 
						|
          <select class="form-select" name="step">
 | 
						|
            <option value="">همه</option>
 | 
						|
            {% for s in steps_list %}
 | 
						|
              <option value="{{ s.id }}" {% if filter_step|default:''|stringformat:'s' == s.id|stringformat:'s' %}selected{% endif %}>{{ s.process.name }} - {{ s.name }}</option>
 | 
						|
            {% endfor %}
 | 
						|
          </select>
 | 
						|
        </div>
 | 
						|
        <div class="col-12 d-flex gap-2 justify-content-end mt-3">
 | 
						|
          <button type="submit" class="btn btn-primary">
 | 
						|
            <i class="bx bx-filter-alt me-1"></i>
 | 
						|
            اعمال فیلتر
 | 
						|
          </button>
 | 
						|
          <a href="?" class="btn btn-outline-secondary">
 | 
						|
            <i class="bx bx-x me-1"></i>
 | 
						|
            حذف فیلتر
 | 
						|
          </a>
 | 
						|
        </div>
 | 
						|
      </form>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
  <div class="card">
 | 
						|
    <div class="card-datatable table-responsive">
 | 
						|
      <table id="requests-table" class="datatables-basic table border-top">
 | 
						|
        <thead>
 | 
						|
          <tr>
 | 
						|
            <th>شناسه</th>
 | 
						|
            <th>فرآیند</th>
 | 
						|
            <th>مرحله فعلی</th>
 | 
						|
            <th>شماره اشتراک آب</th>
 | 
						|
            <th>نماینده</th>
 | 
						|
            <th>استان</th>
 | 
						|
            <th>امور</th>
 | 
						|
            <th>پیشرفت</th>
 | 
						|
            <th>وضعیت</th>
 | 
						|
            <th>تاریخ نصب/تاخیر</th>
 | 
						|
            <th>تاریخ ایجاد</th>
 | 
						|
            <th>عملیات</th>
 | 
						|
          </tr>
 | 
						|
        </thead>
 | 
						|
        <tbody>
 | 
						|
          {% for item in instances_with_progress %}
 | 
						|
          <tr>
 | 
						|
            <td>{{ item.instance.code }}</td>
 | 
						|
            <td>{{ item.instance.process.name }}</td>
 | 
						|
            <td>
 | 
						|
              {% if item.instance.status == 'completed' %}
 | 
						|
                <a href="{% url 'processes:instance_summary' item.instance.id %}" class="text-primary">{{ item.instance.current_step.name|default:"--" }}</a>
 | 
						|
              {% elif item.instance.current_step %}
 | 
						|
                <a href="{% url 'processes:instance_steps' item.instance.id %}" class="text-primary">{{ item.instance.current_step.name }}</a>
 | 
						|
                {% if item.current_step_approval_status %}
 | 
						|
                  <br>
 | 
						|
                  <small class="{% if item.current_step_approval_status.status == 'rejected' %}text-danger{% elif item.current_step_approval_status.status == 'approved' %}text-success{% else %}text-warning{% endif %}">
 | 
						|
                    {% if item.current_step_approval_status.status == 'rejected' %}
 | 
						|
                      <i class="bx bx-x-circle"></i>
 | 
						|
                    {% elif item.current_step_approval_status.status == 'approved' %}
 | 
						|
                      <i class="bx bx-check-circle"></i>
 | 
						|
                    {% else %}
 | 
						|
                      <i class="bx bx-time"></i>
 | 
						|
                    {% endif %}
 | 
						|
                    {{ item.current_step_approval_status.display }}
 | 
						|
                  </small>
 | 
						|
                {% endif %}
 | 
						|
              {% else %}
 | 
						|
                --
 | 
						|
              {% endif %}
 | 
						|
            </td>
 | 
						|
            <td>{{ item.instance.well.water_subscription_number }}</td>
 | 
						|
            <td>{% if item.instance.representative %}{{ item.instance.representative.get_full_name }}{% else %}-{% endif %}</td>
 | 
						|
            <td>{% if item.instance.well and item.instance.well.county %}{{ item.instance.well.county }}{% else %}-{% endif %}</td>
 | 
						|
            <td>{% if item.instance.well and item.instance.well.affairs %}{{ item.instance.well.affairs }}{% else %}-{% endif %}</td>
 | 
						|
            <td>
 | 
						|
              <div class="d-flex align-items-center">
 | 
						|
                <div class="progress me-2" style="width: 80px; height: 6px;">
 | 
						|
                  <div class="progress-bar {% if item.progress_percentage == 100 %}bg-success{% elif item.progress_percentage >= 70 %}bg-info{% elif item.progress_percentage >= 40 %}bg-warning{% else %}bg-secondary{% endif %}" role="progressbar" style="width: {{ item.progress_percentage }}%;" aria-valuenow="{{ item.progress_percentage }}" aria-valuemin="0" aria-valuemax="100">
 | 
						|
                  </div>
 | 
						|
                </div>
 | 
						|
                <small class="text-muted">{{ item.progress_percentage }}%</small>
 | 
						|
              </div>
 | 
						|
            </td>
 | 
						|
            <td>
 | 
						|
              {{ item.instance.get_status_display_with_color|safe }}
 | 
						|
              {% if item.emergency_approved %}
 | 
						|
                <span class="badge bg-warning text-dark ms-1" title="تایید اضطراری">تایید اضطراری</span>
 | 
						|
              {% endif %}
 | 
						|
            </td>
 | 
						|
            <td>
 | 
						|
              {% if item.installation_scheduled_date %}
 | 
						|
                <div>
 | 
						|
                  <span title="{{ item.installation_scheduled_date|date:'Y-m-d' }}">{{ item.installation_scheduled_date | to_jalali }}</span>
 | 
						|
                </div>
 | 
						|
                {% if item.installation_overdue_days and item.installation_overdue_days > 0 %}
 | 
						|
                  <small class="text-danger d-block">{{ item.installation_overdue_days }} روز تاخیر</small>
 | 
						|
                {% else %}
 | 
						|
                  <small class="text-muted d-block">بدون تاخیر</small>
 | 
						|
                {% endif %}
 | 
						|
              {% else %}
 | 
						|
                <span class="text-muted">تاریخ نصب تعیین نشده</span>
 | 
						|
              {% endif %}
 | 
						|
            </td>
 | 
						|
            <td>{{ item.instance.jcreated_date }}</td>
 | 
						|
            <td>
 | 
						|
              <div class="d-inline-block">
 | 
						|
                <a href="javascript:;" class="btn btn-icon dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
 | 
						|
                  <i class="icon-base bx bx-dots-vertical-rounded"></i>
 | 
						|
                </a>
 | 
						|
                <ul class="dropdown-menu dropdown-menu-end m-0">
 | 
						|
                  <li>
 | 
						|
                    {% if item.instance.status == 'completed' %}
 | 
						|
                      <a href="{% url 'processes:instance_summary' item.instance.id %}" class="dropdown-item">
 | 
						|
                        <i class="bx bx-show me-1"></i>مشاهده گزارش
 | 
						|
                      </a>
 | 
						|
                    {% else %}
 | 
						|
                      <a href="{% url 'processes:instance_steps' item.instance.id %}" class="dropdown-item">
 | 
						|
                        <i class="bx bx-show me-1"></i>مشاهده جزئیات
 | 
						|
                      </a>
 | 
						|
                    {% endif %}
 | 
						|
                  </li>
 | 
						|
                  {% if request.user|is_broker %}
 | 
						|
                  <div class="dropdown-divider"></div>
 | 
						|
                  <li>
 | 
						|
                    <a href="#" class="dropdown-item text-danger" data-instance-id="{{ item.instance.id }}" data-instance-code="{{ item.instance.code }}" onclick="deleteRequest(this.getAttribute('data-instance-id'), this.getAttribute('data-instance-code'))">
 | 
						|
                      <i class="bx bx-trash me-1"></i>حذف
 | 
						|
                    </a>
 | 
						|
                  </li>
 | 
						|
                  {% endif %}
 | 
						|
                </ul>
 | 
						|
              </div>
 | 
						|
            </td>
 | 
						|
          </tr>
 | 
						|
          {% empty %}
 | 
						|
          <tr>
 | 
						|
            <td class="text-center text-muted">موردی ثبت نشده است</td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
            <td></td>
 | 
						|
          </tr>
 | 
						|
          {% endfor %}
 | 
						|
        </tbody>
 | 
						|
      </table>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
 | 
						|
  <!-- Modal -->
 | 
						|
  <div class="modal fade" id="requestModal" tabindex="-1" aria-hidden="true">
 | 
						|
    <div class="modal-dialog modal-lg modal-dialog-centered">
 | 
						|
      <div class="modal-content">
 | 
						|
        <div class="modal-header">
 | 
						|
          <h5 class="modal-title">درخواست جدید</h5>
 | 
						|
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 | 
						|
        </div>
 | 
						|
        <div class="modal-body">
 | 
						|
          <form id="requestForm">
 | 
						|
            {% csrf_token %}
 | 
						|
            <div class="row g-3">
 | 
						|
              <div class="col-sm-12">
 | 
						|
                <label class="form-label">فرآیند</label>
 | 
						|
                <select class="form-select" name="process" id="req_process" required>
 | 
						|
                  {% for process in processes %}
 | 
						|
                  <option value="{{ process.id }}">{{ process.name }}</option>
 | 
						|
                  {% endfor %}
 | 
						|
                </select>
 | 
						|
              </div>
 | 
						|
              <hr class="mt-3 border border-dashed">
 | 
						|
              <div class="col-sm-12">
 | 
						|
                <label class="form-label">شماره اشتراک آب</label>
 | 
						|
                <div class="input-group">
 | 
						|
                  <input type="text" class="form-control" id="req_water_sub" name="water_subscription_number" data-field="water_subscription_number" placeholder="مثال: 12345" required>
 | 
						|
                  <button class="btn btn-outline-secondary" type="button" id="btnLookupWell">
 | 
						|
                    بررسی/افزودن چاه
 | 
						|
                  </button>
 | 
						|
                </div>
 | 
						|
                <div class="form-text" id="wellStatus"></div>
 | 
						|
              </div>
 | 
						|
 | 
						|
 | 
						|
              <!-- Well form fields (from WellForm) -->
 | 
						|
              <div id="wellFormBlock" class="col-sm-12" style="display:none;">
 | 
						|
                <div class="row g-3">
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_electricity_subscription_number">{{ well_form.electricity_subscription_number.label }}</label>
 | 
						|
                    {{ well_form.electricity_subscription_number }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_water_meter_manufacturer">{{ well_form.water_meter_manufacturer.label }}</label>
 | 
						|
                    <div class="input-group">
 | 
						|
                      <select name="water_meter_manufacturer" class="form-select" id="id_water_meter_manufacturer">
 | 
						|
                        <option value="" selected="">انتخاب شرکت سازنده</option>
 | 
						|
                        {% for manufacturer in manufacturers %}
 | 
						|
                        <option value="{{ manufacturer.id }}">{{ manufacturer.name }}</option>
 | 
						|
                        {% endfor %}
 | 
						|
                      </select>
 | 
						|
                      <input type="text" class="form-control" id="id_new_manufacturer" name="new_manufacturer" placeholder="شرکت سازنده جدید" style="display:none;">
 | 
						|
                      <button class="btn btn-outline-primary" type="button" id="btnToggleManufacturer">
 | 
						|
                        <i class="bx bx-plus"></i>
 | 
						|
                      </button>
 | 
						|
                    </div>
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_water_meter_serial_number">{{ well_form.water_meter_serial_number.label }}</label>
 | 
						|
                    {{ well_form.water_meter_serial_number }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_water_meter_old_serial_number">{{ well_form.water_meter_old_serial_number.label }}</label>
 | 
						|
                    {{ well_form.water_meter_old_serial_number }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_utm_x">{{ well_form.utm_x.label }}</label>
 | 
						|
                    {{ well_form.utm_x }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_utm_y">{{ well_form.utm_y.label }}</label>
 | 
						|
                    {{ well_form.utm_y }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_utm_zone">{{ well_form.utm_zone.label }}</label>
 | 
						|
                    {{ well_form.utm_zone }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_utm_hemisphere">{{ well_form.utm_hemisphere.label }}</label>
 | 
						|
                    {{ well_form.utm_hemisphere }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_well_power">{{ well_form.well_power.label }}</label>
 | 
						|
                    {{ well_form.well_power }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6"></div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_reference_letter_number">{{ well_form.reference_letter_number.label }}</label>
 | 
						|
                    {{ well_form.reference_letter_number }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_reference_letter_date">{{ well_form.reference_letter_date.label }}</label>
 | 
						|
                    <input type="text" class="form-control" id="id_reference_letter_date" name="reference_letter_date" placeholder="انتخاب تاریخ" readonly>
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-12">
 | 
						|
                    <label class="form-label" for="id_representative_letter_file">{{ well_form.representative_letter_file.label }}</label>
 | 
						|
                    {{ well_form.representative_letter_file }}
 | 
						|
                    <!-- نمایش فایل موجود -->
 | 
						|
                    <div id="current-file-display" style="display: none; margin-top: 10px;">
 | 
						|
                      <div class="alert alert-info d-flex align-items-center justify-content-between">
 | 
						|
                        <div class="d-flex align-items-center">
 | 
						|
                          <i class="bx bx-file me-2"></i>
 | 
						|
                          <span id="current-file-name" class="text-truncate" style="max-width: 200px;" title=""></span>
 | 
						|
                        </div>
 | 
						|
                        <button type="button" class="btn btn-sm btn-outline-danger" onclick="removeCurrentFile()">
 | 
						|
                          <i class="bx bx-trash me-1"></i>حذف
 | 
						|
                        </button>
 | 
						|
                      </div>
 | 
						|
                    </div>
 | 
						|
                    <input type="hidden" id="remove-file" name="remove_file" value="false">
 | 
						|
                  </div>
 | 
						|
                </div>
 | 
						|
              </div>
 | 
						|
              <hr class="mt-3 border border-dashed">
 | 
						|
              <div class="col-sm-12">
 | 
						|
                <label class="form-label">کد ملی نماینده</label>
 | 
						|
                <div class="input-group">
 | 
						|
                  <input type="text" class="form-control" id="rep_national_code" data-field="national_code" placeholder="مثال: 0012345678" maxlength="10" inputmode="numeric" pattern="\d*">
 | 
						|
                  <button class="btn btn-outline-secondary" type="button" id="btnLookupRep">
 | 
						|
                    بررسی/افزودن نماینده
 | 
						|
                  </button>
 | 
						|
                </div>
 | 
						|
                <div class="form-text" id="repStatus"></div>
 | 
						|
              </div>
 | 
						|
 | 
						|
              <div id="repNewFields" class="col-sm-12" style="display:none;">
 | 
						|
                <div class="row g-3">
 | 
						|
                  <div class="col-sm-12">
 | 
						|
                    <label class="form-label" for="id_user_type">{{ customer_form.user_type.label }}</label>
 | 
						|
                    {{ customer_form.user_type }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_first_name">{{ customer_form.first_name.label }}</label>
 | 
						|
                    {{ customer_form.first_name }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_last_name">{{ customer_form.last_name.label }}</label>
 | 
						|
                    {{ customer_form.last_name }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_phone_number_1">{{ customer_form.phone_number_1.label }}</label>
 | 
						|
                    {{ customer_form.phone_number_1 }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_phone_number_2">{{ customer_form.phone_number_2.label }}</label>
 | 
						|
                    {{ customer_form.phone_number_2 }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_national_code">{{ customer_form.national_code.label }}</label>
 | 
						|
                    {{ customer_form.national_code }}
 | 
						|
                  </div>
 | 
						|
                  <!-- Company fields for legal entities -->
 | 
						|
                  <div class="col-sm-6 company-fields" style="display:none;">
 | 
						|
                    <label class="form-label" for="id_company_name">{{ customer_form.company_name.label }}</label>
 | 
						|
                    {{ customer_form.company_name }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6 company-fields" style="display:none;">
 | 
						|
                    <label class="form-label" for="id_company_national_id">{{ customer_form.company_national_id.label }}</label>
 | 
						|
                    {{ customer_form.company_national_id }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_card_number">{{ customer_form.card_number.label }}</label>
 | 
						|
                    {{ customer_form.card_number }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_account_number">{{ customer_form.account_number.label }}</label>
 | 
						|
                    {{ customer_form.account_number }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-6">
 | 
						|
                    <label class="form-label" for="id_bank_name">{{ customer_form.bank_name.label }}</label>
 | 
						|
                    {{ customer_form.bank_name }}
 | 
						|
                  </div>
 | 
						|
                  <div class="col-sm-12">
 | 
						|
                    <label class="form-label" for="id_address">{{ customer_form.address.label }}</label>
 | 
						|
                    {{ customer_form.address }}
 | 
						|
                  </div>
 | 
						|
                </div>
 | 
						|
              </div>
 | 
						|
              <hr class="mt-3 border border-dashed">
 | 
						|
              <div class="col-sm-12">
 | 
						|
                <label class="form-label">توضیحات</label>
 | 
						|
                <textarea class="form-control" rows="3" id="req_description" name="description"></textarea>
 | 
						|
              </div>
 | 
						|
            </div>
 | 
						|
          </form>
 | 
						|
        </div>
 | 
						|
        <div class="modal-footer">
 | 
						|
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">بستن</button>
 | 
						|
          <button type="button" class="btn btn-primary" id="btnSaveRequest" disabled>ذخیره</button>
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</div>
 | 
						|
 | 
						|
<!-- Delete Confirmation Modal -->
 | 
						|
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-labelledby="deleteConfirmModalLabel" aria-hidden="true">
 | 
						|
  <div class="modal-dialog">
 | 
						|
    <div class="modal-content">
 | 
						|
      <div class="modal-header">
 | 
						|
        <h5 class="modal-title" id="deleteConfirmModalLabel">تایید حذف</h5>
 | 
						|
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 | 
						|
      </div>
 | 
						|
      <div class="modal-body">
 | 
						|
        <p id="deleteConfirmText">آیا از حذف این درخواست اطمینان دارید؟</p>
 | 
						|
      </div>
 | 
						|
      <div class="modal-footer">
 | 
						|
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">انصراف</button>
 | 
						|
        <button type="button" class="btn btn-danger" id="confirmDeleteBtn">حذف</button>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</div>
 | 
						|
{% endblock %}
 | 
						|
 | 
						|
{% block script %}
 | 
						|
<!-- DataTables JS -->
 | 
						|
<script src="{% static 'assets/vendor/libs/datatables-bs5/datatables-bootstrap5.js' %}"></script>
 | 
						|
<!-- Persian DataTable defaults -->
 | 
						|
<script src="{% static 'assets/js/persian-datatable.js' %}"></script>
 | 
						|
 | 
						|
<!-- Persian Date Picker JS -->
 | 
						|
<script src="https://unpkg.com/persian-date@latest/dist/persian-date.min.js"></script>
 | 
						|
<script src="https://unpkg.com/persian-datepicker@latest/dist/js/persian-datepicker.min.js"></script>
 | 
						|
 | 
						|
 | 
						|
<script>
 | 
						|
 | 
						|
  // Function to initialize Persian Date Picker
 | 
						|
  function initPersianDatePicker() {
 | 
						|
    if ($.fn.persianDatepicker && $('#id_reference_letter_date').length) {
 | 
						|
      try {
 | 
						|
        $('#id_reference_letter_date').persianDatepicker({
 | 
						|
          format: 'YYYY/MM/DD',
 | 
						|
          initialValue: false,
 | 
						|
          autoClose: true,
 | 
						|
          persianDigit: false,
 | 
						|
          observer: true,
 | 
						|
          calendar: {
 | 
						|
            persian: {
 | 
						|
              locale: 'fa',
 | 
						|
              leapYearMode: 'astronomical'
 | 
						|
            }
 | 
						|
          },
 | 
						|
          onSelect: function(unix) {
 | 
						|
            // تبدیل تاریخ شمسی به میلادی برای ارسال به سرور
 | 
						|
            const gregorianDate = new Date(unix);
 | 
						|
            const year = gregorianDate.getFullYear();
 | 
						|
            const month = String(gregorianDate.getMonth() + 1).padStart(2, '0');
 | 
						|
            const day = String(gregorianDate.getDate()).padStart(2, '0');
 | 
						|
            const gregorianDateString = `${year}-${month}-${day}`;
 | 
						|
            
 | 
						|
            // نمایش تاریخ شمسی در فیلد
 | 
						|
            if (window.persianDate) {
 | 
						|
              const persianDate = new window.persianDate(unix);
 | 
						|
              const persianDateString = persianDate.format('YYYY/MM/DD');
 | 
						|
              $('#id_reference_letter_date').val(persianDateString);
 | 
						|
            } else {
 | 
						|
              // اگر persianDate در دسترس نبود، تاریخ میلادی را نمایش بده
 | 
						|
              $('#id_reference_letter_date').val(gregorianDateString);
 | 
						|
            }
 | 
						|
            
 | 
						|
            // ذخیره تاریخ میلادی در فیلد مخفی برای ارسال به سرور
 | 
						|
            $('#id_reference_letter_date').attr('data-gregorian', gregorianDateString);
 | 
						|
          }
 | 
						|
        });
 | 
						|
      } catch (e) {
 | 
						|
        console.error('Error initializing Persian Date Picker:', e);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  $(function() {
 | 
						|
    // Initialize DataTable similar to customer_list
 | 
						|
    $('#requests-table').DataTable({
 | 
						|
      pageLength: 10,
 | 
						|
      lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "همه"]],
 | 
						|
      order: [],
 | 
						|
      responsive: true,
 | 
						|
    });
 | 
						|
    let currentWellId = null;
 | 
						|
    let currentRepId = null;
 | 
						|
    let wellChecked = false;
 | 
						|
    let repChecked = false;
 | 
						|
 | 
						|
    function setStatus(el, text, type) {
 | 
						|
      $(el).text(text).removeClass('text-danger text-success text-muted').addClass(type ? 'text-' + type : 'text-muted');
 | 
						|
    }
 | 
						|
 | 
						|
    function checkSaveButton() {
 | 
						|
      const canSave = wellChecked && repChecked;
 | 
						|
      $('#btnSaveRequest').prop('disabled', !canSave);
 | 
						|
    }
 | 
						|
 | 
						|
    // Inline error helpers
 | 
						|
    function clearInlineErrors() {
 | 
						|
      $('#requestModal .is-invalid').removeClass('is-invalid');
 | 
						|
      $('#requestModal .invalid-feedback.inline-error').remove();
 | 
						|
    }
 | 
						|
 | 
						|
    function applyErrorTo(selector, message) {
 | 
						|
      const $el = $(selector);
 | 
						|
      if (!$el.length) return false;
 | 
						|
      $el.addClass('is-invalid');
 | 
						|
      const $feedback = $('<div class="invalid-feedback inline-error"></div>').text(message);
 | 
						|
      const $grp = $el.closest('.input-group, .form-group, .mb-3');
 | 
						|
      if ($grp.length) {
 | 
						|
        $feedback.insertAfter($grp);
 | 
						|
      } else {
 | 
						|
        $feedback.insertAfter($el);
 | 
						|
      }
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generic field resolution with small exception map
 | 
						|
    const exceptionMap = {
 | 
						|
      water_subscription_number: '#req_water_sub',
 | 
						|
      national_code: '#rep_national_code',
 | 
						|
      representative: '#rep_national_code'
 | 
						|
    };
 | 
						|
 | 
						|
    function findFieldSelector(field, context) {
 | 
						|
      const $ctx = context ? $(context) : $('#requestModal');
 | 
						|
      let $el = $ctx.find(`#id_${field}`).first();
 | 
						|
      if ($el.length) return $el;
 | 
						|
      $el = $ctx.find(`[name="${field}"]`).first();
 | 
						|
      if ($el.length) return $el;
 | 
						|
      $el = $ctx.find(`[data-field="${field}"]`).first();
 | 
						|
      if ($el.length) return $el;
 | 
						|
      const ex = exceptionMap[field];
 | 
						|
      return ex ? $(ex) : $();
 | 
						|
    }
 | 
						|
 | 
						|
    function showInlineErrors(errors) {
 | 
						|
      if (!errors) return;
 | 
						|
      let nonFieldWell = '';
 | 
						|
      let nonFieldCustomer = '';
 | 
						|
      // Request-level errors (e.g., process)
 | 
						|
      if (errors.request) {
 | 
						|
        for (const key in errors.request) {
 | 
						|
          const msgs = Array.isArray(errors.request[key]) ? errors.request[key] : [errors.request[key]];
 | 
						|
          if (key === '__all__' || key === 'non_field_errors') { continue; }
 | 
						|
          applyErrorTo(findFieldSelector(key, '#requestForm'), msgs[0]);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (errors.well) {
 | 
						|
        for (const key in errors.well) {
 | 
						|
          const msgs = Array.isArray(errors.well[key]) ? errors.well[key] : [errors.well[key]];
 | 
						|
          if (key === '__all__' || key === 'non_field_errors') { nonFieldWell = msgs.join('، '); continue; }
 | 
						|
          applyErrorTo(findFieldSelector(key, '#wellFormBlock'), msgs[0]);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (errors.customer) {
 | 
						|
        for (const key in errors.customer) {
 | 
						|
          const msgs = Array.isArray(errors.customer[key]) ? errors.customer[key] : [errors.customer[key]];
 | 
						|
          if (key === '__all__' || key === 'non_field_errors') { nonFieldCustomer = msgs.join('، '); continue; }
 | 
						|
          applyErrorTo(findFieldSelector(key, '#repNewFields'), msgs[0]);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (nonFieldWell) setStatus('#wellStatus', nonFieldWell, 'danger');
 | 
						|
      if (nonFieldCustomer) setStatus('#repStatus', nonFieldCustomer, 'danger');
 | 
						|
    }
 | 
						|
 | 
						|
    $('#btnLookupWell').on('click', function() {
 | 
						|
      const sub = $('#req_water_sub').val().trim();
 | 
						|
      if (!sub) { setStatus('#wellStatus', 'لطفا شماره اشتراک آب را وارد کنید', 'danger'); return; }
 | 
						|
      setStatus('#wellStatus', 'در حال بررسی...', 'muted');
 | 
						|
      wellChecked = true;
 | 
						|
      checkSaveButton();
 | 
						|
      $.get('{% url "processes:lookup_well_by_subscription" %}', { water_subscription_number: sub })
 | 
						|
        .done(function(resp){
 | 
						|
            if (resp.exists) {
 | 
						|
            currentWellId = resp.well.id;
 | 
						|
            $('#wellFormBlock').show();
 | 
						|
            // Initialize Persian Date Picker after well form is shown
 | 
						|
            setTimeout(initPersianDatePicker, 100);
 | 
						|
 | 
						|
            // Prefill well form
 | 
						|
            $('#id_electricity_subscription_number').val(resp.well.electricity_subscription_number || '');
 | 
						|
            $('#id_water_meter_serial_number').val(resp.well.water_meter_serial_number || '');
 | 
						|
            $('#id_water_meter_old_serial_number').val(resp.well.water_meter_old_serial_number || '');
 | 
						|
            $('#id_water_meter_manufacturer').val(resp.well.water_meter_manufacturer || '');
 | 
						|
            $('#id_utm_x').val(resp.well.utm_x || '');
 | 
						|
            $('#id_utm_y').val(resp.well.utm_y || '');
 | 
						|
            $('#id_utm_zone').val(resp.well.utm_zone || '');
 | 
						|
            $('#id_utm_hemisphere').val(resp.well.utm_hemisphere || '');
 | 
						|
            $('#id_well_power').val(resp.well.well_power || '');
 | 
						|
            $('#id_reference_letter_number').val(resp.well.reference_letter_number || '');
 | 
						|
            // Prefill date: show Persian in input, keep Gregorian in data attribute
 | 
						|
            if (resp.well.reference_letter_date) {
 | 
						|
              try {
 | 
						|
                if (window.persianDate) {
 | 
						|
                  const gregorianDate = new Date(resp.well.reference_letter_date);
 | 
						|
                  const persianDateObj = new window.persianDate(gregorianDate);
 | 
						|
                  const persianDateString = persianDateObj.format('YYYY/MM/DD');
 | 
						|
                  $('#id_reference_letter_date').val(persianDateString);
 | 
						|
                } else {
 | 
						|
                  $('#id_reference_letter_date').val(resp.well.reference_letter_date);
 | 
						|
                }
 | 
						|
                $('#id_reference_letter_date').attr('data-gregorian', resp.well.reference_letter_date);
 | 
						|
              } catch (e) {
 | 
						|
                $('#id_reference_letter_date').val(resp.well.reference_letter_date);
 | 
						|
              }
 | 
						|
            } else {
 | 
						|
              $('#id_reference_letter_date').val('');
 | 
						|
              $('#id_reference_letter_date').removeAttr('data-gregorian');
 | 
						|
            }
 | 
						|
              // Existing representative letter file display
 | 
						|
              if (resp.well.representative_letter_file_url) {
 | 
						|
                $('#current-file-display').show();
 | 
						|
                const fileName = resp.well.representative_letter_file_name || 'فایل موجود';
 | 
						|
                $('#current-file-name').text(fileName).attr('title', fileName);
 | 
						|
                $('#id_representative_letter_file').hide();
 | 
						|
                $('#remove-file').val('false');
 | 
						|
              } else {
 | 
						|
                $('#current-file-display').hide();
 | 
						|
                $('#id_representative_letter_file').show();
 | 
						|
                $('#remove-file').val('false');
 | 
						|
              }
 | 
						|
            setStatus('#wellStatus', 'چاه یافت شد', 'success');
 | 
						|
          } else {
 | 
						|
            currentWellId = null;
 | 
						|
            $('#wellFormBlock').show();
 | 
						|
            $('#wellFormBlock').find('input, select').val('');
 | 
						|
            $('#id_reference_letter_date').removeAttr('data-gregorian');
 | 
						|
              // Reset file UI for new well
 | 
						|
              $('#current-file-display').hide();
 | 
						|
              $('#id_representative_letter_file').show().val('');
 | 
						|
              $('#remove-file').val('false');
 | 
						|
            // Initialize Persian Date Picker after well form is shown
 | 
						|
            setTimeout(initPersianDatePicker, 100);
 | 
						|
            setStatus('#wellStatus', 'چاه یافت نشد. اطلاعات چاه را وارد کنید.', 'danger');
 | 
						|
          }
 | 
						|
        })
 | 
						|
        .fail(function(){ setStatus('#wellStatus', 'خطا در بررسی چاه', 'danger'); });
 | 
						|
    });
 | 
						|
 | 
						|
    function toggleRepCompanyFields() {
 | 
						|
      const userType = $('#user-type-select').val();
 | 
						|
      if (userType === 'legal') {
 | 
						|
        $('#repNewFields .company-fields').show();
 | 
						|
        $('input[name="company_name"]').attr('required', true);
 | 
						|
        $('input[name="company_national_id"]').attr('required', true);
 | 
						|
      } else {
 | 
						|
        $('#repNewFields .company-fields').hide();
 | 
						|
        $('input[name="company_name"]').removeAttr('required');
 | 
						|
        $('input[name="company_national_id"]').removeAttr('required');
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    $('#user-type-select').on('change', toggleRepCompanyFields);
 | 
						|
 | 
						|
    $('#btnLookupRep').on('click', function() {
 | 
						|
      const nc = $('#rep_national_code').val().trim();
 | 
						|
      if (!nc) { setStatus('#repStatus', 'لطفا کد ملی نماینده را وارد کنید', 'danger'); return; }
 | 
						|
      setStatus('#repStatus', 'در حال بررسی...', 'muted');
 | 
						|
      repChecked = true;
 | 
						|
      checkSaveButton();
 | 
						|
      $.get('{% url "processes:lookup_representative_by_national_code" %}', { national_code: nc })
 | 
						|
        .done(function(resp){
 | 
						|
          if (resp.exists) {
 | 
						|
            currentRepId = resp.user.id;
 | 
						|
            $('#repNewFields').show();
 | 
						|
            // Prefill customer form fields for editing
 | 
						|
            $('#id_first_name').val(resp.user.first_name || '');
 | 
						|
            $('#id_last_name').val(resp.user.last_name || '');
 | 
						|
            if (resp.user.profile) {
 | 
						|
              $('#user-type-select').val(resp.user.profile.user_type || 'individual');
 | 
						|
              $('#id_national_code').val(resp.user.profile.national_code || nc);
 | 
						|
              $('#id_phone_number_1').val(resp.user.profile.phone_number_1 || '');
 | 
						|
              $('#id_phone_number_2').val(resp.user.profile.phone_number_2 || '');
 | 
						|
              $('#id_company_name').val(resp.user.profile.company_name || '');
 | 
						|
              $('#id_company_national_id').val(resp.user.profile.company_national_id || '');
 | 
						|
              $('#id_card_number').val(resp.user.profile.card_number || '');
 | 
						|
              $('#id_account_number').val(resp.user.profile.account_number || '');
 | 
						|
              $('#id_bank_name').val(resp.user.profile.bank_name || '');
 | 
						|
              $('#id_address').val(resp.user.profile.address || '');
 | 
						|
            } else {
 | 
						|
              $('#user-type-select').val('individual');
 | 
						|
              $('#id_national_code').val(nc);
 | 
						|
              $('#id_phone_number_1').val('');
 | 
						|
              $('#id_phone_number_2').val('');
 | 
						|
              $('#id_company_name').val('');
 | 
						|
              $('#id_company_national_id').val('');
 | 
						|
              $('#id_card_number').val('');
 | 
						|
              $('#id_account_number').val('');
 | 
						|
              $('#id_bank_name').val('');
 | 
						|
              $('#id_address').val('');
 | 
						|
            }
 | 
						|
            toggleRepCompanyFields();
 | 
						|
            setStatus('#repStatus', 'نماینده یافت شد.', 'success');
 | 
						|
          } else {
 | 
						|
            currentRepId = null;
 | 
						|
            $('#repNewFields').show();
 | 
						|
            // Clear form and prefill national code
 | 
						|
            $('#user-type-select').val('individual');
 | 
						|
            $('#id_first_name').val('');
 | 
						|
            $('#id_last_name').val('');
 | 
						|
            $('#id_national_code').val(nc);
 | 
						|
            $('#id_phone_number_1').val('');
 | 
						|
            $('#id_phone_number_2').val('');
 | 
						|
            $('#id_company_name').val('');
 | 
						|
            $('#id_company_national_id').val('');
 | 
						|
            $('#id_card_number').val('');
 | 
						|
            $('#id_account_number').val('');
 | 
						|
            $('#id_bank_name').val('');
 | 
						|
            $('#id_address').val('');
 | 
						|
            toggleRepCompanyFields();
 | 
						|
            setStatus('#repStatus', 'نماینده یافت نشد. لطفا اطلاعات را تکمیل کنید.', 'danger');
 | 
						|
          }
 | 
						|
        })
 | 
						|
        .fail(function(){ setStatus('#repStatus', 'خطا در بررسی نماینده', 'danger'); });
 | 
						|
    });
 | 
						|
 | 
						|
    $('#btnSaveRequest').on('click', function(){
 | 
						|
      clearInlineErrors();
 | 
						|
      // Use form's native FormData - much cleaner!
 | 
						|
      const formData = new FormData(document.getElementById('requestForm'));
 | 
						|
      
 | 
						|
      // Add custom fields that aren't in the form
 | 
						|
      if (currentWellId) formData.append('well_id', currentWellId);
 | 
						|
      if (currentRepId) formData.append('representative_id', currentRepId);
 | 
						|
      
 | 
						|
      // Handle special national_code logic (prefer visible field)
 | 
						|
      const ncField = $('#id_national_code').val();
 | 
						|
      if (ncField) {
 | 
						|
        formData.set('national_code', ncField);
 | 
						|
      } else {
 | 
						|
        formData.set('national_code', $('#rep_national_code').val().trim());
 | 
						|
      }
 | 
						|
      
 | 
						|
      // Handle Persian date conversion
 | 
						|
      const gregorianDate = $('#id_reference_letter_date').attr('data-gregorian');
 | 
						|
      if (gregorianDate) {
 | 
						|
        formData.set('reference_letter_date', gregorianDate);
 | 
						|
      }
 | 
						|
 | 
						|
      const $btn = $(this).prop('disabled', true).text('در حال ذخیره...');
 | 
						|
      $.ajax({
 | 
						|
        url: '{% url "processes:create_request_with_entities" %}',
 | 
						|
        method: 'POST',
 | 
						|
        data: formData,
 | 
						|
        processData: false,
 | 
						|
        contentType: false,
 | 
						|
      }).done(function(resp){
 | 
						|
        if (resp.ok) {
 | 
						|
          showToast('درخواست با موفقیت ثبت شد', 'success');
 | 
						|
          if (resp.redirect) {
 | 
						|
            setTimeout(function(){ window.location.href = resp.redirect; }, 800);
 | 
						|
          } else {
 | 
						|
            setTimeout(function(){ location.reload(); }, 1200);
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          clearInlineErrors();
 | 
						|
          if (resp.errors) {
 | 
						|
            showInlineErrors(resp.errors);
 | 
						|
          }
 | 
						|
          const msg = buildErrorMessage(resp);
 | 
						|
          showToast(msg, 'danger');
 | 
						|
        }
 | 
						|
      }).fail(function(xhr){
 | 
						|
        let msg = 'خطا در ذخیره';
 | 
						|
        try {
 | 
						|
          const resp = JSON.parse(xhr.responseText);
 | 
						|
          clearInlineErrors();
 | 
						|
          if (resp && resp.errors) {
 | 
						|
            showInlineErrors(resp.errors);
 | 
						|
          }
 | 
						|
          msg = buildErrorMessage(resp) || msg;
 | 
						|
        } catch(e) {}
 | 
						|
        showToast(msg, 'danger');
 | 
						|
      }).always(function(){
 | 
						|
        $btn.prop('disabled', false).text('ذخیره');
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    function buildErrorMessage(resp){
 | 
						|
      if (!resp) return '';
 | 
						|
      if (resp.error) return resp.error;
 | 
						|
      if (resp.errors) {
 | 
						|
        // Collect form-related errors
 | 
						|
        const parts = [];
 | 
						|
        if (resp.errors.customer) {
 | 
						|
          parts.push('خطای نماینده: ' + flattenErrors(resp.errors.customer));
 | 
						|
        }
 | 
						|
        if (resp.errors.well) {
 | 
						|
          parts.push('خطای چاه: ' + flattenErrors(resp.errors.well));
 | 
						|
        }
 | 
						|
        return parts.join(' | ');
 | 
						|
      }
 | 
						|
      return '';
 | 
						|
    }
 | 
						|
 | 
						|
    function flattenErrors(errorsObj){
 | 
						|
      if (typeof errorsObj === 'string') return errorsObj;
 | 
						|
      try {
 | 
						|
        const parts = [];
 | 
						|
        for (const k in errorsObj){
 | 
						|
          const v = errorsObj[k];
 | 
						|
          if (Array.isArray(v)) parts.push(`${k}: ${v[0]}`);
 | 
						|
          else if (typeof v === 'string') parts.push(`${k}: ${v}`);
 | 
						|
        }
 | 
						|
        return parts.join('، ');
 | 
						|
      } catch(e){
 | 
						|
        return '';
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    $('#btnToggleManufacturer').on('click', function() {
 | 
						|
      const $select = $('#id_water_meter_manufacturer');
 | 
						|
      const $input = $('#id_new_manufacturer');
 | 
						|
      const $btn = $(this);
 | 
						|
      
 | 
						|
      if ($select.is(':visible')) {
 | 
						|
        $select.hide();
 | 
						|
        $input.show().focus();
 | 
						|
        $btn.html('<i class="bx bx-check"></i>');
 | 
						|
      } else {
 | 
						|
        $input.hide();
 | 
						|
        $select.show();
 | 
						|
        $btn.html('<i class="bx bx-plus"></i>');
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    // Enforce digit-only and max length for national code input
 | 
						|
    $('#rep_national_code').on('input', function() {
 | 
						|
      const cleaned = (this.value || '').replace(/\D/g, '').slice(0, 10);
 | 
						|
      if (this.value !== cleaned) {
 | 
						|
        this.value = cleaned;
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    $('#requestModal').on('hidden.bs.modal', function(){
 | 
						|
      $('#requestForm')[0].reset();
 | 
						|
      $('#wellFormBlock').hide();
 | 
						|
      $('#repNewFields').hide();
 | 
						|
      $('#id_reference_letter_date').removeAttr('data-gregorian');
 | 
						|
      // Reset file UI
 | 
						|
      $('#current-file-display').hide();
 | 
						|
      $('#id_representative_letter_file').show().val('');
 | 
						|
      $('#remove-file').val('false');
 | 
						|
      setStatus('#wellStatus', '', '');
 | 
						|
      setStatus('#repStatus', '', '');
 | 
						|
      currentWellId = null;
 | 
						|
      currentRepId = null;
 | 
						|
      wellChecked = false;
 | 
						|
      repChecked = false;
 | 
						|
      checkSaveButton();
 | 
						|
      clearInlineErrors(); // Clear inline errors on modal close
 | 
						|
    });
 | 
						|
 | 
						|
    // Handle selecting a new file: hide existing file display and cancel removal flag
 | 
						|
    $('#id_representative_letter_file').on('change', function() {
 | 
						|
      if (this.files && this.files.length > 0) {
 | 
						|
        $('#current-file-display').hide();
 | 
						|
        $('#remove-file').val('false');
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    // Expose remove function
 | 
						|
    window.removeCurrentFile = function() {
 | 
						|
      $('#current-file-display').hide();
 | 
						|
      $('#remove-file').val('true');
 | 
						|
      $('#id_representative_letter_file').show().val('');
 | 
						|
    };
 | 
						|
 | 
						|
    // Delete request function
 | 
						|
    window.deleteRequest = function(instanceId, instanceCode) {
 | 
						|
      // Set modal content
 | 
						|
      document.getElementById('deleteConfirmText').textContent = `آیا از حذف درخواست ${instanceCode} اطمینان دارید؟`;
 | 
						|
      
 | 
						|
      // Show modal
 | 
						|
      const modal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
 | 
						|
      modal.show();
 | 
						|
      
 | 
						|
      // Handle confirm button click
 | 
						|
      document.getElementById('confirmDeleteBtn').onclick = function() {
 | 
						|
        $.ajax({
 | 
						|
          url: '{% url "processes:delete_request" 0 %}'.replace('0', instanceId),
 | 
						|
          type: 'POST',
 | 
						|
          data: {
 | 
						|
            'csrfmiddlewaretoken': $('[name=csrfmiddlewaretoken]').val()
 | 
						|
          },
 | 
						|
          success: function(response) {
 | 
						|
            if (response.success) {
 | 
						|
              showToast(response.message, 'success');
 | 
						|
              modal.hide();
 | 
						|
              setTimeout(() => {
 | 
						|
                window.location.reload();
 | 
						|
              }, 1500);
 | 
						|
            } else {
 | 
						|
              showToast(response.message, 'danger');
 | 
						|
            }
 | 
						|
          },
 | 
						|
          error: function() {
 | 
						|
            showToast('خطا در ارتباط با سرور', 'danger');
 | 
						|
          }
 | 
						|
        });
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    // Export to Excel function
 | 
						|
    window.exportToExcel = function() {
 | 
						|
      // Get current filter parameters from the form
 | 
						|
      const form = document.querySelector('form[method="get"]');
 | 
						|
      const formData = new FormData(form);
 | 
						|
      
 | 
						|
      // Build query string
 | 
						|
      const params = new URLSearchParams();
 | 
						|
      for (const [key, value] of formData.entries()) {
 | 
						|
        if (value.trim()) {
 | 
						|
          params.append(key, value);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      
 | 
						|
      // Create export URL with current filters
 | 
						|
      const exportUrl = '{% url "processes:export_requests_excel" %}' + '?' + params.toString();
 | 
						|
      
 | 
						|
      // Show loading state
 | 
						|
      const btn = document.querySelector('button[onclick="exportToExcel()"]');
 | 
						|
      const originalText = btn.innerHTML;
 | 
						|
      btn.innerHTML = '<i class="bx bx-loader-circle bx-spin me-1"></i>در حال تولید...';
 | 
						|
      btn.disabled = true;
 | 
						|
      
 | 
						|
      // Create invisible link and trigger download
 | 
						|
      const link = document.createElement('a');
 | 
						|
      link.href = exportUrl;
 | 
						|
      link.style.display = 'none';
 | 
						|
      document.body.appendChild(link);
 | 
						|
      link.click();
 | 
						|
      document.body.removeChild(link);
 | 
						|
      
 | 
						|
      // Reset button after a short delay
 | 
						|
      setTimeout(() => {
 | 
						|
        btn.innerHTML = originalText;
 | 
						|
        btn.disabled = false;
 | 
						|
        showToast('فایل اکسل آماده دانلود است', 'success');
 | 
						|
      }, 1000);
 | 
						|
    };
 | 
						|
  });
 | 
						|
</script>
 | 
						|
{% endblock %}
 | 
						|
 | 
						|
 |