from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from rest_framework import generics, status, serializers
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.exceptions import PermissionDenied, ValidationError
from drf_spectacular.utils import extend_schema
from .models import InventoryReceipt, Invoice
from .serializers import (
InventoryReceiptSerializer,
InvoiceSerializer,
InvoicePaymentStatusSerializer,
InvoiceVendorRatingSerializer,
)
from .tasks import generate_report_and_save, send_logistics_email
from purchase.models import PurchaseOrder
from accounts.models import Vendor
from accounts.permissions import IsProcurementOfficer, IsVendor
[docs]
class BaseInventoryReceiptAPIView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsProcurementOfficer]
serializer_class = InventoryReceiptSerializer
[docs]
def get_queryset(self):
return InventoryReceipt.objects.filter(
order__bid__requisition__inventory__procurement_officer=self.request.user
)
[docs]
def get_object(self):
order_id = self.kwargs.get("order_id")
# If order_id is None, then we are not creating a new inventory receipt
# Return the object of InventoryInspection based on the primary key
if order_id is None:
return get_object_or_404(self.get_queryset(), id=self.kwargs.get("pk"))
order = get_object_or_404(
PurchaseOrder,
id=order_id,
)
if order.bid.requisition.inventory.procurement_officer != self.request.user:
raise PermissionDenied(
"You do not have permission to access this purchase order."
)
obj = get_object_or_404(self.get_queryset(), order=order)
return obj
# @method_decorator(cache_page(60 * 15), name="dispatch")
[docs]
class InventoryReceiptListView(BaseInventoryReceiptAPIView, generics.ListAPIView):
pass
[docs]
class InventoryReceiptCreateView(BaseInventoryReceiptAPIView, generics.CreateAPIView):
queryset = InventoryReceipt.objects.all()
[docs]
class InventoryReceiptRetrieveView(
BaseInventoryReceiptAPIView, generics.RetrieveAPIView
):
pass
[docs]
class InventoryReceiptUpdateView(BaseInventoryReceiptAPIView, generics.UpdateAPIView):
queryset = InventoryReceipt.objects.all()
[docs]
def patch(self, request, *args, **kwargs):
if not request.data:
return Response(
{"error": "No data provided"}, status=status.HTTP_400_BAD_REQUEST
)
return super().patch(request, *args, **kwargs)
[docs]
class InventoryReceiptDeleteView(BaseInventoryReceiptAPIView, generics.DestroyAPIView):
queryset = InventoryReceipt.objects.all()
[docs]
class BaseInventoryReceiptVendorAPIView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsVendor]
serializer_class = InventoryReceiptSerializer
[docs]
def get_queryset(self):
return InventoryReceipt.objects.filter(order__bid__supplier=self.request.user)
[docs]
def get_object(self):
order_id = self.kwargs.get("order_id")
# If order_id is None, then we are not creating a new invoice
# Return the object of Invoice based on the primary key
if order_id is None:
return get_object_or_404(self.get_queryset(), id=self.kwargs.get("pk"))
order = get_object_or_404(
PurchaseOrder,
id=order_id,
)
if order.bid.supplier != self.request.user:
raise PermissionDenied(
"You do not have permission to access this purchase order."
)
obj = get_object_or_404(self.get_queryset(), order=order)
return obj
# @method_decorator(cache_page(60 * 15), name="dispatch")
[docs]
class InventoryReceiptVendorListView(
BaseInventoryReceiptVendorAPIView, generics.ListAPIView
):
pass
[docs]
class InventoryReceiptVendorRetrieveView(
BaseInventoryReceiptVendorAPIView, generics.RetrieveAPIView
):
pass
[docs]
class BaseInvoiceAPIView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsVendor]
serializer_class = InvoiceSerializer
[docs]
def get_queryset(self):
return Invoice.objects.filter(order__bid__supplier=self.request.user)
[docs]
def get_object(self):
order_id = self.kwargs.get("order_id")
# If order_id is None, then we are not creating a new invoice
# Return the object of Invoice based on the primary key
if order_id is None:
return get_object_or_404(self.get_queryset(), id=self.kwargs.get("pk"))
order = get_object_or_404(
PurchaseOrder,
id=order_id,
)
if order.bid.supplier != self.request.user:
raise PermissionDenied(
"You do not have permission to access this purchase order."
)
obj = get_object_or_404(self.get_queryset(), order=order)
return obj
# @method_decorator(cache_page(60 * 15), name="dispatch")
[docs]
class InvoiceListView(BaseInvoiceAPIView, generics.ListAPIView):
pass
[docs]
class InvoiceCreateView(BaseInvoiceAPIView, generics.CreateAPIView):
queryset = Invoice.objects.all()
[docs]
class InvoiceRetrieveView(BaseInvoiceAPIView, generics.RetrieveAPIView):
pass
[docs]
class InvoiceUpdateView(BaseInvoiceAPIView, generics.UpdateAPIView):
queryset = Invoice.objects.all()
[docs]
def patch(self, request, *args, **kwargs):
if not request.data:
return Response(
{"error": "No data provided"}, status=status.HTTP_400_BAD_REQUEST
)
return super().patch(request, *args, **kwargs)
[docs]
class InvoiceDeleteView(BaseInvoiceAPIView, generics.DestroyAPIView):
queryset = Invoice.objects.all()
[docs]
class BaseInvoiceProcurementOfficerAPIView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsProcurementOfficer]
serializer_class = InvoiceSerializer
[docs]
def get_queryset(self):
return Invoice.objects.filter(
order__bid__requisition__inventory__procurement_officer=self.request.user
)
[docs]
def get_object(self):
order_id = self.kwargs.get("order_id")
# If order_id is None, then we are not creating a new inventory receipt
# Return the object of InventoryInspection based on the primary key
if order_id is None:
return get_object_or_404(self.get_queryset(), id=self.kwargs.get("pk"))
order = get_object_or_404(
PurchaseOrder,
id=order_id,
)
if order.bid.requisition.inventory.procurement_officer != self.request.user:
raise PermissionDenied(
"You do not have permission to access this purchase order."
)
obj = get_object_or_404(self.get_queryset(), order=order)
return obj
# @method_decorator(cache_page(60 * 15), name="dispatch")
[docs]
class InvoiceProcurementOfficerListView(
BaseInvoiceProcurementOfficerAPIView, generics.ListAPIView
):
pass
[docs]
class InvoiceProcurementOfficerRetrieveView(
BaseInvoiceProcurementOfficerAPIView, generics.RetrieveAPIView
):
pass
[docs]
class InvoicePaymentStatusUpdateView(generics.UpdateAPIView):
serializer_class = InvoicePaymentStatusSerializer
permission_classes = [IsAuthenticated, IsProcurementOfficer]
[docs]
def get_queryset(self):
return Invoice.objects.filter(
order__bid__requisition__inventory__procurement_officer=self.request.user
)
[docs]
def get_object(self):
order_id = self.kwargs.get("order_id")
# If order_id is None, then we are not creating a new invoice
# Return the object of Invoice based on the primary key
if order_id is None:
return get_object_or_404(self.get_queryset(), id=self.kwargs.get("pk"))
order = get_object_or_404(
PurchaseOrder,
id=order_id,
)
if order.bid.requisition.inventory.procurement_officer != self.request.user:
raise PermissionDenied(
"You do not have permission to access this purchase order."
)
obj = get_object_or_404(self.get_queryset(), order=order)
return obj
[docs]
def patch(self, request, *args, **kwargs):
if not request.data:
return Response(
{"error": "No data provided"}, status=status.HTTP_400_BAD_REQUEST
)
return super().patch(request, *args, **kwargs)
[docs]
class InvoiceVendorRatingUpdateView(generics.UpdateAPIView):
serializer_class = InvoiceVendorRatingSerializer
permission_classes = [IsAuthenticated, IsProcurementOfficer]
[docs]
def get_queryset(self):
return Invoice.objects.filter(
order__bid__requisition__inventory__procurement_officer=self.request.user
)
[docs]
def get_object(self):
order_id = self.kwargs.get("order_id")
# If order_id is None, then we are not creating a new invoice
# Return the object of Invoice based on the primary key
if order_id is None:
return get_object_or_404(self.get_queryset(), id=self.kwargs.get("pk"))
order = get_object_or_404(
PurchaseOrder,
id=order_id,
)
if order.bid.requisition.inventory.procurement_officer != self.request.user:
raise PermissionDenied(
"You do not have permission to access this purchase order."
)
obj = get_object_or_404(self.get_queryset(), order=order)
return obj
[docs]
def patch(self, request, *args, **kwargs):
if not request.data:
return Response(
{"error": "No data provided"}, status=status.HTTP_400_BAD_REQUEST
)
return super().patch(request, *args, **kwargs)
[docs]
@extend_schema(exclude=True)
@api_view(["GET"])
@permission_classes([AllowAny])
def getRoutes(request):
routes = [
"/inventory-receipt/list/",
"/inventory-receipt/create/<int:order_id>/",
"/inventory-receipt/<int:pk>/",
"/inventory-receipt/<int:pk>/update/",
"/inventory-receipt/<int:pk>/delete/",
"/inventory-receipt/vendor/list/",
"/inventory-receipt/vendor/<int:pk>/",
"/invoice/list/",
"/invoice/create/<int:order_id>/",
"/invoice/<int:pk>/",
"/invoice/<int:pk>/update/",
"/invoice/<int:pk>/delete/",
"/invoice/procurement-officer/list/",
"/invoice/procurement-officer/<int:pk>/",
"/invoice/<int:pk>/payment-status/",
"/invoice/<int:pk>/vendor-rating/",
]
return Response(routes)