-                  {% if invoice.remaining_amount <= 0 %}
+                  {% if invoice.get_remaining_amount <= 0 %}
                     
@@ -157,7 +166,7 @@
                   {% for p in payments %}
                   
                     | {% if p.direction == 'in' %}دریافتی{% else %}پرداختی{% endif %} | 
-                    {{ p.amount|floatformat:0|intcomma:False }} تومان | 
+                    {{ p.amount|floatformat:0|intcomma:False }} ریال | 
                     {{ p.jpayment_date }} | 
                     {{ p.get_payment_method_display }} | 
                     {{ p.reference_number|default:'-' }} | 
@@ -184,15 +193,22 @@
           
         
       
-      {% if approver_statuses %}
+      {% if approver_statuses and needs_approval and step_instance.status != 'completed' %}
       
 
+
+
+
 
 
 
@@ -276,9 +318,13 @@
           
         
         
-          {% if invoice.remaining_amount != 0 %}
+          {% if not needs_approval %}
+            
+              فاکتور کاملاً تسویه شده است و نیازی به تایید ندارد.
+            
+          {% elif invoice.get_remaining_amount != 0 %}
             
-              مانده فاکتور: {{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان
+              مانده فاکتور: {{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} ریال
               امکان تایید تا تسویه کامل فاکتور وجود ندارد.
             
           {% else %}
@@ -287,7 +333,7 @@
         
 
         
       
     
@@ -363,6 +409,14 @@
 
   function buildForm(){
     const fd = new FormData(document.getElementById('formFinalPayment'));
+    // Ensure raw numeric amount is sent
+    (function ensureRawAmount(){
+      const amountInput = document.getElementById('id_amount');
+      if (amountInput){
+        const raw = (amountInput.getAttribute('data-raw-value') || amountInput.value.replace(/\D/g, ''));
+        if (raw) fd.set('amount', raw);
+      }
+    })();
     
     // تبدیل تاریخ شمسی به میلادی برای ارسال
     const persianDateValue = $('#id_payment_date').val();
@@ -423,6 +477,24 @@
   }
 
   // Legacy approve button removed; using modal forms below
+
+  // Handle AJAX form submission with number formatting
+  $(document).ready(function() {
+    // Override buildForm function for AJAX submission
+    const originalBuildForm = window.buildForm;
+    window.buildForm = function() {
+      // Set raw values before creating FormData
+      if (window.setRawValuesForSubmission) {
+        window.setRawValuesForSubmission();
+      }
+      const result = originalBuildForm ? originalBuildForm() : new FormData(document.querySelector('form'));
+      // Restore formatted values for display
+      if (window.restoreFormattedValues) {
+        window.restoreFormattedValues();
+      }
+      return result;
+    };
+  });
 
 {% endblock %}
 
diff --git a/invoices/templates/invoices/quote_payment_step.html b/invoices/templates/invoices/quote_payment_step.html
index 551420b..5e2cda9 100644
--- a/invoices/templates/invoices/quote_payment_step.html
+++ b/invoices/templates/invoices/quote_payment_step.html
@@ -71,11 +71,11 @@
                     
                     
                       
-                        
-                        
+                        
+                        
                       
                       
-                        
+                        
                         
                       
                       
@@ -89,7 +89,7 @@
                         
                       
                       
-                        
+                        
                         
                       
                       
@@ -116,20 +116,20 @@
                       
                         
                           
-                            
مبلغ نهایی پیشفاکتور
-                            
{{ totals.final_amount|floatformat:0|intcomma:False }} تومان
+                            
مبلغ نهایی پیشفاکتور (با مالیات)
+                            
{{ totals.final_amount|floatformat:0|intcomma:False }} ریال
                            
                          
                         
                           
                             مبلغ پرداختشده
-                            
{{ totals.paid_amount|floatformat:0|intcomma:False }} تومان
+                            
{{ totals.paid_amount|floatformat:0|intcomma:False }} ریال
                            
                          
                         
                           
                             مانده
-                            
{{ totals.remaining_amount|floatformat:0|intcomma:False }} تومان
+                            
{{ totals.remaining_amount|floatformat:0|intcomma:False }} ریال
                            
                          
                         
@@ -153,17 +153,19 @@
                       
                         
                           
+                            | نوع | 
                             مبلغ | 
-                            تاریخ | 
+                            تاریخ پرداخت/سررسید چک | 
                             روش | 
-                            شماره مرجع/چک | 
+                            شماره پیگیری/شماره صیادی چک | 
                             عملیات | 
                           
                         
                         
                           {% for p in payments %}
                           
-                            | {{ p.amount|floatformat:0|intcomma:False }} تومان | 
+                            {% if p.direction == 'in' %}دریافتی{% else %}پرداختی{% endif %} | 
+                            {{ p.amount|floatformat:0|intcomma:False }} ریال | 
                             {{ p.jpayment_date }} | 
                             {{ p.get_payment_method_display }} | 
                             {{ p.reference_number|default:'-' }} | 
@@ -175,9 +177,7 @@
                                 
                                 {% endif %}
                                 {% if is_broker %}
-                                
+                                
                                 {% endif %}
                               
                             
@@ -197,10 +197,17 @@
                     
                     
@@ -294,7 +301,7 @@
           {% if not totals.is_fully_paid %}
             
               مبلغی از پیشفاکتور هنوز پرداخت نشده است.
-              
مانده: {{ totals.remaining_amount|floatformat:0|intcomma:False }} تومان
+              
مانده: {{ totals.remaining_amount|floatformat:0|intcomma:False }} ریال
             
             آیا مطمئن هستید که میخواهید مرحله را تایید کنید؟
           {% else %}
@@ -359,6 +366,12 @@
     }
     const form = document.getElementById('formAddPayment');
     const fd = buildFormData(form);
+    // Ensure raw numeric amount is sent
+    (function ensureRawAmount(){
+      const amountInput = document.getElementById('id_amount');
+      const raw = (amountInput.getAttribute('data-raw-value') || amountInput.value.replace(/\D/g, ''));
+      if (raw) fd.set('amount', raw);
+    })();
     
     // تبدیل تاریخ شمسی به میلادی برای ارسال
     const persianDateValue = $('#id_payment_date').val();
@@ -376,7 +389,7 @@
           setTimeout(() => { window.location.href = resp.redirect; }, 700);
         }
       } else {
-        showToast(resp.message + ':' + resp.error || 'خطا در ثبت فیش', 'danger');
+        showToast((resp.message || resp.error || 'خطا در ثبت فیش'), 'danger');
       }
     }).catch(() => showToast('خطا در ارتباط با سرور', 'danger'));
   });
@@ -453,6 +466,7 @@
       } catch (e) { console.error('Error initializing Persian Date Picker:', e); }
     }
   })();
+
 
 
 {% endblock %}
diff --git a/invoices/templates/invoices/quote_preview_step.html b/invoices/templates/invoices/quote_preview_step.html
index 7243f4b..10fe329 100644
--- a/invoices/templates/invoices/quote_preview_step.html
+++ b/invoices/templates/invoices/quote_preview_step.html
@@ -2,6 +2,7 @@
 {% load static %}
 {% load processes_tags %}
 {% load humanize %}
+{% load common_tags %}
 
 {% block sidebar %}
     {% include 'sidebars/admin.html' %}
@@ -56,8 +57,9 @@
             
       
         
-          
-            
+          
پیشفاکتور
+          
+            
               
               
             
-            
-              
-                
#{{ quote.name }}
+            
+              
+                
شماره : {{ quote.name }}
               
               
                 
-                  تاریخ صدور:
+                  تاریخ صدور:
                   {{ quote.jcreated_date }}
                 
                
@@ -110,39 +112,59 @@
         
         
           
-            
+            
               
                 
                   
-                    اطلاعات مشترک
+                    
+                    {% if instance.representative.profile.user_type == 'legal' %}
+                      اطلاعات مشترک (حقوقی)
+                    {% else %}
+                      اطلاعات مشترک (حقیقی)
+                    {% endif %}
                   
-                  
-                    
نام:
-                    
{{ quote.customer.get_full_name }}
+                  
+                    
+                      شماره اشتراک آب:
+                      {{ instance.well.water_subscription_number }}
+                    
+                    {% if instance.representative.profile.user_type == 'legal' %}
+                    
+                      نام شرکت:
+                      {{ instance.representative.profile.company_name|default:"-" }}
+                    
+                    
+                      شناسه ملی:
+                      {{ instance.representative.profile.company_national_id|default:"-" }}
+                    
+                    {% endif %}
+                    
+                      نام:
+                      {{ quote.customer.get_full_name }}
+                    
+                    {% if instance.representative.profile.national_code %}
+                    
+                      کد ملی:
+                      {{ instance.representative.profile.national_code }}
+                    
+                    {% endif %}
+                    {% if instance.representative.profile.phone_number_1 %}
+                    
+                      تلفن:
+                      {{ instance.representative.profile.phone_number_1 }}
+                    
+                    {% endif %}
+                    {% if instance.representative.profile.address %}
+                    
+                      آدرس:
+                      {{ instance.representative.profile.address }}
+                    
+                    {% endif %}
                   
-                  {% if instance.representative.profile.national_code %}
-                  
-                    کد ملی:
-                    {{ instance.representative.profile.national_code }}
-                  
-                  {% endif %}
-                  {% if instance.representative.profile.phone_number_1 %}
-                  
-                    تلفن:
-                    {{ instance.representative.profile.phone_number_1 }}
-                  
-                  {% endif %}
-                  {% if instance.representative.profile.address %}
-                  
-                    آدرس:
-                    {{ instance.representative.profile.address }}
-                  
-                  {% endif %}
-
                 
 
                
              
-            
+            
               
                 
                   
@@ -185,9 +207,9 @@
               
                 | {{ quote_item.item.name }} | 
                 {{ quote_item.item.description|default:"-" }} | 
-                {{ quote_item.unit_price|floatformat:0|intcomma:False }} تومان | 
+                {{ quote_item.unit_price|floatformat:0|intcomma:False }} ریال | 
                 {{ quote_item.quantity }} | 
-                {{ quote_item.total_price|floatformat:0|intcomma:False }} تومان | 
+                {{ quote_item.total_price|floatformat:0|intcomma:False }} ریال | 
               
               {% endfor %}
               
@@ -198,14 +220,18 @@
                   {% if quote.discount_amount > 0 %}
                   تخفیف:
                   {% endif %}
-                  مبلغ نهایی:
+                  مالیات بر ارزش افزوده:
+                  مبلغ نهایی (شامل مالیات):
+                  مبلغ نهایی به حروف:
                 
                 
-                   {{ quote.total_amount|floatformat:0|intcomma:False }} تومان 
+                  {{ quote.total_amount|floatformat:0|intcomma:False }} ریال 
                   {% if quote.discount_amount > 0 %}
-                  {{ quote.discount_amount|floatformat:0|intcomma:False }} تومان 
+                  {{ quote.discount_amount|floatformat:0|intcomma:False }} ریال 
                   {% endif %}
-                  {{ quote.final_amount|floatformat:0|intcomma:False }} تومان 
+                  {{ quote.get_vat_amount|floatformat:0|intcomma:False }} ریال 
+                  {{ quote.final_amount|floatformat:0|intcomma:False }} ریال 
+                  {{ quote.final_amount|amount_to_words }} 
                  | 
               
             
       
@@ -228,50 +254,53 @@
                     
                     این برگه صرفاً جهت اعلام قیمت بوده و ارزش قانونی دیگری ندارد
                   
-                  {% if instance.broker.company.signature %}
-                  
-                    
-                  
-                  {% endif %}
                 
+                {% if instance.broker.company %}
+                  
+                    
اطلاعات پرداخت:
+                    
+                      {% if instance.broker.company.card_number %}
+                      
+                        
شماره کارت:
+                        
{{ instance.broker.company.card_number }}
+                      
+                      {% endif %}
+                      {% if instance.broker.company.account_number %}
+                      
+                        
شماره حساب:
+                        
{{ instance.broker.company.account_number }}
+                      
+                      {% endif %}
+                      {% if instance.broker.company.sheba_number %}
+                      
+                        
شماره شبا:
+                        
{{ instance.broker.company.sheba_number }}
+                      
+                      {% endif %}
+                      {% if instance.broker.company.bank_name %}
+                      
+                        
بانک:
+                        
{{ instance.broker.company.get_bank_name_display }}
+                      
+                      {% endif %}
+                      {% if instance.broker.company.branch_name %}
+                      
+                        
شعبه:
+                        
{{ instance.broker.company.branch_name }}
+                      
+                      {% endif %}
+                    
+                  
 
