from django.shortcuts import redirect from django.urls import reverse_lazy from django.views.generic import TemplateView, ListView, UpdateView from django.contrib.auth.mixins import LoginRequiredMixin from django.utils import timezone from .models import Item, Machine # Класс главной страницы (роутер) class IndexView(TemplateView): template_name = 'shiftflow/landing.html' def get(self, request, *args, **kwargs): # Если юзер авторизован — сразу отправляем его в реестр if request.user.is_authenticated: return redirect('registry') # Если нет — показываем кнопку "Войти" return super().get(request, *args, **kwargs) # Класс реестра деталей (защищен LoginRequiredMixin) class RegistryView(LoginRequiredMixin, ListView): model = Item template_name = 'shiftflow/registry.html' context_object_name = 'items' def get_queryset(self): queryset = Item.objects.select_related('task', 'task__deal', 'task__material', 'machine') user = self.request.user profile = getattr(user, 'profile', None) role = profile.role if profile else 'operator' filtered = self.request.GET.get('filtered') # Станки m_ids = self.request.GET.getlist('m_ids') if filtered and role != 'operator' and not m_ids: return queryset.none() if m_ids: queryset = queryset.filter(machine_id__in=m_ids) # Статусы (+ агрегат "closed" = done+partial) statuses = self.request.GET.getlist('statuses') if filtered and not statuses: return queryset.none() if statuses: expanded = [] for s in statuses: if s == 'closed': expanded += ['done', 'partial'] else: expanded.append(s) queryset = queryset.filter(status__in=expanded) # Даты start_date = self.request.GET.get('start_date') end_date = self.request.GET.get('end_date') if not filtered: today = timezone.now().date() queryset = queryset.filter(date=today, status__in=['work', 'leftover']) else: if start_date: queryset = queryset.filter(date__gte=start_date) if end_date: queryset = queryset.filter(date__lte=end_date) # Списание (1С) is_synced = self.request.GET.get('is_synced') if is_synced in ['0', '1']: queryset = queryset.filter(is_synced_1c=bool(int(is_synced))) # Ограничения по ролям if role == 'operator': user_machines = profile.machines.all() if profile else Machine.objects.none() queryset = queryset.filter(machine__in=user_machines, status='work') elif role == 'master' and not filtered: queryset = queryset.filter(status='work') return queryset.order_by('status', '-date', 'machine__name', 'task__deal__number') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) user = self.request.user profile = getattr(user, 'profile', None) role = profile.role if profile else 'operator' context['user_role'] = role machines = Machine.objects.all() context['machines'] = machines filtered = self.request.GET.get('filtered') if not filtered: today_str = timezone.now().date().strftime('%Y-%m-%d') context['start_date'] = today_str context['end_date'] = today_str context['selected_statuses'] = ['work', 'leftover'] context['selected_machines'] = [m.id for m in machines] context['all_selected_machines'] = True else: context['selected_machines'] = [int(i) for i in self.request.GET.getlist('m_ids') if i.isdigit()] context['selected_statuses'] = self.request.GET.getlist('statuses') context['start_date'] = self.request.GET.get('start_date', '') context['end_date'] = self.request.GET.get('end_date', '') context['is_synced'] = self.request.GET.get('is_synced', '') context['all_selected_machines'] = False return context # Вьюха детального вида и редактирования class ItemUpdateView(LoginRequiredMixin, UpdateView): model = Item template_name = 'shiftflow/item_detail.html' # Перечисляем поля, которые можно редактировать в сменке fields = [ 'machine', 'quantity_plan', 'quantity_fact', 'status', 'is_synced_1c', 'material_taken', 'usable_waste', 'scrap_weight' ] context_object_name = 'item' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Обязательно добавляем роль в контекст этого шаблона! if hasattr(self.request.user, 'profile'): context['user_role'] = self.request.user.profile.role return context def post(self, request, *args, **kwargs): self.object = self.get_object() profile = getattr(request.user, 'profile', None) role = profile.role if profile else 'operator' # Общие поля self.object.material_taken = request.POST.get('material_taken', self.object.material_taken) self.object.usable_waste = request.POST.get('usable_waste', self.object.usable_waste) self.object.scrap_weight = request.POST.get('scrap_weight', self.object.scrap_weight or 0) status = request.POST.get('status', self.object.status) if role in ['operator', 'master']: if status == 'done': self.object.quantity_fact = self.object.quantity_plan self.object.status = 'done' self.object.save() elif status == 'partial': try: fact = int(request.POST.get('quantity_fact', '0')) except ValueError: fact = 0 fact = max(0, min(fact, self.object.quantity_plan)) residual = self.object.quantity_plan - fact self.object.quantity_fact = fact self.object.status = 'partial' self.object.save() if residual > 0: Item.objects.create( task=self.object.task, date=self.object.date, machine=self.object.machine, quantity_plan=residual, quantity_fact=0, status='leftover', is_synced_1c=False, ) else: # Просто сохранить без спец-логики return super().post(request, *args, **kwargs) elif role == 'clerk': # Учетчик может отмечать списание 1С self.object.is_synced_1c = bool(request.POST.get('is_synced_1c')) self.object.save() else: return super().post(request, *args, **kwargs) return redirect('registry') def get_success_url(self): return reverse_lazy('registry')