diff --git a/accounts/forms.py b/accounts/forms.py
index a5d493b..e5f3b90 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -39,7 +39,8 @@ class CustomerForm(forms.ModelForm):
             }),
             'phone_number_1': forms.TextInput(attrs={
                 'class': 'form-control',
-                'placeholder': '09123456789'
+                'placeholder': '09123456789',
+                'required': True
             }),
             'phone_number_2': forms.TextInput(attrs={
                 'class': 'form-control',
diff --git a/accounts/migrations/0008_alter_historicalprofile_phone_number_1_and_more.py b/accounts/migrations/0008_alter_historicalprofile_phone_number_1_and_more.py
new file mode 100644
index 0000000..a005ff8
--- /dev/null
+++ b/accounts/migrations/0008_alter_historicalprofile_phone_number_1_and_more.py
@@ -0,0 +1,25 @@
+# Generated by Django 5.2.4 on 2025-10-02 09:32
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('accounts', '0007_historicalprofile_company_name_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='historicalprofile',
+            name='phone_number_1',
+            field=models.CharField(default=1, max_length=11, verbose_name='شماره تماس ۱'),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='profile',
+            name='phone_number_1',
+            field=models.CharField(default=1, max_length=11, verbose_name='شماره تماس ۱'),
+            preserve_default=False,
+        ),
+    ]
diff --git a/accounts/models.py b/accounts/models.py
index 348304e..f6ccf3d 100644
--- a/accounts/models.py
+++ b/accounts/models.py
@@ -78,9 +78,7 @@ class Profile(BaseModel):
     )
     phone_number_1 = models.CharField(
         max_length=11,
-        null=True,
         verbose_name="شماره تماس ۱",
-        blank=True
     )
     phone_number_2 = models.CharField(
         max_length=11,
diff --git a/certificates/views.py b/certificates/views.py
index 9a8f1de..5149334 100644
--- a/certificates/views.py
+++ b/certificates/views.py
@@ -4,6 +4,8 @@ from django.contrib import messages
 from django.http import JsonResponse
 from django.urls import reverse
 from django.utils import timezone
+from django.template import Template, Context
+from django.utils.safestring import mark_safe
 
 from processes.models import ProcessInstance, StepInstance
 from invoices.models import Invoice
@@ -28,20 +30,33 @@ def _render_template(template: CertificateTemplate, instance: ProcessInstance):
     well = instance.well
     rep = instance.representative
     latest_report = InstallationReport.objects.filter(assignment__process_instance=instance).order_by('-created').first()
+    individual = True if rep.profile and rep.profile.user_type == 'individual' else False
+    customer_company_name = rep.profile.company_name if rep.profile and rep.profile.user_type == 'legal' else None
+    city = template.company.broker.affairs.county.city.name if template.company and template.company.broker and template.company.broker.affairs and template.company.broker.affairs.county and template.company.broker.affairs.county.city else None
+    county = template.company.broker.affairs.county.name if template.company and template.company.broker and template.company.broker.affairs and template.company.broker.affairs.county else None
+
     ctx = {
-        'today_jalali': _to_jalali(timezone.now().date()),
-        'request_code': instance.code,
-        'company_name': (template.company.name if template.company else '') or '',
-        'customer_full_name': rep.get_full_name() if rep else '',
-        'water_subscription_number': getattr(well, 'water_subscription_number', '') or '',
-        'address': getattr(well, 'county', '') or '',
-        'visit_date_jalali': _to_jalali(getattr(latest_report, 'visited_date', None)) if latest_report else '',
+        'today_jalali': mark_safe(f"{_to_jalali(timezone.now().date())}"),
+        'request_code': mark_safe(f"{instance.code}"),
+        'company_name': mark_safe(f"{(template.company.name if template.company else '') or ''}"),
+        'customer_full_name': mark_safe(f"{rep.get_full_name() if rep else ''}"),
+        'water_subscription_number': mark_safe(f"{getattr(well, 'water_subscription_number', '') or ''}"),
+        'address': mark_safe(f"{getattr(well, 'county', '') or ''}"),
+        'visit_date_jalali': mark_safe(f"{_to_jalali(getattr(latest_report, 'visited_date', None)) if latest_report else ''}"),
+        'city': mark_safe(f"{city or ''}"),
+        'county': mark_safe(f"{county or ''}"),
+        'customer_company_name': mark_safe(f"{customer_company_name or ''}"),
+        'individual': individual,
     }
-    title = (template.title or '').format(**ctx)
-    body = (template.body or '')
-    # Render body placeholders with bold values
-    for k, v in ctx.items():
-        body = body.replace(f"{{{{ {k} }}}}", f"{str(v)}")
+    
+    # Render title using Django template engine
+    title_template = Template(template.title or '')
+    title = title_template.render(Context(ctx))
+    
+    # Render body using Django template engine
+    body_template = Template(template.body or '')
+    body = body_template.render(Context(ctx))
+    
     return title, body
 
 
@@ -63,7 +78,7 @@ def certificate_step(request, instance_id, step_id):
     if inv:
         if prev_si and not prev_si.status == 'approved':
             inv.calculate_totals()
-            if inv.remaining_amount != 0:
+            if inv.get_remaining_amount() != 0:
                 messages.error(request, 'مانده فاکتور باید صفر باشد')
                 return redirect('processes:request_list')
 
diff --git a/db.sqlite3 b/db.sqlite3
index 194dde7..02dd5e4 100644
Binary files a/db.sqlite3 and b/db.sqlite3 differ
diff --git a/installations/templates/installations/installation_report_step.html b/installations/templates/installations/installation_report_step.html
index df12a29..d6a7cfc 100644
--- a/installations/templates/installations/installation_report_step.html
+++ b/installations/templates/installations/installation_report_step.html
@@ -75,7 +75,6 @@
                 
                 
                   این گزارش رد شده است.
-                  
علت رد: {{ step_instance.get_latest_rejection.reason }}
                  
               
               {% endif %}
@@ -99,9 +98,9 @@
                   UTM Y: {{ report.utm_y|default:'-' }}
                   نوع مصرف: {{ report.get_usage_type_display|default:'-' }}
                   شماره پروانه بهرهبرداری: {{ report.exploitation_license_number|default:'-' }}
-                  (کیلووات ساعت)قدرت موتور: {{ report.motor_power|default:'-' }}
-                  (لیتر/ثانیه) دبی قبل کالیبراسیون: {{ report.pre_calibration_flow_rate|default:'-' }}
-                  (لیتر/ثانیه) دبی بعد کالیبراسیون: {{ report.post_calibration_flow_rate|default:'-' }}
+                  قدرت موتور(کیلووات ساعت): {{ report.motor_power|default:'-' }}
+                  دبی قبل کالیبراسیون(لیتر/ثانیه): {{ report.pre_calibration_flow_rate|default:'-' }}
+                  دبی بعد کالیبراسیون(لیتر/ثانیه): {{ report.post_calibration_flow_rate|default:'-' }}
                   
                 
               
diff --git a/installations/views.py b/installations/views.py
index 177ccc3..367edac 100644
--- a/installations/views.py
+++ b/installations/views.py
@@ -320,15 +320,29 @@ def installation_report_step(request, instance_id, step_id):
         can_approve_reject = False
     user_can_approve = can_approve_reject
     approvals_list = list(step_instance.approvals.select_related('role', 'approved_by').filter(is_deleted=False))
+    rejections_list = list(step_instance.rejections.select_related('role', 'rejected_by').filter(is_deleted=False))
     approvals_by_role = {a.role_id: a for a in approvals_list}
-    approver_statuses = [
-        {
+    rejections_by_role = {r.role_id: r for r in rejections_list}
+    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,
+        })
 
     # Determine if current user has already approved/rejected (to disable buttons)
     current_user_has_decided = False
@@ -356,10 +370,11 @@ def installation_report_step(request, instance_id, step_id):
 
         if action == 'approve':
             # Record this user's approval for their role
-            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=''
             )
             # Only mark report approved when ALL required roles have approved
             if step_instance.is_fully_approved():