+                {% endif %}
               
               {% if instance.broker.company %}
-              
-                
اطلاعات پرداخت:
-                
-                  {% if instance.broker.company.card_number %}
-                  
-                    
شماره کارت:
-                    
{{ instance.broker.company.card_number }}
-                  
+              
+                
+                  
مهر و امضا
+                  {% if instance.broker.company.signature %}
+                    

                   {% endif %}
-                  {% if instance.broker.company.account_number %}
-                  
-                    
شماره حساب:
-                    
{{ instance.broker.company.account_number }}
-                  
-                  {% endif %}
-                  {% if instance.broker.company.sheba_number %}
-                  
-                    
شماره شبا:
-                    
{{ instance.broker.company.sheba_number }}
-                  
-                  {% endif %}
-                  {% if instance.broker.company.bank_name %}
-                  
-                    
بانک:
-                    
{{ instance.broker.company.get_bank_name_display }}
-                  
-                  {% endif %}
-                  {% if instance.broker.company.branch_name %}
-                  
-                    
شعبه:
-                    
{{ instance.broker.company.branch_name }}
-                  
-                  {% endif %}
-                  
                 
-
               
               {% endif %}
             
diff --git a/invoices/templates/invoices/quote_print.html b/invoices/templates/invoices/quote_print.html
index 282ff44..cbb0c13 100644
--- a/invoices/templates/invoices/quote_print.html
+++ b/invoices/templates/invoices/quote_print.html
@@ -7,6 +7,7 @@
     
     {% load static %}
     {% load humanize %}
+    {% load common_tags %}
 
     
     
@@ -75,6 +76,7 @@
         .items-table td {
             border-bottom: 1px solid #dee2e6;
             text-align: center;
+            font-size: 8px;
         }
         
         .total-section {
@@ -105,38 +107,12 @@
         
         
         
@@ -218,14 +204,11 @@
                     
اعتبار پیشفاکتور صادر شده ۴۸ ساعت پس از تاریخ صدور میباشد
                     مبلغ فوق به صورت علیالحساب دریافت میگردد
                     این برگه صرفاً جهت اعلام قیمت بوده و ارزش قانونی دیگری ندارد
-                    {% if instance.broker.company and instance.broker.company.signature %}
-                    

-                    {% endif %}
+                    
                 
-            
-            {% if instance.broker.company %}
-            
-                
اطلاعات پرداخت
+
+                {% if instance.broker.company %}
+                
اطلاعات پرداخت
                 {% if instance.broker.company.card_number %}
                 
شماره کارت: {{ instance.broker.company.card_number }}
                 {% endif %}
@@ -238,8 +221,22 @@
                 {% if instance.broker.company.bank_name %}
                 
بانک: {{ instance.broker.company.get_bank_name_display }}
                 {% endif %}
+                {% endif %}
+
+            
+
+            
+                {% if instance.broker.company and instance.broker.company.signature %}
+                
+                    
مهر و امضا
+                        {% if instance.broker.company.signature %}
+                      
+                    {% endif %}
+                    
+                    
+                
+                {% endif %}
             
-            {% endif %}
         
 
         
         
diff --git a/invoices/templates/invoices/quote_step.html b/invoices/templates/invoices/quote_step.html
index 404cf14..82ec091 100644
--- a/invoices/templates/invoices/quote_step.html
+++ b/invoices/templates/invoices/quote_step.html
@@ -57,7 +57,7 @@
                   
                     
پیشفاکتور موجود
                     {{ existing_quote.name }} | 
-                    مبلغ کل: {{ existing_quote.final_amount|floatformat:0|intcomma:False }} تومان | 
+                    مبلغ کل (با احتساب مالیات): {{ existing_quote.final_amount|floatformat:0|intcomma:False }} ریال | 
                     وضعیت: {{ existing_quote.get_status_display_with_color|safe }}
                   
                 
@@ -97,7 +97,7 @@
                               {% if item.description %}
{{ item.description }}{% endif %}
                             
 
                           
-                          {{ item.unit_price|floatformat:0|intcomma:False }} تومان | 
+                          {{ item.unit_price|floatformat:0|intcomma:False }} ریال | 
                           
                              0
     except Exception:
         can_approve_reject = False
+
+    # Compute whether current user has already decided (approved/rejected)
+    current_user_has_decided = False
+    try:
+        user_has_approval = step_instance.approvals.filter(approved_by=request.user, is_deleted=False).exists()
+        user_has_rejection = step_instance.rejections.filter(rejected_by=request.user, is_deleted=False).exists()
+        current_user_has_decided = bool(user_has_approval or user_has_rejection)
+    except Exception:
+        current_user_has_decided = False
         
 
     # Accountant/Admin approval and rejection via POST (multi-role)
@@ -388,22 +412,39 @@ def quote_payment_step(request, instance_id, step_id):
 
         action = request.POST.get('action')
         if action == 'approve':
-            StepApproval.objects.update_or_create(
+            StepApproval.objects.create(
                 step_instance=step_instance,
                 role=matching_role,
-                defaults={'approved_by': request.user, 'decision': 'approved', 'reason': ''}
+                approved_by=request.user,
+                reason=''
             )
             if step_instance.is_fully_approved():
                 step_instance.status = 'completed'
                 step_instance.completed_at = timezone.now()
                 step_instance.save()
-                # move to next step
-                redirect_url = 'processes:request_list'
+                
+                # Auto-complete next step if it exists
                 if next_step:
-                    instance.current_step = next_step
-                    instance.save()
-                    return redirect('processes:step_detail', instance_id=instance.id, step_id=next_step.id)
-                return redirect(redirect_url)
+                    next_step_instance, _ = StepInstance.objects.get_or_create(
+                        process_instance=instance,
+                        step=next_step,
+                        defaults={'status': 'in_progress'}
+                    )
+                    next_step_instance.status = 'completed'
+                    next_step_instance.completed_at = timezone.now()
+                    next_step_instance.save()
+                    
+                    # Move to the step after next
+                    step_after_next = instance.process.steps.filter(order__gt=next_step.order).first()
+                    if step_after_next:
+                        instance.current_step = step_after_next
+                        instance.save()
+                        return redirect('processes:step_detail', instance_id=instance.id, step_id=step_after_next.id)
+                    else:
+                        # No more steps, go to request list
+                        return redirect('processes:request_list')
+                
+                return redirect('processes:request_list')
             messages.success(request, 'تایید شما ثبت شد. منتظر تایید سایر نقشها.')
             return redirect('invoices:quote_payment_step', instance_id=instance.id, step_id=step.id)
 
@@ -412,12 +453,12 @@ def quote_payment_step(request, instance_id, step_id):
             if not reason:
                 messages.error(request, 'علت رد شدن را وارد کنید')
                 return redirect('invoices:quote_payment_step', instance_id=instance.id, step_id=step.id)
-            StepApproval.objects.update_or_create(
+            StepRejection.objects.create(
                 step_instance=step_instance,
                 role=matching_role,
-                defaults={'approved_by': request.user, 'decision': 'rejected', 'reason': reason}
-            )
-            StepRejection.objects.create(step_instance=step_instance, rejected_by=request.user, reason=reason)
+                rejected_by=request.user,
+                reason=reason
+                )
             # If current step is ahead of this step, reset it back to this step
             try:
                 if instance.current_step and instance.current_step.order > step.order:
@@ -452,6 +493,7 @@ def quote_payment_step(request, instance_id, step_id):
         'is_broker': is_broker,
         'is_accountant': is_accountant,
         'can_approve_reject': can_approve_reject,
+        'current_user_has_decided': current_user_has_decided,
     })
 
 
@@ -522,6 +564,7 @@ def add_quote_payment(request, instance_id, step_id):
             amount=amount_dec,
             payment_date=payment_date,
             payment_method=payment_method,
+            payment_stage='quote',
             reference_number=reference_number,
             receipt_image=receipt_image,
             notes=notes,
@@ -537,7 +580,17 @@ def add_quote_payment(request, instance_id, step_id):
         si.status = 'in_progress'
         si.completed_at = None
         si.save()
-        si.approvals.all().delete()
+    except Exception:
+        pass
+
+    try:
+        for appr in list(si.approvals.all()):
+            appr.delete()
+    except Exception:
+        pass
+    try:
+        for rej in list(si.rejections.all()):
+            rej.delete()
     except Exception:
         pass
     
@@ -554,7 +607,8 @@ def add_quote_payment(request, instance_id, step_id):
                 )
                 # Clear previous approvals if the step requires re-approval
                 try:
-                    subsequent_step_instance.approvals.all().delete()
+                    for appr in list(subsequent_step_instance.approvals.all()):
+                        appr.delete()
                 except Exception:
                     pass
     except Exception:
@@ -596,7 +650,7 @@ def delete_quote_payment(request, instance_id, step_id, payment_id):
 
     try:
         # soft delete using project's BaseModel delete override
-        payment.delete()
+        payment.hard_delete()
     except Exception:
         return JsonResponse({'success': False, 'message': 'خطا در حذف فیش'})
     # On delete, return to awaiting approval
@@ -605,7 +659,10 @@ def delete_quote_payment(request, instance_id, step_id, payment_id):
         si.status = 'in_progress'
         si.completed_at = None
         si.save()
-        si.approvals.all().delete()
+        for appr in list(si.approvals.all()):
+            appr.delete()
+        for rej in list(si.rejections.all()):
+            rej.delete()
     except Exception:
         pass
 
@@ -622,7 +679,8 @@ def delete_quote_payment(request, instance_id, step_id, payment_id):
                 )
                 # Clear previous approvals if the step requires re-approval
                 try:
-                    subsequent_step_instance.approvals.all().delete()
+                    for appr in list(subsequent_step_instance.approvals.all()):
+                        appr.delete()
                 except Exception:
                     pass
     except Exception:
@@ -707,16 +765,15 @@ def final_invoice_step(request, instance_id, step_id):
                 if ch.unit_price:
                     row['base_price'] = _to_decimal(ch.unit_price)
 
-    # Compute final invoice lines
+    # Compute final invoice lines (include fully removed items for display)
     rows = []
     total_amount = Decimal('0')
     for _, r in item_id_to_row.items():
         final_qty = max(0, (r['base_qty'] + r['added_qty'] - r['removed_qty']))
-        if final_qty == 0:
-            continue
         unit_price_dec = _to_decimal(r['base_price'])
-        line_total = Decimal(final_qty) * unit_price_dec
-        total_amount += line_total
+        line_total = Decimal(final_qty) * unit_price_dec if final_qty > 0 else Decimal('0')
+        if final_qty > 0:
+            total_amount += line_total
         rows.append({
             'item': r['item'],
             'quantity': final_qty,
@@ -725,6 +782,7 @@ def final_invoice_step(request, instance_id, step_id):
             'base_qty': r['base_qty'],
             'added_qty': r['added_qty'],
             'removed_qty': r['removed_qty'],
+            'is_removed': True if final_qty == 0 else False,
         })
 
     # Create or reuse final invoice
@@ -745,6 +803,8 @@ def final_invoice_step(request, instance_id, step_id):
     except Exception:
         qs.delete()
     for r in rows:
+        if r['quantity'] <= 0:
+            continue
         from .models import InvoiceItem
         InvoiceItem.objects.create(
             invoice=invoice,
@@ -826,6 +886,8 @@ def add_special_charge(request, instance_id, step_id):
     """افزودن هزینه ویژه تعمیر/تعویض به فاکتور نهایی بهصورت آیتم جداگانه"""
     instance = get_scoped_instance_or_404(request, instance_id)
     invoice = get_object_or_404(Invoice, process_instance=instance)
+    step = get_object_or_404(instance.process.steps, id=step_id)
+
     # only MANAGER can add special charges
     try:
         if not (hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.MANAGER)):
@@ -855,6 +917,50 @@ def add_special_charge(request, instance_id, step_id):
         unit_price=amount_dec,
     )
     invoice.calculate_totals()
