From 390a1320514e636725719f3e6fb9218c4e67ee19 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 13:48:46 +0530 Subject: [PATCH 01/22] api changes --- apps/sage300/serializers.py | 13 ++++++++++++- apps/sage300/urls.py | 3 ++- apps/sage300/views.py | 27 +++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/apps/sage300/serializers.py b/apps/sage300/serializers.py index 2e49badd..7f58a8e4 100644 --- a/apps/sage300/serializers.py +++ b/apps/sage300/serializers.py @@ -4,6 +4,8 @@ from rest_framework.response import Response from rest_framework.views import status +from fyle_accounting_mappings.models import DestinationAttribute + from apps.workspaces.models import Workspace, Sage300Credential from apps.sage300.helpers import sync_dimensions, check_interval_and_sync_dimension @@ -51,4 +53,13 @@ def create(self, validated_data): # Handle unexpected exceptions and log the error logger.error('Something unexpected happened workspace_id: %s %s', workspace_id, exception) # Raise a custom exception or re-raise the original exception - raise Exception() + raise + + +class Sage300FieldSerializer(serializers.ModelSerializer): + """ + Expense Fields Serializer + """ + class Meta: + model = DestinationAttribute + fields = ['attribute_type', 'display_name'] diff --git a/apps/sage300/urls.py b/apps/sage300/urls.py index 919e6227..0350cd42 100644 --- a/apps/sage300/urls.py +++ b/apps/sage300/urls.py @@ -1,9 +1,10 @@ from django.urls import path -from apps.sage300.views import ImportSage300AttributesView +from apps.sage300.views import ImportSage300AttributesView, Sage300FieldsView urlpatterns = [ path('import_attributes/', ImportSage300AttributesView.as_view(), name='import-sage300-attributes'), + path('fields/', Sage300FieldsView.as_view(), name='sage300-fields') ] diff --git a/apps/sage300/views.py b/apps/sage300/views.py index d3b6cc45..69457024 100644 --- a/apps/sage300/views.py +++ b/apps/sage300/views.py @@ -1,10 +1,14 @@ -from datetime import datetime +from django.db.models import Q import logging from rest_framework import generics +from fyle_accounting_mappings.models import DestinationAttribute + +from apps.sage300.serializers import Sage300FieldSerializer from apps.sage300.serializers import ImportSage300AttributesSerializer + logger = logging.getLogger(__name__) logger.level = logging.INFO @@ -13,5 +17,24 @@ class ImportSage300AttributesView(generics.CreateAPIView): """ Import Sage300 Attributes View """ - serializer_class = ImportSage300AttributesSerializer + + +class Sage300FieldsView(generics.ListAPIView): + pagination_class = None + serializer_class = Sage300FieldSerializer + + + def get_queryset(self): + attribute_types = ['VENDOR', 'ACCOUNT', 'JOB', 'CATEGORY', 'COST_CODE', 'PAYMENT'] + attributes = DestinationAttribute.objects.filter( + ~Q(attribute_type__in=attribute_types), + workspace_id=self.kwargs['workspace_id'] + ).values('attribute_type', 'display_name').distinct() + + serialized_attributes = Sage300FieldSerializer(attributes, many=True).data + + # Adding job by default since we can support importing projects from Sage300 even though they don't exist + serialized_attributes.append({'attribute_type': 'JOB', 'display_name': 'Job'}) + + return serialized_attributes From d3e6f050219b94c42a0d4cae7827b8ceaf823af0 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 14:02:54 +0530 Subject: [PATCH 02/22] fix tests --- apps/sage300/serializers.py | 29 ++++++++++++++++++--------- apps/sage300/urls.py | 9 ++++++--- apps/sage300/views.py | 25 ++++++++++++++++------- tests/test_sage300/test_views.py | 34 +++++++++++++++++++++----------- 4 files changed, 66 insertions(+), 31 deletions(-) diff --git a/apps/sage300/serializers.py b/apps/sage300/serializers.py index 7f58a8e4..bd9e158f 100644 --- a/apps/sage300/serializers.py +++ b/apps/sage300/serializers.py @@ -4,7 +4,7 @@ from rest_framework.response import Response from rest_framework.views import status -from fyle_accounting_mappings.models import DestinationAttribute +from fyle_accounting_mappings.models import DestinationAttribute from apps.workspaces.models import Workspace, Sage300Credential from apps.sage300.helpers import sync_dimensions, check_interval_and_sync_dimension @@ -22,14 +22,18 @@ class ImportSage300AttributesSerializer(serializers.Serializer): def create(self, validated_data): try: # Get the workspace ID from the URL kwargs - workspace_id = self.context['request'].parser_context['kwargs']['workspace_id'] - + workspace_id = self.context["request"].parser_context["kwargs"][ + "workspace_id" + ] + # Check if the 'refresh' field is provided in the request data - refresh_dimension = self.context['request'].data.get('refresh', False) + refresh_dimension = self.context["request"].data.get("refresh", False) # Retrieve the workspace and Sage 300 credentials workspace = Workspace.objects.get(pk=workspace_id) - sage_intacct_credentials = Sage300Credential.objects.get(workspace_id=workspace.id) + sage_intacct_credentials = Sage300Credential.objects.get( + workspace_id=workspace.id + ) if refresh_dimension: # If 'refresh' is true, perform a full sync of dimensions @@ -40,18 +44,24 @@ def create(self, validated_data): # Update the destination_synced_at field and save the workspace workspace.destination_synced_at = datetime.now() - workspace.save(update_fields=['destination_synced_at']) + workspace.save(update_fields=["destination_synced_at"]) # Return a success response return Response(status=status.HTTP_200_OK) except Sage300Credential.DoesNotExist: # Handle the case when Sage 300 credentials are not found or invalid - raise serializers.ValidationError({'message': 'Sage300 credentials not found / invalid in workspace'}) + raise serializers.ValidationError( + {"message": "Sage300 credentials not found / invalid in workspace"} + ) except Exception as exception: # Handle unexpected exceptions and log the error - logger.error('Something unexpected happened workspace_id: %s %s', workspace_id, exception) + logger.error( + "Something unexpected happened workspace_id: %s %s", + workspace_id, + exception, + ) # Raise a custom exception or re-raise the original exception raise @@ -60,6 +70,7 @@ class Sage300FieldSerializer(serializers.ModelSerializer): """ Expense Fields Serializer """ + class Meta: model = DestinationAttribute - fields = ['attribute_type', 'display_name'] + fields = ["attribute_type", "display_name"] diff --git a/apps/sage300/urls.py b/apps/sage300/urls.py index 0350cd42..d5d8a954 100644 --- a/apps/sage300/urls.py +++ b/apps/sage300/urls.py @@ -1,10 +1,13 @@ - from django.urls import path from apps.sage300.views import ImportSage300AttributesView, Sage300FieldsView urlpatterns = [ - path('import_attributes/', ImportSage300AttributesView.as_view(), name='import-sage300-attributes'), - path('fields/', Sage300FieldsView.as_view(), name='sage300-fields') + path( + "import_attributes/", + ImportSage300AttributesView.as_view(), + name="import-sage300-attributes", + ), + path("fields/", Sage300FieldsView.as_view(), name="sage300-fields"), ] diff --git a/apps/sage300/views.py b/apps/sage300/views.py index 69457024..d795163e 100644 --- a/apps/sage300/views.py +++ b/apps/sage300/views.py @@ -17,6 +17,7 @@ class ImportSage300AttributesView(generics.CreateAPIView): """ Import Sage300 Attributes View """ + serializer_class = ImportSage300AttributesSerializer @@ -24,17 +25,27 @@ class Sage300FieldsView(generics.ListAPIView): pagination_class = None serializer_class = Sage300FieldSerializer - def get_queryset(self): - attribute_types = ['VENDOR', 'ACCOUNT', 'JOB', 'CATEGORY', 'COST_CODE', 'PAYMENT'] - attributes = DestinationAttribute.objects.filter( - ~Q(attribute_type__in=attribute_types), - workspace_id=self.kwargs['workspace_id'] - ).values('attribute_type', 'display_name').distinct() + attribute_types = [ + "VENDOR", + "ACCOUNT", + "JOB", + "CATEGORY", + "COST_CODE", + "PAYMENT", + ] + attributes = ( + DestinationAttribute.objects.filter( + ~Q(attribute_type__in=attribute_types), + workspace_id=self.kwargs["workspace_id"], + ) + .values("attribute_type", "display_name") + .distinct() + ) serialized_attributes = Sage300FieldSerializer(attributes, many=True).data # Adding job by default since we can support importing projects from Sage300 even though they don't exist - serialized_attributes.append({'attribute_type': 'JOB', 'display_name': 'Job'}) + serialized_attributes.append({"attribute_type": "JOB", "display_name": "Job"}) return serialized_attributes diff --git a/tests/test_sage300/test_views.py b/tests/test_sage300/test_views.py index 81ff6e0c..1354e4d9 100644 --- a/tests/test_sage300/test_views.py +++ b/tests/test_sage300/test_views.py @@ -3,22 +3,18 @@ from apps.workspaces.models import Sage300Credential -def test_sync_dimensions(api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds): + +def test_sync_dimensions( + api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds +): workspace_id = 1 access_token = test_connection.access_token - url = reverse( - 'import-sage300-attributes', kwargs={ - 'workspace_id': workspace_id - } - ) + url = reverse("import-sage300-attributes", kwargs={"workspace_id": workspace_id}) - api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(access_token)) + api_client.credentials(HTTP_AUTHORIZATION="Bearer {}".format(access_token)) - mocker.patch( - 'apps.sage300.helpers.sync_dimensions', - return_value=None - ) + mocker.patch("apps.sage300.helpers.sync_dimensions", return_value=None) response = api_client.post(url) assert response.status_code == 201 @@ -30,4 +26,18 @@ def test_sync_dimensions(api_client, test_connection, mocker, create_temp_worksp assert response.status_code == 400 response = json.loads(response.content) - assert response['message'] == 'Sage300 credentials not found / invalid in workspace' + assert response["message"] == "Sage300 credentials not found / invalid in workspace" + + +def test_sage300_fields(api_client, test_connection): + workspace_id = 1 + + access_token = test_connection.access_token + url = reverse("sage300-fields", kwargs={"workspace_id": workspace_id}) + + api_client.credentials(HTTP_AUTHORIZATION="Bearer {}".format(access_token)) + + response = api_client.get(url) + assert response.status_code == 200 + + assert response.data == [{"attribute_type": "JOB", "display_name": "Job"}] From 80c8a2d08f6ccb9a83dc2a81a0bca61d4a3007fd Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 14:37:00 +0530 Subject: [PATCH 03/22] add support for github workflow for pytest --- .github/workflows/tests.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..96dd5d6e --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,30 @@ +name: Continuous Integration + +on: + pull_request: + types: [assigned, opened, synchronize, reopened] + +jobs: + pytest: + runs-on: ubuntu-latest + environment: CI Environment + steps: + - uses: actions/checkout@v2 + - name: Bring up Services and Run Tests + run: | + docker-compose -f docker-compose-pipeline.yml build + docker-compose -f docker-compose-pipeline.yml up -d + docker-compose -f docker-compose-pipeline.yml exec -T api pytest tests/ + echo "STATUS=$(cat pytest-coverage.txt | grep 'Required test' | awk '{ print $1 }')" >> $GITHUB_ENV + echo "FAILED=$(cat test-reports/report.xml | awk -F'=' '{print $5}' | awk -F' ' '{gsub(/"/, "", $1); print $1}')" >> $GITHUB_ENV + - name: Upload coverage reports to Codecov with GitHub Action + uses: codecov/codecov-action@v3 + - name: Pytest coverage comment + uses: MishaKav/pytest-coverage-comment@main + if: ${{ always() && github.ref != 'refs/heads/master' }} + with: + create-new-comment: true + junitxml-path: ./test-reports/report.xml + - name: Evaluate Coverage + if: ${{ (env.STATUS == 'FAIL') || (env.FAILED > 0) }} + run: exit 1 From 17fdaed27b00e3ea5cfaccb7a367f7e82a25f977 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 17:20:23 +0530 Subject: [PATCH 04/22] fix tsts --- apps/sage300/helpers.py | 1 - apps/sage300/serializers.py | 2 +- apps/sage300/utils.py | 10 +-- apps/sage300/views.py | 1 - apps/workspaces/models.py | 2 +- apps/workspaces/serializers.py | 5 +- apps/workspaces/urls.py | 2 +- apps/workspaces/views.py | 1 - tests/conftest.py | 2 +- tests/test_sage300/test_views.py | 1 + tests/test_workspaces/test_views.py | 106 ++++++++++------------------ 11 files changed, 47 insertions(+), 86 deletions(-) diff --git a/apps/sage300/helpers.py b/apps/sage300/helpers.py index 4b0e85b4..952190a4 100644 --- a/apps/sage300/helpers.py +++ b/apps/sage300/helpers.py @@ -5,7 +5,6 @@ from django.utils.module_loading import import_string from apps.workspaces.models import Workspace, Sage300Credential -from apps.sage300.utils import SageDesktopConnector logger = logging.getLogger(__name__) diff --git a/apps/sage300/serializers.py b/apps/sage300/serializers.py index 2e49badd..678ba976 100644 --- a/apps/sage300/serializers.py +++ b/apps/sage300/serializers.py @@ -21,7 +21,7 @@ def create(self, validated_data): try: # Get the workspace ID from the URL kwargs workspace_id = self.context['request'].parser_context['kwargs']['workspace_id'] - + # Check if the 'refresh' field is provided in the request data refresh_dimension = self.context['request'].data.get('refresh', False) diff --git a/apps/sage300/utils.py b/apps/sage300/utils.py index b309f858..1a72254e 100644 --- a/apps/sage300/utils.py +++ b/apps/sage300/utils.py @@ -1,8 +1,8 @@ -from django.conf import settings from fyle_accounting_mappings.models import DestinationAttribute from apps.workspaces.models import Sage300Credential from sage_desktop_sdk.sage_desktop_sdk import SageDesktopSDK + class SageDesktopConnector: """ Sage300 utility functions for syncing data from Sage Desktop SDK to your application @@ -25,7 +25,6 @@ def __init__(self, credentials_object: Sage300Credential, workspace_id: int): self.workspace_id = workspace_id - def _create_destination_attribute(self, attribute_type, display_name, value, destination_id, active, detail): """ Create a destination attribute object @@ -46,7 +45,6 @@ def _create_destination_attribute(self, attribute_type, display_name, value, des 'detail': detail } - def _sync_data(self, data, attribute_type, display_name, workspace_id, field_names): """ Synchronize data from Sage Desktop SDK to your application @@ -73,7 +71,6 @@ def _sync_data(self, data, attribute_type, display_name, workspace_id, field_nam DestinationAttribute.bulk_create_or_update_destination_attributes( destination_attributes, attribute_type, workspace_id, True) - def sync_accounts(self): """ Synchronize accounts from Sage Desktop SDK to your application @@ -82,7 +79,6 @@ def sync_accounts(self): self._sync_data(accounts, 'ACCOUNT', 'accounts', self.workspace_id, ['code', 'version']) return [] - def sync_vendors(self): """ Synchronize vendors from Sage Desktop SDK to your application @@ -95,7 +91,6 @@ def sync_vendors(self): self._sync_data(vendors, 'VENDOR', 'vendor', self.workspace_id, field_names) return [] - def sync_jobs(self): """ Synchronize jobs from Sage Desktop SDK to your application @@ -107,7 +102,6 @@ def sync_jobs(self): self._sync_data(jobs, 'JOB', 'job', self.workspace_id, field_names) return [] - def sync_cost_codes(self): """ Synchronize cost codes from Sage Desktop SDK to your application @@ -117,7 +111,6 @@ def sync_cost_codes(self): self._sync_data(cost_codes, 'COST_CODE', 'cost_code', self.workspace_id, field_names) return [] - def sync_categories(self): """ Synchronize categories from Sage Desktop SDK to your application @@ -127,7 +120,6 @@ def sync_categories(self): self._sync_data(categories, 'CATEGORY', 'category', self.workspace_id, field_names) return [] - def sync_commitments(self): """ Synchronize commitments from Sage Desktop SDK to your application diff --git a/apps/sage300/views.py b/apps/sage300/views.py index d3b6cc45..353c6f8c 100644 --- a/apps/sage300/views.py +++ b/apps/sage300/views.py @@ -1,4 +1,3 @@ -from datetime import datetime import logging from rest_framework import generics diff --git a/apps/workspaces/models.py b/apps/workspaces/models.py index 913ed11a..0793baf6 100644 --- a/apps/workspaces/models.py +++ b/apps/workspaces/models.py @@ -180,7 +180,7 @@ class ImportSetting(BaseModel): import_categories = BooleanFalseField(help_text='toggle for import of chart of accounts from sage300') import_vendors_as_merchants = BooleanFalseField(help_text='toggle for import of vendors as merchant from sage300') - + class Meta: db_table = 'import_settings' diff --git a/apps/workspaces/serializers.py b/apps/workspaces/serializers.py index 712a8df9..22a82c5b 100644 --- a/apps/workspaces/serializers.py +++ b/apps/workspaces/serializers.py @@ -7,7 +7,6 @@ from fyle_rest_auth.helpers import get_fyle_admin from fyle_rest_auth.models import AuthToken -from apps.fyle.helpers import get_cluster_domain from sage_desktop_api.utils import assert_valid from sage_desktop_sdk.sage_desktop_sdk import SageDesktopSDK from sage_desktop_sdk.exceptions import ( @@ -81,7 +80,7 @@ def create(self, validated_data): class Sage300CredentialSerializer(serializers.ModelSerializer): - + api_key = serializers.CharField(required=False) api_secret = serializers.CharField(required=False) @@ -89,7 +88,6 @@ class Meta: model = Sage300Credential fields = '__all__' - def create(self, validated_data): try: username = validated_data.get('username') @@ -166,6 +164,7 @@ class Meta: model = ImportSetting fields = '__all__' read_only_fields = ('id', 'workspace', 'created_at', 'updated_at') + def create(self, validated_data): """ Create Export Settings diff --git a/apps/workspaces/urls.py b/apps/workspaces/urls.py index 480477ab..502c5ee6 100644 --- a/apps/workspaces/urls.py +++ b/apps/workspaces/urls.py @@ -34,7 +34,7 @@ ] other_app_paths = [ - path('/sage_300/', include('apps.sage300.urls')), + path('/sage_300/', include('apps.sage300.urls')), ] urlpatterns = [] diff --git a/apps/workspaces/views.py b/apps/workspaces/views.py index 110e1456..4c3c43a8 100644 --- a/apps/workspaces/views.py +++ b/apps/workspaces/views.py @@ -3,7 +3,6 @@ from rest_framework import generics from rest_framework.views import Response, status -from rest_framework.permissions import IsAuthenticated from fyle_rest_auth.utils import AuthUtils diff --git a/tests/conftest.py b/tests/conftest.py index 97246ea9..8c9ba75b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,7 +12,7 @@ from apps.fyle.helpers import get_access_token from apps.workspaces.models import ( - Workspace, + Workspace, FyleCredential, Sage300Credential ) diff --git a/tests/test_sage300/test_views.py b/tests/test_sage300/test_views.py index 81ff6e0c..9927de67 100644 --- a/tests/test_sage300/test_views.py +++ b/tests/test_sage300/test_views.py @@ -3,6 +3,7 @@ from apps.workspaces.models import Sage300Credential + def test_sync_dimensions(api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds): workspace_id = 1 diff --git a/tests/test_workspaces/test_views.py b/tests/test_workspaces/test_views.py index c227354a..ed7403e2 100644 --- a/tests/test_workspaces/test_views.py +++ b/tests/test_workspaces/test_views.py @@ -1,23 +1,13 @@ import json -import pytest # noqa from django.urls import reverse - -from apps.workspaces.models import ( - Workspace, - Sage300Credential, - ExportSetting, - ImportSetting, - AdvancedSetting -) +from apps.workspaces.models import Workspace, Sage300Credential, ExportSetting, ImportSetting, AdvancedSetting def test_post_of_workspace(api_client, test_connection): ''' Test post of workspace ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.post(url) @@ -38,9 +28,7 @@ def test_get_of_workspace(api_client, test_connection): ''' Test get of workspace ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.get(url) @@ -66,26 +54,23 @@ def test_post_of_sage300_creds(api_client, test_connection, mocker): Test post of sage300 creds ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.post(url) url = reverse( - 'sage300-creds', kwargs={ - 'workspace_id': response.data['id'] - } + 'sage300-creds', + kwargs={'workspace_id': response.data['id']} ) - payload = { + payload = { 'identifier': "indentifier", - 'password': "passeord", + 'password': "passeord", 'username': "username", 'workspace': response.data['id'] } - + mocker.patch( 'sage_desktop_sdk.core.client.Client.update_cookie', return_value={'text': {'Result': 2}} @@ -100,28 +85,24 @@ def test_get_of_sage300_creds(api_client, test_connection): Test get of workspace ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.post(url) url = reverse( - 'sage300-creds', kwargs={ - 'workspace_id': response.data['id'] - } + 'sage300-creds', + kwargs={'workspace_id': response.data['id']} ) Sage300Credential.objects.create( - identifier='identifier', - username='username', - password='password', - workspace_id=response.data['id'], - api_key='apiley', - api_secret='apisecret' - ) - + identifier='identifier', + username='username', + password='password', + workspace_id=response.data['id'], + api_key='apiley', + api_secret='apisecret' + ) api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.get(url) @@ -135,9 +116,7 @@ def test_export_settings(api_client, test_connection): ''' Test export settings ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.post(url) @@ -145,9 +124,8 @@ def test_export_settings(api_client, test_connection): workspace_id = response.data['id'] url = reverse( - 'export-settings', kwargs={ - 'workspace_id': workspace_id - } + 'export-settings', + kwargs={'workspace_id': workspace_id} ) api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) @@ -160,7 +138,7 @@ def test_export_settings(api_client, test_connection): 'reimbursable_expense_date': 'LAST_SPENT_AT', 'reimbursable_expense_grouped_by': 'EXPENSE', 'credit_card_expense_export_type': 'JOURNAL_ENTRY', - 'credit_card_expense_state': 'PAID', + 'credit_card_expense_state': 'PAID', 'credit_card_expense_grouped_by': 'EXPENSE', 'credit_card_expense_date': 'CREATED_AT', 'default_credit_card_account_name': 'credit card account', @@ -210,16 +188,13 @@ def test_import_settings(api_client, test_connection): ''' Test export settings ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.post(url) workspace_id = response.data['id'] url = reverse( - 'import-settings', kwargs={ - 'workspace_id': workspace_id - } + 'import-settings', + kwargs={'workspace_id': workspace_id} ) payload = { @@ -229,22 +204,20 @@ def test_import_settings(api_client, test_connection): response = api_client.post(url, payload) import_settings = ImportSetting.objects.filter(workspace_id=workspace_id).first() assert response.status_code == 201 - assert import_settings.import_categories == True - assert import_settings.import_vendors_as_merchants == True + assert import_settings.import_categories is True + assert import_settings.import_vendors_as_merchants is True response = api_client.get(url) assert response.status_code == 200 - assert import_settings.import_categories == True - assert import_settings.import_vendors_as_merchants == True + assert import_settings.import_categories is True + assert import_settings.import_vendors_as_merchants is True def test_advanced_settings(api_client, test_connection): ''' Test advanced settings ''' - url = reverse( - 'workspaces' - ) + url = reverse('workspaces') api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) response = api_client.post(url) @@ -252,9 +225,8 @@ def test_advanced_settings(api_client, test_connection): workspace_id = response.data['id'] url = reverse( - 'advanced-settings', kwargs={ - 'workspace_id': workspace_id - } + 'advanced-settings', + kwargs={'workspace_id': workspace_id} ) api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token)) @@ -291,8 +263,8 @@ def test_advanced_settings(api_client, test_connection): 'report_number', 'expense_link' ] - assert response.data['schedule_is_enabled'] == False - assert response.data['schedule_id'] == None + assert response.data['schedule_is_enabled'] is False + assert response.data['schedule_id'] is None assert response.data['emails_selected'] == [ { 'name': 'Shwetabh Kumar', @@ -314,8 +286,8 @@ def test_advanced_settings(api_client, test_connection): 'report_number', 'expense_link' ] - assert response.data['schedule_is_enabled'] == False - assert response.data['schedule_id'] == None + assert response.data['schedule_is_enabled'] is False + assert response.data['schedule_id'] is None assert response.data['emails_selected'] == [ { 'name': 'Shwetabh Kumar', @@ -340,8 +312,8 @@ def test_advanced_settings(api_client, test_connection): 'purpose', 'report_number' ] - assert response.data['schedule_is_enabled'] == False - assert response.data['schedule_id'] == None + assert response.data['schedule_is_enabled'] is False + assert response.data['schedule_id'] is None assert response.data['emails_selected'] == [ { 'name': 'Shwetabh Kumar', From 3c39af4418acee055b32d9aae4209810f79b5e58 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 17:21:36 +0530 Subject: [PATCH 05/22] fix tsts --- sage_desktop_api/models/fields.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sage_desktop_api/models/fields.py b/sage_desktop_api/models/fields.py index f0b449ad..e6cfd7c6 100644 --- a/sage_desktop_api/models/fields.py +++ b/sage_desktop_api/models/fields.py @@ -1,5 +1,6 @@ from django.db import models + class StringNotNullField(models.CharField): description = "Custom String with Not Null" @@ -9,6 +10,7 @@ def __init__(self, *args, **kwargs): kwargs['help_text'] = kwargs.get('help_text', 'string field with null false') super(StringNotNullField, self).__init__(*args, **kwargs) + class StringNullField(models.CharField): description = "Custom String with Null" @@ -18,6 +20,7 @@ def __init__(self, *args, **kwargs): kwargs['help_text'] = kwargs.get('help_text', 'string field with null True') super(StringNullField, self).__init__(*args, **kwargs) + class IntegerNullField(models.IntegerField): description = "Custom Integer with Null" @@ -26,6 +29,7 @@ def __init__(self, *args, **kwargs): kwargs['help_text'] = kwargs.get('help_text', 'Integer field with null True') super(IntegerNullField, self).__init__(*args, **kwargs) + class IntegerNotNullField(models.IntegerField): description = "Custom Integer with Not Null" @@ -34,6 +38,7 @@ def __init__(self, *args, **kwargs): kwargs['help_text'] = kwargs.get('help_text', 'Integer field with null false') super(IntegerNotNullField, self).__init__(*args, **kwargs) + class CustomJsonField(models.JSONField): description = "Custom Json Field with Null" @@ -43,6 +48,7 @@ def __init__(self, *args, **kwargs): kwargs['help_text'] = kwargs.get('help_text', 'Json field with null true') super(CustomJsonField, self).__init__(*args, **kwargs) + class CustomDateTimeField(models.DateTimeField): description = "Custom DateTime Field with Auto-Add Now" @@ -50,6 +56,7 @@ def __init__(self, *args, **kwargs): kwargs['null'] = True # Allow the field to be nullable super(CustomDateTimeField, self).__init__(*args, **kwargs) + class TextNotNullField(models.TextField): description = "Custom Text Field with Not Null" @@ -58,6 +65,7 @@ def __init__(self, *args, **kwargs): kwargs['help_text'] = kwargs.get('help_text', 'text field with null false') super(TextNotNullField, self).__init__(*args, **kwargs) + class StringOptionsField(models.CharField): description = "Custom String Field with Options" @@ -69,6 +77,7 @@ def __init__(self, *args, **kwargs): kwargs['null'] = True # Allow the field to be nullable super(StringOptionsField, self).__init__(max_length=max_length, choices=choices, default=default, **kwargs) + class BooleanFalseField(models.BooleanField): description = "Custom Boolean Field with Default True" @@ -81,6 +90,7 @@ def toggle(self, instance): setattr(instance, self.attname, not value) instance.save() + class BooleanTrueField(models.BooleanField): description = "Custom Boolean Field with Default True" From 3b337771a5ea5e4c9084c333e093c5960d4abc2d Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 17:51:22 +0530 Subject: [PATCH 06/22] fix test --- tests/test_sage300/test_views.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/test_sage300/test_views.py b/tests/test_sage300/test_views.py index 04ee8a45..05d2fc6d 100644 --- a/tests/test_sage300/test_views.py +++ b/tests/test_sage300/test_views.py @@ -4,21 +4,15 @@ from apps.workspaces.models import Sage300Credential -<<<<<<< HEAD -def test_sync_dimensions( - api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds -): -======= def test_sync_dimensions(api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds): ->>>>>>> 3c39af4418acee055b32d9aae4209810f79b5e58 workspace_id = 1 access_token = test_connection.access_token - url = reverse("import-sage300-attributes", kwargs={"workspace_id": workspace_id}) + url = reverse('import-sage300-attributes', kwargs={'workspace_id': workspace_id}) - api_client.credentials(HTTP_AUTHORIZATION="Bearer {}".format(access_token)) + api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(access_token)) - mocker.patch("apps.sage300.helpers.sync_dimensions", return_value=None) + mocker.patch('apps.sage300.helpers.sync_dimensions', return_value=None) response = api_client.post(url) assert response.status_code == 201 @@ -30,18 +24,18 @@ def test_sync_dimensions(api_client, test_connection, mocker, create_temp_worksp assert response.status_code == 400 response = json.loads(response.content) - assert response["message"] == "Sage300 credentials not found / invalid in workspace" + assert response['message'] == 'Sage300 credentials not found / invalid in workspace' def test_sage300_fields(api_client, test_connection): workspace_id = 1 access_token = test_connection.access_token - url = reverse("sage300-fields", kwargs={"workspace_id": workspace_id}) + url = reverse('sage300-fields', kwargs={'workspace_id': workspace_id}) - api_client.credentials(HTTP_AUTHORIZATION="Bearer {}".format(access_token)) + api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(access_token)) response = api_client.get(url) assert response.status_code == 200 - assert response.data == [{"attribute_type": "JOB", "display_name": "Job"}] + assert response.data == [{'attribute_type': 'JOB', 'display_name': 'Job'}] From 434f8de5b87b3f2b78bf2806693e3f1208b6c33d Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 17:54:12 +0530 Subject: [PATCH 07/22] er --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 96dd5d6e..52d31384 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: run: | docker-compose -f docker-compose-pipeline.yml build docker-compose -f docker-compose-pipeline.yml up -d - docker-compose -f docker-compose-pipeline.yml exec -T api pytest tests/ + docker-compose -f docker-compose-pipeline.yml exec -T api pytest tests/ --cov='.' echo "STATUS=$(cat pytest-coverage.txt | grep 'Required test' | awk '{ print $1 }')" >> $GITHUB_ENV echo "FAILED=$(cat test-reports/report.xml | awk -F'=' '{print $5}' | awk -F' ' '{gsub(/"/, "", $1); print $1}')" >> $GITHUB_ENV - name: Upload coverage reports to Codecov with GitHub Action From 0509baf327aa6dd8195bf4c2bf943350395aa823 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 17:58:37 +0530 Subject: [PATCH 08/22] minor change --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 52d31384..e7d2c1b6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: run: | docker-compose -f docker-compose-pipeline.yml build docker-compose -f docker-compose-pipeline.yml up -d - docker-compose -f docker-compose-pipeline.yml exec -T api pytest tests/ --cov='.' + docker-compose -f docker-compose-pipeline.yml exec -T api pytest tests/ --cov --junit-xml=test-reports/report.xml --cov-report=xml --cov-fail-under=70 echo "STATUS=$(cat pytest-coverage.txt | grep 'Required test' | awk '{ print $1 }')" >> $GITHUB_ENV echo "FAILED=$(cat test-reports/report.xml | awk -F'=' '{print $5}' | awk -F' ' '{gsub(/"/, "", $1); print $1}')" >> $GITHUB_ENV - name: Upload coverage reports to Codecov with GitHub Action From 31d42d78fa7d8e9a6b4158fb6d5216b4957553aa Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:02:12 +0530 Subject: [PATCH 09/22] minor fix --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index af3c5034..8c0792ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ gevent==23.9.1 gunicorn==20.1.0 # Platform SDK -fyle==0.30.0 +fyle==0.34.0 # Reusable Fyle Packages fyle-rest-auth==1.4.0 From 377e2a0a72df8f38dba7533ba12625c98851b0c0 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:02:41 +0530 Subject: [PATCH 10/22] asdg --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index af3c5034..8c0792ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ gevent==23.9.1 gunicorn==20.1.0 # Platform SDK -fyle==0.30.0 +fyle==0.34.0 # Reusable Fyle Packages fyle-rest-auth==1.4.0 From 4cfd159541381adfa9386573242227d773804395 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:12:02 +0530 Subject: [PATCH 11/22] fix --- sage_desktop_api/settings.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sage_desktop_api/settings.py b/sage_desktop_api/settings.py index 77232cdb..bd2974a3 100644 --- a/sage_desktop_api/settings.py +++ b/sage_desktop_api/settings.py @@ -173,9 +173,6 @@ DATABASE_ROUTERS = ['sage_desktop_api.cache_router.CacheRouter'] -# Password validation -# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators - AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', @@ -203,12 +200,10 @@ FYLE_APP_URL = os.environ.get('APP_URL') FYLE_EXPENSE_URL = os.environ.get('FYLE_APP_URL') - # Sage300 Settings SD_API_KEY = os.environ.get('SD_API_KEY') SD_API_SECRET = os.environ.get('SD_API_SECRET') - # Internationalization # https://docs.djangoproject.com/en/3.1/topics/i18n/ @@ -222,7 +217,6 @@ USE_TZ = True - # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ From 7d614d0004b4709568d47997a01f3a7d6f5304f6 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:15:14 +0530 Subject: [PATCH 12/22] ad --- sage_desktop_api/tests/settings.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sage_desktop_api/tests/settings.py b/sage_desktop_api/tests/settings.py index d1a16b6e..e66e841d 100644 --- a/sage_desktop_api/tests/settings.py +++ b/sage_desktop_api/tests/settings.py @@ -155,12 +155,6 @@ } } -# DATABASE_ROUTERS = ['sage_desktop_api.cache_router.CacheRouter'] - - -# Password validation -# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators - AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', @@ -176,7 +170,6 @@ }, ] - # Fyle Settings API_URL = os.environ.get('API_URL') FYLE_TOKEN_URI = os.environ.get('FYLE_TOKEN_URI') @@ -205,7 +198,6 @@ USE_TZ = True - # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ From da70cab183d12310bb85e75bc1ed6c8e4bb274f3 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:19:30 +0530 Subject: [PATCH 13/22] minor dix --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 24ba3c01..86c20b00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ COPY . /fyle-sage-desktop-api/ WORKDIR /fyle-sage-desktop-api # Do linting checks -RUN flake8 . +# RUN flake8 . # Expose development port EXPOSE 8000 From bbf69ae5904088a24cb3ad1bf95cfe442d15adf0 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:29:12 +0530 Subject: [PATCH 14/22] asd --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 86c20b00..24ba3c01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ COPY . /fyle-sage-desktop-api/ WORKDIR /fyle-sage-desktop-api # Do linting checks -# RUN flake8 . +RUN flake8 . # Expose development port EXPOSE 8000 From 65286c56a308548a5ac9582e98078dfc9fcb3dcb Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Mon, 23 Oct 2023 18:32:12 +0530 Subject: [PATCH 15/22] asd --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 24ba3c01..86c20b00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ COPY . /fyle-sage-desktop-api/ WORKDIR /fyle-sage-desktop-api # Do linting checks -RUN flake8 . +# RUN flake8 . # Expose development port EXPOSE 8000 From f82c8536d9421ac99c66a99a57967db9c28c742e Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 10:55:10 +0530 Subject: [PATCH 16/22] add support --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ab5f4333..6ede4da4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ COPY . /fyle-sage-desktop-api/ WORKDIR /fyle-sage-desktop-api # Do linting checks -# RUN flake8 . +RUN flake8 . # Expose development port EXPOSE 8000 From 05db708f023879a7546e6bd93ad04e2b6e138c86 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 11:01:59 +0530 Subject: [PATCH 17/22] lint fix --- sage_desktop_api/settings.py | 2 -- sage_desktop_api/tests/settings.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/sage_desktop_api/settings.py b/sage_desktop_api/settings.py index e5c96f6e..1e12e8a1 100644 --- a/sage_desktop_api/settings.py +++ b/sage_desktop_api/settings.py @@ -176,8 +176,6 @@ } } - - CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', diff --git a/sage_desktop_api/tests/settings.py b/sage_desktop_api/tests/settings.py index d24f0082..2f274aa3 100644 --- a/sage_desktop_api/tests/settings.py +++ b/sage_desktop_api/tests/settings.py @@ -179,11 +179,9 @@ FYLE_APP_URL = os.environ.get('APP_URL') FYLE_EXPENSE_URL = os.environ.get('FYLE_APP_URL') - SD_API_KEY = os.environ.get('SD_API_KEY') SD_API_SECRET = os.environ.get('SD_API_SECRET') - # Internationalization # https://docs.djangoproject.com/en/3.1/topics/i18n/ From eadad7de400a2232c29a3f3bc260b278fc5aedf5 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 11:14:35 +0530 Subject: [PATCH 18/22] asd --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fe0ab1a8..9e8f7d7d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ gevent==23.9.1 gunicorn==20.1.0 # Platform SDK -fyle==0.34.0 +fyle==0.32.0 # Reusable Fyle Packages fyle-rest-auth==1.4.0 From 4e46df11e516e8483e9bb6c0c408f5304d32a44e Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 11:19:10 +0530 Subject: [PATCH 19/22] ad ; ; --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9e8f7d7d..fe0ab1a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ gevent==23.9.1 gunicorn==20.1.0 # Platform SDK -fyle==0.32.0 +fyle==0.34.0 # Reusable Fyle Packages fyle-rest-auth==1.4.0 From 5a162ab4edaaa98585e9adecda287d3dada48fce Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 13:21:00 +0530 Subject: [PATCH 20/22] minor change --- apps/sage300/serializers.py | 29 +++++++++++++++++++++++++++++ apps/sage300/views.py | 27 +-------------------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/apps/sage300/serializers.py b/apps/sage300/serializers.py index 2b649048..38c4d519 100644 --- a/apps/sage300/serializers.py +++ b/apps/sage300/serializers.py @@ -1,4 +1,5 @@ import logging +from django.db.models import Q from datetime import datetime from rest_framework import serializers from rest_framework.response import Response @@ -68,6 +69,34 @@ class Sage300FieldSerializer(serializers.ModelSerializer): """ Expense Fields Serializer """ + attribute_type = serializers.CharField() + display_name = serializers.CharField() + + def format_sage300_fields(self, workspace_id): + attribute_types = [ + "VENDOR", + "ACCOUNT", + "JOB", + "CATEGORY", + "COST_CODE", + "PAYMENT", + ] + attributes = ( + DestinationAttribute.objects.filter( + ~Q(attribute_type__in=attribute_types), + workspace_id=workspace_id, + ) + .values("attribute_type", "display_name") + .distinct() + ) + + serialized_attributes = Sage300FieldSerializer(attributes, many=True).data + + # Adding "Job" by default since it can be supported even if it doesn't exist + attributes_list = list(serialized_attributes) + attributes_list.append({"attribute_type": "JOB", "display_name": "Job"}) + + return attributes_list class Meta: model = DestinationAttribute diff --git a/apps/sage300/views.py b/apps/sage300/views.py index d795163e..c99309b7 100644 --- a/apps/sage300/views.py +++ b/apps/sage300/views.py @@ -1,10 +1,7 @@ -from django.db.models import Q import logging from rest_framework import generics -from fyle_accounting_mappings.models import DestinationAttribute - from apps.sage300.serializers import Sage300FieldSerializer from apps.sage300.serializers import ImportSage300AttributesSerializer @@ -26,26 +23,4 @@ class Sage300FieldsView(generics.ListAPIView): serializer_class = Sage300FieldSerializer def get_queryset(self): - attribute_types = [ - "VENDOR", - "ACCOUNT", - "JOB", - "CATEGORY", - "COST_CODE", - "PAYMENT", - ] - attributes = ( - DestinationAttribute.objects.filter( - ~Q(attribute_type__in=attribute_types), - workspace_id=self.kwargs["workspace_id"], - ) - .values("attribute_type", "display_name") - .distinct() - ) - - serialized_attributes = Sage300FieldSerializer(attributes, many=True).data - - # Adding job by default since we can support importing projects from Sage300 even though they don't exist - serialized_attributes.append({"attribute_type": "JOB", "display_name": "Job"}) - - return serialized_attributes + return Sage300FieldSerializer().format_sage300_fields(self.kwargs["workspace_id"]) From cd5ef2adb2687e87f6daa2583c62c0df3de96bac Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 14:01:43 +0530 Subject: [PATCH 21/22] minor support --- apps/sage300/serializers.py | 14 ++++++++------ apps/sage300/views.py | 7 +++++-- tests/test_sage300/test_views.py | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/sage300/serializers.py b/apps/sage300/serializers.py index 38c4d519..6a29aadf 100644 --- a/apps/sage300/serializers.py +++ b/apps/sage300/serializers.py @@ -65,10 +65,16 @@ def create(self, validated_data): raise -class Sage300FieldSerializer(serializers.ModelSerializer): +class DestinationAttributeSerializer(serializers.Serializer): + attribute_type = serializers.CharField() + display_name = serializers.CharField() + + +class Sage300FieldSerializer(serializers.Serializer): """ - Expense Fields Serializer + Sage300 Expense Fields Serializer """ + attribute_type = serializers.CharField() display_name = serializers.CharField() @@ -97,7 +103,3 @@ def format_sage300_fields(self, workspace_id): attributes_list.append({"attribute_type": "JOB", "display_name": "Job"}) return attributes_list - - class Meta: - model = DestinationAttribute - fields = ['attribute_type', 'display_name'] diff --git a/apps/sage300/views.py b/apps/sage300/views.py index c99309b7..3064c93e 100644 --- a/apps/sage300/views.py +++ b/apps/sage300/views.py @@ -2,6 +2,8 @@ from rest_framework import generics +from fyle_accounting_mappings.models import DestinationAttribute + from apps.sage300.serializers import Sage300FieldSerializer from apps.sage300.serializers import ImportSage300AttributesSerializer @@ -14,12 +16,13 @@ class ImportSage300AttributesView(generics.CreateAPIView): """ Import Sage300 Attributes View """ - serializer_class = ImportSage300AttributesSerializer class Sage300FieldsView(generics.ListAPIView): - pagination_class = None + """ + Sage300 Expense Fields View + """ serializer_class = Sage300FieldSerializer def get_queryset(self): diff --git a/tests/test_sage300/test_views.py b/tests/test_sage300/test_views.py index 05d2fc6d..d97208dc 100644 --- a/tests/test_sage300/test_views.py +++ b/tests/test_sage300/test_views.py @@ -38,4 +38,4 @@ def test_sage300_fields(api_client, test_connection): response = api_client.get(url) assert response.status_code == 200 - assert response.data == [{'attribute_type': 'JOB', 'display_name': 'Job'}] + assert response.data['results'] == [{'attribute_type': 'JOB', 'display_name': 'Job'}] From 8e1b9de6f11985fe9de7d7450267976eb7e20f71 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Wed, 25 Oct 2023 14:06:35 +0530 Subject: [PATCH 22/22] minor support --- apps/sage300/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/sage300/views.py b/apps/sage300/views.py index 3064c93e..e9dd506a 100644 --- a/apps/sage300/views.py +++ b/apps/sage300/views.py @@ -2,8 +2,6 @@ from rest_framework import generics -from fyle_accounting_mappings.models import DestinationAttribute - from apps.sage300.serializers import Sage300FieldSerializer from apps.sage300.serializers import ImportSage300AttributesSerializer