Skip to content

Commit

Permalink
Resource Custom Expense Field: refactored imports
Browse files Browse the repository at this point in the history
  • Loading branch information
Hrishabh17 committed Feb 29, 2024
1 parent 097c343 commit 2d59c34
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 211 deletions.
2 changes: 1 addition & 1 deletion apps/mappings/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def construct_tasks_and_chain_import_fields_to_fyle(workspace_id: int):

if mapping_settings:
for mapping_setting in mapping_settings:
if mapping_setting.source_field in ALLOWED_SOURCE_FIELDS:
if mapping_setting.source_field in ALLOWED_SOURCE_FIELDS or mapping_setting.is_custom:

Check warning on line 139 in apps/mappings/queue.py

View check run for this annotation

Codecov / codecov/patch

apps/mappings/queue.py#L139

Added line #L139 was not covered by tests
task_settings['mapping_settings'].append(
{
'source_field': mapping_setting.source_field,
Expand Down
37 changes: 18 additions & 19 deletions apps/mappings/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django_q.tasks import async_task
from django_q.tasks import Chain, async_task
from fyle_accounting_mappings.models import Mapping, MappingSetting

from apps.fyle.enums import FyleAttributeEnum
from apps.mappings.models import TenantMapping
from apps.mappings.queue import schedule_fyle_attributes_creation
from apps.mappings.tasks import upload_attributes_to_fyle
from apps.tasks.models import Error
from apps.workspaces.models import WorkspaceGeneralSettings
from apps.mappings.schedules import new_schedule_or_delete_fyle_import_tasks
from apps.workspaces.models import XeroCredentials
from apps.mappings.constants import SYNC_METHODS
from apps.mappings.helpers import is_auto_sync_allowed


@receiver(post_save, sender=Mapping)
Expand Down Expand Up @@ -45,17 +46,14 @@ def run_post_mapping_settings_triggers(sender, instance: MappingSetting, **kwarg
FyleAttributeEnum.COST_CENTER,
]

if instance.source_field in ALLOWED_SOURCE_FIELDS:
if instance.source_field in ALLOWED_SOURCE_FIELDS or instance.is_custom:

Check warning on line 49 in apps/mappings/signals.py

View check run for this annotation

Codecov / codecov/patch

apps/mappings/signals.py#L49

Added line #L49 was not covered by tests
new_schedule_or_delete_fyle_import_tasks(
workspace_general_settings_instance=workspace_general_settings,
mapping_settings=MappingSetting.objects.filter(
workspace_id=instance.workspace_id
).values()
)

if instance.is_custom:
schedule_fyle_attributes_creation(int(instance.workspace_id))


@receiver(pre_save, sender=MappingSetting)
def run_pre_mapping_settings_triggers(sender, instance: MappingSetting, **kwargs):
Expand All @@ -76,23 +74,24 @@ def run_pre_mapping_settings_triggers(sender, instance: MappingSetting, **kwargs
instance.source_field = instance.source_field.upper().replace(" ", "_")

if instance.source_field not in default_attributes:
upload_attributes_to_fyle(
workspace_id=int(instance.workspace_id),
xero_attribute_type=instance.destination_field,
fyle_attribute_type=instance.source_field,
source_placeholder=instance.source_placeholder,
)
chain = Chain()

Check warning on line 77 in apps/mappings/signals.py

View check run for this annotation

Codecov / codecov/patch

apps/mappings/signals.py#L77

Added line #L77 was not covered by tests

async_task(
"apps.mappings.tasks.auto_create_expense_fields_mappings",
int(instance.workspace_id),
chain.append(

Check warning on line 79 in apps/mappings/signals.py

View check run for this annotation

Codecov / codecov/patch

apps/mappings/signals.py#L79

Added line #L79 was not covered by tests
'fyle_integrations_imports.tasks.trigger_import_via_schedule',
instance.workspace_id,
instance.destination_field,
instance.source_field,
q_options={
'cluster': 'import'
}
'apps.xero.utils.XeroConnector',
XeroCredentials.get_active_xero_credentials(workspace_id=instance.workspace_id),
[SYNC_METHODS.get(instance.destination_field.upper(), 'tracking_categories')],
is_auto_sync_allowed(WorkspaceGeneralSettings.objects.get(workspace_id=instance.workspace_id), instance),
False,
None,
True
)

chain.run()

Check warning on line 93 in apps/mappings/signals.py

View check run for this annotation

Codecov / codecov/patch

apps/mappings/signals.py#L93

Added line #L93 was not covered by tests


@receiver(post_save, sender=TenantMapping)
def run_post_tenant_mapping_trigger(sender, instance: TenantMapping, **kwargs):
Expand Down
162 changes: 1 addition & 161 deletions apps/mappings/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
from typing import Dict, List

from django_q.tasks import Chain
from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute, Mapping, MappingSetting
from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute, Mapping
from fyle_integrations_platform_connector import PlatformConnector

from apps.fyle.enums import FyleAttributeEnum
from apps.mappings.constants import FYLE_EXPENSE_SYSTEM_FIELDS
from apps.mappings.exceptions import handle_import_exceptions
from apps.tasks.models import Error
from apps.workspaces.models import FyleCredential, WorkspaceGeneralSettings, XeroCredentials
Expand Down Expand Up @@ -317,165 +316,6 @@ def disable_renamed_projects(workspace_id, destination_field):
return expense_attribute_to_be_disabled


def create_fyle_expense_custom_fields_payload(
xero_attributes: List[DestinationAttribute],
workspace_id: int,
fyle_attribute: str,
platform: PlatformConnector,
source_placeholder: str = None,
):
"""
Create Fyle Expense Custom Field Payload from Xero Objects
:param workspace_id: Workspace ID
:param xero_attributes: Xero Objects
:param fyle_attribute: Fyle Attribute
:return: Fyle Expense Custom Field Payload
"""

fyle_expense_custom_field_options = []

[
fyle_expense_custom_field_options.append(xero_attribute.value)
for xero_attribute in xero_attributes
]

if fyle_attribute.lower() not in FYLE_EXPENSE_SYSTEM_FIELDS:
existing_attribute = (
ExpenseAttribute.objects.filter(
attribute_type=fyle_attribute, workspace_id=workspace_id
)
.values_list("detail", flat=True)
.first()
)

custom_field_id = None
placeholder = None
if existing_attribute is not None:
custom_field_id = existing_attribute["custom_field_id"]
placeholder = (
existing_attribute["placeholder"]
if "placeholder" in existing_attribute
else None
)

fyle_attribute = fyle_attribute.replace("_", " ").title()

new_placeholder = None

# Here is the explanation of what's happening in the if-else ladder below
# source_field is the field that's save in mapping settings, this field user may or may not fill in the custom field form
# placeholder is the field that's saved in the detail column of destination attributes
# fyle_attribute is what we're constructing when both of these fields would not be available

if not (source_placeholder or placeholder):
# If source_placeholder and placeholder are both None, then we're creating adding a self constructed placeholder
new_placeholder = "Select {0}".format(fyle_attribute)
elif not source_placeholder and placeholder:
# If source_placeholder is None but placeholder is not, then we're choosing same place holder as 1 in detail section
new_placeholder = placeholder
elif source_placeholder and not placeholder:
# If source_placeholder is not None but placeholder is None, then we're choosing the placeholder as filled by user in form
new_placeholder = source_placeholder
else:
# Else, we're choosing the placeholder as filled by user in form or None
new_placeholder = source_placeholder

expense_custom_field_payload = {
"field_name": fyle_attribute,
"type": "SELECT",
"is_enabled": True,
"is_mandatory": False,
"placeholder": new_placeholder,
"options": fyle_expense_custom_field_options,
"code": None,
}

if custom_field_id:
expense_field = platform.expense_custom_fields.get_by_id(custom_field_id)
expense_custom_field_payload["id"] = custom_field_id
expense_custom_field_payload["is_mandatory"] = expense_field["is_mandatory"]

logger.info("| Importing Custom Fields to Fyle | Content: {{Fyle Payload count: {}}}".format(len(expense_custom_field_payload)))
return expense_custom_field_payload


def upload_attributes_to_fyle(
workspace_id: int,
xero_attribute_type: str,
fyle_attribute_type: str,
source_placeholder: str = None,
):
"""
Upload attributes to Fyle
"""
fyle_credentials: FyleCredential = FyleCredential.objects.get(
workspace_id=workspace_id
)

platform = PlatformConnector(fyle_credentials)

xero_attributes: List[DestinationAttribute] = DestinationAttribute.objects.filter(
workspace_id=workspace_id, attribute_type=xero_attribute_type
)

xero_attributes = remove_duplicates(xero_attributes)

fyle_custom_field_payload = create_fyle_expense_custom_fields_payload(
xero_attributes=xero_attributes,
workspace_id=workspace_id,
fyle_attribute=fyle_attribute_type,
source_placeholder=source_placeholder,
platform=platform,
)

if fyle_custom_field_payload:
platform.expense_custom_fields.post(fyle_custom_field_payload)
platform.expense_custom_fields.sync()

return xero_attributes


@handle_import_exceptions(task_name="auto create expense fields_mappings")
def auto_create_expense_fields_mappings(
workspace_id: int,
xero_attribute_type: str,
fyle_attribute_type: str,
source_placeholder: str = None,
):
"""
Create Fyle Attributes Mappings
:return: mappings
"""

fyle_attributes = upload_attributes_to_fyle(
workspace_id=workspace_id,
xero_attribute_type=xero_attribute_type,
fyle_attribute_type=fyle_attribute_type,
source_placeholder=source_placeholder,
)
if fyle_attributes:
Mapping.bulk_create_mappings(
fyle_attributes, fyle_attribute_type, xero_attribute_type, workspace_id
)


@handle_import_exceptions(task_name="async auto create custom field_mappings")
def async_auto_create_custom_field_mappings(workspace_id: str):
mapping_settings = MappingSetting.objects.filter(
is_custom=True, import_to_fyle=True, workspace_id=workspace_id
).all()

for mapping_setting in mapping_settings:
if mapping_setting.import_to_fyle:
sync_xero_attributes(mapping_setting.destination_field, workspace_id)
auto_create_expense_fields_mappings(
workspace_id,
mapping_setting.destination_field,
mapping_setting.source_field,
mapping_setting.source_placeholder,
)


def upload_tax_groups_to_fyle(
platform_connection: PlatformConnector, workspace_id: int
):
Expand Down
23 changes: 3 additions & 20 deletions apps/workspaces/apis/import_settings/triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from fyle_accounting_mappings.models import MappingSetting

from apps.mappings.queue import (
schedule_fyle_attributes_creation,
schedule_tax_groups_creation,
schedule_tax_groups_creation
)
from apps.workspaces.models import WorkspaceGeneralSettings
from apps.mappings.schedules import new_schedule_or_delete_fyle_import_tasks
Expand Down Expand Up @@ -52,25 +51,9 @@ def post_save_workspace_general_settings(

def pre_save_mapping_settings(self):
"""
Post save action for mapping settings
Pre save action for mapping settings
"""
mapping_settings = self.__mapping_settings

cost_center_mapping_available = False

# Here we are checking if any of the mappings have PROJECT and COST_CENTER mapping
for setting in mapping_settings:
if setting["source_field"] == "COST_CENTER":
cost_center_mapping_available = True

if not cost_center_mapping_available:
new_schedule_or_delete_fyle_import_tasks(
workspace_general_settings_instance=self.__workspace_general_settings,
mapping_settings=self.__mapping_settings,
)

# Schdule for auto creating custom field mappings
schedule_fyle_attributes_creation(self.__workspace_id)
pass

def post_save_mapping_settings(
self, workspace_general_settings_instance: WorkspaceGeneralSettings
Expand Down
11 changes: 1 addition & 10 deletions apps/xero/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def refersh_xero_dimension(workspace_id):
]

for mapping_setting in mapping_settings:
if mapping_setting.source_field in ALLOWED_SOURCE_FIELDS:
if mapping_setting.source_field in ALLOWED_SOURCE_FIELDS or mapping_setting.is_custom:
# run new_schedule_or_delete_fyle_import_tasks
chain.append(
'fyle_integrations_imports.tasks.trigger_import_via_schedule',
Expand All @@ -74,15 +74,6 @@ def refersh_xero_dimension(workspace_id):
mapping_setting.is_custom
)

elif mapping_setting.is_custom:
# run async_auto_create_custom_field_mappings
chain.append(
"apps.mappings.tasks.async_auto_create_custom_field_mappings",
int(workspace_id),
q_options={
'cluster': 'import'
}
)
elif workspace_general_settings.import_suppliers_as_merchants:
# run auto_create_suppliers_as_merchant
chain.append(
Expand Down

0 comments on commit 2d59c34

Please sign in to comment.