+
+
+    # After modifying payments, set step back to in_progress
+    try:
+        si, _ = StepInstance.objects.get_or_create(process_instance=instance, step=step)
+        si.status = 'in_progress'
+        si.completed_at = None
+        si.save()
+    except Exception:
+        pass
+
+    # Reset ALL subsequent completed steps to in_progress
+    try:
+        subsequent_steps = instance.process.steps.filter(order__gt=step.order)
+        for subsequent_step in subsequent_steps:
+            subsequent_step_instance = instance.step_instances.filter(step=subsequent_step).first()
+            if subsequent_step_instance:
+                # Bypass validation by using update() instead of save()
+                instance.step_instances.filter(step=subsequent_step).update(
+                    status='in_progress',
+                    completed_at=None
+                )
+                 # Clear prior approvals/rejections as the underlying totals changed
+                try:
+                    for appr in list(subsequent_step_instance.approvals.all()):
+                        appr.delete()
+                except Exception:
+                    pass
+                try:
+                    for rej in list(subsequent_step_instance.rejections.all()):
+                        rej.delete()
+                except Exception:
+                    pass
+    except Exception:
+        pass
+
+    # If current step is ahead of this step, reset it back to this step
+    try:
+        if instance.current_step and instance.current_step.order > step.order:
+            instance.current_step = step
+            instance.save(update_fields=['current_step'])
+    except Exception:
+        pass
+
     return JsonResponse({'success': True, 'redirect': reverse('invoices:final_invoice_step', args=[instance.id, step_id])})
 
 
@@ -863,6 +969,8 @@ def add_special_charge(request, instance_id, step_id):
 def delete_special_charge(request, instance_id, step_id, item_id):
     instance = get_scoped_instance_or_404(request, instance_id)
     invoice = get_object_or_404(Invoice, process_instance=instance)
+    step = get_object_or_404(instance.process.steps, id=step_id)
+
     # only MANAGER can delete special charges
     try:
         if not (hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.MANAGER)):
@@ -878,6 +986,51 @@ def delete_special_charge(request, instance_id, step_id, item_id):
         return JsonResponse({'success': False, 'message': 'امکان حذف این مورد وجود ندارد'})
     inv_item.hard_delete()
     invoice.calculate_totals()
+    
+
+    # After modifying payments, set step back to in_progress
+    try:
+        si, _ = StepInstance.objects.get_or_create(process_instance=instance, step=step)
+        si.status = 'in_progress'
+        si.completed_at = None
+        si.save()
+    except Exception:
+        pass
+
+    # Reset ALL subsequent completed steps to in_progress
+    try:
+        subsequent_steps = instance.process.steps.filter(order__gt=step.order)
+        for subsequent_step in subsequent_steps:
+            subsequent_step_instance = instance.step_instances.filter(step=subsequent_step).first()
+            if subsequent_step_instance:
+                # Bypass validation by using update() instead of save()
+                instance.step_instances.filter(step=subsequent_step).update(
+                    status='in_progress',
+                    completed_at=None
+                )
+                 # Clear prior approvals/rejections as the underlying totals changed
+                try:
+                    for appr in list(subsequent_step_instance.approvals.all()):
+                        appr.delete()
+                except Exception:
+                    pass
+                try:
+                    for rej in list(subsequent_step_instance.rejections.all()):
+                        rej.delete()
+                except Exception:
+                    pass
+    except Exception:
+        pass
+
+    # If current step is ahead of this step, reset it back to this step
+    try:
+        if instance.current_step and instance.current_step.order > step.order:
+            instance.current_step = step
+            instance.save(update_fields=['current_step'])
+    except Exception:
+        pass
+
+
     return JsonResponse({'success': True, 'redirect': reverse('invoices:final_invoice_step', args=[instance.id, step_id])})
 
 
@@ -896,19 +1049,96 @@ def final_settlement_step(request, instance_id, step_id):
 
     # Ensure step instance exists
     step_instance, _ = StepInstance.objects.get_or_create(process_instance=instance, step=step, defaults={'status': 'in_progress'})
+
+    # Check if there are changes that require approval
+    # (used for both auto-complete and UI display)
+    has_special_charges = False
+    has_installation_changes = False
+    has_final_settlement_payments = False
+    
+    try:
+        has_special_charges = invoice.items.filter(item__is_special=True, is_deleted=False).exists()
+    except Exception:
+        pass
+    
+    try:
+        from installations.models import InstallationAssignment
+        assignment = InstallationAssignment.objects.filter(process_instance=instance).first()
+        if assignment:
+            reports = assignment.reports.all()
+            for report in reports:
+                if report.item_changes.filter(is_deleted=False).exists():
+                    has_installation_changes = True
+                    break
+    except Exception:
+        pass
+    
+    # Check if there are payments added during final settlement step
+    # using the payment_stage field
+    try:
+        final_settlement_payments = invoice.payments.filter(
+            is_deleted=False,
+            payment_stage='final_settlement'
+        )
+        if final_settlement_payments.exists():
+            has_final_settlement_payments = True
+    except Exception:
+        pass
+
+    # Auto-complete step when invoice is fully settled (no approvals needed)
+    # BUT only if no special charges were added in final_invoice step
+    # AND no installation item changes were made
+    # AND no payments were added in this final settlement step
+    # (meaning the remaining amount is from the original quote_payment step)
+    try:
+        invoice.calculate_totals()
+        remaining = invoice.get_remaining_amount()
+        
+        # Only auto-complete if:
+        # 1. Remaining amount is zero
+        # 2. No special charges were added (meaning this is settling the original quote)
+        # 3. No installation item changes (meaning no items added/removed in installation step)
+        # 4. No payments added in final settlement step (meaning no new receipts need approval)
+        if remaining == 0 and not has_special_charges and not has_installation_changes and not has_final_settlement_payments:
+            if step_instance.status != 'completed':
+                step_instance.status = 'completed'
+                step_instance.completed_at = timezone.now()
+                step_instance.save()
+            if next_step:
+                instance.current_step = next_step
+                instance.save(update_fields=['current_step'])
+            #     return redirect('processes:step_detail', instance_id=instance.id, step_id=next_step.id)
+            # return redirect('processes:request_list')
+    except Exception:
+        # If totals calculation fails, continue with normal flow
+        pass
     
     # Build approver statuses for template (include reason to display in UI)
     reqs = list(step.approver_requirements.select_related('role').all())
-    approvals = list(step_instance.approvals.select_related('role').all())
+    approvals = list(step_instance.approvals.select_related('role', 'approved_by').filter(is_deleted=False))
+    rejections = list(step_instance.rejections.select_related('role', 'rejected_by').filter(is_deleted=False))
     approvals_by_role = {a.role_id: a for a in approvals}
-    approver_statuses = [
-        {
+    rejections_by_role = {r.role_id: r for r in rejections}
+    approver_statuses = []
+    for r in reqs:
+        appr = approvals_by_role.get(r.role_id)
+        rejection = rejections_by_role.get(r.role_id)
+        
+        if appr:
+            status = 'approved'
+            reason = appr.reason
+        elif rejection:
+            status = 'rejected'
+            reason = rejection.reason
+        else:
+            status = None
+            reason = ''
+            
+        approver_statuses.append({
             'role': r.role,
-            'status': (approvals_by_role.get(r.role_id).decision if approvals_by_role.get(r.role_id) else None),
-            'reason': (approvals_by_role.get(r.role_id).reason if approvals_by_role.get(r.role_id) else ''),
-        }
-        for r in reqs
-    ]
+            'status': status,
+            'reason': reason,
+        })
     # dynamic permission to control approve/reject UI
     try:
         user_roles_qs = getattr(getattr(request.user, 'profile', None), 'roles', Role.objects.none())
@@ -918,12 +1148,21 @@ def final_settlement_step(request, instance_id, step_id):
     except Exception:
         can_approve_reject = False
 
+    # Compute whether current user has already decided (approved/rejected)
+    current_user_has_decided = False
+    try:
+        user_has_approval = step_instance.approvals.filter(approved_by=request.user, is_deleted=False).exists()
+        user_has_rejection = step_instance.rejections.filter(rejected_by=request.user, is_deleted=False).exists()
+        current_user_has_decided = bool(user_has_approval or user_has_rejection)
+    except Exception:
+        current_user_has_decided = False
+
     # Accountant/Admin approval and rejection (multi-role)
-    if request.method == 'POST' and request.POST.get('action') in ['approve', 'reject']:
+    if request.method == 'POST' and request.POST.get('action') in ['approve', 'reject', 'force_approve']:
         req_roles = [req.role for req in step.approver_requirements.select_related('role').all()]
         user_roles = list(getattr(getattr(request.user, 'profile', None), 'roles', Role.objects.none()).all())
         matching_role = next((r for r in user_roles if r in req_roles), None)
-        if matching_role is None:
+        if matching_role is None and request.POST.get('action') != 'force_approve':
             messages.error(request, 'شما دسترسی لازم برای تایید/رد این مرحله را ندارید.')
             return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
 
@@ -931,13 +1170,14 @@ def final_settlement_step(request, instance_id, step_id):
         if action == 'approve':
             # enforce zero remaining
             invoice.calculate_totals()
-            if invoice.remaining_amount != 0:
-                messages.error(request, f"تا زمانی که مانده فاکتور صفر نشده امکان تایید نیست (مانده فعلی: {invoice.remaining_amount})")
+            if invoice.get_remaining_amount() != 0:
+                messages.error(request, f"تا زمانی که مانده فاکتور صفر نشده امکان تایید نیست (مانده فعلی: {invoice.get_remaining_amount()})")
                 return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
-            StepApproval.objects.update_or_create(
+            StepApproval.objects.create(
                 step_instance=step_instance,
                 role=matching_role,
-                defaults={'approved_by': request.user, 'decision': 'approved', 'reason': ''}
+                approved_by=request.user,
+                reason=''
             )
             if step_instance.is_fully_approved():
                 step_instance.status = 'completed'
@@ -956,12 +1196,12 @@ def final_settlement_step(request, instance_id, step_id):
             if not reason:
                 messages.error(request, 'علت رد شدن را وارد کنید')
                 return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
-            StepApproval.objects.update_or_create(
+            StepRejection.objects.create(
                 step_instance=step_instance,
                 role=matching_role,
-                defaults={'approved_by': request.user, 'decision': 'rejected', 'reason': reason}
-            )
-            StepRejection.objects.create(step_instance=step_instance, rejected_by=request.user, reason=reason)
+                rejected_by=request.user,
+                reason=reason
+                )
             # If current step is ahead of this step, reset it back to this step (align behavior with other steps)
             try:
                 if instance.current_step and instance.current_step.order > step.order:
@@ -972,6 +1212,32 @@ def final_settlement_step(request, instance_id, step_id):
             messages.success(request, 'مرحله تسویه نهایی رد شد و برای اصلاح بازگشت.')
             return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
 
+        if action == 'force_approve':
+            # Only MANAGER can force approve
+            try:
+                if not (hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.MANAGER)):
+                    messages.error(request, 'فقط مدیر مجاز به تایید اضطراری است.')
+                    return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
+            except Exception:
+                messages.error(request, 'فقط مدیر مجاز به تایید اضطراری است.')
+                return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
+            # Allow emergency approval only when invoice has a remaining (non-zero)
+            try:
+                invoice.calculate_totals()
+                if invoice.get_remaining_amount() == 0:
+                    messages.error(request, 'فاکتور تسویه شده است؛ تایید اضطراری لازم نیست.')
+                    return redirect('invoices:final_settlement_step', instance_id=instance.id, step_id=step.id)
+            except Exception:
+                pass
+            # Mark step completed regardless of remaining amount/approvals
+            step_instance.status = 'approved'
+            step_instance.save()
+            if next_step:
+                instance.current_step = next_step
+                instance.save()
+                return redirect('processes:step_detail', instance_id=instance.id, step_id=next_step.id)
+            return redirect('processes:request_list')
+
     # broker flag for payment management permission
     profile = getattr(request.user, 'profile', None)
     is_broker = False
@@ -980,6 +1246,21 @@ def final_settlement_step(request, instance_id, step_id):
     except Exception:
         is_broker = False
 
