Skip to content

Commit

Permalink
add support for code prepending in MERCHANT
Browse files Browse the repository at this point in the history
  • Loading branch information
Hrishabh17 committed Jul 19, 2024
1 parent a1e19da commit 18219a4
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 6 deletions.
50 changes: 47 additions & 3 deletions apps/mappings/imports/modules/merchants.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import logging
from datetime import datetime
from typing import List
from typing import List, Dict
from apps.mappings.imports.modules.base import Base
from fyle_accounting_mappings.models import DestinationAttribute
from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute
from apps.mappings.models import ImportLog
from apps.mappings.exceptions import handle_import_exceptions
from apps.workspaces.models import FyleCredential
from apps.workspaces.models import FyleCredential, ImportSetting
from fyle_integrations_platform_connector import PlatformConnector
from apps.mappings.helpers import format_attribute_name

logger = logging.getLogger(__name__)
logger.level = logging.INFO


class Merchant(Base):
Expand Down Expand Up @@ -68,3 +73,42 @@ def import_destination_attribute_to_fyle(self, import_log: ImportLog):
self.construct_payload_and_import_to_fyle(platform, import_log)

self.sync_expense_attributes(platform)


def disable_merchants(workspace_id: int, merchants_to_disable: Dict):
"""
merchants_to_disable object format:
{
'destination_id': {
'value': 'old_merchant_name',
'updated_value': 'new_merchant_name',
'code': 'old_code',
'update_code': 'new_code' ---- if the code is updated else same as code
}
}
"""
fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id)
platform = PlatformConnector(fyle_credentials=fyle_credentials)
use_code_in_naming = ImportSetting.objects.filter(workspace_id = workspace_id, import_code_fields__contains=['VENDOR']).first()

merchant_values = []
for merchant_map in merchants_to_disable.values():
merchant_name = format_attribute_name(use_code_in_naming=use_code_in_naming, attribute_name=merchant_map['value'], attribute_code=merchant_map['code'])
merchant_values.append(merchant_name)

filters = {
'workspace_id': workspace_id,
'attribute_type': 'MERCHANT',
'value__in': merchant_values,
'active': True
}

bulk_payload = ExpenseAttribute.objects.filter(**filters).values_list('value', flat=True)

if bulk_payload:
logger.info(f"Disabling Merchants in Fyle | WORKSPACE_ID: {workspace_id} | COUNT: {len(bulk_payload)}")
platform.merchants.post(bulk_payload, delete_merchants=True)
else:
logger.info(f"No Merchants to Disable in Fyle | WORKSPACE_ID: {workspace_id}")

return bulk_payload
4 changes: 3 additions & 1 deletion apps/mappings/imports/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ def chain_import_fields_to_fyle(workspace_id):
'apps.mappings.imports.tasks.trigger_import_via_schedule',
workspace_id,
'VENDOR',
'MERCHANT'
'MERCHANT',
False,
True if 'VENDOR' in import_code_fields else False
)

for mapping_setting in mapping_settings:
Expand Down
1 change: 1 addition & 0 deletions apps/sage300/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ATTRIBUTE_CALLBACK_MAP = {
'JOB': 'apps.sage300.helpers.disable_projects',
'ACCOUNT': 'apps.mappings.imports.modules.categories.disable_categories',
'VENDOR': 'apps.mappings.imports.modules.merchants.disable_merchants',
}


Expand Down
38 changes: 38 additions & 0 deletions tests/test_mappings/test_imports/test_modules/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,44 @@ def add_merchant_mappings():
detail='Merchant - Platform APIs, Id - 10081',
active=True
)
DestinationAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='VENDOR',
display_name='CRE Platform',
value='CRE Platform',
destination_id='10065',
detail='Sage 300 Merchant - CRE Platform, Id - 10065',
active=True,
code='123'
)
DestinationAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='VENDOR',
display_name='Integrations CRE',
value='Integrations CRE',
destination_id='10082',
detail='Sage 300 Merchant - Integrations CRE, Id - 10082',
active=True,
code='123'
)
ExpenseAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='MERCHANT',
display_name='CRE Platform',
value='123 CRE Platform',
source_id='10065',
detail='Sage 300 Merchant - 123 CRE Platform, Id - 10065',
active=True
)
ExpenseAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='MERCHANT',
display_name='Integrations CRE',
value='123 Integrations CRE',
source_id='10082',
detail='Sage 300 Merchant - 123 Integrations CRE, Id - 10082',
active=True
)