@@ -386,12 +401,8 @@ def installation_report_step(request, instance_id, step_id):
             if not reason:
                 messages.error(request, 'لطفاً علت رد شدن را وارد کنید.')
                 return redirect('processes:step_detail', instance_id=instance.id, step_id=step.id)
-            StepApproval.objects.update_or_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)
+            # Only create StepRejection for rejections, not StepApproval
+            StepRejection.objects.create(step_instance=step_instance, role=matching_role, rejected_by=request.user, reason=reason)
             existing_report.approved = False
             existing_report.save()
             # If current step moved ahead of this step, reset it back for correction (align with invoices)
diff --git a/invoices/admin.py b/invoices/admin.py
index f8a46cb..72df296 100644
--- a/invoices/admin.py
+++ b/invoices/admin.py
@@ -44,11 +44,11 @@ class PaymentInline(admin.TabularInline):
 
 @admin.register(Invoice)
 class InvoiceAdmin(SimpleHistoryAdmin):
-    list_display = ['name', 'process_instance', 'customer', 'status_display', 'final_amount', 'paid_amount', 'remaining_amount', 'due_date']
+    list_display = ['name', 'process_instance', 'customer', 'status_display', 'final_amount', 'paid_amount_display', 'remaining_amount_display', 'due_date']
     list_filter = ['status', 'created', 'due_date', 'process_instance__process']
     search_fields = ['name', 'customer__username', 'customer__first_name', 'customer__last_name', 'notes']
     prepopulated_fields = {'slug': ('name',)}