+    # Determine if approval is needed
+    # Approval is needed if:
+    # 1. Remaining amount is not zero, OR
+    # 2. Special charges were added (meaning new balance was created in final_invoice step), OR
+    # 3. Installation item changes were made (meaning items were added/removed in installation step), OR
+    # 4. Payments were added in final settlement step (new receipts need approval)
+    needs_approval = True
+    try:
+        remaining = invoice.get_remaining_amount()
+        # No approval needed only if: remaining is zero AND no special charges AND no installation changes AND no final settlement payments
+        if remaining == 0 and not has_special_charges and not has_installation_changes and not has_final_settlement_payments:
+            needs_approval = False
+    except Exception:
+        needs_approval = True
+
     return render(request, 'invoices/final_settlement_step.html', {
         'instance': instance,
         'step': step,
@@ -991,6 +1272,9 @@ def final_settlement_step(request, instance_id, step_id):
         'approver_statuses': approver_statuses,
         'can_approve_reject': can_approve_reject,
         'is_broker': is_broker,
+        'current_user_has_decided': current_user_has_decided,
+        'needs_approval': needs_approval,
+        'is_manager': bool(getattr(getattr(request.user, 'profile', None), 'roles', Role.objects.none()).filter(slug=UserRoles.MANAGER.value).exists()) if getattr(request.user, 'profile', None) else False,
     })
 
 
@@ -1007,6 +1291,14 @@ def add_final_payment(request, instance_id, step_id):
     except Exception:
         return JsonResponse({'success': False, 'message': 'شما مجوز افزودن تراکنش تسویه را ندارید'}, status=403)
 
+    # Prevent adding payments if invoice already settled
+    try:
+        invoice.calculate_totals()
+        if invoice.get_remaining_amount() == 0:
+            return JsonResponse({'success': False, 'message': 'فاکتور تسویه شده است؛ افزودن تراکنش مجاز نیست'})
+    except Exception:
+        pass
+
     amount = (request.POST.get('amount') or '').strip()
     payment_date = (request.POST.get('payment_date') or '').strip()
     payment_method = (request.POST.get('payment_method') or '').strip()
@@ -1054,6 +1346,7 @@ def add_final_payment(request, instance_id, step_id):
         amount=amount_dec,
         payment_date=payment_date,
         payment_method=payment_method,
+        payment_stage='final_settlement',
         reference_number=reference_number,
         direction='in' if direction != 'out' else 'out',
         receipt_image=receipt_image,
@@ -1065,10 +1358,20 @@ def add_final_payment(request, instance_id, step_id):
     # On delete, return to awaiting approval
     try:
         si, _ = StepInstance.objects.get_or_create(process_instance=instance, step=step)
-        si.status = 'in_progress'
+        if si.status != 'approved':
+            si.status = 'in_progress'
         si.completed_at = None
         si.save()
-        si.approvals.all().delete()
+        try:
+            for appr in list(si.approvals.all()):
+                appr.delete()
+        except Exception:
+            pass
+        try:
+            for rej in list(si.rejections.all()):
+                rej.delete()
+        except Exception:
+            pass
     except Exception:
         pass
     
@@ -1085,7 +1388,8 @@ def add_final_payment(request, instance_id, step_id):
                 )
                 # Clear previous approvals if the step requires re-approval
                 try:
-                    subsequent_step_instance.approvals.all().delete()
+                    for appr in list(subsequent_step_instance.approvals.all()):
+                        appr.delete()
                 except Exception:
                     pass
     except Exception:
@@ -1105,8 +1409,8 @@ def add_final_payment(request, instance_id, step_id):
         'redirect': reverse('invoices:final_settlement_step', args=[instance.id, step_id]),
         'totals': {
             'final_amount': str(invoice.final_amount),
-            'paid_amount': str(invoice.paid_amount),
-            'remaining_amount': str(invoice.remaining_amount),
+            'paid_amount': str(invoice.get_paid_amount()),
+            'remaining_amount': str(invoice.get_remaining_amount()),
         }
     })
 
@@ -1118,14 +1422,17 @@ def delete_final_payment(request, instance_id, step_id, payment_id):
     step = get_object_or_404(instance.process.steps, id=step_id)
     invoice = get_object_or_404(Invoice, process_instance=instance)
     payment = get_object_or_404(Payment, id=payment_id, invoice=invoice)
+    
     # Only BROKER can delete final settlement payments
     try:
         if not (hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.BROKER)):
             return JsonResponse({'success': False, 'message': 'شما مجوز حذف تراکنش تسویه را ندارید'}, status=403)
     except Exception:
         return JsonResponse({'success': False, 'message': 'شما مجوز حذف تراکنش تسویه را ندارید'}, status=403)
-    payment.delete()
-    invoice.refresh_from_db()
+    
+    # Delete payment and recalculate invoice totals
+    payment.hard_delete()
+    invoice.calculate_totals()  # This is what was missing!
 
     # On delete, return to awaiting approval
     try:
@@ -1133,7 +1440,11 @@ def delete_final_payment(request, instance_id, step_id, payment_id):
         si.status = 'in_progress'
         si.completed_at = None
         si.save()
-        si.approvals.all().delete()
+        # Clear approvals and rejections (like in quote_payment)
+        for appr in list(si.approvals.all()):
+            appr.delete()
+        for rej in list(si.rejections.all()):
+            rej.delete()
     except Exception:
         pass
 
@@ -1150,7 +1461,8 @@ def delete_final_payment(request, instance_id, step_id, payment_id):
                 )
                 # Clear previous approvals if the step requires re-approval
                 try:
-                    subsequent_step_instance.approvals.all().delete()
+                    for appr in list(subsequent_step_instance.approvals.all()):
+                        appr.delete()
                 except Exception:
                     pass
     except Exception:
@@ -1166,7 +1478,7 @@ def delete_final_payment(request, instance_id, step_id, payment_id):
 
     return JsonResponse({'success': True, 'redirect': reverse('invoices:final_settlement_step', args=[instance.id, step_id]), 'totals': {
         'final_amount': str(invoice.final_amount),
-        'paid_amount': str(invoice.paid_amount),
-        'remaining_amount': str(invoice.remaining_amount),
+        'paid_amount': str(invoice.get_paid_amount()),
+        'remaining_amount': str(invoice.get_remaining_amount()),
     }})
 
diff --git a/locations/migrations/0004_alter_county_city.py b/locations/migrations/0004_alter_county_city.py
new file mode 100644
index 0000000..7716961
--- /dev/null
+++ b/locations/migrations/0004_alter_county_city.py
@@ -0,0 +1,19 @@
+# Generated by Django 5.2.4 on 2025-09-21 07:37
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('locations', '0003_remove_broker_company'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='county',
+            name='city',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='locations.city', verbose_name='استان'),
+        ),
+    ]
diff --git a/processes/admin.py b/processes/admin.py
index 0da4cf5..42d4bca 100644
--- a/processes/admin.py
+++ b/processes/admin.py
@@ -162,9 +162,9 @@ class StepInstanceAdmin(SimpleHistoryAdmin):
 
 @admin.register(StepRejection)
 class StepRejectionAdmin(SimpleHistoryAdmin):
-    list_display = ['step_instance', 'rejected_by', 'reason_short', 'created_at']
-    list_filter = ['rejected_by', 'created_at', 'step_instance__step__process']
-    search_fields = ['step_instance__step__name', 'rejected_by__username', 'reason']
+    list_display = ['step_instance', 'role', 'rejected_by', 'reason_short', 'created_at', 'is_deleted']
+    list_filter = ['role', 'rejected_by', 'created_at', 'step_instance__step__process']
+    search_fields = ['step_instance__step__name', 'rejected_by__username', 'reason', 'role__name']
     readonly_fields = ['created_at']
     ordering = ['-created_at']
 
@@ -182,6 +182,6 @@ class StepApproverRequirementAdmin(admin.ModelAdmin):
 
 @admin.register(StepApproval)
 class StepApprovalAdmin(admin.ModelAdmin):
-    list_display = ("step_instance", "role", "decision", "approved_by", "created_at")
-    list_filter = ("decision", "role", "step_instance__step__process")
+    list_display = ("step_instance", "role", "approved_by", "created_at", "is_deleted")
+    list_filter = ("role", "step_instance__step__process")
     search_fields = ("step_instance__process_instance__code", "role__name", "approved_by__username")
diff --git a/processes/migrations/0004_historicalsteprejection_is_deleted_and_more.py b/processes/migrations/0004_historicalsteprejection_is_deleted_and_more.py
new file mode 100644
index 0000000..13af0d4
--- /dev/null
+++ b/processes/migrations/0004_historicalsteprejection_is_deleted_and_more.py
@@ -0,0 +1,28 @@
+# Generated by Django 5.2.4 on 2025-09-27 06:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('processes', '0003_historicalstepinstance_edit_count_and_more'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='historicalsteprejection',
+            name='is_deleted',
+            field=models.BooleanField(default=False, verbose_name='حذف شده'),
+        ),
+        migrations.AddField(
+            model_name='stepapproval',
+            name='is_deleted',
+            field=models.BooleanField(default=False, verbose_name='حذف شده'),
+        ),
+        migrations.AddField(
+            model_name='steprejection',
+            name='is_deleted',
+            field=models.BooleanField(default=False, verbose_name='حذف شده'),
+        ),
+    ]
diff --git a/processes/migrations/0005_alter_historicalstepinstance_status_and_more.py b/processes/migrations/0005_alter_historicalstepinstance_status_and_more.py
new file mode 100644
index 0000000..631a8f3
--- /dev/null
+++ b/processes/migrations/0005_alter_historicalstepinstance_status_and_more.py
@@ -0,0 +1,23 @@
+# Generated by Django 5.2.4 on 2025-09-27 15:37
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('processes', '0004_historicalsteprejection_is_deleted_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='historicalstepinstance',
+            name='status',
+            field=models.CharField(choices=[('pending', 'در انتظار'), ('in_progress', 'در حال انجام'), ('completed', 'تکمیل شده'), ('skipped', 'رد شده'), ('blocked', 'مسدود شده'), ('rejected', 'رد شده و نیاز به اصلاح'), ('approved', 'تایید اضطراری')], default='pending', max_length=20, verbose_name='وضعیت'),
+        ),
+        migrations.AlterField(
+            model_name='stepinstance',
+            name='status',
+            field=models.CharField(choices=[('pending', 'در انتظار'), ('in_progress', 'در حال انجام'), ('completed', 'تکمیل شده'), ('skipped', 'رد شده'), ('blocked', 'مسدود شده'), ('rejected', 'رد شده و نیاز به اصلاح'), ('approved', 'تایید اضطراری')], default='pending', max_length=20, verbose_name='وضعیت'),
+        ),
+    ]
diff --git a/processes/migrations/0006_alter_stepapproval_unique_together_and_more.py b/processes/migrations/0006_alter_stepapproval_unique_together_and_more.py
new file mode 100644
index 0000000..f4cb896
--- /dev/null
+++ b/processes/migrations/0006_alter_stepapproval_unique_together_and_more.py
@@ -0,0 +1,34 @@
+# Generated by Django 5.2.4 on 2025-10-02 09:32
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('accounts', '0008_alter_historicalprofile_phone_number_1_and_more'),
+        ('processes', '0005_alter_historicalstepinstance_status_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='stepapproval',
+            unique_together=set(),
+        ),
+        migrations.AddField(
+            model_name='historicalsteprejection',
+            name='role',
+            field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='accounts.role', verbose_name='نقش'),
+        ),
+        migrations.AddField(
+            model_name='steprejection',
+            name='role',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.role', verbose_name='نقش'),
+        ),
+        migrations.AlterField(
+            model_name='stepapproval',
+            name='role',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.role', verbose_name='نقش'),
+        ),
+    ]
diff --git a/processes/migrations/0007_remove_stepapproval_decision_and_more.py b/processes/migrations/0007_remove_stepapproval_decision_and_more.py
new file mode 100644
index 0000000..d97d16b
--- /dev/null
+++ b/processes/migrations/0007_remove_stepapproval_decision_and_more.py
@@ -0,0 +1,22 @@
+# Generated by Django 5.2.4 on 2025-10-02 09:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('processes', '0006_alter_stepapproval_unique_together_and_more'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='stepapproval',
+            name='decision',
+        ),
+        migrations.AlterField(
+            model_name='stepapproval',
+            name='reason',
+            field=models.TextField(blank=True, verbose_name='توضیحات'),
+        ),
+    ]
diff --git a/processes/models.py b/processes/models.py
index 414d475..9cd0ddd 100644
--- a/processes/models.py
+++ b/processes/models.py
@@ -290,6 +290,10 @@ class ProcessInstance(SluggedModel):
         dependencies = step.get_dependencies()
         for dependency_id in dependencies:
             step_instance = self.step_instances.filter(step_id=dependency_id).first()
