diff --git a/core/settings.py b/core/settings.py index 3f92579..bfcda8e 100644 --- a/core/settings.py +++ b/core/settings.py @@ -90,7 +90,8 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', - 'shiftflow.context_processors.env_info', # Правильный путь + 'shiftflow.context_processors.env_info', + 'shiftflow.context_processors.authz_info', ], }, }, diff --git a/shiftflow/context_processors.py b/shiftflow/context_processors.py index 4f1cbce..16b4227 100644 --- a/shiftflow/context_processors.py +++ b/shiftflow/context_processors.py @@ -1,9 +1,19 @@ from django.conf import settings +from shiftflow.authz import get_user_roles, primary_role + + def env_info(request): - """ - Прокидываем ENV_TYPE во все шаблоны. - """ return { 'ENV_TYPE': getattr(settings, 'ENV_TYPE', 'local') + } + + +def authz_info(request): + roles = get_user_roles(getattr(request, 'user', None)) + profile = getattr(getattr(request, 'user', None), 'profile', None) + return { + 'user_roles': sorted(roles), + 'user_role': primary_role(roles), + 'is_readonly': bool(getattr(profile, 'is_readonly', False)) if profile else False, } \ No newline at end of file diff --git a/shiftflow/templates/shiftflow/customers.html b/shiftflow/templates/shiftflow/customers.html index 98a0c81..54d11ed 100644 --- a/shiftflow/templates/shiftflow/customers.html +++ b/shiftflow/templates/shiftflow/customers.html @@ -4,7 +4,7 @@

Заказчики

- {% if user_role in 'admin,technologist' %} + {% if user_role in 'admin,technologist,clerk,manager' %} diff --git a/shiftflow/templates/shiftflow/warehouse_stocks.html b/shiftflow/templates/shiftflow/warehouse_stocks.html index 23c346f..4b83f2b 100644 --- a/shiftflow/templates/shiftflow/warehouse_stocks.html +++ b/shiftflow/templates/shiftflow/warehouse_stocks.html @@ -229,7 +229,7 @@
diff --git a/shiftflow/views.py b/shiftflow/views.py index 0850c2b..9d7a9c7 100644 --- a/shiftflow/views.py +++ b/shiftflow/views.py @@ -2938,9 +2938,8 @@ class MaterialUpsertView(LoginRequiredMixin, View): class CompanyUpsertView(LoginRequiredMixin, View): def post(self, request, *args, **kwargs): - profile = getattr(request.user, 'profile', None) - role = profile.role if profile else ('admin' if request.user.is_superuser else 'operator') - if role not in ['admin', 'technologist']: + roles = get_user_roles(request.user) + if not has_any_role(roles, ['admin', 'clerk', 'manager', 'technologist']): return JsonResponse({'error': 'forbidden'}, status=403) company_id = request.POST.get('id') @@ -3991,6 +3990,7 @@ class WarehouseStocksView(LoginRequiredMixin, TemplateView): allowed_transfer_locations = list(Location.objects.filter(id__in=allowed_loc_ids).order_by('name')) ctx['transfer_locations'] = allowed_transfer_locations if allowed_transfer_locations is not None else locations + ctx['receipt_locations'] = allowed_transfer_locations if allowed_transfer_locations is not None else locations ctx['materials'] = Material.objects.select_related('category').all().order_by('full_name') ctx['entities'] = ProductEntity.objects.all().order_by('drawing_number', 'name') @@ -4087,6 +4087,19 @@ class WarehouseReceiptCreateView(LoginRequiredMixin, View): messages.error(request, 'Выбери склад.') return redirect(next_url) + profile = getattr(request.user, 'profile', None) + role = primary_role(roles) + if role == 'master' and not has_any_role(roles, ['admin', 'technologist', 'clerk', 'prod_head', 'director']): + allowed_ws_ids = list(profile.allowed_workshops.values_list('id', flat=True)) if profile else [] + if not allowed_ws_ids and profile: + user_machine_ids = list(profile.machines.values_list('id', flat=True)) + allowed_ws_ids = list(Machine.objects.filter(id__in=user_machine_ids).exclude(workshop_id__isnull=True).values_list('workshop_id', flat=True)) + + allowed_loc_ids = list(Workshop.objects.filter(id__in=allowed_ws_ids).exclude(location_id__isnull=True).values_list('location_id', flat=True)) + if not allowed_loc_ids or int(location_id) not in {int(x) for x in allowed_loc_ids}: + messages.error(request, 'Мастер может делать приход только на склад своего цеха.') + return redirect(next_url) + try: qty = float(quantity_raw) except ValueError: