197 lines
6.7 KiB
Python
197 lines
6.7 KiB
Python
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
|
from django.db.models import Count, Q
|
|
from django.utils import timezone
|
|
from django.views.generic import TemplateView, ListView, DetailView
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
from apps.batches.models import ProcessingBatch
|
|
from apps.qc.models import QCResult
|
|
from apps.shipments.models import Shipment
|
|
from apps.capa.models import CAPARecord
|
|
from apps.documents.models import Document
|
|
from apps.esg.models import ESGFieldReport
|
|
from apps.notifications.models import Notification
|
|
|
|
|
|
class OpsRequiredMixin(UserPassesTestMixin):
|
|
def test_func(self):
|
|
user = self.request.user
|
|
return user.is_authenticated and (user.role in ('ops', 'admin') or user.is_superuser)
|
|
|
|
|
|
class DashboardView(OpsRequiredMixin, TemplateView):
|
|
template_name = 'ops/dashboard.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx['total_batches'] = ProcessingBatch.objects.count()
|
|
ctx['batches_by_status'] = {
|
|
s: ProcessingBatch.objects.filter(status=s).count()
|
|
for s, _ in ProcessingBatch.Status.choices
|
|
}
|
|
ctx['recent_qc'] = QCResult.objects.select_related('batch').order_by('-tested_at')[:10]
|
|
ctx['qc_summary'] = QCResult.objects.aggregate(
|
|
passed=Count('id', filter=Q(overall_pass=True)),
|
|
failed=Count('id', filter=Q(overall_pass=False)),
|
|
)
|
|
ctx['active_shipments'] = Shipment.objects.exclude(status='delivered').count()
|
|
ctx['open_capas'] = CAPARecord.objects.filter(status__in=('open', 'in_progress')).count()
|
|
ctx['recent_notifications'] = Notification.objects.filter(
|
|
user=self.request.user, is_read=False
|
|
)[:5]
|
|
ctx['recent_batches'] = ProcessingBatch.objects.order_by('-created_at')[:5]
|
|
return ctx
|
|
|
|
|
|
class BatchListView(OpsRequiredMixin, ListView):
|
|
model = ProcessingBatch
|
|
template_name = 'ops/batch_list.html'
|
|
context_object_name = 'batches'
|
|
paginate_by = 25
|
|
|
|
def get_queryset(self):
|
|
qs = ProcessingBatch.objects.all()
|
|
status = self.request.GET.get('status')
|
|
grade = self.request.GET.get('grade')
|
|
search = self.request.GET.get('q')
|
|
if status:
|
|
qs = qs.filter(status=status)
|
|
if grade:
|
|
qs = qs.filter(grade=grade)
|
|
if search:
|
|
qs = qs.filter(batch_reference__icontains=search)
|
|
return qs
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx['status_choices'] = ProcessingBatch.Status.choices
|
|
ctx['grade_choices'] = ProcessingBatch.Grade.choices
|
|
ctx['current_status'] = self.request.GET.get('status', '')
|
|
ctx['current_grade'] = self.request.GET.get('grade', '')
|
|
ctx['current_q'] = self.request.GET.get('q', '')
|
|
return ctx
|
|
|
|
|
|
class BatchDetailView(OpsRequiredMixin, DetailView):
|
|
model = ProcessingBatch
|
|
template_name = 'ops/batch_detail.html'
|
|
context_object_name = 'batch'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
batch = self.object
|
|
ctx['qc_results'] = QCResult.objects.filter(batch=batch)
|
|
ctx['shipments'] = Shipment.objects.filter(batch=batch)
|
|
ctx['capa_records'] = CAPARecord.objects.filter(batch=batch)
|
|
ctx['documents'] = Document.objects.filter(batch=batch)
|
|
ctx['esg_reports'] = ESGFieldReport.objects.filter(batch=batch)
|
|
return ctx
|
|
|
|
|
|
class QCListView(OpsRequiredMixin, ListView):
|
|
model = QCResult
|
|
template_name = 'ops/qc_list.html'
|
|
context_object_name = 'results'
|
|
paginate_by = 25
|
|
|
|
def get_queryset(self):
|
|
qs = QCResult.objects.select_related('batch').all()
|
|
passed = self.request.GET.get('passed')
|
|
if passed == '1':
|
|
qs = qs.filter(overall_pass=True)
|
|
elif passed == '0':
|
|
qs = qs.filter(overall_pass=False)
|
|
return qs
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx['current_passed'] = self.request.GET.get('passed', '')
|
|
return ctx
|
|
|
|
|
|
class QCDetailView(OpsRequiredMixin, DetailView):
|
|
model = QCResult
|
|
template_name = 'ops/qc_detail.html'
|
|
context_object_name = 'result'
|
|
|
|
|
|
class ShipmentListView(OpsRequiredMixin, ListView):
|
|
model = Shipment
|
|
template_name = 'ops/shipment_list.html'
|
|
context_object_name = 'shipments'
|
|
paginate_by = 25
|
|
|
|
def get_queryset(self):
|
|
qs = Shipment.objects.select_related('batch').all()
|
|
status = self.request.GET.get('status')
|
|
if status:
|
|
qs = qs.filter(status=status)
|
|
return qs
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx['status_choices'] = Shipment.Status.choices
|
|
ctx['current_status'] = self.request.GET.get('status', '')
|
|
return ctx
|
|
|
|
|
|
class ShipmentDetailView(OpsRequiredMixin, DetailView):
|
|
model = Shipment
|
|
template_name = 'ops/shipment_detail.html'
|
|
context_object_name = 'shipment'
|
|
|
|
|
|
class CAPAListView(OpsRequiredMixin, ListView):
|
|
model = CAPARecord
|
|
template_name = 'ops/capa_list.html'
|
|
context_object_name = 'records'
|
|
paginate_by = 25
|
|
|
|
def get_queryset(self):
|
|
qs = CAPARecord.objects.select_related('batch').all()
|
|
status = self.request.GET.get('status')
|
|
if status:
|
|
qs = qs.filter(status=status)
|
|
return qs
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx['status_choices'] = CAPARecord.Status.choices
|
|
ctx['current_status'] = self.request.GET.get('status', '')
|
|
return ctx
|
|
|
|
|
|
class CAPADetailView(OpsRequiredMixin, DetailView):
|
|
model = CAPARecord
|
|
template_name = 'ops/capa_detail.html'
|
|
context_object_name = 'record'
|
|
|
|
|
|
class DocumentListView(OpsRequiredMixin, ListView):
|
|
model = Document
|
|
template_name = 'ops/document_list.html'
|
|
context_object_name = 'documents'
|
|
paginate_by = 25
|
|
|
|
def get_queryset(self):
|
|
qs = Document.objects.select_related('batch', 'uploaded_by').all()
|
|
doc_type = self.request.GET.get('doc_type')
|
|
if doc_type:
|
|
qs = qs.filter(doc_type=doc_type)
|
|
return qs
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx['doc_type_choices'] = Document.DocType.choices
|
|
ctx['current_doc_type'] = self.request.GET.get('doc_type', '')
|
|
return ctx
|
|
|
|
|
|
class ESGListView(OpsRequiredMixin, ListView):
|
|
model = ESGFieldReport
|
|
template_name = 'ops/esg_list.html'
|
|
context_object_name = 'reports'
|
|
paginate_by = 25
|
|
|
|
def get_queryset(self):
|
|
return ESGFieldReport.objects.select_related('batch').all()
|