@pytest.fixture()
Expand Down
139 changes: 137 additions & 2 deletions tests/test_mappings/test_imports/test_modules/test_merchants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from apps.mappings.imports.modules.merchants import Merchant
from fyle_accounting_mappings.models import DestinationAttribute
from apps.mappings.models import ImportLog
from apps.workspaces.models import ImportSetting
from apps.mappings.imports.modules.merchants import Merchant, disable_merchants
from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute


def test_construct_fyle_payload(api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds, add_fyle_credentials, add_merchant_mappings):
Expand Down Expand Up @@ -63,3 +64,137 @@ def test_import_destination_attribute_to_fyle(

merchant.import_destination_attribute_to_fyle(import_log)
assert True


def test_get_existing_fyle_attributes(
db,
create_temp_workspace,
add_merchant_mappings,
add_import_settings
):
merchant = Merchant(1, 'VENDOR', None)

paginated_destination_attributes = DestinationAttribute.objects.filter(workspace_id=1, attribute_type='VENDOR')
paginated_destination_attributes_without_duplicates = merchant.remove_duplicate_attributes(paginated_destination_attributes)
paginated_destination_attribute_values = [attribute.value for attribute in paginated_destination_attributes_without_duplicates]
existing_fyle_attributes_map = merchant.get_existing_fyle_attributes(paginated_destination_attribute_values)

assert existing_fyle_attributes_map == {}

# with code prepending
merchant.use_code_in_naming = True
paginated_destination_attributes = DestinationAttribute.objects.filter(workspace_id=1, attribute_type='VENDOR', code__isnull=False)
paginated_destination_attributes_without_duplicates = merchant.remove_duplicate_attributes(paginated_destination_attributes)
paginated_destination_attribute_values = [attribute.value for attribute in paginated_destination_attributes_without_duplicates]
existing_fyle_attributes_map = merchant.get_existing_fyle_attributes(paginated_destination_attribute_values)

assert existing_fyle_attributes_map == {'123 cre platform': '10065', '123 integrations cre': '10082'}


def test_construct_fyle_payload_with_code(
db,
create_temp_workspace,
add_merchant_mappings,
add_import_settings
):
merchant = Merchant(1, 'VENDOR', None, True)

paginated_destination_attributes = DestinationAttribute.objects.filter(workspace_id=1, attribute_type='VENDOR')
paginated_destination_attributes_without_duplicates = merchant.remove_duplicate_attributes(paginated_destination_attributes)
paginated_destination_attribute_values = [attribute.value for attribute in paginated_destination_attributes_without_duplicates]
existing_fyle_attributes_map = merchant.get_existing_fyle_attributes(paginated_destination_attribute_values)

# already exists
fyle_payload = merchant.construct_fyle_payload(
paginated_destination_attributes,
existing_fyle_attributes_map,
True
)

assert fyle_payload == []

# create new case
existing_fyle_attributes_map = {}
fyle_payload = merchant.construct_fyle_payload(
paginated_destination_attributes,
existing_fyle_attributes_map,
True
)

assert fyle_payload == ['123 CRE Platform', '123 Integrations CRE']


def test_disable_merchants(
db,
mocker,
create_temp_workspace,
add_fyle_credentials,
add_merchant_mappings,
add_import_settings
):
workspace_id = 1

projects_to_disable = {
'destination_id': {
'value': 'old_merchant',
'updated_value': 'new_merchant',
'code': 'old_merchant_code',
'updated_code': 'old_merchant_code'
}
}

ExpenseAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='MERCHANT',
display_name='Merchant',
value='old_merchant',
source_id='source_id',
active=True
)

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)

assert bulk_post_call.call_count == 1

projects_to_disable = {
'destination_id': {
'value': 'old_merchant_2',
'updated_value': 'new_merchant',
'code': 'old_merchant_code',
'updated_code': 'new_merchant_code'
}
}

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

# Test disable projects with code in naming
import_settings = ImportSetting.objects.get(workspace_id=workspace_id)
import_settings.import_code_fields = ['VENDOR']
import_settings.save()

ExpenseAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='MERCHANT',
display_name='Merchant',
value='old_merchant_code old_merchant',
source_id='source_id_123',
active=True
)

projects_to_disable = {
'destination_id': {
'value': 'old_merchant',
'updated_value': 'new_merchant',
'code': 'old_merchant_code',
'updated_code': 'old_merchant_code'
}
}

payload = ['old_merchant_code old_merchant']

bulk_payload = disable_merchants(workspace_id, projects_to_disable)
assert bulk_payload[0] == payload[0]

0 comments on commit 18219a4

Please sign in to comment.