add scope to filter data
This commit is contained in:
		
							parent
							
								
									394546dc67
								
							
						
					
					
						commit
						e9dec3292c
					
				
					 13 changed files with 386 additions and 36 deletions
				
			
		| 
						 | 
				
			
			@ -7,19 +7,62 @@ from django.http import JsonResponse
 | 
			
		|||
from django.views.decorators.http import require_POST, require_GET
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.contrib.auth import get_user_model
 | 
			
		||||
from .models import Process, ProcessInstance, StepInstance
 | 
			
		||||
from .models import Process, ProcessInstance, StepInstance, ProcessStep
 | 
			
		||||
from .utils import scope_instances_queryset, get_scoped_instance_or_404
 | 
			
		||||
from installations.models import InstallationAssignment
 | 
			
		||||
from wells.models import Well
 | 
			
		||||
from accounts.models import Profile
 | 
			
		||||
from accounts.models import Profile, Broker
 | 
			
		||||
from locations.models import Affairs
 | 
			
		||||
from accounts.forms import CustomerForm
 | 
			
		||||
from wells.forms import WellForm
 | 
			
		||||
from wells.models import WaterMeterManufacturer
 | 
			
		||||
from common.consts import UserRoles
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
def request_list(request):
 | 
			
		||||
    """نمایش لیست درخواستها با جدول و مدال ایجاد"""
 | 
			
		||||
    instances = ProcessInstance.objects.select_related('well', 'representative', 'requester').prefetch_related('step_instances__step').filter(is_deleted=False).order_by('-created')
 | 
			
		||||
    instances = ProcessInstance.objects.select_related('well', 'representative', 'requester', 'broker', 'current_step', 'process').prefetch_related('step_instances__step').filter(is_deleted=False).order_by('-created')
 | 
			
		||||
    access_denied = False
 | 
			
		||||
 | 
			
		||||
    # filter by roles (scoped queryset)
 | 
			
		||||
    try:
 | 
			
		||||
        instances = scope_instances_queryset(request.user, instances)
 | 
			
		||||
        if not instances.exists() and not getattr(request.user, 'profile', None):
 | 
			
		||||
            access_denied = True
 | 
			
		||||
            instances = instances.none()
 | 
			
		||||
    except Exception:
 | 
			
		||||
        access_denied = True
 | 
			
		||||
        instances = instances.none()
 | 
			
		||||
        
 | 
			
		||||
    # Filters
 | 
			
		||||
    status_q = (request.GET.get('status') or '').strip()
 | 
			
		||||
    affairs_q = (request.GET.get('affairs') or '').strip()
 | 
			
		||||
    broker_q = (request.GET.get('broker') or '').strip()
 | 
			
		||||
    step_q = (request.GET.get('step') or '').strip()
 | 
			
		||||
 | 
			
		||||
    if status_q:
 | 
			
		||||
        instances = instances.filter(status=status_q)
 | 
			
		||||
    if affairs_q:
 | 
			
		||||
        try:
 | 
			
		||||
            instances = instances.filter(well__affairs_id=int(affairs_q))
 | 
			
		||||
        except Exception:
 | 
			
		||||
            pass
 | 
			
		||||
    if broker_q:
 | 
			
		||||
        try:
 | 
			
		||||
            instances = instances.filter(broker_id=int(broker_q))
 | 
			
		||||
        except Exception:
 | 
			
		||||
            pass
 | 
			
		||||
    if step_q:
 | 
			
		||||
        try:
 | 
			
		||||
            instances = instances.filter(current_step_id=int(step_q))
 | 
			
		||||
        except Exception:
 | 
			
		||||
            pass
 | 
			
		||||
    processes = Process.objects.filter(is_active=True)
 | 
			
		||||
    status_choices = list(ProcessInstance.STATUS_CHOICES)
 | 
			
		||||
    affairs_list = Affairs.objects.all().order_by('name')
 | 
			
		||||
    brokers_list = Broker.objects.all().order_by('name')
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +95,16 @@ def request_list(request):
 | 
			
		|||
        'completed_count': completed_count,
 | 
			
		||||
        'in_progress_count': in_progress_count,
 | 
			
		||||
        'pending_count': pending_count,
 | 
			
		||||
        # filter context
 | 
			
		||||
        'status_choices': status_choices,
 | 
			
		||||
        'affairs_list': affairs_list,
 | 
			
		||||
        'brokers_list': brokers_list,
 | 
			
		||||
        'steps_list': steps_list,
 | 
			
		||||
        'filter_status': status_q,
 | 
			
		||||
        'filter_affairs': affairs_q,
 | 
			
		||||
        'filter_broker': broker_q,
 | 
			
		||||
        'filter_step': step_q,
 | 
			
		||||
        'access_denied': access_denied,
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +178,13 @@ def lookup_representative_by_national_code(request):
 | 
			
		|||