-    readonly_fields = ['deleted_at', 'created', 'updated', 'total_amount', 'discount_amount', 'final_amount', 'paid_amount', 'remaining_amount']
+    readonly_fields = ['deleted_at', 'created', 'updated', 'total_amount', 'discount_amount', 'final_amount', 'paid_amount_display', 'remaining_amount_display']
     inlines = [InvoiceItemInline, PaymentInline]
     ordering = ['-created']
 
@@ -56,6 +56,16 @@ class InvoiceAdmin(SimpleHistoryAdmin):
         return mark_safe(obj.get_status_display_with_color())
     status_display.short_description = "وضعیت"
 
+    def paid_amount_display(self, obj):
+        return f"{obj.get_paid_amount():,.0f} تومان"
+    paid_amount_display.short_description = "مبلغ پرداخت شده"
+
+    def remaining_amount_display(self, obj):
+        amount = obj.get_remaining_amount()
+        color = "green" if amount <= 0 else "red"
+        return format_html('{:,.0f} تومان', color, amount)
+    remaining_amount_display.short_description = "مبلغ باقیمانده"
+
 @admin.register(Payment)
 class PaymentAdmin(SimpleHistoryAdmin):
     list_display = ['invoice', 'amount', 'payment_method', 'payment_date', 'created_by']
diff --git a/invoices/migrations/0002_remove_historicalinvoice_paid_amount_and_more.py b/invoices/migrations/0002_remove_historicalinvoice_paid_amount_and_more.py
new file mode 100644
index 0000000..4617568
--- /dev/null
+++ b/invoices/migrations/0002_remove_historicalinvoice_paid_amount_and_more.py
@@ -0,0 +1,29 @@
+# Generated by Django 5.2.4 on 2025-10-04 08:16
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('invoices', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='historicalinvoice',
+            name='paid_amount',
+        ),
+        migrations.RemoveField(
+            model_name='historicalinvoice',
+            name='remaining_amount',
+        ),
+        migrations.RemoveField(
+            model_name='invoice',
+            name='paid_amount',
+        ),
+        migrations.RemoveField(
+            model_name='invoice',
+            name='remaining_amount',
+        ),
+    ]
diff --git a/invoices/models.py b/invoices/models.py
index 854f46b..4a48c8c 100644
--- a/invoices/models.py
+++ b/invoices/models.py
@@ -228,18 +228,6 @@ class Invoice(NameSlugModel):
         default=0, 
         verbose_name="مبلغ نهایی"
     )