+            if step_instance and step_instance.status == 'in_progress' and step_instance.step.order == 3 and step.order == 4:
+                return True
+            if step_instance and step_instance.status == 'approved' and step_instance.step.order == 8 and step.order == 9:
+                return True
             if not step_instance or step_instance.status != 'completed':
                 return False
         return True
@@ -320,6 +324,7 @@ class StepInstance(models.Model):
             ('skipped', 'رد شده'),
             ('blocked', 'مسدود شده'),
             ('rejected', 'رد شده و نیاز به اصلاح'),
+            ('approved', 'تایید اضطراری'),
         ],
         default='pending',
         verbose_name="وضعیت"
@@ -373,7 +378,7 @@ class StepInstance(models.Model):
 
     def get_latest_rejection(self):
         """دریافت آخرین رد شدن"""
-        return self.rejections.order_by('-created_at').first()
+        return self.rejections.filter(is_deleted=False).order_by('-created_at').first()
 
     # -------- Multi-role approval helpers --------
     def required_roles(self):
@@ -381,8 +386,8 @@ class StepInstance(models.Model):
 
     def approvals_by_role(self):
         decisions = {}
-        for a in self.approvals.select_related('role').order_by('created_at'):
-            decisions[a.role_id] = a.decision
+        for a in self.approvals.filter(is_deleted=False).select_related('role').order_by('created_at'):
+            decisions[a.role_id] = 'approved'
         return decisions
 
     def is_fully_approved(self) -> bool:
@@ -404,6 +409,7 @@ class StepRejection(models.Model):
         related_name='rejections',
         verbose_name="نمونه مرحله"
     )
+    role = models.ForeignKey(Role, on_delete=models.SET_NULL, blank=True, null=True, verbose_name="نقش")
     rejected_by = models.ForeignKey(
         User, 
         on_delete=models.CASCADE, 
@@ -417,6 +423,7 @@ class StepRejection(models.Model):
         blank=True
     )
     created_at = models.DateTimeField(auto_now_add=True, verbose_name="تاریخ رد شدن")
+    is_deleted = models.BooleanField(default=False, verbose_name='حذف شده')
     history = HistoricalRecords()
 
     class Meta:
@@ -425,14 +432,22 @@ class StepRejection(models.Model):
         ordering = ['-created_at']
 
     def __str__(self):
-        return f"رد شدن {self.step_instance} توسط {self.rejected_by.get_full_name()}"
+        return f"رد شدن {self.step_instance} توسط {self.rejected_by.get_full_name()} ({self.role.name})"
 
     def save(self, *args, **kwargs):
         """ذخیره با تغییر وضعیت مرحله"""
-        self.step_instance.status = 'rejected'
-        self.step_instance.save()
+        if self.is_deleted == False:
+            self.step_instance.status = 'rejected'
+            self.step_instance.save()
         super().save(*args, **kwargs)
 
+    def hard_delete(self):
+        super().delete()
+
+    def delete(self, *args, **kwargs):
+        self.is_deleted = True
+        self.save()
+
 
 class StepApproverRequirement(models.Model):
     """Required approver roles for a step."""
@@ -452,16 +467,23 @@ class StepApproverRequirement(models.Model):
 class StepApproval(models.Model):
     """Approvals per role for a concrete step instance."""
     step_instance = models.ForeignKey(StepInstance, on_delete=models.CASCADE, related_name='approvals', verbose_name="نمونه مرحله")
-    role = models.ForeignKey(Role, on_delete=models.CASCADE, verbose_name="نقش")
+    role = models.ForeignKey(Role, on_delete=models.SET_NULL, blank=True, null=True, verbose_name="نقش")
     approved_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="تاییدکننده")
-    decision = models.CharField(max_length=8, choices=[('approved', 'تایید'), ('rejected', 'رد')], verbose_name='نتیجه')
-    reason = models.TextField(blank=True, verbose_name='علت (برای رد)')
+    reason = models.TextField(blank=True, verbose_name='توضیحات')
     created_at = models.DateTimeField(auto_now_add=True, verbose_name='تاریخ')
+    is_deleted = models.BooleanField(default=False, verbose_name='حذف شده')
 
     class Meta:
-        unique_together = ('step_instance', 'role')
         verbose_name = 'تایید مرحله'
         verbose_name_plural = 'تاییدهای مرحله'
+    
+    def delete(self, *args, **kwargs):
+        self.is_deleted = True
+        self.save()
+
+    def hard_delete(self):
+        super().delete()
+
 
     def __str__(self):
-        return f"{self.step_instance} - {self.role} - {self.decision}"
+        return f"{self.step_instance} - {self.role} - تایید شده"
diff --git a/processes/templates/processes/instance_summary.html b/processes/templates/processes/instance_summary.html
index ad84b59..59f910f 100644
--- a/processes/templates/processes/instance_summary.html
+++ b/processes/templates/processes/instance_summary.html
@@ -3,6 +3,7 @@
 {% load humanize %}
 {% load common_tags %}
 {% load processes_tags %}
+{% load accounts_tags %}
 
 {% block sidebar %}
   {% include 'sidebars/admin.html' %}
@@ -37,9 +38,11 @@
                پرینت فاکتور
             
           {% endif %}
-          
+          {% if request.user|is_broker or request.user|is_manager %}
+          
+          
+          {% endif %}
           
             
             بازگشت
@@ -56,9 +59,9 @@
             
               {% if invoice %}
                
-                 مبلغ نهایی {{ invoice.final_amount|floatformat:0|intcomma:False }} تومان 
-                 پرداختیها {{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان 
-                 مانده {{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان 
+                 مبلغ نهایی {{ invoice.final_amount|floatformat:0|intcomma:False }} ریال 
+                 پرداختیها {{ invoice.get_paid_amount|floatformat:0|intcomma:False }} ریال 
+                 مانده {{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} ریال  
                
               
                 
@@ -95,32 +98,113 @@
           
             
             
               {% if latest_report %}
-                 
-                   
-                     تاریخ مراجعه: {{ latest_report.visited_date|to_jalali|default:'-' }} 
+                
+                 
+                   
+                     تاریخ مراجعه: {{ latest_report.visited_date|to_jalali|default:'-' }} 
+                   
+                  {% if installation_assignment.scheduled_date %}
+                   
+                     تاریخ برنامهریزی: {{ installation_assignment.scheduled_date|to_jalali }} 
+                   
+                  {% endif %}
+                   
                     سریال کنتور جدید: {{ latest_report.new_water_meter_serial|default:'-' }} 
+                    
+                   
                     شماره پلمپ: {{ latest_report.seal_number|default:'-' }} 
                    
-                   
+                   
                     کنتور مشکوک: {{ latest_report.is_meter_suspicious|yesno:'بله,خیر' }} 
+                    
+                  {% if latest_report.sim_number %}
+                   
+                     شماره سیمکارت: {{ latest_report.sim_number }} 
+                   
+                  {% endif %}
+                  {% if latest_report.meter_type %}
+                   
+                     نوع کنتور: {{ latest_report.get_meter_type_display }} 
+                   
+                  {% endif %}
+                  {% if latest_report.meter_size %}
+                   
+                     سایز کنتور: {{ latest_report.meter_size }} 
+                   
+                  {% endif %}
+                  {% if latest_report.water_meter_manufacturer %}
+                   
+                     سازنده: {{ latest_report.water_meter_manufacturer.name }} 
+                   
+                  {% endif %}
+                  {% if latest_report.discharge_pipe_diameter %}
+                   
+                     قطر لوله آبده: {{ latest_report.discharge_pipe_diameter }} اینچ 
+                   
+                  {% endif %}
+                  {% if latest_report.usage_type %}
+                   
+                     نوع مصرف: {{ latest_report.get_usage_type_display }} 
+                   
+                  {% endif %}
+                  {% if latest_report.driving_force %}
+                   
+                     نیرو محرکه: {{ latest_report.driving_force }} 
+                   
+                  {% endif %}
+                  {% if latest_report.motor_power %}
+                   
+                     قدرت موتور: {{ latest_report.motor_power }} کیلووات ساعت 
+                   
+                  {% endif %}
+                  {% if latest_report.exploitation_license_number %}
+                   
+                     شماره پروانه: {{ latest_report.exploitation_license_number }} 
+                   
+                  {% endif %}
+                  {% if latest_report.pre_calibration_flow_rate %}
+                   
+                     دبی قبل از کالیبراسیون: {{ latest_report.pre_calibration_flow_rate }} لیتر/ثانیه 
+                   
+                  {% endif %}
+                  {% if latest_report.post_calibration_flow_rate %}
+                   
+                     دبی بعد از کالیبراسیون: {{ latest_report.post_calibration_flow_rate }} لیتر/ثانیه 
+                   
+                  {% endif %}
+                   
                     UTM X: {{ latest_report.utm_x|default:'-' }} 
+                    
+                   
                     UTM Y: {{ latest_report.utm_y|default:'-' }} 
                    
                 
+
                 {% if latest_report.description %}
-                   
-                     توضیحات: 
+                   
+                     توضیحات
                     {{ latest_report.description }} 
                   
                 {% endif %}
-                 
 
-                 عکسها
+                
+                 عکسها
                 
                   {% for p in latest_report.photos.all %}
                      
@@ -156,7 +240,7 @@
                     {% for p in payments %}
                      
                       | {% if p.direction == 'in' %}دریافتی{% else %}پرداختی{% endif %} | 
-                      {{ p.amount|floatformat:0|intcomma:False }} تومان | 
+                      {{ p.amount|floatformat:0|intcomma:False }} ریال | 
                       {{ p.payment_date|date:'Y/m/d' }} | 
                       {{ p.get_payment_method_display }} | 
                       {{ p.reference_number|default:'-' }} | 
@@ -175,6 +259,30 @@
     
   
 
+
+
+
 {% endblock %}
 
 
diff --git a/processes/templates/processes/request_list.html b/processes/templates/processes/request_list.html
index ecd2956..1ae210a 100644
--- a/processes/templates/processes/request_list.html
+++ b/processes/templates/processes/request_list.html
@@ -1,6 +1,7 @@
 {% extends '_base.html' %}
 {% load static %}
 {% load accounts_tags %}
+{% load common_tags %}
 
 {% block sidebar %}
     {% include 'sidebars/admin.html' %}
@@ -36,14 +37,14 @@
      
@@ -221,11 +223,24 @@
            
             | {{ item.instance.code }} | 
             {{ item.instance.process.name }} | 
-            
+             | 
               {% if item.instance.status == 'completed' %}
                 {{ item.instance.current_step.name|default:"--" }}
               {% elif item.instance.current_step %}
                 {{ item.instance.current_step.name }}
+                {% if item.current_step_approval_status %}
+                   
+                  
+                    {% if item.current_step_approval_status.status == 'rejected' %}
+                      
+                    {% elif item.current_step_approval_status.status == 'approved' %}
+                      
+                    {% else %}
+                      
+                    {% endif %}
+                    {{ item.current_step_approval_status.display }}
+                  
+                {% endif %}
               {% else %}
                 --
               {% endif %}
@@ -243,7 +258,26 @@
                 {{ item.progress_percentage }}%
               
              | 
-            {{ item.instance.get_status_display_with_color|safe }} | 
+            
+              {{ item.instance.get_status_display_with_color|safe }}
+              {% if item.emergency_approved %}
+                تایید اضطراری
+              {% endif %}
+             | 
+            
+              {% if item.installation_scheduled_date %}
+                 
+                  {{ item.installation_scheduled_date | to_jalali }}
+                 
+                {% if item.installation_overdue_days and item.installation_overdue_days > 0 %}
+                  {{ item.installation_overdue_days }} روز تاخیر
+                {% else %}
+                  بدون تاخیر
+                {% endif %}
+              {% else %}
+                تاریخ نصب تعیین نشده
+              {% endif %}
+             | 
             {{ item.instance.jcreated_date }} | 
             
                
@@ -287,6 +321,7 @@
               |  | 
              | 
              | 
+             | 
            
           {% endfor %}
         
@@ -419,6 +454,10 @@
 
                
                 
+                   
+                    
+                    {{ customer_form.user_type }}
+                   
                   
                     
                     {{ customer_form.first_name }}
@@ -439,6 +478,15 @@
                     
                     {{ customer_form.national_code }}
                    
+                  
+                   
+                    
+                    {{ customer_form.company_name }}
+                   
+                   
+                    
+                    {{ customer_form.company_national_id }}
+                   
                   
                     
                     {{ customer_form.card_number }}
@@ -717,6 +765,21 @@
         .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; }
@@ -732,36 +795,47 @@
             $('#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');
           }
         })
@@ -954,6 +1028,45 @@
         });
       };
     };
