from django.urls import re_path from rest_framework import routers, viewsets, status from rest_framework.decorators import api_view, permission_classes, action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from rest_framework import serializers from .models import Shipment from inventory.models import Item from tickets.models import IssueThread class ShipmentSerializer(serializers.ModelSerializer): related_items = serializers.PrimaryKeyRelatedField( many=True, queryset=Item.objects.all(), required=False ) related_tickets = serializers.PrimaryKeyRelatedField( many=True, queryset=IssueThread.objects.all(), required=False ) class Meta: model = Shipment fields = [ 'id', 'public_secret', 'state', 'review_requirement', 'recipient_name', 'address_supplements', 'street_address', 'city', 'state_province', 'postal_code', 'country', 'related_items', 'related_tickets', 'created_at', 'updated_at', 'shipped_at', 'completed_at' ] read_only_fields = ['id', 'public_secret', 'created_at', 'updated_at', 'shipped_at', 'completed_at'] class ShipmentViewSet(viewsets.ModelViewSet): serializer_class = ShipmentSerializer queryset = Shipment.objects.all() permission_classes = [IsAuthenticated] @action(detail=True, methods=['post']) def add_items(self, request, pk=None): shipment = self.get_object() review_requirement = request.data.get('review_requirement') item_ids = request.data.get('item_ids', []) try: items = Item.objects.filter(id__in=item_ids) shipment.related_items.add(*items) shipment.add_items(review_requirement) return Response(ShipmentSerializer(shipment).data) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, methods=['post']) def approve(self, request, pk=None): shipment = self.get_object() try: shipment.approve() return Response(ShipmentSerializer(shipment).data) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, methods=['post']) def reject(self, request, pk=None): shipment = self.get_object() try: shipment.reject() return Response(ShipmentSerializer(shipment).data) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, methods=['post']) def mark_shipped(self, request, pk=None): shipment = self.get_object() try: # Validate state transition before attempting to mark as shipped if shipment.state != Shipment.READY_FOR_SHIPPING: return Response( {'error': f'Invalid state transition: Cannot mark shipment as shipped from {shipment.state} state. Shipment must be in READY_FOR_SHIPPING state.'}, status=status.HTTP_400_BAD_REQUEST ) shipment.mark_shipped() return Response(ShipmentSerializer(shipment).data) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, methods=['post']) def mark_completed(self, request, pk=None): shipment = self.get_object() try: # Validate state transition before attempting to mark as completed if shipment.state != Shipment.SHIPPED: return Response( {'error': f'Invalid state transition: Cannot mark shipment as completed from {shipment.state} state. Shipment must be in SHIPPED state.'}, status=status.HTTP_400_BAD_REQUEST ) shipment.mark_completed() return Response(ShipmentSerializer(shipment).data) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) router = routers.SimpleRouter() router.register(r'shipments', ShipmentViewSet, basename='shipments') urlpatterns = router.urls