-    paid_amount = models.DecimalField(
-        max_digits=15, 
-        decimal_places=2, 
-        default=0, 
-        verbose_name="مبلغ پرداخت شده"
-    )
-    remaining_amount = models.DecimalField(
-        max_digits=15, 
-        decimal_places=2, 
-        default=0, 
-        verbose_name="مبلغ باقیمانده"
-    )
     due_date = models.DateField(verbose_name="تاریخ سررسید")
     notes = models.TextField(verbose_name="یادداشتها", blank=True)
     created_by = models.ForeignKey(
@@ -278,22 +266,31 @@ class Invoice(NameSlugModel):
         vat_amount = base_amount * vat_rate
         self.final_amount = base_amount + vat_amount
         
-        # خالص مانده به نفع شرکت (مثبت) یا به نفع مشتری (منفی)
-        net_due = self.final_amount - self.paid_amount
-        self.remaining_amount = net_due
-
-        # وضعیت بر اساس مانده خالص
+        # وضعیت بر اساس مانده خالص (استفاده از تابعها)
+        paid = self.get_paid_amount()
+        net_due = self.final_amount - paid
+        
         if net_due == 0:
             self.status = 'paid'
         elif net_due > 0:
             # مشتری هنوز باید پرداخت کند
-            self.status = 'partially_paid' if self.paid_amount > 0 else 'sent'
+            self.status = 'partially_paid' if paid > 0 else 'sent'
         else:
             # شرکت باید به مشتری پرداخت کند
             self.status = 'partially_paid'
         
         self.save()
 
+    def get_paid_amount(self):
+        """مبلغ پرداخت شده بر اساس پرداختها (مثل Quote)"""
+        return sum((p.amount if p.direction == 'in' else -p.amount) for p in self.payments.filter(is_deleted=False).all())
+
+    def get_remaining_amount(self):
+        """مبلغ باقیمانده بر اساس پرداختها (مثل Quote)"""
+        paid = self.get_paid_amount()
+        remaining = self.final_amount - paid
+        return remaining
+
 
     def get_status_display_with_color(self):
         """نمایش وضعیت با رنگ"""
@@ -373,17 +370,13 @@ class Payment(BaseModel):
     def save(self, *args, **kwargs):
         """بروزرسانی مبالغ فاکتور"""
         super().save(*args, **kwargs)
-        # بروزرسانی مبلغ پرداخت شده فاکتور
-        total_paid = sum((p.amount if p.direction == 'in' else -p.amount) for p in self.invoice.payments.filter(is_deleted=False).all())
-        self.invoice.paid_amount = total_paid
+        # فقط مجدداً calculate_totals را صدا کن (مثل Quote)
         self.invoice.calculate_totals()
 
     def delete(self, using=None, keep_parents=False):
         """حذف نرم و بروزرسانی مبالغ فاکتور پس از حذف"""
         result = super().delete(using=using, keep_parents=keep_parents)
         try:
-            total_paid = sum((p.amount if p.direction == 'in' else -p.amount) for p in self.invoice.payments.filter(is_deleted=False).all())
-            self.invoice.paid_amount = total_paid
             self.invoice.calculate_totals()
         except Exception:
             pass
diff --git a/invoices/templates/invoices/final_invoice_print.html b/invoices/templates/invoices/final_invoice_print.html
index 36f0ffd..d9c8333 100644
--- a/invoices/templates/invoices/final_invoice_print.html
+++ b/invoices/templates/invoices/final_invoice_print.html
@@ -159,11 +159,11 @@
           
           
             | پرداختیها(تومان): | 
-            {{ invoice.paid_amount|floatformat:0|intcomma:False }} | 
+            {{ invoice.get_paid_amount|floatformat:0|intcomma:False }} | 
           
           
             | مانده(تومان): | 
-            {{ invoice.remaining_amount|floatformat:0|intcomma:False }} | 
+            {{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} | 
           
         
       
diff --git a/invoices/templates/invoices/final_invoice_step.html b/invoices/templates/invoices/final_invoice_step.html
index 9fc706c..1d99072 100644
--- a/invoices/templates/invoices/final_invoice_step.html
+++ b/invoices/templates/invoices/final_invoice_step.html
@@ -74,17 +74,17 @@
             
               
                 پرداختیها
-                
{{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان
+                
{{ invoice.get_paid_amount|floatformat:0|intcomma:False }} تومان
                
              
             
               
                 مانده
-                
{{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان
+                
{{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} تومان
                
              
             
-              {% if invoice.remaining_amount <= 0 %}
+              {% if invoice.get_remaining_amount <= 0 %}
                 
تسویه کامل
               {% else %}
                 
باقیمانده دارد
@@ -165,11 +165,11 @@
                 
                 
                   | پرداختیها | 
-                  {{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان | 
+                  {{ invoice.get_paid_amount|floatformat:0|intcomma:False }} تومان | 
                 
                 
                   | مانده | 
-                  {{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان | 
+                  {{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} تومان | 
                 
               
             
diff --git a/invoices/templates/invoices/final_settlement_step.html b/invoices/templates/invoices/final_settlement_step.html
index a1514c9..a4767d4 100644
--- a/invoices/templates/invoices/final_settlement_step.html
+++ b/invoices/templates/invoices/final_settlement_step.html
@@ -42,7 +42,7 @@
           
              پرینت
           
-          {% if request.user|is_manager and step_instance.status != 'approved' and step_instance.status != 'completed' and invoice.remaining_amount != 0 %}
+          {% if request.user|is_manager and step_instance.status != 'approved' and step_instance.status != 'completed' and invoice.get_remaining_amount != 0 %}
           
@@ -128,17 +128,17 @@
                 
                   
                     پرداختیها
-                    
{{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان
+                    
{{ invoice.get_paid_amount|floatformat:0|intcomma:False }} تومان
                    
                  
                 
                   
                     مانده
-                    
{{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان
+                    
{{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} تومان
                    
                  
                 
-                  {% if invoice.remaining_amount <= 0 %}
+                  {% if invoice.get_remaining_amount <= 0 %}
                     تسویه کامل
                   {% else %}
                     باقیمانده دارد
@@ -318,9 +318,9 @@
           
         
         
-          {% if invoice.remaining_amount != 0 %}
+          {% if invoice.get_remaining_amount != 0 %}
             
-              مانده فاکتور: {{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان
+              مانده فاکتور: {{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} تومان
               امکان تایید تا تسویه کامل فاکتور وجود ندارد.
             
           {% else %}
@@ -329,7 +329,7 @@
         
 
         
       
      
diff --git a/invoices/templates/invoices/quote_print.html b/invoices/templates/invoices/quote_print.html
index bbf7a97..fc445a6 100644
--- a/invoices/templates/invoices/quote_print.html
+++ b/invoices/templates/invoices/quote_print.html
@@ -145,7 +145,17 @@
         
         
             
-                
اطلاعات مشترک
+                
+                    {% if instance.representative.profile.user_type == 'legal' %}
+                      اطلاعات مشترک (حقوقی)
+                    {% else %}
+                      اطلاعات مشترک (حقیقی)
+                    {% endif %}
+                
+                {% 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 and instance.representative.profile.national_code %}
                 
کد ملی: {{ instance.representative.profile.national_code }}
diff --git a/invoices/templates/invoices/quote_step.html b/invoices/templates/invoices/quote_step.html
index 404cf14..853f250 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 }}
                   
                 
diff --git a/invoices/views.py b/invoices/views.py
index 6e467b9..778d837 100644
--- a/invoices/views.py
+++ b/invoices/views.py
@@ -358,14 +358,28 @@ def quote_payment_step(request, instance_id, step_id):
     user_roles_qs = getattr(getattr(request.user, 'profile', None), 'roles', None)
     user_roles = list(user_roles_qs.all()) if user_roles_qs is not None else []
     approvals_list = list(step_instance.approvals.select_related('role', 'approved_by').filter(is_deleted=False))
+    rejections_list = list(step_instance.rejections.select_related('role', 'rejected_by').filter(is_deleted=False))
     approvals_by_role = {a.role_id: a for a in approvals_list}
+    rejections_by_role = {r.role_id: r for r in rejections_list}
     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': (appr.decision if appr else None),
-            'reason': (appr.reason if appr else ''),
+            'status': status,
+            'reason': reason,
         })
 
     # dynamic permission: who can approve/reject this step (based on requirements)
@@ -398,10 +412,11 @@ 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'
@@ -422,12 +437,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:
@@ -927,16 +942,30 @@ def final_settlement_step(request, instance_id, step_id):
     
     # 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())
@@ -949,8 +978,8 @@ def final_settlement_step(request, instance_id, step_id):
     # 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).exists()
-        user_has_rejection = step_instance.rejections.filter(rejected_by=request.user).exists()
+        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
@@ -968,13 +997,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'
@@ -993,12 +1023,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:
@@ -1173,8 +1203,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()),
         }
     })
 
@@ -1186,14 +1216,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)
+    
+    # Delete payment and recalculate invoice totals
     payment.hard_delete()
-    invoice.refresh_from_db()
+    invoice.calculate_totals()  # This is what was missing!
 
     # On delete, return to awaiting approval
     try:
@@ -1201,16 +1234,11 @@ def delete_final_payment(request, instance_id, step_id, payment_id):
         si.status = 'in_progress'
         si.completed_at = None
         si.save()
-        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
+        # 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
 
@@ -1244,7 +1272,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/processes/admin.py b/processes/admin.py
index 4739742..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', 'is_deleted']
-    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", "is_deleted")
-    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/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 391fd26..9cd0ddd 100644
--- a/processes/models.py
+++ b/processes/models.py
@@ -378,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):
@@ -386,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:
@@ -409,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, 
@@ -431,12 +432,13 @@ 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):
@@ -447,7 +449,6 @@ class StepRejection(models.Model):
         self.save()
 
 
-
 class StepApproverRequirement(models.Model):
     """Required approver roles for a step."""
     step = models.ForeignKey(ProcessStep, on_delete=models.CASCADE, related_name='approver_requirements', verbose_name="مرحله")
@@ -466,15 +467,13 @@ 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 = 'تاییدهای مرحله'
     
@@ -487,4 +486,4 @@ class StepApproval(models.Model):
 
 
     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..52b0bf2 100644
--- a/processes/templates/processes/instance_summary.html
+++ b/processes/templates/processes/instance_summary.html
@@ -37,9 +37,9 @@
               
 پرینت فاکتور
             
           {% endif %}
-          
+          
+          
           
             
             بازگشت
@@ -57,8 +57,8 @@
               {% if invoice %}
               
                 مبلغ نهایی
{{ invoice.final_amount|floatformat:0|intcomma:False }} تومان
-                
پرداختیها
{{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان
-                
مانده
{{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان
+                
پرداختیها
{{ invoice.get_paid_amount|floatformat:0|intcomma:False }} تومان
+                
مانده
{{ invoice.get_remaining_amount|floatformat:0|intcomma:False }} تومان
 
                
               
                 
@@ -95,32 +95,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 %}
                     
@@ -175,6 +256,30 @@
     
 
    
 
+
+
+
 {% endblock %}
 
 
diff --git a/processes/templates/processes/request_list.html b/processes/templates/processes/request_list.html
index 5640425..9ec7e92 100644
--- a/processes/templates/processes/request_list.html
+++ b/processes/templates/processes/request_list.html
@@ -37,12 +37,14 @@