from django.db.models import Count from django_filters.rest_framework import DjangoFilterBackend from rest_framework import filters, viewsets from rest_framework.decorators import action from rest_framework.response import Response from commerce.models import ( Cost, Product, ProductBinding, Sale, SaleLine, SourceSystem, StockSnapshot, ) from commerce.services import get_product_metrics from .permissions import CommerceAccessPermission from .serializers import ( CostSerializer, ProductBindingSerializer, ProductMetricsQuerySerializer, ProductSerializer, SaleSerializer, SaleLineSerializer, SourceSystemSerializer, StockSnapshotSerializer, ) class SourceSystemViewSet(viewsets.ModelViewSet): queryset = SourceSystem.objects.all() serializer_class = SourceSystemSerializer permission_classes = [CommerceAccessPermission] filter_backends = [filters.SearchFilter, filters.OrderingFilter] search_fields = ["code", "name"] ordering_fields = ["code", "name", "created_at"] ordering = ["name"] class ProductViewSet(viewsets.ModelViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer permission_classes = [CommerceAccessPermission] filter_backends = [ DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter, ] filterset_fields = ["kind", "is_active", "parent"] search_fields = ["sku", "name", "barcode", "bindings__external_sku"] ordering_fields = ["sku", "name", "created_at", "updated_at"] ordering = ["name", "sku"] def get_queryset(self): return ( super() .get_queryset() .select_related("parent") .prefetch_related("bindings__source") .annotate(variants_count=Count("variants", distinct=True)) .distinct() ) @action(detail=True, methods=["get"]) def analytics(self, request, pk=None): query = ProductMetricsQuerySerializer(data=request.query_params) query.is_valid(raise_exception=True) product = self.get_object() return Response(get_product_metrics(product, **query.validated_data)) class ProductBindingViewSet(viewsets.ModelViewSet): queryset = ProductBinding.objects.select_related("product", "source") serializer_class = ProductBindingSerializer permission_classes = [CommerceAccessPermission] filter_backends = [DjangoFilterBackend, filters.SearchFilter] filterset_fields = ["product", "source", "is_primary"] search_fields = ["external_id", "external_sku", "product__sku", "product__name"] class SaleViewSet(viewsets.ModelViewSet): queryset = Sale.objects.select_related("source", "source_record").prefetch_related( "lines__product" ) serializer_class = SaleSerializer permission_classes = [CommerceAccessPermission] filter_backends = [ DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter, ] filterset_fields = [ "source", "event_type", "channel", "status", "counts_as_sale", "currency", ] search_fields = ["external_id", "number", "lines__external_sku", "lines__name"] ordering_fields = ["occurred_at", "created_at", "updated_at"] ordering = ["-occurred_at"] class SaleLineViewSet(viewsets.ModelViewSet): queryset = SaleLine.objects.select_related("sale", "product", "sale__source") serializer_class = SaleLineSerializer permission_classes = [CommerceAccessPermission] filter_backends = [DjangoFilterBackend, filters.SearchFilter] filterset_fields = ["sale", "product"] search_fields = ["external_id", "external_product_id", "external_sku", "name"] class CostViewSet(viewsets.ModelViewSet): queryset = Cost.objects.select_related("source", "product", "sale_line") serializer_class = CostSerializer permission_classes = [CommerceAccessPermission] filter_backends = [DjangoFilterBackend, filters.OrderingFilter] filterset_fields = ["source", "product", "channel", "cost_type", "currency"] ordering_fields = ["occurred_at", "amount", "created_at"] ordering = ["-occurred_at"] class StockSnapshotViewSet(viewsets.ModelViewSet): queryset = StockSnapshot.objects.select_related("source", "product") serializer_class = StockSnapshotSerializer permission_classes = [CommerceAccessPermission] filter_backends = [DjangoFilterBackend, filters.OrderingFilter] filterset_fields = ["source", "product", "warehouse_external_id"] ordering_fields = ["captured_at", "quantity", "created_at"] ordering = ["-captured_at"]