From 7e0f4c3465e734dbe43d2aa70e0f5783b5df35d7 Mon Sep 17 00:00:00 2001 From: ruuushhh <66899387+ruuushhh@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:17:40 +0530 Subject: [PATCH] Fyle expense fields apis (#23) * Fyle expense fields apis * Test case resolved * Test case resolved * Test case resolved --- apps/fyle/constants.py | 22 +++++++++++++++++++++ apps/fyle/helpers.py | 29 ++++++++++++++++++++++++++++ apps/fyle/serializers.py | 18 ++++++++++++++++++ apps/fyle/urls.py | 3 ++- apps/fyle/views.py | 12 +++++++++++- tests/test_fyle/fixtures.py | 36 +++++++++++++++++++++++++++++++++++ tests/test_fyle/test_views.py | 22 +++++++++++++++++++++ 7 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 apps/fyle/constants.py diff --git a/apps/fyle/constants.py b/apps/fyle/constants.py new file mode 100644 index 0000000..2171b9a --- /dev/null +++ b/apps/fyle/constants.py @@ -0,0 +1,22 @@ +DEFAULT_FYLE_CONDITIONS = [ + { + 'field_name': 'employee_email', + 'type': 'SELECT', + 'is_custom': False + }, + { + 'field_name': 'claim_number', + 'type': 'TEXT', + 'is_custom': False + }, + { + 'field_name': 'report_title', + 'type': 'TEXT', + 'is_custom': False + }, + { + 'field_name': 'spent_at', + 'type': 'DATE', + 'is_custom': False + } +] diff --git a/apps/fyle/helpers.py b/apps/fyle/helpers.py index 6cfb45d..a65641d 100644 --- a/apps/fyle/helpers.py +++ b/apps/fyle/helpers.py @@ -2,6 +2,11 @@ import requests from django.conf import settings +from fyle_integrations_platform_connector import PlatformConnector + +from apps.workspaces.models import FyleCredential +from apps.fyle.constants import DEFAULT_FYLE_CONDITIONS + def post_request(url, body, refresh_token=None): """ @@ -50,3 +55,27 @@ def get_cluster_domain(refresh_token: str) -> str: cluster_api_url = '{0}/oauth/cluster/'.format(settings.FYLE_BASE_URL) return post_request(cluster_api_url, {}, refresh_token)['cluster_domain'] + + +def get_expense_fields(workspace_id: int): + """ + Get expense custom fields from fyle + :param workspace_id: (int) + :return: list of custom expense fields + """ + + fyle_credentails = FyleCredential.objects.get(workspace_id=workspace_id) + platform = PlatformConnector(fyle_credentails) + custom_fields = platform.expense_custom_fields.list_all() + + response = [] + response.extend(DEFAULT_FYLE_CONDITIONS) + for custom_field in custom_fields: + if custom_field['type'] in ('SELECT', 'NUMBER', 'TEXT', 'BOOLEAN'): + response.append({ + 'field_name': custom_field['field_name'], + 'type': custom_field['type'], + 'is_custom': custom_field['is_custom'] + }) + + return response diff --git a/apps/fyle/serializers.py b/apps/fyle/serializers.py index 4954118..5b39a2a 100644 --- a/apps/fyle/serializers.py +++ b/apps/fyle/serializers.py @@ -14,6 +14,7 @@ from apps.fyle.models import ExpenseFilter from apps.workspaces.models import Workspace, FyleCredential +from apps.fyle.helpers import get_expense_fields logger = logging.getLogger(__name__) logger.level = logging.INFO @@ -105,3 +106,20 @@ def format_fyle_fields(self, workspace_id): }) return attributes_list + + +class ExpenseFieldSerializer(serializers.Serializer): + """ + Workspace Admin Serializer + """ + expense_fields = serializers.SerializerMethodField() + + def get_expense_fields(self, validated_data): + """ + Get Expense Fields + """ + + workspace_id = self.context['request'].parser_context.get('kwargs').get('workspace_id') + expense_fields = get_expense_fields(workspace_id=workspace_id) + + return expense_fields diff --git a/apps/fyle/urls.py b/apps/fyle/urls.py index ff353b1..f913444 100644 --- a/apps/fyle/urls.py +++ b/apps/fyle/urls.py @@ -15,7 +15,7 @@ """ from django.urls import path -from apps.fyle.views import ExpenseFilterView, ExpenseFilterDeleteView, ImportFyleAttributesView, FyleFieldsView +from apps.fyle.views import ExpenseFilterView, ExpenseFilterDeleteView, ImportFyleAttributesView, FyleFieldsView, CustomFieldView urlpatterns = [ @@ -23,4 +23,5 @@ path('expense_filters/', ExpenseFilterView.as_view(), name='expense-filters'), path('import_attributes/', ImportFyleAttributesView.as_view(), name='import-fyle-attributes'), path('fields/', FyleFieldsView.as_view(), name='fyle-fields'), + path('expense_fields/', CustomFieldView.as_view(), name='fyle-expense-fields'), ] diff --git a/apps/fyle/views.py b/apps/fyle/views.py index c6cb33e..71d2e84 100644 --- a/apps/fyle/views.py +++ b/apps/fyle/views.py @@ -1,7 +1,8 @@ import logging from rest_framework import generics from ms_business_central_api.utils import LookupFieldMixin -from apps.fyle.serializers import ExpenseFilterSerializer, ImportFyleAttributesSerializer, FyleFieldsSerializer +from apps.workspaces.models import Workspace +from apps.fyle.serializers import ExpenseFilterSerializer, ImportFyleAttributesSerializer, FyleFieldsSerializer, ExpenseFieldSerializer from apps.fyle.models import ExpenseFilter logger = logging.getLogger(__name__) @@ -42,3 +43,12 @@ class FyleFieldsView(generics.ListAPIView): def get_queryset(self): return FyleFieldsSerializer().format_fyle_fields(self.kwargs["workspace_id"]) + + +class CustomFieldView(generics.ListAPIView): + """ + Custom Field view + """ + + serializer_class = ExpenseFieldSerializer + queryset = Workspace.objects.all() diff --git a/tests/test_fyle/fixtures.py b/tests/test_fyle/fixtures.py index 2c0b7e5..06c33d9 100644 --- a/tests/test_fyle/fixtures.py +++ b/tests/test_fyle/fixtures.py @@ -165,4 +165,40 @@ 'is_dependant': False } ], + "fyle_expense_custom_fields": [ + {"field_name": "employee_email", "type": "SELECT", "is_custom": False}, + {"field_name": "claim_number", "type": "TEXT", "is_custom": False}, + {"field_name": "report_title", "type": "TEXT", "is_custom": False}, + {"field_name": "spent_at", "type": "DATE", "is_custom": False}, + {"field_name": "Class", "type": "SELECT", "is_custom": True}, + {"field_name": "Fyle Categories", "type": "SELECT", "is_custom": True}, + {"field_name": "Operating System", "type": "SELECT", "is_custom": True}, + {"field_name": "User Dimension", "type": "SELECT", "is_custom": True}, + {"field_name": "Asdasdas", "type": "SELECT", "is_custom": True}, + {"field_name": "Nilesh Custom Field", "type": "SELECT", "is_custom": True}, + ], + "get_all_custom_fields": [ + { + "data": [ + { + "category_ids": [142151], + "code": None, + "column_name": "text_column6", + "created_at": "2021-10-22T07:50:04.613487+00:00", + "default_value": None, + "field_name": "Class", + "id": 197380, + "is_custom": True, + "is_enabled": True, + "is_mandatory": False, + "options": ["Servers", "Home", "Office"], + "org_id": "orGcBCVPijjO", + "placeholder": "Select Class", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-01-01T05:35:26.345303+00:00", + }, + ] + } + ], } diff --git a/tests/test_fyle/test_views.py b/tests/test_fyle/test_views.py index e5f3eef..62ff5f4 100644 --- a/tests/test_fyle/test_views.py +++ b/tests/test_fyle/test_views.py @@ -78,3 +78,25 @@ def test_fyle_fields(api_client, test_connection, create_temp_workspace, add_fyl response = json.loads(response.content) assert response['results'] == data['fyle_fields_response'] + + +def test_fyle_expense_fields(api_client, test_connection, create_temp_workspace, add_fyle_credentials, mocker): + workspace_id = 1 + + access_token = test_connection.access_token + url = reverse('fyle-expense-fields', kwargs={'workspace_id': workspace_id}) + + mocker.patch( + 'fyle.platform.apis.v1beta.admin.ExpenseFields.list_all', + return_value = data['get_all_custom_fields'], + ) + + api_client.credentials(HTTP_AUTHORIZATION="Bearer {}".format(access_token)) + + response = api_client.get(url) + assert response.status_code == 200 + response = json.loads(response.content) + + assert ( + dict_compare_keys(response['results'], data['fyle_expense_custom_fields']) == [] + ), 'expense group api return diffs in keys'