Skip to content

Commit

Permalink
Fix Auto map employees (#74)
Browse files Browse the repository at this point in the history
* Fix Auto map employees

* validation fixed:

* Fix default_bank_account_id

* comments fixed
  • Loading branch information
ruuushhh authored Jan 19, 2024
1 parent dc94361 commit bc4f659
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 219 deletions.
2 changes: 1 addition & 1 deletion apps/business_central/exports/journal_entry/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def create_or_update_object(self, accounting_export: AccountingExport, _: Advanc
"""
expenses = accounting_export.expenses.all()

accounts_payable_account_id = export_settings.default_back_account_id
accounts_payable_account_id = export_settings.default_bank_account_id

document_number = accounting_export.description['claim_number'] if accounting_export.description and accounting_export.description.get('claim_number') else accounting_export.description['expense_number']

Expand Down
4 changes: 2 additions & 2 deletions apps/fyle/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from rest_framework.views import status

from apps.fyle.helpers import get_expense_fields
from apps.fyle.models import ExpenseFilter, Expense
from apps.fyle.models import Expense, ExpenseFilter
from apps.workspaces.models import FyleCredential, Workspace

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -86,7 +86,7 @@ def format_fyle_fields(self, workspace_id):
Get Fyle Fields
"""

attribute_types = ['EMPLOYEE', 'CATEGORY', 'PROJECT', 'COST_CENTER', 'TAX_GROUP', 'CORPORATE_CARD', 'MERCHANT']
attribute_types = ['CATEGORY', 'PROJECT', 'COST_CENTER', 'TAX_GROUP', 'CORPORATE_CARD', 'MERCHANT']

attributes = ExpenseAttribute.objects.filter(
~Q(attribute_type__in=attribute_types),
Expand Down
201 changes: 0 additions & 201 deletions apps/mappings/imports/modules/employees.py

This file was deleted.

2 changes: 1 addition & 1 deletion apps/mappings/imports/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def chain_import_fields_to_fyle(workspace_id):
)

for mapping_setting in mapping_settings:
if mapping_setting.source_field in ['PROJECT', 'COST_CENTER', 'EMPLOYEE']:
if mapping_setting.source_field in ['PROJECT', 'COST_CENTER']:
chain.append(
'apps.mappings.imports.tasks.trigger_import_via_schedule',
workspace_id,
Expand Down
4 changes: 1 addition & 3 deletions apps/mappings/imports/tasks.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from apps.mappings.imports.modules.categories import Category
from apps.mappings.imports.modules.cost_centers import CostCenter
from apps.mappings.imports.modules.employees import Employee
from apps.mappings.imports.modules.expense_custom_fields import ExpenseCustomField
from apps.mappings.imports.modules.merchants import Merchant
from apps.mappings.imports.modules.projects import Project
Expand All @@ -10,8 +9,7 @@
'CATEGORY': Category,
'MERCHANT': Merchant,
'COST_CENTER': CostCenter,
'PROJECT': Project,
'EMPLOYEE': Employee,
'PROJECT': Project
}


Expand Down
10 changes: 8 additions & 2 deletions apps/mappings/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
from apps.mappings.imports.modules.expense_custom_fields import ExpenseCustomField
from apps.mappings.imports.schedules import schedule_or_delete_fyle_import_tasks
from apps.mappings.models import ImportLog
from apps.workspaces.models import FyleCredential, ImportSetting
from apps.mappings.tasks import schedule_auto_map_employees
from apps.workspaces.models import ExportSetting, FyleCredential, ImportSetting

logger = logging.getLogger(__name__)


@receiver(post_save, sender=ExportSetting)
def run_post_export_settings_triggers(sender, instance: ExportSetting, **kwargs):
schedule_auto_map_employees(employee_mapping_preference=instance.auto_map_employees, workspace_id=int(instance.workspace_id))


@receiver(post_save, sender=MappingSetting)
def run_post_mapping_settings_triggers(sender, instance: MappingSetting, **kwargs):
"""
Expand All @@ -42,7 +48,7 @@ def run_pre_mapping_settings_triggers(sender, instance: MappingSetting, **kwargs
:param instance: Row instance of Sender Class
:return: None
"""
default_attributes = ['EMPLOYEE', 'CATEGORY', 'PROJECT', 'COST_CENTER', 'TAX_GROUP', 'CORPORATE_CARD']
default_attributes = ['CATEGORY', 'PROJECT', 'COST_CENTER', 'TAX_GROUP', 'CORPORATE_CARD']

instance.source_field = instance.source_field.upper().replace(' ', '_')

Expand Down
107 changes: 106 additions & 1 deletion apps/mappings/tasks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import logging
from datetime import datetime
from typing import List

from django_q.models import Schedule
from fyle_accounting_mappings.helpers import EmployeesAutoMappingHelper
from fyle_accounting_mappings.models import EmployeeMapping
from fyle_integrations_platform_connector import PlatformConnector

from apps.accounting_exports.models import Error
from apps.business_central.utils import BusinessCentralConnector
from apps.workspaces.models import BusinessCentralCredentials
from apps.mappings.exceptions import handle_import_exceptions
from apps.workspaces.models import BusinessCentralCredentials, ExportSetting, FyleCredential

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


def sync_business_central_attributes(business_central_attribute_type: str, workspace_id: int):
Expand All @@ -20,3 +34,94 @@ def sync_business_central_attributes(business_central_attribute_type: str, works

sync_function = sync_functions[business_central_attribute_type]
sync_function()


def get_mapped_attributes_ids(source_attribute_type: str, destination_attribute_type: str, errored_attribute_ids: List[int]):

mapped_attribute_ids = []

if source_attribute_type == "EMPLOYEE":
params = {
'source_employee_id__in': errored_attribute_ids,
}

if destination_attribute_type == "EMPLOYEE":
params['destination_employee_id__isnull'] = False
else:
params['destination_vendor_id__isnull'] = False
mapped_attribute_ids: List[int] = EmployeeMapping.objects.filter(
**params
).values_list('source_employee_id', flat=True)

return mapped_attribute_ids


def resolve_expense_attribute_errors(
source_attribute_type: str, workspace_id: int, destination_attribute_type: str = None):
"""
Resolve Expense Attribute Errors
:return: None
"""
errored_attribute_ids: List[int] = Error.objects.filter(
is_resolved=False,
workspace_id=workspace_id,
type='{}_MAPPING'.format(source_attribute_type)
).values_list('expense_attribute_id', flat=True)

if errored_attribute_ids:
mapped_attribute_ids = get_mapped_attributes_ids(source_attribute_type, destination_attribute_type, errored_attribute_ids)

if mapped_attribute_ids:
Error.objects.filter(expense_attribute_id__in=mapped_attribute_ids).update(is_resolved=True)


@handle_import_exceptions
def async_auto_map_employees(workspace_id: int):
export_settings: ExportSetting = ExportSetting.objects.get(workspace_id=workspace_id)

employee_mapping_preference = export_settings.auto_map_employees

destination_type = export_settings.employee_field_mapping

fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id)

platform = PlatformConnector(fyle_credentials=fyle_credentials)
sage_intacct_credentials = BusinessCentralCredentials.objects.get(workspace_id=workspace_id)
sage_intacct_connection = BusinessCentralConnector(
credentials_object=sage_intacct_credentials, workspace_id=workspace_id)

platform.employees.sync()
if destination_type == 'EMPLOYEE':
sage_intacct_connection.sync_employees()
else:
sage_intacct_connection.sync_vendors()

EmployeesAutoMappingHelper(workspace_id, destination_type, employee_mapping_preference).reimburse_mapping()
resolve_expense_attribute_errors(
source_attribute_type="EMPLOYEE",
workspace_id=workspace_id,
destination_attribute_type=destination_type,
)


def schedule_auto_map_employees(employee_mapping_preference: str, workspace_id: int):
if employee_mapping_preference:
start_datetime = datetime.now()

schedule, _ = Schedule.objects.update_or_create(
func='apps.mappings.tasks.async_auto_map_employees',
args='{}'.format(workspace_id),
defaults={
'schedule_type': Schedule.MINUTES,
'minutes': 24 * 60,
'next_run': start_datetime
}
)
else:
schedule: Schedule = Schedule.objects.filter(
func='apps.mappings.tasks.async_auto_map_employees',
args='{}'.format(workspace_id)
).first()

if schedule:
schedule.delete()
Loading

0 comments on commit bc4f659

Please sign in to comment.