From 9b95ecabaecf6fc14ab1db3850d368a081d0c1b2 Mon Sep 17 00:00:00 2001 From: Ashutosh singh <55102089+Ashutosh619-sudo@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:48:45 +0530 Subject: [PATCH] Advance search API for Export Log page (#519) * Advance search API for Export Log page * comment resolved --- apps/fyle/helpers.py | 62 ++++++++++++++++++++++++++++++++++++++++++++ apps/fyle/urls.py | 4 ++- apps/fyle/views.py | 23 +++++++++++++++- 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/apps/fyle/helpers.py b/apps/fyle/helpers.py index b887a733..23002b21 100644 --- a/apps/fyle/helpers.py +++ b/apps/fyle/helpers.py @@ -16,6 +16,8 @@ from apps.workspaces.models import FyleCredential, Workspace, Configuration from typing import List, Union +import django_filters + logger = logging.getLogger(__name__) SOURCE_ACCOUNT_MAP = {'PERSONAL': 'PERSONAL_CASH_ACCOUNT', 'CCC': 'PERSONAL_CORPORATE_CREDIT_CARD_ACCOUNT'} @@ -383,3 +385,63 @@ def construct_expense_filter(expense_filter: ExpenseFilter): constructed_expense_filter = Q(**filter1) return constructed_expense_filter + + +class AdvanceSearchFilter(django_filters.FilterSet): + def filter_queryset(self, queryset): + or_filtered_queryset = queryset.none() + or_filter_fields = getattr(self.Meta, 'or_fields', []) + or_field_present = False + + for field_name in self.Meta.fields: + value = self.data.get(field_name) + if value: + if field_name == 'is_skipped': + value = True if str(value) == 'true' else False + filter_instance = self.filters[field_name] + queryset = filter_instance.filter(queryset, value) + + for field_name in or_filter_fields: + value = self.data.get(field_name) + if value: + or_field_present = True + filter_instance = self.filters[field_name] + field_filtered_queryset = filter_instance.filter(queryset, value) + or_filtered_queryset |= field_filtered_queryset + + if or_field_present: + queryset = queryset & or_filtered_queryset + return queryset + + return queryset + + +class ExpenseGroupSearchFilter(AdvanceSearchFilter): + exported_at__gte = django_filters.DateTimeFilter(lookup_expr='gte', field_name='exported_at') + exported_at__lte = django_filters.DateTimeFilter(lookup_expr='lte', field_name='exported_at') + tasklog__status = django_filters.CharFilter() + expenses__expense_number = django_filters.CharFilter(field_name='expenses__expense_number', lookup_expr='icontains') + expenses__employee_name = django_filters.CharFilter(field_name='expenses__employee_name', lookup_expr='icontains') + expenses__employee_email = django_filters.CharFilter(field_name='expenses__employee_email', lookup_expr='icontains') + expenses__claim_number = django_filters.CharFilter(field_name='expenses__claim_number', lookup_expr='icontains') + + class Meta: + model = ExpenseGroup + fields = ['exported_at__gte', 'exported_at__lte', 'tasklog__status'] + or_fields = ['expenses__expense_number', 'expenses__employee_name', 'expenses__employee_email', 'expenses__claim_number'] + + +class ExpenseSearchFilter(AdvanceSearchFilter): + org_id = django_filters.CharFilter() + is_skipped = django_filters.BooleanFilter() + updated_at__gte = django_filters.DateTimeFilter(lookup_expr='gte', field_name='updated_at') + updated_at__lte = django_filters.DateTimeFilter(lookup_expr='lte', field_name='updated_at') + expense_number = django_filters.CharFilter(field_name='expense_number', lookup_expr='icontains') + employee_name = django_filters.CharFilter(field_name='employee_name', lookup_expr='icontains') + employee_email = django_filters.CharFilter(field_name='employee_email', lookup_expr='icontains') + claim_number = django_filters.CharFilter(field_name='claim_number', lookup_expr='icontains') + + class Meta: + model = Expense + fields = ['org_id', 'is_skipped', 'updated_at__gte', 'updated_at__lte'] + or_fields = ['expense_number', 'employee_name', 'employee_email', 'claim_number'] diff --git a/apps/fyle/urls.py b/apps/fyle/urls.py index 322d8279..b6db6fd7 100644 --- a/apps/fyle/urls.py +++ b/apps/fyle/urls.py @@ -2,12 +2,13 @@ from django.urls import path -from .views import ExpenseGroupSyncView, ExpenseGroupView, ExpenseGroupByIdView, ExpenseGroupScheduleView, ExportableExpenseGroupsView, FyleFieldsView, ExpenseView,\ +from .views import ExpenseGroupSyncView, ExpenseGroupView, ExpenseGroupByIdView, ExpenseGroupScheduleView, ExpenseGroupViewV2, ExpenseViewV2, ExportableExpenseGroupsView, FyleFieldsView, ExpenseView,\ ExpenseAttributesView, ExpenseGroupSettingsView, SyncFyleDimensionView, RefreshFyleDimensionView,\ ExpenseGroupCountView, ExpenseFilterView, ExpenseGroupExpenseView, CustomFieldView, ExportView expense_groups_paths = [ path('expense_groups/', ExpenseGroupView.as_view(), name='expense-groups'), + path('expense_groups/v2/', ExpenseGroupViewV2.as_view(), name='expense-groups-v2'), path('expense_groups/count/', ExpenseGroupCountView.as_view(), name='expense-groups-count'), path('expense_groups/trigger/', ExpenseGroupScheduleView.as_view(), name='expense-groups-trigger'), path('expense_groups//', ExpenseGroupByIdView.as_view(), name='expense-group-by-id'), @@ -29,6 +30,7 @@ path('fields/', FyleFieldsView.as_view(), name='fyle-fields-v2'), path('expense_filters/', ExpenseFilterView.as_view(), name='expense-filters'), path('expenses/', ExpenseView.as_view(), name='expenses'), + path('expenses/v2/', ExpenseViewV2.as_view(), name='expenses-v2'), path('custom_fields/', CustomFieldView.as_view(), name='custom-field') ] diff --git a/apps/fyle/views.py b/apps/fyle/views.py index 1525f529..7f743f48 100644 --- a/apps/fyle/views.py +++ b/apps/fyle/views.py @@ -14,9 +14,10 @@ from fyle_accounting_mappings.serializers import ExpenseAttributeSerializer from apps.workspaces.models import Configuration, FyleCredential, Workspace +from fyle_netsuite_api.utils import LookupFieldMixin from .tasks import schedule_expense_group_creation, get_task_log_and_fund_source, create_expense_groups -from .helpers import check_interval_and_sync_dimension, sync_dimensions +from .helpers import ExpenseGroupSearchFilter, ExpenseSearchFilter, check_interval_and_sync_dimension, sync_dimensions from .models import Expense, ExpenseGroup, ExpenseGroupSettings, ExpenseFilter from .serializers import ExpenseGroupSerializer, ExpenseSerializer, ExpenseFieldSerializer, \ ExpenseGroupSettingsSerializer, ExpenseFilterSerializer, ExpenseGroupExpenseSerializer @@ -26,10 +27,30 @@ from fyle.platform import Platform from fyle_netsuite_api import settings +from django_filters.rest_framework import DjangoFilterBackend + logger = logging.getLogger(__name__) logger.level = logging.INFO +class ExpenseGroupViewV2(LookupFieldMixin, generics.ListCreateAPIView): + + queryset = ExpenseGroup.objects.all().order_by("-updated_at").distinct() + serializer_class = ExpenseGroupSerializer + filter_backends = (DjangoFilterBackend,) + filterset_class = ExpenseGroupSearchFilter + +class ExpenseViewV2(LookupFieldMixin, generics.ListAPIView): + """ + Expense view + """ + + queryset = Expense.objects.all().order_by("-updated_at").distinct() + serializer_class = ExpenseSerializer + filter_backends = (DjangoFilterBackend,) + filterset_class = ExpenseSearchFilter + + class ExpenseGroupView(generics.ListCreateAPIView): """ List Fyle Expenses