From 02b896c46974563b5cc15caf2935358cd2cf48b5 Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sat, 2 Aug 2025 14:40:56 +0330 Subject: [PATCH 1/9] add filter to excels --- apps/product/services/excel/excel_processing.py | 6 +++++- apps/warehouse/services/excel/excel_processing.py | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index 1dcd4ad..084c231 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -186,11 +186,12 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): today = datetime.now().date() user_relations = product_models.UserRelations.objects.filter(user=request.user).first() + incentive_plans = user_relations.incentive_plans.filter( Q(is_time_unlimited=False) | Q(start_date_limit__lte=today, end_date_limit__gte=today) ) - + user_relations = self.filter_query(incentive_plans) ser_data = IncentivePlanSerializer(incentive_plans, many=True).data excel_options = [ @@ -268,6 +269,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): ) def detail_quota_excel(self, request): queryset = product_models.Quota.objects.filter(id=request.GET['id'], trash=False) + queryset = self.filter_query(queryset) serializer_class = QuotaSerializer filter_backends = [filters.SearchFilter] search_fields = [ @@ -526,6 +528,8 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): ) def quota_excel(self, request): queryset = product_models.Quota.objects.all() + queryset = self.filter_query(queryset) + serializer_class = QuotaSerializer filter_backends = [filters.SearchFilter] search_fields = [ diff --git a/apps/warehouse/services/excel/excel_processing.py b/apps/warehouse/services/excel/excel_processing.py index 23e6631..e085def 100644 --- a/apps/warehouse/services/excel/excel_processing.py +++ b/apps/warehouse/services/excel/excel_processing.py @@ -6,6 +6,7 @@ from openpyxl.styles import Font from rest_framework import viewsets from rest_framework.decorators import action +from apps.core.mixins.search_mixin import DynamicSearchMixin from apps.warehouse import models as warehouse_models from apps.warehouse.web.api.v1 import serializers as warehouse_serializers from common.helper_excel import create_header, excel_description, create_header_freez, create_value, shamsi_date, \ @@ -13,7 +14,7 @@ from common.helper_excel import create_header, excel_description, create_header_ from common.helpers import get_organization_by_user -class WareHouseExcelViewSet(viewsets.ModelViewSet): +class WareHouseExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = warehouse_models.InventoryEntry.objects.all() serializer_class = warehouse_serializers.InventoryEntrySerializer @@ -31,8 +32,9 @@ class WareHouseExcelViewSet(viewsets.ModelViewSet): worksheet = workbook.active worksheet.sheet_view.rightToLeft = True worksheet.insert_rows(1) + queryset = self.filter_query(self.queryset) - entries = self.queryset.filter(organization=get_organization_by_user(request.user)) + entries = queryset.filter(organization=get_organization_by_user(request.user)) ser_data = self.serializer_class(entries, many=True).data excel_options = [ From fcdb1cdee92d303ff123b8ed5fea5e4ddbf61063 Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sat, 2 Aug 2025 14:44:06 +0330 Subject: [PATCH 2/9] mege --- apps/authorization/services/excel/excel_processing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/authorization/services/excel/excel_processing.py b/apps/authorization/services/excel/excel_processing.py index 5eb92de..ab42af2 100644 --- a/apps/authorization/services/excel/excel_processing.py +++ b/apps/authorization/services/excel/excel_processing.py @@ -7,10 +7,11 @@ from rest_framework.decorators import action from apps.authorization.api.v1.serializers import UserRelationSerializer from apps.authorization.models import UserRelations +from apps.core.mixins.search_mixin import DynamicSearchMixin from common.helper_excel import excel_description, create_header_freez, create_value -class AuthExcelViewSet(viewsets.ModelViewSet): +class AuthExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = UserRelations.objects.all() serializer_class = UserRelationSerializer From a1485e83b8d586f98fc2864d98a48c642c22eb7a Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sat, 2 Aug 2025 15:10:14 +0330 Subject: [PATCH 3/9] mege --- apps/product/services/excel/excel_processing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index 084c231..4719426 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -552,7 +552,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): organization = get_organization_by_user(request.user) - if active: + if active == 'true': queryset = queryset.filter( Q(registerer_organization=organization), Q(is_closed=False) From 0351d408e8675a3b9d694fde3a527337831c7a6f Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sat, 2 Aug 2025 15:56:40 +0330 Subject: [PATCH 4/9] mege --- .../services/excel/excel_processing.py | 38 +++++++++---------- .../services/excel/excel_processing.py | 9 +++++ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index 4719426..4e5c6c7 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -21,6 +21,22 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = product_models.QuotaDistribution.objects.all() serializer_class = distribution_serializers.QuotaDistributionSerializer filter_backends = [filters.SearchFilter] + search_fields = [ + "assigner_organization__name", + "assigned_organization__name", + "distribution_id", + "quota__quota_id", + "quota__product__name", + "quota__sale_type", + "quota__group", + "registerer_organization__name", + "quota_id", + "product__name", + "sale_type", + "sale_unit__unit", + "group" + + ] # noqa # سهمیه و توزیع @action( @@ -191,7 +207,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): Q(is_time_unlimited=False) | Q(start_date_limit__lte=today, end_date_limit__gte=today) ) - user_relations = self.filter_query(incentive_plans) + incentive_plans = self.filter_query(incentive_plans) ser_data = IncentivePlanSerializer(incentive_plans, many=True).data excel_options = [ @@ -271,15 +287,6 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = product_models.Quota.objects.filter(id=request.GET['id'], trash=False) queryset = self.filter_query(queryset) serializer_class = QuotaSerializer - filter_backends = [filters.SearchFilter] - search_fields = [ - "registerer_organization__name", - "quota_id", - "product__name", - "sale_type", - "sale_unit__unit", - "group", - ] output = BytesIO() workbook = Workbook() @@ -529,18 +536,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): def quota_excel(self, request): queryset = product_models.Quota.objects.all() queryset = self.filter_query(queryset) - serializer_class = QuotaSerializer - filter_backends = [filters.SearchFilter] - search_fields = [ - "registerer_organization__name", - "quota_id", - "product__name", - "sale_type", - "sale_unit__unit", - "group", - ] - output = BytesIO() workbook = Workbook() worksheet = workbook.active diff --git a/apps/warehouse/services/excel/excel_processing.py b/apps/warehouse/services/excel/excel_processing.py index e085def..de80204 100644 --- a/apps/warehouse/services/excel/excel_processing.py +++ b/apps/warehouse/services/excel/excel_processing.py @@ -17,6 +17,15 @@ from common.helpers import get_organization_by_user class WareHouseExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = warehouse_models.InventoryEntry.objects.all() serializer_class = warehouse_serializers.InventoryEntrySerializer + search_fields = [ + "distribution__distribution_id", + "organization__name", + "weight", + "balance", + "lading_number", + "is_confirmed", + ] + date_field = "create_date" # noqa # ورودی به انبار @action( From fe234e9db0407332cd72e8aa471e56888293fe79 Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sat, 2 Aug 2025 15:57:04 +0330 Subject: [PATCH 5/9] add search ro excel --- apps/product/services/excel/excel_processing.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index 4e5c6c7..b60ef0c 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -35,7 +35,6 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): "sale_type", "sale_unit__unit", "group" - ] # noqa # سهمیه و توزیع From 06738b7546d528ea565440a084e03bf9dc638ddd Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sat, 2 Aug 2025 16:00:31 +0330 Subject: [PATCH 6/9] add search ro excel --- .../services/excel/excel_processing.py | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index b60ef0c..4c0dd27 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -22,19 +22,12 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): serializer_class = distribution_serializers.QuotaDistributionSerializer filter_backends = [filters.SearchFilter] search_fields = [ - "assigner_organization__name", - "assigned_organization__name", - "distribution_id", - "quota__quota_id", - "quota__product__name", - "quota__sale_type", - "quota__group", "registerer_organization__name", "quota_id", "product__name", "sale_type", "sale_unit__unit", - "group" + "group", ] # noqa # سهمیه و توزیع @@ -286,6 +279,15 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = product_models.Quota.objects.filter(id=request.GET['id'], trash=False) queryset = self.filter_query(queryset) serializer_class = QuotaSerializer + filter_backends = [filters.SearchFilter] + search_fields = [ + "registerer_organization__name", + "quota_id", + "product__name", + "sale_type", + "sale_unit__unit", + "group", + ] output = BytesIO() workbook = Workbook() @@ -533,9 +535,21 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): name='quota_excel' ) def quota_excel(self, request): + search_fields = [ + "registerer_organization__name", + "quota_id", + "product__name", + "sale_type", + "sale_unit__unit", + "group", + ] queryset = product_models.Quota.objects.all() queryset = self.filter_query(queryset) + serializer_class = QuotaSerializer + filter_backends = [filters.SearchFilter] + + output = BytesIO() workbook = Workbook() worksheet = workbook.active From 8474097ec72e004b7e8c9ebd9ce459725e75a1ab Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sun, 3 Aug 2025 07:47:09 +0330 Subject: [PATCH 7/9] update search for excel --- apps/core/mixins/search_mixin.py | 31 +++++++++++++++++++ .../services/excel/excel_processing.py | 22 ++++++------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/apps/core/mixins/search_mixin.py b/apps/core/mixins/search_mixin.py index 57dcb12..d26c5cb 100644 --- a/apps/core/mixins/search_mixin.py +++ b/apps/core/mixins/search_mixin.py @@ -28,3 +28,34 @@ class DynamicSearchMixin: end=end, date_field=date_field ).apply() + + +class ExcelDynamicSearchMixin: + """ search query sets with introduced fields in view set """ + + def get_search_fields(self): + return getattr(self, "search_fields", []) + + def get_date_field(self): + return getattr(self, "date_field", "create_date") + + def filter_query(self, queryset, search_list=None): + queryset = queryset # noqa + + q = self.request.query_params.get("search") # noqa + start = self.request.query_params.get("start") # noqa + end = self.request.query_params.get("end") # noqa + if search_list: + search_fields = search_list + else: + search_fields = self.get_search_fields() + date_field = self.get_date_field() + + return DynamicSearchService( + queryset=queryset, + query_string=q, + search_fields=search_fields, + start=start, + end=end, + date_field=date_field + ).apply() \ No newline at end of file diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index 4c0dd27..a7f16f7 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -7,7 +7,7 @@ from openpyxl import Workbook from rest_framework import viewsets, filters from rest_framework.decorators import action -from apps.core.mixins.search_mixin import DynamicSearchMixin +from apps.core.mixins.search_mixin import ExcelDynamicSearchMixin from apps.product import models as product_models from apps.product.web.api.v1.serializers import quota_distribution_serializers as distribution_serializers from apps.product.web.api.v1.serializers.product_serializers import IncentivePlanSerializer @@ -17,7 +17,7 @@ from common.helper_excel import create_header, excel_description, create_header_ from common.helpers import get_organization_by_user -class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): +class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): queryset = product_models.QuotaDistribution.objects.all() serializer_class = distribution_serializers.QuotaDistributionSerializer filter_backends = [filters.SearchFilter] @@ -191,6 +191,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): worksheet = workbook.active worksheet.sheet_view.rightToLeft = True worksheet.insert_rows(1) + search_fields_incentive_plans = ['plan_type', 'name'] today = datetime.now().date() user_relations = product_models.UserRelations.objects.filter(user=request.user).first() @@ -199,7 +200,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): Q(is_time_unlimited=False) | Q(start_date_limit__lte=today, end_date_limit__gte=today) ) - incentive_plans = self.filter_query(incentive_plans) + incentive_plans = self.filter_query(incentive_plans, search_list=search_fields_incentive_plans) ser_data = IncentivePlanSerializer(incentive_plans, many=True).data excel_options = [ @@ -279,8 +280,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): queryset = product_models.Quota.objects.filter(id=request.GET['id'], trash=False) queryset = self.filter_query(queryset) serializer_class = QuotaSerializer - filter_backends = [filters.SearchFilter] - search_fields = [ + search_fields_detail_quota = [ "registerer_organization__name", "quota_id", "product__name", @@ -296,7 +296,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): worksheet.insert_rows(1) active = request.GET.get('active') - queryset = self.filter_query(queryset) # return by search param or all objects + queryset = self.filter_query(queryset, search_list=search_fields_detail_quota) # return by search param or all objects organization = get_organization_by_user(request.user) queryset = queryset.filter( @@ -535,7 +535,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): name='quota_excel' ) def quota_excel(self, request): - search_fields = [ + search_fields_quota = [ "registerer_organization__name", "quota_id", "product__name", @@ -543,13 +543,9 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): "sale_unit__unit", "group", ] + queryset = product_models.Quota.objects.all() - queryset = self.filter_query(queryset) - serializer_class = QuotaSerializer - filter_backends = [filters.SearchFilter] - - output = BytesIO() workbook = Workbook() worksheet = workbook.active @@ -557,7 +553,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): worksheet.insert_rows(1) active = request.GET.get('active') - queryset = self.filter_query(queryset) # return by search param or all objects + queryset = self.filter_query(queryset, search_list=search_fields_quota) # return by search param or all objects organization = get_organization_by_user(request.user) From 38a9755b2e898cff47748eedee40f0918eb29f33 Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sun, 3 Aug 2025 08:14:46 +0330 Subject: [PATCH 8/9] update search for excel --- apps/warehouse/services/excel/excel_processing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/warehouse/services/excel/excel_processing.py b/apps/warehouse/services/excel/excel_processing.py index de80204..48f2e85 100644 --- a/apps/warehouse/services/excel/excel_processing.py +++ b/apps/warehouse/services/excel/excel_processing.py @@ -6,7 +6,7 @@ from openpyxl.styles import Font from rest_framework import viewsets from rest_framework.decorators import action -from apps.core.mixins.search_mixin import DynamicSearchMixin +from apps.core.mixins.search_mixin import ExcelDynamicSearchMixin from apps.warehouse import models as warehouse_models from apps.warehouse.web.api.v1 import serializers as warehouse_serializers from common.helper_excel import create_header, excel_description, create_header_freez, create_value, shamsi_date, \ @@ -14,7 +14,7 @@ from common.helper_excel import create_header, excel_description, create_header_ from common.helpers import get_organization_by_user -class WareHouseExcelViewSet(viewsets.ModelViewSet, DynamicSearchMixin): +class WareHouseExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): queryset = warehouse_models.InventoryEntry.objects.all() serializer_class = warehouse_serializers.InventoryEntrySerializer search_fields = [ From 6ebe67bd52be97202c86e6d40ad22d221381b09f Mon Sep 17 00:00:00 2001 From: 7nimor Date: Sun, 3 Aug 2025 08:37:48 +0330 Subject: [PATCH 9/9] update search for excel --- apps/product/services/excel/excel_processing.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/product/services/excel/excel_processing.py b/apps/product/services/excel/excel_processing.py index a7f16f7..4c71d14 100644 --- a/apps/product/services/excel/excel_processing.py +++ b/apps/product/services/excel/excel_processing.py @@ -278,7 +278,6 @@ class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): ) def detail_quota_excel(self, request): queryset = product_models.Quota.objects.filter(id=request.GET['id'], trash=False) - queryset = self.filter_query(queryset) serializer_class = QuotaSerializer search_fields_detail_quota = [ "registerer_organization__name", @@ -288,6 +287,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): "sale_unit__unit", "group", ] + queryset = self.filter_query(queryset, search_list=search_fields_detail_quota) output = BytesIO() workbook = Workbook() @@ -296,7 +296,6 @@ class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): worksheet.insert_rows(1) active = request.GET.get('active') - queryset = self.filter_query(queryset, search_list=search_fields_detail_quota) # return by search param or all objects organization = get_organization_by_user(request.user) queryset = queryset.filter( @@ -553,7 +552,6 @@ class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): worksheet.insert_rows(1) active = request.GET.get('active') - queryset = self.filter_query(queryset, search_list=search_fields_quota) # return by search param or all objects organization = get_organization_by_user(request.user) @@ -571,6 +569,7 @@ class ProductExcelViewSet(viewsets.ModelViewSet, ExcelDynamicSearchMixin): ).order_by('-modify_date') quta_type = 'بایگانی' + queryset = self.filter_query(queryset, search_list=search_fields_quota) # return by search param or all objects ser_data = serializer_class(queryset, many=True).data excel_options = [