Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import Vendors as Merchants #68

Merged
merged 4 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions apps/mappings/imports/modules/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand All @@ -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(
Expand All @@ -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
Expand All @@ -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]):
"""
Expand All @@ -268,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)
Expand Down
57 changes: 57 additions & 0 deletions apps/mappings/imports/modules/cost_centers.py
Original file line number Diff line number Diff line change
@@ -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
69 changes: 69 additions & 0 deletions apps/mappings/imports/modules/merchants.py
Original file line number Diff line number Diff line change
@@ -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
ruuushhh marked this conversation as resolved.
Show resolved Hide resolved
):
"""
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)
6 changes: 5 additions & 1 deletion apps/mappings/imports/tasks.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
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.merchants import Merchant
from apps.mappings.imports.modules.expense_custom_fields import ExpenseCustomField


SOURCE_FIELD_CLASS_MAP = {
'CATEGORY': Category,
'PROJECT': Project
'PROJECT': Project,
'COST_CENTER': CostCenter,
'MERCHANT': Merchant
}


Expand Down
31 changes: 0 additions & 31 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from rest_framework.test import APIClient
from fyle.platform.platform import Platform
from fyle_rest_auth.models import User, AuthToken
from fyle_accounting_mappings.models import DestinationAttribute

from apps.fyle.helpers import get_access_token
from apps.workspaces.models import (
Expand Down Expand Up @@ -276,33 +275,3 @@ def add_accounting_export_summary():
successful_accounting_export_count = 5,
failed_accounting_export_count = 5
)


@pytest.fixture()
@pytest.mark.django_db(databases=['default'])
def add_project_mappings():
"""
Pytest fixtue to add project mappings to a workspace
"""
workspace_ids = [
1, 2, 3
]
for workspace_id in workspace_ids:
DestinationAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='PROJECT',
display_name='Direct Mail Campaign',
value='Direct Mail Campaign',
destination_id='10064',
detail='Sage 300 Project - Direct Mail Campaign, Id - 10064',
active=True
)
DestinationAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='PROJECT',
display_name='Platform APIs',
value='Platform APIs',
destination_id='10081',
detail='Sage 300 Project - Platform APIs, Id - 10081',
active=True
)
96 changes: 96 additions & 0 deletions tests/test_mappings/test_imports/test_modules/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""
Fixture configuration for import tests
"""
import pytest

from fyle_accounting_mappings.models import DestinationAttribute


@pytest.fixture()
@pytest.mark.django_db(databases=['default'])
def add_project_mappings():
"""
Pytest fixtue to add project mappings to a workspace
"""
workspace_ids = [
1, 2, 3
]
for workspace_id in workspace_ids:
DestinationAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='PROJECT',
display_name='Direct Mail Campaign',
value='Direct Mail Campaign',
destination_id='10064',
detail='Sage 300 Project - Direct Mail Campaign, Id - 10064',
active=True
)
DestinationAttribute.objects.create(
workspace_id=workspace_id,
attribute_type='PROJECT',
display_name='Platform APIs',
value='Platform APIs',
destination_id='10081',
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
)


@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
)
15 changes: 15 additions & 0 deletions tests/test_mappings/test_imports/test_modules/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}
]
}
21 changes: 21 additions & 0 deletions tests/test_mappings/test_imports/test_modules/test_cost_centers.py
Original file line number Diff line number Diff line change
@@ -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']
Loading
Loading