From b52999a0e6c088b783ae5230d90681a2cdf44783 Mon Sep 17 00:00:00 2001 From: Hrishabh Tiwari <74908943+Hrishabh17@users.noreply.github.com> Date: Mon, 29 Apr 2024 09:12:29 +0530 Subject: [PATCH] Fix common issues (#596) * Fixes related to common issues * Fixes related to common issues * Decrease cov to 95 from 96 * fix test case * Add missing test case, Increased test coverage --- apps/fyle/tasks.py | 30 +++++++++++++- apps/mappings/tasks.py | 19 ++++++--- apps/workspaces/tasks.py | 2 +- ...3-fix-last-sync-and-ccc-last-sync-null.sql | 23 +++++++++++ tests/test_fyle/test_tasks.py | 41 +++++++++++++++++-- tests/test_mappings/test_tasks.py | 14 ++++++- 6 files changed, 115 insertions(+), 14 deletions(-) create mode 100644 sql/scripts/023-fix-last-sync-and-ccc-last-sync-null.sql diff --git a/apps/fyle/tasks.py b/apps/fyle/tasks.py index 90dfb60f..c179a8dd 100644 --- a/apps/fyle/tasks.py +++ b/apps/fyle/tasks.py @@ -3,7 +3,11 @@ from typing import Dict, List from django.db import transaction -from fyle.platform.exceptions import RetryException +from fyle.platform.exceptions import ( + RetryException, + InternalServerError, + InvalidTokenError +) from fyle_accounting_mappings.models import ExpenseAttribute from fyle_integrations_platform_connector import PlatformConnector @@ -19,7 +23,7 @@ from apps.fyle.queue import async_post_accounting_export_summary from apps.tasks.models import TaskLog from apps.workspaces.actions import export_to_qbo -from apps.workspaces.models import FyleCredential, Workspace +from apps.workspaces.models import FyleCredential, Workspace, WorkspaceGeneralSettings logger = logging.getLogger(__name__) logger.level = logging.INFO @@ -155,6 +159,22 @@ def async_create_expense_groups(workspace_id: int, fund_source: List[str], task_ task_log.status = 'FATAL' task_log.save() + except InvalidTokenError: + logger.info('Invalid Token for Fyle') + task_log.detail = { + 'message': 'Invalid Token for Fyle' + } + task_log.status = 'FAILED' + task_log.save() + + except InternalServerError: + logger.info('Fyle Internal Server Error occured in workspace_id: %s', workspace_id) + task_log.detail = { + 'message': 'Fyle Internal Server Error occured' + } + task_log.status = 'FAILED' + task_log.save() + except Exception: handle_import_exception(task_log) @@ -262,5 +282,11 @@ def import_and_export_expenses(report_id: str, org_id: str) -> None: if len(expense_group_ids): export_to_qbo(workspace.id, None, expense_group_ids) + except WorkspaceGeneralSettings.DoesNotExist: + logger.info('Workspace general settings not found %s', workspace.id) + task_log.detail = {'message': 'Workspace general settings do not exist in workspace'} + task_log.status = 'FAILED' + task_log.save() + except Exception: handle_import_exception(task_log) diff --git a/apps/mappings/tasks.py b/apps/mappings/tasks.py index 61ad1436..5da2902a 100644 --- a/apps/mappings/tasks.py +++ b/apps/mappings/tasks.py @@ -3,6 +3,10 @@ from fyle_accounting_mappings.models import DestinationAttribute, EmployeeMapping, ExpenseAttribute from fyle_integrations_platform_connector import PlatformConnector +from fyle.platform.exceptions import ( + InvalidTokenError as FyleInvalidTokenError, + InternalServerError +) from apps.mappings.exceptions import handle_import_exceptions from apps.mappings.models import GeneralMapping @@ -253,9 +257,12 @@ def async_auto_map_ccc_account(workspace_id: int): default_ccc_account_id = general_mappings.default_ccc_account_id if default_ccc_account_id: - fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) - platform = PlatformConnector(fyle_credentials) - - platform.employees.sync() - - auto_map_ccc_employees(default_ccc_account_id, workspace_id) + try: + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + platform = PlatformConnector(fyle_credentials) + platform.employees.sync() + auto_map_ccc_employees(default_ccc_account_id, workspace_id) + except FyleInvalidTokenError: + logger.info('Invalid Token for fyle in workspace - %s', workspace_id) + except InternalServerError: + logger.info('Fyle Internal Server Error in workspace - %s', workspace_id) diff --git a/apps/workspaces/tasks.py b/apps/workspaces/tasks.py index 4857a33c..a982689b 100644 --- a/apps/workspaces/tasks.py +++ b/apps/workspaces/tasks.py @@ -195,7 +195,7 @@ def run_email_notification(workspace_id): def async_update_fyle_credentials(fyle_org_id: str, refresh_token: str): fyle_credentials = FyleCredential.objects.filter(workspace__fyle_org_id=fyle_org_id).first() - if fyle_credentials: + if fyle_credentials and refresh_token: fyle_credentials.refresh_token = refresh_token fyle_credentials.save() diff --git a/sql/scripts/023-fix-last-sync-and-ccc-last-sync-null.sql b/sql/scripts/023-fix-last-sync-and-ccc-last-sync-null.sql new file mode 100644 index 00000000..dff80d63 --- /dev/null +++ b/sql/scripts/023-fix-last-sync-and-ccc-last-sync-null.sql @@ -0,0 +1,23 @@ +rollback; +begin; + +update workspaces +set last_synced_at = ( + select max(case when e.fund_source = 'PERSONAL' then e.created_at end) + from expenses e + where + e.fund_source = 'PERSONAL' + and + e.workspace_id = workspaces.id + group by e.workspace_id +), +ccc_last_synced_at = ( + select max(case when e.fund_source = 'CCC' then e.created_at end) + from expenses e + where + e.fund_source = 'CCC' + and + e.workspace_id = workspaces.id + group by e.workspace_id +) +where workspaces.last_synced_at is null and workspaces.ccc_last_synced_at is null; \ No newline at end of file diff --git a/tests/test_fyle/test_tasks.py b/tests/test_fyle/test_tasks.py index 222ddee2..ed51effa 100644 --- a/tests/test_fyle/test_tasks.py +++ b/tests/test_fyle/test_tasks.py @@ -10,18 +10,20 @@ from apps.fyle.tasks import ( create_expense_groups, post_accounting_export_summary, - import_and_export_expenses + import_and_export_expenses, + sync_dimensions ) from apps.fyle.actions import mark_expenses_as_skipped from apps.tasks.models import TaskLog -from apps.workspaces.models import FyleCredential, Workspace +from apps.workspaces.models import FyleCredential, Workspace, WorkspaceGeneralSettings from tests.helper import dict_compare_keys from tests.test_fyle.fixtures import data +from fyle.platform.exceptions import InternalServerError, InvalidTokenError @pytest.mark.django_db() def test_create_expense_groups(mocker, db): - mocker.patch('fyle_integrations_platform_connector.apis.Expenses.get', return_value=data['expenses']) + mock_call = mocker.patch('fyle_integrations_platform_connector.apis.Expenses.get', return_value=data['expenses']) task_log, _ = TaskLog.objects.update_or_create(workspace_id=3, type='FETCHING_EXPENSES', defaults={'status': 'IN_PROGRESS'}) @@ -51,6 +53,14 @@ def test_create_expense_groups(mocker, db): task_log = TaskLog.objects.get(workspace_id=1) assert task_log.status == 'FATAL' + mock_call.side_effect = InternalServerError('Error') + create_expense_groups(1, ['PERSONAL', 'CCC'], task_log) + + mock_call.side_effect = InvalidTokenError('Invalid Token') + create_expense_groups(1, ['PERSONAL', 'CCC'], task_log) + + mock_call.call_count = 2 + @pytest.mark.django_db() def test_create_expense_group_skipped_flow(mocker, api_client, test_connection): @@ -113,5 +123,28 @@ def test_post_accounting_export_summary(db, mocker): assert Expense.objects.filter(id=expense_id).first().accounting_export_summary['synced'] == True -def test_import_and_export_expenses(db): +def test_import_and_export_expenses(db, mocker): + import_and_export_expenses('rp1s1L3QtMpF', 'or79Cob97KSh') + + mock_call = mocker.patch('apps.fyle.helpers.get_fund_source') + mock_call.side_effect = WorkspaceGeneralSettings.DoesNotExist('Error') import_and_export_expenses('rp1s1L3QtMpF', 'or79Cob97KSh') + + assert mock_call.call_count == 0 + + +def test_sync_dimension(db, mocker): + mock_platform_connector = mocker.patch('apps.fyle.tasks.PlatformConnector') + + mock_platform_instance = mock_platform_connector.return_value + mocker.patch.object(mock_platform_instance.categories, 'sync', return_value=None) + mock_platform_instance.categories.get_count.return_value = 5 + mock_platform_instance.projects.get_count.return_value = 10 + + fyle_creds = FyleCredential.objects.filter(workspace_id = 1).first() + + sync_dimensions(fyle_credentials=fyle_creds, is_export=True) + + mock_platform_instance.import_fyle_dimensions.assert_called_once_with(is_export=True) + mock_platform_instance.categories.sync.assert_called_once() + mock_platform_instance.projects.sync.assert_called_once() diff --git a/tests/test_mappings/test_tasks.py b/tests/test_mappings/test_tasks.py index bf4b00ee..938e9f52 100644 --- a/tests/test_mappings/test_tasks.py +++ b/tests/test_mappings/test_tasks.py @@ -16,6 +16,10 @@ ) from apps.tasks.models import Error from apps.workspaces.models import QBOCredential, WorkspaceGeneralSettings +from fyle.platform.exceptions import ( + InvalidTokenError as FyleInvalidTokenError, + InternalServerError +) def test_auto_map_employees(db): @@ -81,13 +85,21 @@ def test_auto_map_ccc_employees(db): def test_async_auto_map_ccc_account(mocker, db): - mocker.patch('fyle_integrations_platform_connector.apis.Employees.sync', return_value=[]) + mock_call = mocker.patch('fyle_integrations_platform_connector.apis.Employees.sync', return_value=[]) workspace_id = 3 async_auto_map_ccc_account(workspace_id) employee_mappings = EmployeeMapping.objects.filter(workspace_id=workspace_id).count() assert employee_mappings == 17 + mock_call.side_effect = FyleInvalidTokenError('Invalid Token') + async_auto_map_ccc_account(workspace_id) + + mock_call.side_effect = InternalServerError('Internal Server Error') + async_auto_map_ccc_account(workspace_id) + + assert mock_call.call_count == 3 + def test_schedule_auto_map_ccc_employees(db): workspace_id = 3