Дал мастеру доступ к пунктам
All checks were successful
Deploy MES Core / deploy (push) Successful in 11s

This commit is contained in:
2026-04-13 08:10:21 +03:00
parent 28537447f8
commit fa881877d7
3 changed files with 81 additions and 56 deletions

View File

@@ -224,7 +224,7 @@
<div class="col-md-4">
<label class="form-label">Склад</label>
<select class="form-select" name="location_id" required>
{% for loc in locations %}
{% for loc in transfer_locations %}
<option value="{{ loc.id }}">{{ loc }}</option>
{% endfor %}
</select>

View File

@@ -966,9 +966,8 @@ class PlanningStagesView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/planning_stages.html'
def dispatch(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', 'master', 'clerk', 'manager', 'observer']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'manager', 'observer', 'prod_head', 'director']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
@@ -1888,17 +1887,18 @@ class PlanningView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/planning.html'
def dispatch(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', 'master', 'clerk', 'prod_head', 'director']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director', 'observer']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
context['user_role'] = role
context['user_roles'] = sorted(roles)
allowed_ws = list(profile.allowed_workshops.values_list('id', flat=True)) if profile else []
context['allowed_workshop_ids'] = allowed_ws
@@ -1923,17 +1923,18 @@ class DealPlanningView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/planning_deal.html'
def dispatch(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', 'master', 'clerk']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director', 'observer']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
context['user_role'] = role
context['user_roles'] = sorted(roles)
allowed_ws = list(profile.allowed_workshops.values_list('id', flat=True)) if profile else []
context['allowed_workshop_ids'] = allowed_ws
@@ -2525,17 +2526,17 @@ class CustomersView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/customers.html'
def dispatch(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', 'master', 'clerk']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director', 'observer']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
context['user_role'] = role
context['user_roles'] = sorted(roles)
companies = Company.objects.all().order_by('name')
context['companies'] = companies
@@ -2546,17 +2547,18 @@ class CustomerDealsView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/customer_deals.html'
def dispatch(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', 'master', 'clerk']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director', 'observer']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
context['user_role'] = role
context['user_roles'] = sorted(roles)
allowed_ws = list(profile.allowed_workshops.values_list('id', flat=True)) if profile else []
context['allowed_workshop_ids'] = allowed_ws
@@ -3296,17 +3298,17 @@ class DirectoriesView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/directories.html'
def dispatch(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', 'master', 'clerk', 'prod_head', 'director']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'observer', 'prod_head', 'director']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
ctx['user_role'] = role
ctx['user_roles'] = sorted(roles)
return ctx
@@ -3314,26 +3316,25 @@ class LocationsCatalogView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/locations_catalog.html'
def dispatch(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', 'master', 'clerk', 'prod_head', 'director']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'observer', 'prod_head', 'director']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
ctx['user_role'] = role
ctx['can_edit'] = role in ['admin', 'prod_head', 'director']
ctx['user_roles'] = sorted(roles)
ctx['can_edit'] = has_any_role(roles, ['admin', 'prod_head', 'director'])
ctx['locations'] = list(Location.objects.order_by('name'))
return ctx
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', 'prod_head', 'director']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'prod_head', 'director']):
return redirect('locations_catalog')
action = (request.POST.get('action') or '').strip()
@@ -3377,17 +3378,17 @@ class WorkshopsCatalogView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/workshops_catalog.html'
def dispatch(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', 'master', 'clerk', 'prod_head', 'director']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'observer', 'prod_head', 'director']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
ctx['user_role'] = role
ctx['user_roles'] = sorted(roles)
workshops = list(Workshop.objects.select_related('location').order_by('id'))
ws_ids = [int(w.id) for w in workshops]
@@ -3414,12 +3415,12 @@ class MachinesCatalogView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/machines_catalog.html'
def dispatch(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', 'master', 'clerk', 'prod_head', 'director']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'observer', 'prod_head', 'director']):
return redirect('registry')
self.role = role
self.can_edit = role in ['admin', 'prod_head', 'director']
self.roles = roles
self.role = primary_role(roles)
self.can_edit = has_any_role(roles, ['admin', 'prod_head', 'director'])
return super().dispatch(request, *args, **kwargs)
def _workshop_id(self):
@@ -3889,17 +3890,18 @@ class WarehouseStocksView(LoginRequiredMixin, TemplateView):
template_name = 'shiftflow/warehouse_stocks.html'
def dispatch(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', 'master', 'clerk', 'observer']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'observer', 'prod_head', 'director']):
return redirect('registry')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
profile = getattr(self.request.user, 'profile', None)
role = profile.role if profile else ('admin' if self.request.user.is_superuser else 'operator')
roles = get_user_roles(self.request.user)
role = primary_role(roles)
ctx['user_role'] = role
ctx['user_roles'] = sorted(roles)
ship_loc = (
Location.objects.filter(
@@ -3975,8 +3977,20 @@ class WarehouseStocksView(LoginRequiredMixin, TemplateView):
ctx['selected_kind'] = kind
ctx['q'] = q
ctx['can_transfer'] = role in ['admin', 'technologist', 'master', 'clerk']
ctx['can_receive'] = role in ['admin', 'technologist', 'master', 'clerk']
ctx['can_transfer'] = has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director'])
ctx['can_receive'] = has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director'])
allowed_transfer_locations = None
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 allowed_loc_ids:
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['materials'] = Material.objects.select_related('category').all().order_by('full_name')
ctx['entities'] = ProductEntity.objects.all().order_by('drawing_number', 'name')
@@ -3991,8 +4005,9 @@ class WarehouseStocksView(LoginRequiredMixin, TemplateView):
class WarehouseTransferCreateView(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', 'master', 'clerk']:
roles = get_user_roles(request.user)
role = primary_role(roles)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director']):
return JsonResponse({'error': 'forbidden'}, status=403)
stock_item_id = (request.POST.get('stock_item_id') or '').strip()
@@ -4021,6 +4036,17 @@ class WarehouseTransferCreateView(LoginRequiredMixin, View):
messages.error(request, 'Склад назначения должен отличаться от склада-источника.')
return redirect(next_url)
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(to_location_id) not in {int(x) for x in allowed_loc_ids}:
messages.error(request, 'Мастер может перемещать только на склад своего цеха.')
return redirect(next_url)
tr = TransferRecord.objects.create(
from_location_id=si.location_id,
to_location_id=int(to_location_id),
@@ -4044,9 +4070,8 @@ class WarehouseTransferCreateView(LoginRequiredMixin, View):
class WarehouseReceiptCreateView(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', 'master', 'clerk']:
roles = get_user_roles(request.user)
if not has_any_role(roles, ['admin', 'technologist', 'master', 'clerk', 'prod_head', 'director']):
return JsonResponse({'error': 'forbidden'}, status=403)
next_url = (request.POST.get('next') or '').strip()