diff --git a/apps/pos_device/migrations/0011_alter_deviceactivationcode_expires_at.py b/apps/pos_device/migrations/0011_alter_deviceactivationcode_expires_at.py new file mode 100644 index 0000000..dde291b --- /dev/null +++ b/apps/pos_device/migrations/0011_alter_deviceactivationcode_expires_at.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0 on 2025-07-30 07:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pos_device', '0010_alter_deviceactivationcode_expires_at'), + ] + + operations = [ + migrations.AlterField( + model_name='deviceactivationcode', + name='expires_at', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 30, 10, 32, 15, 135566)), + ), + ] diff --git a/apps/product/services/search/quota_search.py b/apps/product/services/search/quota_search.py new file mode 100644 index 0000000..eeb7bc7 --- /dev/null +++ b/apps/product/services/search/quota_search.py @@ -0,0 +1,39 @@ +from django.db.models import Q +from django.db.models.functions import TruncDate +from apps.product.models import Quota + + +class QuotaSearch: + 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 = QuotaDistribution.objects.all() # noqa + + 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(registerer_organization__name__icontains=keyword) + combined_q |= Q(quota_id__icontains=keyword) + combined_q |= Q(product__name__icontains=keyword) + combined_q |= Q(sale_type__icontains=keyword) + combined_q |= Q(sale_unit__unit__icontains=keyword) + combined_q |= Q(group__icontains=keyword) + + queryset = queryset.filter(combined_q) + + return queryset.distinct() diff --git a/apps/product/signals.py b/apps/product/signals.py index 515cc4a..a74e28c 100644 --- a/apps/product/signals.py +++ b/apps/product/signals.py @@ -47,6 +47,10 @@ def remaining_distribution_weight(instance: QuotaDistribution): total=Sum('weight') )['total'] or 0 + print(total_assigner_distribution) + + print(total_assigned_distribution - total_assigner_distribution) + instance.remaining_weight = total_assigned_distribution - total_assigner_distribution instance.distributed = total_assigner_distribution instance._from_signal = True diff --git a/apps/product/web/api/v1/viewsets/quota_api.py b/apps/product/web/api/v1/viewsets/quota_api.py index 20a77a4..35d7f7d 100644 --- a/apps/product/web/api/v1/viewsets/quota_api.py +++ b/apps/product/web/api/v1/viewsets/quota_api.py @@ -1,8 +1,9 @@ from apps.product.web.api.v1.serializers import quota_distribution_serializers +from apps.product.services.services import get_products_in_warehouse from apps.product.web.api.v1.serializers import quota_serializers +from apps.product.services.search.quota_search import QuotaSearch from apps.product.exceptions import QuotaExpiredTimeException from apps.core.pagination import CustomPageNumberPagination -from apps.product.services.services import get_products_in_warehouse from apps.product.web.api.v1.viewsets import product_api from common.helpers import get_organization_by_user from rest_framework.exceptions import APIException @@ -39,6 +40,23 @@ class QuotaViewSet(viewsets.ModelViewSet): # noqa CustomPageNumberPagination.page_size = 5 search_fields = [''] + def list(self, request, *args, **kwargs): + """ search & filter quotas or return all """ + + params = self.request.query_params + query = params.get('search') + start_date = params.get('start') + end_date = params.get('end') + + search = QuotaSearch( + query=query, + start_date=start_date, + end_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 quota """