Skip to content

Commit

Permalink
add test cases (#212)
Browse files Browse the repository at this point in the history
* Job, Dep Field code-prepending support

* auto map feature

* fix comments - add util func, handle code in VENDOR_TYPE

* fix existing test cases

* Add check for syncing jobs, deps and add test cases

* update func name

* added unit tests

* fix failing test

* add project import related test cases

* fix lint

* remove redundant db calls

* add support for code prepending in CATEGORY

* add support for code prepending in MERCHANT

* change the callback methods are sent

* bug fix

* add support for code prepending in COST_CENTER

* rename helper func, fix is_job_sync_allowed method

* rename the helper method

* rename the helper method

* rename the helper method

* fix callback method mapping of vendor

* rename the helper method

* add support for code prepending in CUSTOM attribute

* improve test case

* add test cases

* method refactor
  • Loading branch information
Hrishabh17 authored Jul 24, 2024
1 parent 4c99385 commit 253cb2b
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 23 deletions.
29 changes: 20 additions & 9 deletions apps/sage300/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,7 @@ def _sync_data(self, data_gen, attribute_type, display_name, workspace_id, field
:param workspace_id: ID of the workspace
:param field_names: Names of fields to include in detail
"""
source_type = None
mapping_setting = MappingSetting.objects.filter(workspace_id=workspace_id, destination_field=attribute_type).first()
if mapping_setting:
if attribute_type == 'VENDOR':
source_type = 'MERCHANT'
elif mapping_setting.is_custom:
source_type = 'CUSTOM'
else:
source_type = mapping_setting.source_field
source_type = self.get_source_type(attribute_type, workspace_id)

if is_generator:
for data in data_gen:
Expand Down Expand Up @@ -307,3 +299,22 @@ def sync_cost_categories(self, import_log = None):
CostCategory.bulk_create_or_update(categories, self.workspace_id)
version.cost_category = latest_version
version.save()

def get_source_type(self, attribute_type, workspace_id):
"""
Get the source type to fetch the disable callback function
:return: Source type
"""
source_type = None
mapping_setting = MappingSetting.objects.filter(workspace_id=workspace_id, destination_field=attribute_type).first()
if mapping_setting:
if attribute_type == 'VENDOR':
source_type = 'MERCHANT'
elif mapping_setting.is_custom:
source_type = 'CUSTOM'
else:
source_type = mapping_setting.source_field
elif attribute_type == 'ACCOUNT':
source_type = 'CATEGORY'

return source_type
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fyle==0.37.0

# Reusable Fyle Packages
fyle-rest-auth==1.7.2
fyle-accounting-mappings==1.34.0
fyle-accounting-mappings==1.34.1
fyle-integrations-platform-connector==1.39.0


Expand Down
41 changes: 41 additions & 0 deletions tests/test_mappings/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -5718,4 +5718,45 @@
]
}
],
"paginated_destination_attributes_view_response_1": {
"count": 0,
"next": None,
"previous": None,
"results": []
},
"paginated_destination_attributes_view_response_2": {
"count": 2,
"next": None,
"previous": None,
"results": [
{
"id": 3,
"attribute_type": "JOB",
"display_name": "CRE Platform",
"value": "CRE Platform",
"destination_id": "10065",
"auto_created": False,
"active": True,
"detail": "Sage 300 Project - CRE Platform, Id - 10065",
"code": "123",
"created_at": "2024-07-22T16:10:19.130448Z",
"updated_at": "2024-07-22T16:10:19.130456Z",
"workspace": 1
},
{
"id": 4,
"attribute_type": "JOB",
"display_name": "Integrations CRE",
"value": "Integrations CRE",
"destination_id": "10082",
"auto_created": False,
"active": True,
"detail": "Sage 300 Project - Integrations CRE, Id - 10082",
"code": "123",
"created_at": "2024-07-22T16:10:19.130823Z",
"updated_at": "2024-07-22T16:10:19.130832Z",
"workspace": 1
}
]
}
}
12 changes: 6 additions & 6 deletions tests/test_mappings/test_imports/test_modules/test_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def test_disable_categories(
):
workspace_id = 1

projects_to_disable = {
categories_to_disable = {
'destination_id': {
'value': 'old_category',
'updated_value': 'new_category',
Expand All @@ -177,11 +177,11 @@ def test_disable_categories(
mock_platform = mocker.patch('apps.mappings.imports.modules.categories.PlatformConnector')
bulk_post_call = mocker.patch.object(mock_platform.return_value.categories, 'post_bulk')

disable_categories(workspace_id, projects_to_disable)
disable_categories(workspace_id, categories_to_disable)

assert bulk_post_call.call_count == 1

projects_to_disable = {
categories_to_disable = {
'destination_id': {
'value': 'old_category_2',
'updated_value': 'new_category',
Expand All @@ -190,7 +190,7 @@ def test_disable_categories(
}
}

disable_categories(workspace_id, projects_to_disable)
disable_categories(workspace_id, categories_to_disable)
assert bulk_post_call.call_count == 1

# Test disable projects with code in naming
Expand All @@ -207,7 +207,7 @@ def test_disable_categories(
active=True
)

projects_to_disable = {
categories_to_disable = {
'destination_id': {
'value': 'old_category',
'updated_value': 'new_category',
Expand All @@ -223,5 +223,5 @@ def test_disable_categories(
'id': 'source_id_123'
}]

bulk_payload = disable_categories(workspace_id, projects_to_disable)
bulk_payload = disable_categories(workspace_id, categories_to_disable)
assert bulk_payload == payload
12 changes: 6 additions & 6 deletions tests/test_mappings/test_imports/test_modules/test_merchants.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_disable_merchants(
):
workspace_id = 1

projects_to_disable = {
merchants_to_disable = {
'destination_id': {
'value': 'old_merchant',
'updated_value': 'new_merchant',
Expand All @@ -155,11 +155,11 @@ def test_disable_merchants(
mock_platform = mocker.patch('apps.mappings.imports.modules.merchants.PlatformConnector')
bulk_post_call = mocker.patch.object(mock_platform.return_value.merchants, 'post')

disable_merchants(workspace_id, projects_to_disable)
disable_merchants(workspace_id, merchants_to_disable)

assert bulk_post_call.call_count == 1

projects_to_disable = {
merchants_to_disable = {
'destination_id': {
'value': 'old_merchant_2',
'updated_value': 'new_merchant',
Expand All @@ -168,7 +168,7 @@ def test_disable_merchants(
}
}

disable_merchants(workspace_id, projects_to_disable)
disable_merchants(workspace_id, merchants_to_disable)
assert bulk_post_call.call_count == 1

# Test disable projects with code in naming
Expand All @@ -185,7 +185,7 @@ def test_disable_merchants(
active=True
)

projects_to_disable = {
merchants_to_disable = {
'destination_id': {
'value': 'old_merchant',
'updated_value': 'new_merchant',
Expand All @@ -196,5 +196,5 @@ def test_disable_merchants(

payload = ['old_merchant_code old_merchant']

bulk_payload = disable_merchants(workspace_id, projects_to_disable)
bulk_payload = disable_merchants(workspace_id, merchants_to_disable)
assert bulk_payload[0] == payload[0]
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from apps.mappings.imports.modules.projects import Project
from fyle_accounting_mappings.models import DestinationAttribute
from .fixtures import data
from tests.helper import dict_compare_keys


def test_construct_fyle_payload(api_client, test_connection, mocker, create_temp_workspace, add_cost_category, add_sage300_creds, add_fyle_credentials, add_project_mappings):
Expand Down Expand Up @@ -56,7 +57,7 @@ def test_construct_fyle_payload(api_client, test_connection, mocker, create_temp
True
)

assert fyle_payload == data['create_fyle_project_payload_create_disable_case2']
assert dict_compare_keys(fyle_payload, data['create_fyle_project_payload_create_disable_case2']) == [], 'create fyle project payload create disable case2 return diffs in keys'


def test_get_existing_fyle_attributes(db, create_temp_workspace, add_project_mappings, add_import_settings):
Expand Down
47 changes: 47 additions & 0 deletions tests/test_mappings/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from django.urls import reverse
from rest_framework import status
from tests.test_mappings.fixtures import data
from tests.helper import dict_compare_keys


def test_paginated_destination_attributes_view(db, api_client, test_connection, create_temp_workspace, add_project_mappings):
"""
Test paginated destination attributes view
"""
workspace_id = 1
# url = f'/api/workspaces/{workspace_id}/mappings/paginated_destination_attributes/?limit=100&offset=0&attribute_type={attribute_type}&active=true&value={value}'

url = reverse('paginated_destination_attributes_view', args=[workspace_id])

# Test with no value matching the data
params = {
'limit': 100,
'offset': 0,
'attribute_type': 'JOB',
'active': 'true',
'value': 'Something not in the data'
}

api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token))

response = api_client.get(url, params)
assert response.status_code == status.HTTP_200_OK
assert dict_compare_keys(response.json(), data['paginated_destination_attributes_view_response_1']) == [], 'paginated destination attributes view api return diffs in keys'

# Test with value (code) in the data
params.update(value='123')

api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token))

response = api_client.get(url, params)
assert response.status_code == status.HTTP_200_OK
assert dict_compare_keys(response.json(), data['paginated_destination_attributes_view_response_2']) == [], 'paginated destination attributes view api return diffs in keys'

# Test with value (name) in the data
params.update(value='cre')

api_client.credentials(HTTP_AUTHORIZATION='Bearer {}'.format(test_connection.access_token))

response = api_client.get(url, params)
assert response.status_code == status.HTTP_200_OK
assert dict_compare_keys(response.json(), data['paginated_destination_attributes_view_response_2']) == [], 'paginated destination attributes view api return diffs in keys'
107 changes: 107 additions & 0 deletions tests/test_sage300/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import pytest
from unittest.mock import MagicMock
from apps.sage300.utils import SageDesktopConnector, Sage300Credential
from fyle_accounting_mappings.models import DestinationAttribute
from apps.mappings.models import Version
from apps.workspaces.models import Workspace
from apps.mappings.models import ImportLog
from sage_desktop_sdk.core.schema.read_only import CommitmentItem


def test_sage_desktop_connector(
Expand Down Expand Up @@ -639,3 +642,107 @@ def test_bulk_create_or_update_destination_attributes_without_code(db, create_te
# Verify update
assert DestinationAttribute.objects.get(destination_id='DestID1').value == 'Updated Value 1'
assert DestinationAttribute.objects.get(destination_id='DestID2').value == 'Updated Value 2'


@pytest.fixture
def sync_instance(
db,
mocker,
create_temp_workspace,
add_sage300_creds
):
workspace_id = 1
sage_creds = Sage300Credential.objects.get(workspace_id=workspace_id)

mocker.patch('apps.sage300.utils.SageDesktopSDK')

sage_connector = SageDesktopConnector(
credentials_object=sage_creds,
workspace_id=workspace_id
)

return sage_connector


def test_sync_data_with_generator(sync_instance, mocker):
# Mock dependencies
mock_mapping_setting = mocker.patch('apps.sage300.utils.MappingSetting')
mock_bulk_create = mocker.patch('apps.sage300.utils.DestinationAttribute.bulk_create_or_update_destination_attributes')
mock_get_attribute_class = mocker.patch('apps.sage300.utils.SageDesktopConnector._get_attribute_class')
mock_update_latest_version = mocker.patch('apps.sage300.utils.SageDesktopConnector._update_latest_version')
mock_import_string = mocker.patch('apps.sage300.utils.import_string')

# Setup mock return values
mock_mapping_setting.objects.filter.return_value.first.return_value = MagicMock(is_custom=False, source_field='PROJECT', destination_field='JOB')
mock_get_attribute_class.return_value = 'Job'
mock_update_latest_version.return_value = None
mock_import_string.return_value.from_dict.return_value = MagicMock()

# Mock data generator
data_gen = iter([iter([{'key': 'value'}])])

# Call method
sync_instance._sync_data(data_gen, 'JOB', 'job', 1, ['code', 'version'], is_generator=True)

# Assertions
mock_bulk_create.assert_called_once()
called_args = mock_bulk_create.call_args[0]

assert called_args[1] == 'JOB'
assert called_args[2] == 1
assert mock_bulk_create.call_args[1]['attribute_disable_callback_path'] == 'apps.sage300.helpers.disable_projects' # ATTRIBUTE_CALLBACK_MAP['PROJECT']


def test_sync_data_without_generator(sync_instance, mocker):
# Mock dependencies
mock_bulk_create = mocker.patch('apps.sage300.utils.DestinationAttribute.bulk_create_or_update_destination_attributes')
mock_get_attribute_class = mocker.patch('apps.sage300.utils.SageDesktopConnector._get_attribute_class')
mock_update_latest_version = mocker.patch('apps.sage300.utils.SageDesktopConnector._update_latest_version')
mock_import_string = mocker.patch('apps.sage300.utils.import_string')

# Setup mock return values
mock_get_attribute_class.return_value = 'CommitmentItem'
mock_update_latest_version.return_value = None
mock_import_string.return_value.from_dict.return_value = MagicMock()

# Mock data
data = [
CommitmentItem(
id='ffb326e3-783f-4667-a443-b06c0083ef07',
version=212585,
amount=250.0,
amount_approved=0.0,
amount_invoiced=591.0,
amount_paid=0.0,
amount_original=250.0,
amount_pending=0.0,
amount_retained=22.5,
category_id='ece00064-b585-4f87-b0bc-b06100a9bec8',
code='1',
commitment_id='ddb74931-f138-4e2e-a1f6-b06c0083edd5',
cost_code_id='d3b321be-1e6c-4d4b-add4-b06100a9bd2c',
created_on_utc='2023-08-28T08:00:21Z',
description='',
has_external_id=True,
is_active=True,
is_archived=False,
job_id='5e0eb476-b189-4409-b9b3-b061009602a4',
name='Refrigeration',
standard_category_id='302918fb-2f89-4d7f-972a-b05b00f3c431',
tax=0.0,
tax_group_id='a721a071-9cac-4134-9d8b-b05b00f3cb2a',
tax_group_code='EXMPT',
unit_cost=0.0,
units=0.0
)
]

# Call method
sync_instance._sync_data(data, 'COMMITMENT_ITEM', 'commitment_item', 1, ['code', 'version'], is_generator=False)

# Assertions
mock_bulk_create.assert_called_once()
called_args = mock_bulk_create.call_args[0]
assert called_args[1] == 'COMMITMENT_ITEM'
assert called_args[2] == 1
assert len(called_args) == 4

0 comments on commit 253cb2b

Please sign in to comment.