search & filter on quota
This commit is contained in:
@@ -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)),
|
||||||
|
),
|
||||||
|
]
|
||||||
39
apps/product/services/search/quota_search.py
Normal file
39
apps/product/services/search/quota_search.py
Normal file
@@ -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()
|
||||||
@@ -47,6 +47,10 @@ def remaining_distribution_weight(instance: QuotaDistribution):
|
|||||||
total=Sum('weight')
|
total=Sum('weight')
|
||||||
)['total'] or 0
|
)['total'] or 0
|
||||||
|
|
||||||
|
print(total_assigner_distribution)
|
||||||
|
|
||||||
|
print(total_assigned_distribution - total_assigner_distribution)
|
||||||
|
|
||||||
instance.remaining_weight = total_assigned_distribution - total_assigner_distribution
|
instance.remaining_weight = total_assigned_distribution - total_assigner_distribution
|
||||||
instance.distributed = total_assigner_distribution
|
instance.distributed = total_assigner_distribution
|
||||||
instance._from_signal = True
|
instance._from_signal = True
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
from apps.product.web.api.v1.serializers import quota_distribution_serializers
|
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.web.api.v1.serializers import quota_serializers
|
||||||
|
from apps.product.services.search.quota_search import QuotaSearch
|
||||||
from apps.product.exceptions import QuotaExpiredTimeException
|
from apps.product.exceptions import QuotaExpiredTimeException
|
||||||
from apps.core.pagination import CustomPageNumberPagination
|
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 apps.product.web.api.v1.viewsets import product_api
|
||||||
from common.helpers import get_organization_by_user
|
from common.helpers import get_organization_by_user
|
||||||
from rest_framework.exceptions import APIException
|
from rest_framework.exceptions import APIException
|
||||||
@@ -39,6 +40,23 @@ class QuotaViewSet(viewsets.ModelViewSet): # noqa
|
|||||||
CustomPageNumberPagination.page_size = 5
|
CustomPageNumberPagination.page_size = 5
|
||||||
search_fields = ['']
|
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
|
@transaction.atomic
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
""" custom create quota """
|
""" custom create quota """
|
||||||
|
|||||||
Reference in New Issue
Block a user