+
+    // 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 = ' در حال تولید...';
+      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);
+    };
   });
 
 {% endblock %}
diff --git a/processes/templatetags/processes_tags.py b/processes/templatetags/processes_tags.py
index 5ee7b2f..5087f4e 100644
--- a/processes/templatetags/processes_tags.py
+++ b/processes/templatetags/processes_tags.py
@@ -28,9 +28,11 @@ def stepper_header(instance, current_step=None):
         status = step_id_to_status.get(step.id, 'pending')
         
         # بررسی دسترسی به مرحله (UI navigation constraints):
-        # can_access = instance.can_access_step(step)
+        can_access = instance.can_access_step(step)
+
         # فقط مراحل تکمیلشده یا مرحله جاری قابل کلیک هستند
-        can_access = (step_id_to_status.get(step.id) == 'completed') or (instance.current_step and step.id == instance.current_step.id)
+        # can_access = (step_id_to_status.get(step.id) == 'completed') or (instance.current_step and step.id == instance.current_step.id)
+
         # مرحله انتخابشده (نمایش فعلی)
         is_selected = bool(current_step and step.id == current_step.id)
         # مرحلهای که باید انجام شود (مرحله جاری در instance)
diff --git a/processes/urls.py b/processes/urls.py
index a58ebab..0e1aaa5 100644
--- a/processes/urls.py
+++ b/processes/urls.py
@@ -6,6 +6,7 @@ app_name = 'processes'
 urlpatterns = [
     # Requests UI
     path('requests/', views.request_list, name='request_list'),
+    path('requests/export/excel/', views.export_requests_excel, name='export_requests_excel'),
     path('requests/create/', views.create_request_with_entities, name='create_request_with_entities'),
     path('requests/lookup/well/', views.lookup_well_by_subscription, name='lookup_well_by_subscription'),
     path('requests/lookup/representative/', views.lookup_representative_by_national_code, name='lookup_representative_by_national_code'),
diff --git a/processes/utils.py b/processes/utils.py
index 951398e..717c0fc 100644
--- a/processes/utils.py
+++ b/processes/utils.py
@@ -20,7 +20,7 @@ def scope_instances_queryset(user, queryset=None):
             return qs.filter(id__in=assign_ids)
         if profile.has_role(UserRoles.BROKER):
             return qs.filter(broker=profile.broker)
-        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER):
+        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER) or profile.has_role(UserRoles.WATER_RESOURCE_MANAGER):
             return qs.filter(broker__affairs__county=profile.county)
         if profile.has_role(UserRoles.ADMIN):
             return qs
@@ -69,7 +69,7 @@ def scope_wells_queryset(user, queryset=None):
             return qs
         if profile.has_role(UserRoles.BROKER):
             return qs.filter(broker=profile.broker)
-        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER):
+        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER) or profile.has_role(UserRoles.WATER_RESOURCE_MANAGER):
             return qs.filter(broker__affairs__county=profile.county)
         if profile.has_role(UserRoles.INSTALLER):
             # Wells that have instances assigned to this installer
@@ -102,7 +102,7 @@ def scope_customers_queryset(user, queryset=None):
             return qs
         if profile.has_role(UserRoles.BROKER):
             return qs.filter(broker=profile.broker)
-        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER):
+        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER) or profile.has_role(UserRoles.WATER_RESOURCE_MANAGER):
             return qs.filter(county=profile.county)
         if profile.has_role(UserRoles.INSTALLER):
             # Customers that are representatives of instances assigned to this installer
diff --git a/processes/views.py b/processes/views.py
index 38ad946..9c33e66 100644
--- a/processes/views.py
+++ b/processes/views.py
@@ -3,13 +3,19 @@ from django.urls import reverse
 
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
-from django.http import JsonResponse
+from django.http import JsonResponse, HttpResponse
 from django.views.decorators.http import require_POST, require_GET
+from django.utils import timezone
 from django.db import transaction
 from django.contrib.auth import get_user_model
+import openpyxl
+from openpyxl.styles import Font, Alignment, PatternFill
+from openpyxl.utils import get_column_letter
+from datetime import datetime
+from _helpers.utils import persian_converter3
 from .models import Process, ProcessInstance, StepInstance, ProcessStep
 from .utils import scope_instances_queryset, get_scoped_instance_or_404
-from installations.models import InstallationAssignment
+from installations.models import InstallationAssignment, InstallationReport
 from wells.models import Well
 from accounts.models import Profile, Broker
 from locations.models import Affairs
@@ -65,18 +71,143 @@ def request_list(request):
     steps_list = ProcessStep.objects.select_related('process').all().order_by('process__name', 'order')
     manufacturers = WaterMeterManufacturer.objects.all().order_by('name')
     
-    # Calculate progress for each instance
+    # Prepare installation assignments map (scheduled date by instance)
+    try:
+        instance_ids = list(instances.values_list('id', flat=True))
+    except Exception:
+        instance_ids = []
+    assignments_map = {}
+    reports_map = {}
+    if instance_ids:
+        try:
+            ass_qs = InstallationAssignment.objects.filter(process_instance_id__in=instance_ids).values('process_instance_id', 'scheduled_date')
+            for row in ass_qs:
+                assignments_map[row['process_instance_id']] = row['scheduled_date']
+        except Exception:
+            assignments_map = {}
+        # latest report per instance (visited_date)
+        try:
+            rep_qs = InstallationReport.objects.filter(assignment__process_instance_id__in=instance_ids).order_by('-created').values('assignment__process_instance_id', 'visited_date')
+            for row in rep_qs:
+                pid = row['assignment__process_instance_id']
+                if pid not in reports_map:
+                    reports_map[pid] = row['visited_date']
+        except Exception:
+            reports_map = {}
+    
+    # Build a map to check if installation reports exist (for approval status logic)
+    has_installation_report_map = {}
+    if instance_ids:
+        try:
+            report_exists_qs = InstallationReport.objects.filter(
+                assignment__process_instance_id__in=instance_ids
+            ).values_list('assignment__process_instance_id', flat=True).distinct()
+            has_installation_report_map = {pid: True for pid in report_exists_qs}
+        except Exception:
+            has_installation_report_map = {}
+
+    # Calculate progress for each instance and attach install schedule info
     instances_with_progress = []
     for instance in instances:
         total_steps = instance.process.steps.count()
         completed_steps = instance.step_instances.filter(status='completed').count()
         progress_percentage = (completed_steps / total_steps * 100) if total_steps > 0 else 0
-        
+        sched_date = assignments_map.get(instance.id)
+        overdue_days = 0
+        reference_date = None
+        if sched_date:
+            # Reference date: until installer submits a report, use today; otherwise use visited_date
+            try:
+                visited_date = reports_map.get(instance.id)
+                if visited_date:
+                    reference_date = visited_date
+                else:
+                    try:
+                        reference_date = timezone.localdate()
+                    except Exception:
+                        from datetime import date as _date
+                        reference_date = _date.today()
+                if reference_date > sched_date:
+                    overdue_days = (reference_date - sched_date).days
+            except Exception:
+                overdue_days = 0
+                reference_date = None
+
+        installation_scheduled_date = reference_date if reference_date and reference_date > sched_date else sched_date
+
+        # Emergency approved flag (final settlement step forced approval)
+        try:
+            final_settlement_step = instance.process.steps.filter(order=8).first()
+            emergency_approved = False
+            if final_settlement_step:
+                si = instance.step_instances.filter(step=final_settlement_step).first()
+                emergency_approved = bool(si and si.status == 'approved')
+        except Exception:
+            emergency_approved = False
+
+        # Get current step approval status
+        current_step_approval_status = None
+        if instance.current_step:
+            try:
+                current_step_instance = instance.step_instances.filter(step=instance.current_step).first()
+                if current_step_instance:
+                    # Special check: For installation report step (order=6), only show approval status if report exists
+                    should_show_approval_status = True
+                    if instance.current_step.order == 6:
+                        # Check if installation report exists
+                        if not has_installation_report_map.get(instance.id, False):
+                            should_show_approval_status = False
+                    
+                    if should_show_approval_status:
+                        # Check if this step requires approvals
+                        required_roles = current_step_instance.required_roles()
+                        if required_roles:
+                            # Get approvals by role
+                            approvals_by_role = current_step_instance.approvals_by_role()
+                            
+                            # Check for rejections
+                            latest_rejection = current_step_instance.get_latest_rejection()
+                            if latest_rejection and current_step_instance.status == 'rejected':
+                                role_name = latest_rejection.role.name if latest_rejection.role else 'نامشخص'
+                                current_step_approval_status = {
+                                    'status': 'rejected',
+                                    'role': role_name,
+                                    'display': f'رد شده توسط {role_name}'
+                                }
+                            else:
+                                # Check approval status
+                                pending_roles = []
+                                approved_roles = []
+                                for role in required_roles:
+                                    if approvals_by_role.get(role.id) == 'approved':
+                                        approved_roles.append(role.name)
+                                    else:
+                                        pending_roles.append(role.name)
+                                
+                                if pending_roles:
+                                    current_step_approval_status = {
+                                        'status': 'pending',
+                                        'roles': pending_roles,
+                                        'display': f'در انتظار تایید {" و ".join(pending_roles)}'
+                                    }
+                                elif approved_roles and not pending_roles:
+                                    current_step_approval_status = {
+                                        'status': 'approved',
+                                        'roles': approved_roles,
+                                        'display': f'تایید شده توسط {" و ".join(approved_roles)}'
+                                    }
+            except Exception:
+                current_step_approval_status = None
+
         instances_with_progress.append({
             'instance': instance,
             'progress_percentage': round(progress_percentage),
             'completed_steps': completed_steps,
             'total_steps': total_steps,
+            'installation_scheduled_date': installation_scheduled_date,
+            'installation_overdue_days': overdue_days,
+            'emergency_approved': emergency_approved,
+            'current_step_approval_status': current_step_approval_status,
         })
     
     # Summary stats for header cards
