diff --git a/apps/warehouse/services/search.py b/apps/warehouse/services/search.py index e69de29..a129dee 100644 --- a/apps/warehouse/services/search.py +++ b/apps/warehouse/services/search.py @@ -0,0 +1,39 @@ +from django.db.models import Q +from apps.warehouse.models import InventoryEntry +from django.db.models.functions import TruncDate + + +class InventoryEntrySearch: + def __init__(self, query: str = None, start_date: str = None, end_date: str = None): + self.query = (query or '').strip() + self.start_date = start_date + self.end_date = end_date + + def search(self): + """ multi term search & filter by date range """ + + queryset = InventoryEntry.objects.all() + + if self.start_date or self.end_date: + queryset = queryset.annotate(date_only=TruncDate('create_date')) + if self.start_date: + queryset = queryset.filter(date_only__gte=self.start_date) + if self.end_date: + queryset = queryset.filter(date_only__lte=self.end_date) + + # convert string to list of words + if self.query: + keywords = [word.strip() for word in self.query.split(',') if word.strip()] + if keywords: + combined_q = Q() + for keyword in keywords: + combined_q |= Q(distribution__distribution_id__icontains=keyword) + combined_q |= Q(organization__name__icontains=keyword) + combined_q |= Q(weight__icontains=keyword) + combined_q |= Q(balance__icontains=keyword) + combined_q |= Q(lading_number__icontains=keyword) + combined_q |= Q(is_confirmed__icontains=keyword) + + queryset = queryset.filter(combined_q) + + return queryset.distinct() diff --git a/apps/warehouse/web/api/v1/api.py b/apps/warehouse/web/api/v1/api.py index 70a6abb..685dc5a 100644 --- a/apps/warehouse/web/api/v1/api.py +++ b/apps/warehouse/web/api/v1/api.py @@ -1,6 +1,8 @@ from apps.warehouse.web.api.v1 import serializers as warehouse_serializers +from apps.warehouse.services.search import InventoryEntrySearch from apps.warehouse import models as warehouse_models from common.helpers import get_organization_by_user +from rest_framework.exceptions import APIException from common.generics import base64_to_image_file from common.liara_tools import upload_to_liara from rest_framework.decorators import action @@ -39,6 +41,24 @@ class InventoryEntryViewSet(viewsets.ModelViewSet): inventory.save() return Response(status=status.HTTP_200_OK) + @transaction.atomic + def list(self, request, *args, **kwargs): + """ search & filter by date range or return all objects """ + + query_params = self.request.query_params + query = query_params.get('query') + start_date = query_params.get('start') + end_date = query_params.get('end') + + search = InventoryEntrySearch( + query, + start_date, + end_date + ) + + serializer = self.serializer_class(search.search(), many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + @transaction.atomic def create(self, request, *args, **kwargs): """ custom create of inventory entry """ diff --git a/apps/warehouse/web/api/v1/serializers.py b/apps/warehouse/web/api/v1/serializers.py index d6dbe09..3d72f13 100644 --- a/apps/warehouse/web/api/v1/serializers.py +++ b/apps/warehouse/web/api/v1/serializers.py @@ -48,9 +48,13 @@ class InventoryEntrySerializer(serializers.ModelSerializer): def to_representation(self, instance): representation = super().to_representation(instance) - representation['document'] = instance.document + if instance.document: + representation['document'] = instance.document if instance.distribution: - representation['distribution'] = instance.distribution.distribution_id + representation['distribution'] = { + 'distribution': instance.distribution.distribution_id, + 'id': instance.distribution.id + } return representation diff --git a/common/generics.py b/common/generics.py index 926e25d..15b0d85 100644 --- a/common/generics.py +++ b/common/generics.py @@ -1,4 +1,5 @@ from django.core.files.base import ContentFile +from django.db.models.functions import TruncDate import base64