From ff4b9d40ef2fbe938aee6be0b5d795ee8eed6de6 Mon Sep 17 00:00:00 2001 From: ruuushhh Date: Fri, 3 Nov 2023 15:23:10 +0530 Subject: [PATCH] Import Vendors as Merchants --- apps/mappings/imports/modules/base.py | 4 +- apps/mappings/imports/modules/merchants.py | 69 +++++++++++++++++++ apps/mappings/imports/tasks.py | 4 +- tests/conftest.py | 30 ++++++++ .../test_modules/test_merchants.py | 20 ++++++ 5 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 tests/test_mappings/test_imports/test_modules/test_merchants.py diff --git a/apps/mappings/imports/modules/base.py b/apps/mappings/imports/modules/base.py index 0af877d2..85166c9b 100644 --- a/apps/mappings/imports/modules/base.py +++ b/apps/mappings/imports/modules/base.py @@ -154,7 +154,7 @@ def sync_expense_attributes(self, platform: PlatformConnector): :param platform: PlatformConnector object """ platform_class = self.get_platform_class(platform) - if self.platform_class_name == 'expense_custom_fields': + if self.platform_class_name in ['expense_custom_fields', 'merchants']: platform_class.sync() else: platform_class.sync(sync_after=self.sync_after if self.sync_after else None) @@ -272,7 +272,7 @@ def post_to_fyle_and_sync(self, fyle_payload: List[object], resource_class, is_l :param is_last_batch: bool :param import_log: ImportLog object """ - if fyle_payload and self.platform_class_name == 'expense_custom_fields': + if fyle_payload and self.platform_class_name in ['expense_custom_fields', 'merchants']: resource_class.post(fyle_payload) elif fyle_payload: resource_class.post_bulk(fyle_payload) diff --git a/apps/mappings/imports/modules/merchants.py b/apps/mappings/imports/modules/merchants.py index e69de29b..586149ad 100644 --- a/apps/mappings/imports/modules/merchants.py +++ b/apps/mappings/imports/modules/merchants.py @@ -0,0 +1,69 @@ +from datetime import datetime +from typing import List +from apps.mappings.imports.modules.base import Base +from fyle_accounting_mappings.models import DestinationAttribute +from apps.mappings.models import ImportLog +from apps.mappings.exceptions import handle_import_exceptions +from apps.workspaces.models import FyleCredential +from fyle_integrations_platform_connector import PlatformConnector + + +class Merchant(Base): + """ + Class for Merchant module + """ + def __init__(self, workspace_id: int, destination_field: str, sync_after: datetime): + super().__init__( + workspace_id=workspace_id, + source_field='MERCHANT', + destination_field=destination_field, + platform_class_name='merchants', + sync_after=sync_after + ) + + def trigger_import(self): + """ + Trigger import for Merchant module + """ + self.check_import_log_and_start_import() + + # remove the is_auto_sync_status_allowed parameter + def construct_fyle_payload( + self, + paginated_destination_attributes: List[DestinationAttribute], + existing_fyle_attributes_map: object, + is_auto_sync_status_allowed: bool + ): + """ + Construct Fyle payload for Merchant module + :param paginated_destination_attributes: List of paginated destination attributes + :param existing_fyle_attributes_map: Existing Fyle attributes map + :param is_auto_sync_status_allowed: Is auto sync status allowed + :return: Fyle payload + """ + payload = [] + + for attribute in paginated_destination_attributes: + # Create a new merchant if it does not exist in Fyle + if attribute.value.lower() not in existing_fyle_attributes_map: + payload.append(attribute.value) + + return payload + + # import_destination_attribute_to_fyle method is overridden + @handle_import_exceptions + def import_destination_attribute_to_fyle(self, import_log: ImportLog): + """ + Import destiantion_attributes field to Fyle and Auto Create Mappings + :param import_log: ImportLog object + """ + fyle_credentials = FyleCredential.objects.get(workspace_id=self.workspace_id) + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + self.sync_expense_attributes(platform) + + self.sync_destination_attributes(self.destination_field) + + self.construct_payload_and_import_to_fyle(platform, import_log) + + self.sync_expense_attributes(platform) diff --git a/apps/mappings/imports/tasks.py b/apps/mappings/imports/tasks.py index e1e9be64..d5647c10 100644 --- a/apps/mappings/imports/tasks.py +++ b/apps/mappings/imports/tasks.py @@ -2,13 +2,15 @@ from apps.mappings.imports.modules.categories import Category from apps.mappings.imports.modules.projects import Project from apps.mappings.imports.modules.cost_centers import CostCenter +from apps.mappings.imports.modules.merchants import Merchant from apps.mappings.imports.modules.expense_custom_fields import ExpenseCustomField SOURCE_FIELD_CLASS_MAP = { 'CATEGORY': Category, 'PROJECT': Project, - 'COST_CENTER': CostCenter + 'COST_CENTER': CostCenter, + 'MERCHANT': Merchant } diff --git a/tests/conftest.py b/tests/conftest.py index cc8dae4f..fb761dc7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -336,3 +336,33 @@ def add_cost_center_mappings(): detail='Cost Center - Platform APIs, Id - 10081', active=True ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_merchant_mappings(): + """ + Pytest fixture to add merchant mappings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + for workspace_id in workspace_ids: + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='MERCHANT', + display_name='Direct Mail Campaign', + value='Direct Mail Campaign', + destination_id='10064', + detail='Merchant - Direct Mail Campaign, Id - 10064', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='MERCHANT', + display_name='Platform APIs', + value='Platform APIs', + destination_id='10081', + detail='Merchant - Platform APIs, Id - 10081', + active=True + ) diff --git a/tests/test_mappings/test_imports/test_modules/test_merchants.py b/tests/test_mappings/test_imports/test_modules/test_merchants.py new file mode 100644 index 00000000..1f68d985 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_merchants.py @@ -0,0 +1,20 @@ +from apps.mappings.imports.modules.merchants import Merchant +from fyle_accounting_mappings.models import DestinationAttribute + + +def test_construct_fyle_payload(api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds, add_fyle_credentials, add_merchant_mappings): + merchant = Merchant(1, 'MERCHANT', None) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter(workspace_id=1, attribute_type='MERCHANT') + + existing_fyle_attributes_map = {} + is_auto_sync_status_allowed = merchant.get_auto_sync_permission() + + fyle_payload = merchant.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed + ) + + assert fyle_payload == ['Direct Mail Campaign', 'Platform APIs']