@@ -160,7 +291,10 @@ def lookup_representative_by_national_code(request):
             'last_name': user.last_name,
             'full_name': user.get_full_name(),
             'profile': {
+                'user_type': profile.user_type,
                 'national_code': profile.national_code,
+                'company_name': profile.company_name,
+                'company_national_id': profile.company_national_id,
                 'phone_number_1': profile.phone_number_1,
                 'phone_number_2': profile.phone_number_2,
                 'card_number': profile.card_number,
@@ -240,6 +374,7 @@ def create_request_with_entities(request):
             well = existing
 
     well_data = request.POST.copy()
+    print(well_data)
     # Ensure representative set from created/selected user if not provided
     if representative_user and not well_data.get('representative'):
         well_data['representative'] = str(representative_user.id)
@@ -366,12 +501,12 @@ def step_detail(request, instance_id, step_id):
         return redirect('processes:instance_summary', instance_id=instance.id)
     
     # جلوگیری از پرش به مراحل آینده: فقط اجازه نمایش مرحله جاری یا مراحل تکمیلشده
-    try:
-        if instance.current_step and step.order > instance.current_step.order:
-            messages.error(request, 'ابتدا مراحل قبلی را تکمیل کنید.')
-            return redirect('processes:step_detail', instance_id=instance.id, step_id=instance.current_step.id)
-    except Exception:
-        pass
+    # try:
+    #     if instance.current_step and step.order > instance.current_step.order:
+    #         messages.error(request, 'ابتدا مراحل قبلی را تکمیل کنید.')
+    #         return redirect('processes:step_detail', instance_id=instance.id, step_id=instance.current_step.id)
+    # except Exception:
+    #     pass
 
     # بررسی دسترسی به مرحله
     if not instance.can_access_step(step):
@@ -450,13 +585,22 @@ def instance_summary(request, instance_id):
 
     # Collect final invoice, payments, and certificate if any
     from invoices.models import Invoice
-    from installations.models import InstallationReport
+    from installations.models import InstallationReport, InstallationAssignment
     from certificates.models import CertificateInstance
     invoice = Invoice.objects.filter(process_instance=instance).first()
     payments = invoice.payments.filter(is_deleted=False).all() if invoice else []
     latest_report = InstallationReport.objects.filter(assignment__process_instance=instance).order_by('-created').first()
     certificate = CertificateInstance.objects.filter(process_instance=instance).order_by('-created').first()
 
+    # Calculate installation delay
+    installation_assignment = InstallationAssignment.objects.filter(process_instance=instance).first()
+    installation_delay_days = 0
+    if installation_assignment and latest_report:
+        scheduled_date = installation_assignment.scheduled_date
+        visited_date = latest_report.visited_date
+        if scheduled_date and visited_date and visited_date > scheduled_date:
+            installation_delay_days = (visited_date - scheduled_date).days
+
     # Build rows like final invoice step
     rows = []
     if invoice:
@@ -470,5 +614,374 @@ def instance_summary(request, instance_id):
         'rows': rows,
         'latest_report': latest_report,
         'certificate': certificate,
+        'installation_assignment': installation_assignment,
+        'installation_delay_days': installation_delay_days,
     })
+
+
+def format_date_jalali(date_obj):
+    """Convert date to Jalali format without time"""
+    if not date_obj:
+        return ""
+    try:
+        # If it's a datetime, get just the date part
+        if hasattr(date_obj, 'date'):
+            date_obj = date_obj.date()
+        return persian_converter3(date_obj)
+    except Exception:
+        return ""
+
+def format_datetime_jalali(datetime_obj):
+    """Convert datetime to Jalali format without time"""
+    if not datetime_obj:
+        return ""
+    try:
+        # Get just the date part
+        date_part = datetime_obj.date() if hasattr(datetime_obj, 'date') else datetime_obj
+        return persian_converter3(date_part)
+    except Exception:
+        return ""
+
+@login_required
+def export_requests_excel(request):
+    """Export filtered requests to Excel"""
+    
+    # Get the same queryset as request_list view (with filters)
+    instances = ProcessInstance.objects.select_related(
+        'process', 'current_step', 'representative', 'well', 'well__county', 'well__affairs'
+    ).prefetch_related('step_instances')
+    
+    # Apply scoping
+    instances = scope_instances_queryset(request.user, instances)
+    
+    # Apply filters (same logic as request_list view)
+    filter_status = request.GET.get('status', '').strip()
+    if filter_status:
+        instances = instances.filter(status=filter_status)
+    
+    filter_affairs = request.GET.get('affairs', '').strip()
+    if filter_affairs and filter_affairs.isdigit():
+        instances = instances.filter(well__affairs_id=filter_affairs)
+    
+    filter_broker = request.GET.get('broker', '').strip()
+    if filter_broker and filter_broker.isdigit():
+        instances = instances.filter(well__broker_id=filter_broker)
+    
+    filter_step = request.GET.get('step', '').strip()
+    if filter_step and filter_step.isdigit():
+        instances = instances.filter(current_step_id=filter_step)
+    
+    # Get installation data
+    assignment_ids = list(instances.values_list('id', flat=True))
+    assignments_map = {}
+    reports_map = {}
+    installers_map = {}
+    
+    if assignment_ids:
+        assignments = InstallationAssignment.objects.filter(
+            process_instance_id__in=assignment_ids
+        ).select_related('process_instance', 'installer')
+        assignments_map = {a.process_instance_id: a.scheduled_date for a in assignments}
+        installers_map = {a.process_instance_id: a.installer for a in assignments}
+        
+        reports = InstallationReport.objects.filter(
+            assignment__process_instance_id__in=assignment_ids
+        ).select_related('assignment')
+        reports_map = {r.assignment.process_instance_id: r for r in reports}
+    
+    # Get quotes and payments data
+    from invoices.models import Quote, Payment, Invoice
+    quotes_map = {}
+    payments_map = {}
+    settlement_dates_map = {}
+    approval_dates_map = {}
+    approval_users_map = {}
+    
+    if assignment_ids:
+        # Get quotes
+        quotes = Quote.objects.filter(
+            process_instance_id__in=assignment_ids
+        ).select_related('process_instance')
+        quotes_map = {q.process_instance_id: q for q in quotes}
+        
+        # Get payments with reference numbers
+        payments = Payment.objects.filter(
+            invoice__process_instance_id__in=assignment_ids, 
+            is_deleted=False
+        ).select_related('invoice__process_instance').order_by('created')
+        
+        for payment in payments:
+            if payment.invoice.process_instance_id not in payments_map:
+                payments_map[payment.invoice.process_instance_id] = []
+            payments_map[payment.invoice.process_instance_id].append(payment)
+        
+        # Get final invoices to check settlement dates
+        invoices = Invoice.objects.filter(
+            process_instance_id__in=assignment_ids
+        ).select_related('process_instance')
+        
+        for invoice in invoices:
+            if invoice.get_remaining_amount() == 0:  # Fully settled
+                # Find the last payment date for this invoice
+                last_payment = Payment.objects.filter(
+                    invoice__process_instance=invoice.process_instance,
+                    is_deleted=False
+                ).order_by('-created').first()
+                if last_payment:
+                    settlement_dates_map[invoice.process_instance_id] = last_payment.created
+        
+        # Get installation approval data by Water Resource Manager role
+        from processes.models import StepInstance, StepApproval
+        from accounts.models import Role
+        from common.consts import UserRoles
+        
+        # Get the Water Resource Manager role
+        water_manager_role = Role.objects.filter(slug=UserRoles.WATER_RESOURCE_MANAGER.value).first()
+        
+        installation_steps = StepInstance.objects.filter(
+            process_instance_id__in=assignment_ids,
+            step__order=6,  # Installation report step is order 6
+            status='completed'
+        ).select_related('process_instance')
+        
+        for step_instance in installation_steps:
+            # Get the approval by Water Resource Manager role that completed this step
+            approval = StepApproval.objects.filter(
+                step_instance=step_instance,
+                role=water_manager_role,
+                is_deleted=False
+            ).select_related('approved_by').order_by('-created_at').first()
+            
+            if approval:
+                approval_dates_map[step_instance.process_instance_id] = approval.created_at
+                approval_users_map[step_instance.process_instance_id] = approval.approved_by
+    
+    # Calculate progress and installation data
+    instances_with_progress = []
+    for instance in instances:
+        total_steps = instance.process.steps.count()
+        completed_steps = instance.step_instances.filter(status='completed').count()
+        progress_percentage = (completed_steps / total_steps * 100) if total_steps > 0 else 0
+        
+        sched_date = assignments_map.get(instance.id)
+        overdue_days = 0
+        reference_date = None
+        
+        if sched_date:
+            try:
+                report = reports_map.get(instance.id)
+                if report and report.visited_date:
+                    reference_date = report.visited_date
+                else:
+                    try:
+                        reference_date = timezone.localdate()
+                    except Exception:
+                        from datetime import date as _date
+                        reference_date = _date.today()
+                if reference_date > sched_date:
+                    overdue_days = (reference_date - sched_date).days
+            except Exception:
+                overdue_days = 0
+        
+        installation_scheduled_date = reference_date if reference_date and reference_date > sched_date else sched_date
+        
+        instances_with_progress.append({
+            'instance': instance,
+            'progress_percentage': round(progress_percentage),
+            'completed_steps': completed_steps,
+            'total_steps': total_steps,
+            'installation_scheduled_date': installation_scheduled_date,
+            'installation_overdue_days': overdue_days,
+        })
+    
+    # Create Excel workbook
+    wb = openpyxl.Workbook()
+    ws = wb.active
+    ws.title = "لیست درخواستها"
+    
+    # Set RTL (Right-to-Left) direction
+    ws.sheet_view.rightToLeft = True
+    
+    # Define column headers
+    headers = [
+        'شناسه',
+        'تاریخ ایجاد درخواست',
+        'نام نماینده',
+        'نام خانوادگی نماینده',
+        'کد ملی نماینده',
+        'نام شرکت',
+        'شناسه شرکت',
+        'سریال کنتور',
+        'سریال کنتور جدید',
+        'شماره اشتراک آب',
+        'شماره اشتراک برق',
+        'قدرت چاه',
+        'شماره تماس ۱',
+        'شماره تماس ۲',
+        'آدرس',
+        'مبلغ پیشفاکتور',
+        'تاریخ واریزیها و کدهای رهگیری',
+        'تاریخ مراجعه نصاب',
+        'تاخیر نصاب',
+        'نام نصاب',
+        'تاریخ تایید نصب توسط مدیر',
+        'نام تایید کننده نصب',
+        'تاریخ تسویه'
+    ]
+    
+    # Write headers
+    for col, header in enumerate(headers, 1):
+        cell = ws.cell(row=1, column=col, value=header)
+        cell.font = Font(bold=True)
+        cell.alignment = Alignment(horizontal='center')
+        cell.fill = PatternFill(start_color="CCCCCC", end_color="CCCCCC", fill_type="solid")
+    
+    # Write data rows
+    for row_num, item in enumerate(instances_with_progress, 2):
+        instance = item['instance']
+        
+        # Get representative info
+        rep_first_name = ""
+        rep_last_name = ""
+        rep_national_code = ""
+        rep_phone_1 = ""
+        rep_phone_2 = ""
+        rep_address = ""
+        company_name = ""
+        company_national_id = ""
+        
+        if instance.representative:
+            rep_first_name = instance.representative.first_name or ""
+            rep_last_name = instance.representative.last_name or ""
+            if hasattr(instance.representative, 'profile') and instance.representative.profile:
+                profile = instance.representative.profile
+                rep_national_code = profile.national_code or ""
+                rep_phone_1 = profile.phone_number_1 or ""
+                rep_phone_2 = profile.phone_number_2 or ""
+                rep_address = profile.address or ""
+                if profile.user_type == 'legal':
+                    company_name = profile.company_name or ""
+                    company_national_id = profile.company_national_id or ""
+        
+        # Get well info
+        water_subscription = ""
+        electricity_subscription = ""
+        well_power = ""
+        old_meter_serial = ""
+        if instance.well:
+            water_subscription = instance.well.water_subscription_number or ""
+            electricity_subscription = instance.well.electricity_subscription_number or ""
+            well_power = str(instance.well.well_power) if instance.well.well_power else ""
+            old_meter_serial = instance.well.water_meter_serial_number or ""
+        
+        # Get new meter serial from installation report
+        new_meter_serial = ""
+        installer_visit_date = ""
+        report = reports_map.get(instance.id)
+        if report:
+            new_meter_serial = report.new_water_meter_serial or ""
+            installer_visit_date = format_date_jalali(report.visited_date)
+        
+        # Get quote amount
+        quote_amount = ""
+        quote = quotes_map.get(instance.id)
+        if quote:
+            quote_amount = str(quote.final_amount) if quote.final_amount else ""
+        
+        # Get payments info
+        payments_info = ""
+        payments = payments_map.get(instance.id, [])
+        if payments:
+            payment_strings = []
+            for payment in payments:
+                date_str = format_datetime_jalali(payment.created)
+                reference_number = payment.reference_number or "بدون کد"
+                payment_strings.append(f"{date_str} - {reference_number}")
+            payments_info = " | ".join(payment_strings)
+        
+        # Get installer name
+        installer_name = ""
+        installer = installers_map.get(instance.id)
+        if installer:
+            installer_name = installer.get_full_name() or str(installer)
+        
+        # Get overdue days
+        overdue_days = ""
+        if item['installation_overdue_days'] and item['installation_overdue_days'] > 0:
+            overdue_days = str(item['installation_overdue_days'])
+        
+        # Get approval info
+        approval_date = ""
+        approval_user = ""
+        approval_date_obj = approval_dates_map.get(instance.id)
+        approval_user_obj = approval_users_map.get(instance.id)
+        if approval_date_obj:
+            approval_date = format_datetime_jalali(approval_date_obj)
+        if approval_user_obj:
+            approval_user = approval_user_obj.get_full_name() or str(approval_user_obj)
+        
+        # Get settlement date
+        settlement_date = ""
+        settlement_date_obj = settlement_dates_map.get(instance.id)
+        if settlement_date_obj:
+            settlement_date = format_datetime_jalali(settlement_date_obj)
+        
+        row_data = [
+            instance.code,                    # شناسه
+            format_datetime_jalali(instance.created),  # تاریخ ایجاد درخواست
+            rep_first_name,                   # نام نماینده
+            rep_last_name,                    # نام خانوادگی نماینده
+            rep_national_code,                # کد ملی نماینده
+            company_name,                     # نام شرکت
+            company_national_id,              # شناسه شرکت
+            old_meter_serial,                 # سریال کنتور
+            new_meter_serial,                 # سریال کنتور جدید
+            water_subscription,               # شماره اشتراک آب
+            electricity_subscription,         # شماره اشتراک برق
+            well_power,                       # قدرت چاه
+            rep_phone_1,                      # شماره تماس ۱
+            rep_phone_2,                      # شماره تماس ۲
+            rep_address,                      # آدرس
+            quote_amount,                     # مبلغ پیشفاکتور
+            payments_info,                    # تاریخ واریزیها و کدهای رهگیری
+            installer_visit_date,             # تاریخ مراجعه نصاب
+            overdue_days,                     # تاخیر نصاب
+            installer_name,                   # نام نصاب
+            approval_date,                    # تاریخ تایید نصب توسط مدیر
+            approval_user,                    # نام تایید کننده نصب
+            settlement_date                   # تاریخ تسویه
+        ]
+        
+        for col, value in enumerate(row_data, 1):
+            cell = ws.cell(row=row_num, column=col, value=value)
+            # Set right alignment for Persian text
+            cell.alignment = Alignment(horizontal='right')
+    
+    # Auto-adjust column widths
+    for col in range(1, len(headers) + 1):
+        column_letter = get_column_letter(col)
+        max_length = 0
+        for row in ws[column_letter]:
+            try:
+                if len(str(row.value)) > max_length:
+                    max_length = len(str(row.value))
+            except:
+                pass
+        adjusted_width = min(max_length + 2, 50)
+        ws.column_dimensions[column_letter].width = adjusted_width
+    
+    # Prepare response
+    response = HttpResponse(
+        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+    )
+    
+    # Generate filename with current date
+    current_date = datetime.now().strftime('%Y%m%d_%H%M')
+    filename = f'requests_export_{current_date}.xlsx'
+    response['Content-Disposition'] = f'attachment; filename="{filename}"'
+    
+    # Save workbook to response
+    wb.save(response)
+    
+    return response
     