def create_request_with_entities(request):
 | 
			
		||||
    """ایجاد/بهروزرسانی چاه و نماینده و سپس ایجاد درخواست"""
 | 
			
		||||
    User = get_user_model()
 | 
			
		||||
    # Only BROKER can create requests
 | 
			
		||||
    try:
 | 
			
		||||
        if not (hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.BROKER)):
 | 
			
		||||
            return JsonResponse({'ok': False, 'error': 'فقط کارگزار مجاز به ایجاد درخواست است'}, status=403)
 | 
			
		||||
    except Exception:
 | 
			
		||||
        return JsonResponse({'ok': False, 'error': 'فقط کارگزار مجاز به ایجاد درخواست است'}, status=403)
 | 
			
		||||
        
 | 
			
		||||
    process_id = request.POST.get('process')
 | 
			
		||||
    process = Process.objects.get(id=process_id)
 | 
			
		||||
    description = request.POST.get('description', '')
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +290,14 @@ def create_request_with_entities(request):
 | 
			
		|||
            well.broker = current_profile.broker
 | 
			
		||||
        well.save()
 | 
			
		||||
 | 
			
		||||
    # Ensure no active (non-deleted, non-completed) request exists for this well
 | 
			
		||||
    try:
 | 
			
		||||
        active_exists = ProcessInstance.objects.filter(well=well, is_deleted=False).exclude(status='completed').exists()
 | 
			
		||||
        if active_exists:
 | 
			
		||||
            return JsonResponse({'ok': False, 'error': 'برای این چاه یک درخواست جاری وجود دارد. ابتدا آن را تکمیل یا حذف کنید.'}, status=400)
 | 
			
		||||
    except Exception:
 | 
			
		||||
        return JsonResponse({'ok': False, 'error': 'خطا در بررسی وضعیت درخواستهای قبلی این چاه'}, status=400)
 | 
			
		||||
 | 
			
		||||
    # Create request instance
 | 
			
		||||
    instance = ProcessInstance.objects.create(
 | 
			
		||||
        process=process,
 | 
			
		||||
| 
						 | 
				
			
			@ -261,7 +329,17 @@ def create_request_with_entities(request):
 | 
			
		|||
@login_required
 | 
			
		||||
def delete_request(request, instance_id):
 | 
			
		||||
    """حذف درخواست"""
 | 
			
		||||
    instance = get_object_or_404(ProcessInstance, id=instance_id)
 | 
			
		||||
    instance = get_scoped_instance_or_404(request, instance_id)
 | 
			
		||||
    # Only BROKER can delete requests and only within their scope
 | 
			
		||||
    try:
 | 
			
		||||
        profile = getattr(request.user, 'profile', None)
 | 
			
		||||
        if not (profile and profile.has_role(UserRoles.BROKER)):
 | 
			
		||||
            return JsonResponse({'success': False, 'message': 'فقط کارگزار مجاز به حذف درخواست است'}, status=403)
 | 
			
		||||
        # Enforce ownership by broker (prevent deleting others' requests)
 | 
			
		||||
        if instance.broker_id and profile.broker and instance.broker_id != profile.broker.id:
 | 
			
		||||
            return JsonResponse({'success': False, 'message': 'شما مجاز به حذف این درخواست نیستید'}, status=403)
 | 
			
		||||
    except Exception:
 | 
			
		||||
        return JsonResponse({'success': False, 'message': 'فقط کارگزار مجاز به حذف درخواست است'}, status=403)
 | 
			
		||||
    code = instance.code
 | 
			
		||||
    if instance.status == 'completed':
 | 
			
		||||
        return JsonResponse({
 | 
			
		||||
| 
						 | 
				
			
			@ -278,10 +356,10 @@ def delete_request(request, instance_id):
 | 
			
		|||
@login_required
 | 
			
		||||
def step_detail(request, instance_id, step_id):
 | 
			
		||||
    """نمایش جزئیات مرحله خاص"""
 | 
			
		||||
    instance = get_object_or_404(
 | 
			
		||||
        ProcessInstance.objects.select_related('process', 'well', 'requester', 'representative', 'representative__profile'),
 | 
			
		||||
        id=instance_id
 | 
			
		||||
    )
 | 
			
		||||
    # Enforce scoped access to prevent URL tampering
 | 
			
		||||
    instance = get_scoped_instance_or_404(request, instance_id)
 | 
			
		||||
    # Prefetch for performance
 | 
			
		||||
    instance = ProcessInstance.objects.select_related('process', 'well', 'requester', 'representative', 'representative__profile').get(id=instance.id)
 | 
			
		||||
    step = get_object_or_404(instance.process.steps, id=step_id)
 | 
			
		||||
    # If the request is already completed, redirect to read-only summary page
 | 
			
		||||
    if instance.status == 'completed':
 | 
			
		||||
| 
						 | 
				
			
			@ -339,7 +417,8 @@ def step_detail(request, instance_id, step_id):
 | 
			
		|||
@login_required 
 | 
			
		||||
def instance_steps(request, instance_id):
 | 
			
		||||
    """هدایت به مرحله فعلی instance"""
 | 
			
		||||
    instance = get_object_or_404(ProcessInstance, id=instance_id)
 | 
			
		||||
    # Enforce scoped access to prevent URL tampering
 | 
			
		||||
    instance = get_scoped_instance_or_404(request, instance_id)
 | 
			
		||||
    
 | 
			
		||||
    if not instance.current_step:
 | 
			
		||||
        # اگر مرحله فعلی تعریف نشده، به اولین مرحله برو
 | 
			
		||||
| 
						 | 
				
			
			@ -361,6 +440,9 @@ def instance_steps(request, instance_id):
 | 
			
		|||
@login_required
 | 
			
		||||
def instance_summary(request, instance_id):
 | 
			
		||||
    """نمای خلاصهٔ فقطخواندنی برای درخواستهای تکمیلشده."""
 | 
			
		||||
    # Enforce scoped access to prevent URL tampering
 | 
			
		||||
    instance = get_scoped_instance_or_404(request, instance_id)
 | 
			
		||||
 | 
			
		||||
    instance = get_object_or_404(ProcessInstance.objects.select_related('well', 'representative'), id=instance_id)
 | 
			
		||||
    # Only show for completed requests; otherwise route to steps
 | 
			
		||||
    if instance.status != 'completed':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue