main flow checked
This commit is contained in:
		
							parent
							
								
									b5bf3a5dbe
								
							
						
					
					
						commit
						f853ad9784
					
				
					 21 changed files with 365 additions and 89 deletions
				
			
		| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			@ -928,15 +943,29 @@ 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())
 | 
			
		||||
    rejections = list(step_instance.rejections.select_related('role').all())
 | 
			
		||||
    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())
 | 
			
		||||
| 
						 | 
				
			
			@ -971,10 +1000,11 @@ def final_settlement_step(request, instance_id, step_id):
 | 
			
		|||
            if invoice.remaining_amount != 0:
 | 
			
		||||
                messages.error(request, f"تا زمانی که مانده فاکتور صفر نشده امکان تایید نیست (مانده فعلی: {invoice.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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue