diff --git a/apps/mappings/imports/modules/base.py b/apps/mappings/imports/modules/base.py index 27bf6024..0af877d2 100644 --- a/apps/mappings/imports/modules/base.py +++ b/apps/mappings/imports/modules/base.py @@ -187,6 +187,8 @@ def construct_payload_and_import_to_fyle( """ Construct Payload and Import to fyle in Batches """ + is_auto_sync_status_allowed = self.get_auto_sync_permission() + filters = self.construct_attributes_filter(self.destination_field) destination_attributes_count = DestinationAttribute.objects.filter(**filters).count() @@ -209,7 +211,8 @@ def construct_payload_and_import_to_fyle( for paginated_destination_attributes, is_last_batch in destination_attributes_generator: fyle_payload = self.setup_fyle_payload_creation( - paginated_destination_attributes=paginated_destination_attributes + paginated_destination_attributes=paginated_destination_attributes, + is_auto_sync_status_allowed=is_auto_sync_status_allowed ) self.post_to_fyle_and_sync( @@ -236,7 +239,8 @@ def get_destination_attributes_generator(self, destination_attributes_count: int def setup_fyle_payload_creation( self, - paginated_destination_attributes: List[DestinationAttribute] + paginated_destination_attributes: List[DestinationAttribute], + is_auto_sync_status_allowed: bool ): """ Setup Fyle Payload Creation @@ -247,7 +251,7 @@ def setup_fyle_payload_creation( paginated_destination_attribute_values = [attribute.value for attribute in paginated_destination_attributes] existing_expense_attributes_map = self.get_existing_fyle_attributes(paginated_destination_attribute_values) - return self.construct_fyle_payload(paginated_destination_attributes, existing_expense_attributes_map) + return self.construct_fyle_payload(paginated_destination_attributes, existing_expense_attributes_map, is_auto_sync_status_allowed) def get_existing_fyle_attributes(self, paginated_destination_attribute_values: List[str]): """ diff --git a/apps/mappings/imports/modules/cost_centers.py b/apps/mappings/imports/modules/cost_centers.py new file mode 100644 index 00000000..18a7d29b --- /dev/null +++ b/apps/mappings/imports/modules/cost_centers.py @@ -0,0 +1,57 @@ +from datetime import datetime +from typing import List +from apps.mappings.imports.modules.base import Base +from fyle_accounting_mappings.models import DestinationAttribute + + +class CostCenter(Base): + """ + Class for Cost Center module + """ + + def __init__(self, workspace_id: int, destination_field: str, sync_after: datetime): + super().__init__( + workspace_id=workspace_id, + source_field="COST_CENTER", + destination_field=destination_field, + platform_class_name="cost_centers", + sync_after=sync_after, + ) + + def trigger_import(self): + """ + Trigger import for Cost Center module + """ + self.check_import_log_and_start_import() + + 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 CostCenter 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: + cost_center = { + 'name': attribute.value, + 'code': attribute.destination_id, + 'is_enabled': True if attribute.active is None else attribute.active, + 'description': 'Cost Center - {0}, Id - {1}'.format( + attribute.value, + attribute.destination_id + ) + } + + # Create a new cost-center if it does not exist in Fyle + if attribute.value.lower() not in existing_fyle_attributes_map: + payload.append(cost_center) + + return payload diff --git a/apps/mappings/imports/tasks.py b/apps/mappings/imports/tasks.py index 34c7b7c0..e1e9be64 100644 --- a/apps/mappings/imports/tasks.py +++ b/apps/mappings/imports/tasks.py @@ -1,12 +1,14 @@ from apps.mappings.models import ImportLog 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.expense_custom_fields import ExpenseCustomField SOURCE_FIELD_CLASS_MAP = { 'CATEGORY': Category, - 'PROJECT': Project + 'PROJECT': Project, + 'COST_CENTER': CostCenter } diff --git a/tests/conftest.py b/tests/conftest.py index 82941772..cc8dae4f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -306,3 +306,33 @@ def add_project_mappings(): detail='Sage 300 Project - Platform APIs, Id - 10081', active=True ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_cost_center_mappings(): + """ + Pytest fixtue to add cost center mappings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + for workspace_id in workspace_ids: + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='COST_CENTER', + display_name='Direct Mail Campaign', + value='Direct Mail Campaign', + destination_id='10064', + detail='Cost Center - Direct Mail Campaign, Id - 10064', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='COST_CENTER', + display_name='Platform APIs', + value='Platform APIs', + destination_id='10081', + detail='Cost Center - Platform APIs, Id - 10081', + active=True + ) diff --git a/tests/test_mappings/test_imports/test_modules/fixtures.py b/tests/test_mappings/test_imports/test_modules/fixtures.py index 4f83520c..7315a2bc 100644 --- a/tests/test_mappings/test_imports/test_modules/fixtures.py +++ b/tests/test_mappings/test_imports/test_modules/fixtures.py @@ -29,5 +29,20 @@ 'is_enabled': False, 'name': 'Platform APIs' } + ], + "create_fyle_cost_center_payload_create_new_case": + [ + { + 'code': '10064', + 'description': 'Cost Center - Direct Mail Campaign, Id - 10064', + 'is_enabled': True, + 'name': 'Direct Mail Campaign' + }, + { + 'description': 'Cost Center - Platform APIs, Id - 10081', + 'is_enabled': True, + 'name': 'Platform APIs', + 'code': '10081', + } ] } diff --git a/tests/test_mappings/test_imports/test_modules/test_cost_centers.py b/tests/test_mappings/test_imports/test_modules/test_cost_centers.py new file mode 100644 index 00000000..1a1dbed3 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_cost_centers.py @@ -0,0 +1,21 @@ +from apps.mappings.imports.modules.cost_centers import CostCenter +from fyle_accounting_mappings.models import DestinationAttribute +from .fixtures import data + + +def test_construct_fyle_payload(api_client, test_connection, mocker, create_temp_workspace, add_sage300_creds, add_fyle_credentials, add_cost_center_mappings): + cost_center = CostCenter(1, 'COST_CENTER', None) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter(workspace_id=1, attribute_type='COST_CENTER') + + existing_fyle_attributes_map = {} + is_auto_sync_status_allowed = cost_center.get_auto_sync_permission() + + fyle_payload = cost_center.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed + ) + + assert fyle_payload == data['create_fyle_cost_center_payload_create_new_case']