from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.db.models import Count from django.views.generic import TemplateView, ListView, DetailView from apps.batches.models import ProcessingBatch from apps.shipments.models import Shipment from apps.documents.models import Document from apps.esg.models import ESGFieldReport from apps.subscriptions.models import Subscription class BuyerRequiredMixin(UserPassesTestMixin): def test_func(self): user = self.request.user return user.is_authenticated and (user.role in ("buyer", "admin") or user.is_superuser) class DashboardView(BuyerRequiredMixin, TemplateView): template_name = "portal/dashboard.html" def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx["total_batches"] = ProcessingBatch.objects.count() ctx["recent_batches"] = ProcessingBatch.objects.order_by("-created_at")[:5] ctx["documents"] = Document.objects.filter(visibility="buyer").order_by("-uploaded_at")[:5] ctx["active_shipments"] = Shipment.objects.exclude(status="delivered").count() ctx["subscription"] = Subscription.objects.filter(user=self.request.user).first() return ctx class BatchListView(BuyerRequiredMixin, ListView): model = ProcessingBatch template_name = "portal/batch_list.html" context_object_name = "batches" paginate_by = 25 def get_queryset(self): qs = ProcessingBatch.objects.all() status = self.request.GET.get("status") q = self.request.GET.get("q") if status: qs = qs.filter(status=status) if q: qs = qs.filter(batch_reference__icontains=q) return qs def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx["status_choices"] = ProcessingBatch.Status.choices ctx["current_status"] = self.request.GET.get("status", "") ctx["current_q"] = self.request.GET.get("q", "") return ctx class BatchDetailView(BuyerRequiredMixin, DetailView): model = ProcessingBatch template_name = "portal/batch_detail.html" context_object_name = "batch" def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) b = self.object ctx["shipments"] = Shipment.objects.filter(batch=b) ctx["documents"] = Document.objects.filter(batch=b, visibility="buyer") ctx["esg_reports"] = ESGFieldReport.objects.filter(batch=b) return ctx class DocumentListView(BuyerRequiredMixin, ListView): model = Document template_name = "portal/document_list.html" context_object_name = "documents" paginate_by = 25 def get_queryset(self): qs = Document.objects.filter(visibility="buyer").select_related("batch", "uploaded_by") 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 SubscriptionView(BuyerRequiredMixin, DetailView): model = Subscription template_name = "portal/subscription.html" context_object_name = "sub" def get_object(self): return Subscription.objects.filter(user=self.request.user).first() class ChatView(BuyerRequiredMixin, TemplateView): def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) from apps.ai.models import AgentConfig user = self.request.user if user.role in ("admin", "ops") or user.is_superuser: ctx["agents"] = AgentConfig.objects.filter(is_active=True) else: ctx["agents"] = AgentConfig.objects.filter(is_active=True, user__isnull=True) return ctx template_name = "portal/chat.html" class ChatEmbedView(BuyerRequiredMixin, TemplateView): template_name = "portal/chat_embed.html" def dispatch(self, request, *args, **kwargs): response = super().dispatch(request, *args, **kwargs) response["X-Frame-Options"] = "ALLOWALL" return response class ComplianceView(BuyerRequiredMixin, TemplateView): template_name = "portal/compliance.html" def get_context_data(self, **kwargs): from apps.compliance.models import DueDiligenceCase from apps.documents.models import CertificateOfAnalysis ctx = super().get_context_data(**kwargs) ctx["approved_coas"] = CertificateOfAnalysis.objects.filter( status=CertificateOfAnalysis.Status.PUBLISHED ).select_related("batch", "quality_approved_by").order_by("-published_at") ctx["eudr_cases"] = DueDiligenceCase.objects.select_related("batch", "approved_by").order_by("-updated_at") return ctx