\ No newline at end of file
diff --git a/static/assets/img/logo/fav.png b/static/assets/img/logo/fav.png
new file mode 100644
index 0000000..ffa86d7
Binary files /dev/null and b/static/assets/img/logo/fav.png differ
diff --git a/static/assets/img/logo/logo.png b/static/assets/img/logo/logo.png
new file mode 100644
index 0000000..71216c8
Binary files /dev/null and b/static/assets/img/logo/logo.png differ
diff --git a/static/assets/img/logo/logo.svg b/static/assets/img/logo/logo.svg
new file mode 100644
index 0000000..ba477d9
--- /dev/null
+++ b/static/assets/img/logo/logo.svg
@@ -0,0 +1,13 @@
+ 
diff --git a/static/assets/js/number-formatter.js b/static/assets/js/number-formatter.js
new file mode 100644
index 0000000..47b2e88
--- /dev/null
+++ b/static/assets/js/number-formatter.js
@@ -0,0 +1,144 @@
+/**
+ * Number Formatter Utility
+ * Formats numbers with comma separators for better readability
+ */
+
+// Format number with comma separators (e.g., 1234567 -> 1,234,567)
+function formatNumber(num) {
+  if (!num) return '';
+  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+}
+
+// Remove comma separators from formatted number
+function unformatNumber(str) {
+  if (!str) return '';
+  return str.replace(/,/g, '');
+}
+
+// Extract only digits from any string
+function extractDigits(str) {
+  if (!str) return '';
+  return str.replace(/\D/g, '');
+}
+
+// Initialize number formatting for specified input selectors
+function initNumberFormatting(selectors) {
+  if (typeof $ === 'undefined') {
+    console.warn('jQuery not found. Number formatting requires jQuery.');
+    return;
+  }
+
+  $(document).ready(function() {
+    selectors.forEach(function(selector) {
+      // Store cursor position to maintain it after formatting
+      function setCursorPosition(input, pos) {
+        if (input.setSelectionRange) {
+          input.setSelectionRange(pos, pos);
+        }
+      }
+      
+      $(selector).on('input', function(e) {
+        let input = $(this);
+        let inputElement = this;
+        let value = input.val();
+        let cursorPos = inputElement.selectionStart;
+        
+        // Extract only digits
+        let digitsOnly = extractDigits(value);
+        
+        // Store raw value
+        input.attr('data-raw-value', digitsOnly);
+        
+        // Format and set the value
+        let formattedValue = formatNumber(digitsOnly);
+        input.val(formattedValue);
+        
+        // Adjust cursor position
+        let oldLength = value.length;
+        let newLength = formattedValue.length;
+        let newCursorPos = cursorPos + (newLength - oldLength);
+        
+        // Make sure cursor position is valid
+        if (newCursorPos < 0) newCursorPos = 0;
+        if (newCursorPos > newLength) newCursorPos = newLength;
+        
+        // Set cursor position after a short delay
+        setTimeout(function() {
+          setCursorPosition(inputElement, newCursorPos);
+        }, 1);
+      });
+      
+      // Handle paste events
+      $(selector).on('paste', function(e) {
+        let input = $(this);
+        setTimeout(function() {
+          let value = input.val();
+          let digitsOnly = extractDigits(value);
+          input.attr('data-raw-value', digitsOnly);
+          input.val(formatNumber(digitsOnly));
+        }, 1);
+      });
+    });
+
+    // Before form submission, replace formatted values with raw values
+    $('form').on('submit', function() {
+      selectors.forEach(function(selector) {
+        let input = $(selector);
+        let rawValue = input.attr('data-raw-value');
+        if (rawValue) {
+          input.val(rawValue);
+        }
+      });
+    });
+  });
+}
+
+// Helper function to get raw value from formatted input
+function getRawValue(input) {
+  return $(input).attr('data-raw-value') || unformatNumber($(input).val());
+}
+
+// Helper function to set raw value before AJAX submission
+function setRawValuesForSubmission(selectors) {
+  selectors.forEach(function(selector) {
+    let input = $(selector);
+    let rawValue = input.attr('data-raw-value');
+    if (rawValue) {
+      input.val(rawValue);
+    }
+  });
+}
+
+// Helper function to restore formatted values after AJAX submission
+function restoreFormattedValues(selectors) {
+  selectors.forEach(function(selector) {
+    let input = $(selector);
+    let rawValue = input.attr('data-raw-value');
+    if (rawValue) {
+      input.val(formatNumber(rawValue));
+    }
+  });
+}
+
+// Auto-initialize for common amount input selectors
+$(document).ready(function() {
+  const commonSelectors = [
+    '#id_amount',
+    '#id_charge_amount',
+    'input[name="amount"]',
+    'input[name="unit_price"]',
+    'input[name="price"]'
+  ];
+  
+  initNumberFormatting(commonSelectors);
+  
+  // Make helper functions globally available for AJAX forms
+  window.formatNumber = formatNumber;
+  window.unformatNumber = unformatNumber;
+  window.getRawValue = getRawValue;
+  // Avoid name collision causing recursion by aliasing helpers
+  const __nf_setRawValuesForSubmission = setRawValuesForSubmission;
+  const __nf_restoreFormattedValues = restoreFormattedValues;
+  window.setRawValuesForSubmission = function() { __nf_setRawValuesForSubmission(commonSelectors); };
+  window.restoreFormattedValues = function() { __nf_restoreFormattedValues(commonSelectors); };
+});
diff --git a/static/assets/vendor/css/rtl/core-dark.css b/static/assets/vendor/css/rtl/core-dark.css
index 1c8f60f..bc86e08 100644
--- a/static/assets/vendor/css/rtl/core-dark.css
+++ b/static/assets/vendor/css/rtl/core-dark.css
@@ -24340,8 +24340,8 @@ html:not(.layout-footer-fixed) .content-wrapper {
 }
 
 .menu-vertical .app-brand {
-    padding-right: 2rem;
-    padding-left: 2rem
+    padding-right: 1.5rem;
+    padding-left: 1.5rem
 }
 
 .menu-horizontal .app-brand, .menu-horizontal .app-brand + .menu-divider {
@@ -24379,7 +24379,7 @@ html:not(.layout-footer-fixed) .content-wrapper {
 
 @media (min-width: 1200px) {
     .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand {
-        width: 5.25rem
+        width: 6.75rem
     }
 
     .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand-logo, .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand-link, .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand-text {
diff --git a/static/assets/vendor/css/rtl/core.css b/static/assets/vendor/css/rtl/core.css
index d5f3721..ec1259b 100644
--- a/static/assets/vendor/css/rtl/core.css
+++ b/static/assets/vendor/css/rtl/core.css
@@ -24375,8 +24375,8 @@ html:not(.layout-footer-fixed) .content-wrapper {
 }
 
 .menu-vertical .app-brand {
-    padding-right: 2rem;
-    padding-left: 2rem
+    padding-right: 1.5rem;
+    padding-left: 1.5rem
 }
 
 .menu-horizontal .app-brand, .menu-horizontal .app-brand + .menu-divider {
@@ -24414,7 +24414,7 @@ html:not(.layout-footer-fixed) .content-wrapper {
 
 @media (min-width: 1200px) {
     .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand {
-        width: 5.25rem
+        width: 6.75rem
     }
 
     .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand-logo, .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand-link, .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .layout-menu .app-brand-text {
diff --git a/templates/_base.html b/templates/_base.html
index 94ebdd1..86d87fd 100644
--- a/templates/_base.html
+++ b/templates/_base.html
@@ -17,14 +17,10 @@ layout-navbar-fixed layout-menu-fixed layout-compact
   
 
 
-   
-   
-  
-   
-
+   
 
   
-   
+   
 
   
   
@@ -99,7 +95,7 @@ layout-navbar-fixed layout-menu-fixed layout-compact
            
             
               
-                © {{ current_year|default:"2024" }} تمامی حقوق متعلق به شرکت زیست آب است.
+                © {{ current_year|default:"2024" }} تمامی حقوق متعلق به شرکت زیستآب پرآب است.
                 طراحی و توسعه با ❤️ در ایران
                
              
@@ -112,17 +108,17 @@ layout-navbar-fixed layout-menu-fixed layout-compact
                  |
                 
                   
-                  پشتیبانی: info@zistab.com
+                  پشتیبانی: info@poraab.com
                 
                 |
                 
                   
-                  تلفن: 021-12345678
+                  تلفن: 02188728477
                 
                 |
                 
                   
-                  تهران، خیابان ولیعصر
+                  تهران، خیابان شهید بهشتی، پلاک ۴۳۶
                 
                
              
@@ -169,6 +165,8 @@ layout-navbar-fixed layout-menu-fixed layout-compact
 
 
 
+
+
 
 
 
diff --git a/templates/navbars/admin.html b/templates/navbars/admin.html
index 303ee3e..56847cc 100644
--- a/templates/navbars/admin.html
+++ b/templates/navbars/admin.html
@@ -35,6 +35,7 @@ id="layout-navbar">
  
 
  
+
   
    
@@ -144,6 +145,11 @@ id="layout-navbar">
  
  
 
+  
+  {% if request.user.profile %}
+  {{ request.user.profile.roles_str }} 
+  {% endif %}
+
 
  
  
diff --git a/templates/sidebars/admin.html b/templates/sidebars/admin.html
index 066c177..c2af955 100644
--- a/templates/sidebars/admin.html
+++ b/templates/sidebars/admin.html
@@ -5,55 +5,10 @@
      |