Skip to content

Commit

Permalink
merging latest import-projects-base
Browse files Browse the repository at this point in the history
  • Loading branch information
labhvam5 committed Nov 20, 2023
2 parents 69fb03f + 1b28ed8 commit d4327f7
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 47 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "fyle_integrations_imports"]
path = fyle_integrations_imports
url = https://github.com/fylein/fyle_integrations_imports.git
7 changes: 6 additions & 1 deletion apps/fyle/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,12 @@ def import_and_export_expenses(report_id: str, org_id: str) -> None:

group_expenses_and_save(expenses, task_log, workspace)

export_to_qbo(workspace.id, 'AUTO')
# Export only selected expense groups
expense_ids = Expense.objects.filter(report_id=report_id, org_id=org_id).values_list('id', flat=True)
expense_groups = ExpenseGroup.objects.filter(expenses__id__in=[expense_ids], workspace_id=workspace.id).distinct('id').values('id')
expense_group_ids = [expense_group['id'] for expense_group in expense_groups]

export_to_qbo(workspace.id, None, expense_group_ids)

except Exception:
handle_import_exception(task_log)
54 changes: 54 additions & 0 deletions apps/mappings/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from qbosdk.exceptions import WrongParamsError as QBOWrongParamsError

from apps.workspaces.models import QBOCredential
from fyle_integrations_imports.models import ImportLog

logger = logging.getLogger(__name__)
logger.level = logging.INFO
Expand Down Expand Up @@ -50,3 +51,56 @@ def new_fn(workspace_id: int, *args):
return new_fn

return decorator


def handle_import_exceptions_v2(func):
def new_fn(expense_attribute_instance, *args):
import_log: ImportLog = args[0]
workspace_id = import_log.workspace_id
attribute_type = import_log.attribute_type
error = {
'task': 'Import {0} to Fyle and Auto Create Mappings'.format(attribute_type),
'workspace_id': workspace_id,
'message': None,
'response': None
}
try:
return func(expense_attribute_instance, *args)
except WrongParamsError as exception:
error['message'] = exception.message
error['response'] = exception.response
error['alert'] = True
import_log.status = 'FAILED'

except InvalidTokenError:
error['message'] = 'Invalid Token for fyle'
error['alert'] = False
import_log.status = 'FAILED'

except InternalServerError:
error['message'] = 'Internal server error while importing to Fyle'
error['alert'] = True
import_log.status = 'FAILED'

except (QBOWrongParamsError, QBOInvalidTokenError, QBOCredential.DoesNotExist) as exception:
error['message'] = 'Invalid Token or QBO credentials does not exist workspace_id - {0}'.format(workspace_id)
error['alert'] = False
error['response'] = exception.__dict__
import_log.status = 'FAILED'

except Exception:
response = traceback.format_exc()
error['message'] = 'Something went wrong'
error['response'] = response
error['alert'] = False
import_log.status = 'FATAL'

if error['alert']:
logger.error(error)
else:
logger.info(error)

import_log.error_log = error
import_log.save()

return new_fn
5 changes: 3 additions & 2 deletions apps/mappings/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ def schedule_or_delete_fyle_import_tasks(configuration: WorkspaceGeneralSettings
elif not configuration.import_categories and not configuration.import_items and not configuration.import_vendors_as_merchants:
Schedule.objects.filter(func='apps.mappings.tasks.auto_import_and_map_fyle_fields', args='{}'.format(configuration.workspace_id)).delete()


def get_auto_sync_permission(mapping_setting: MappingSetting):
"""
Get the auto sync permission
:return: bool
"""
is_auto_sync_status_allowed = False
if (mapping_setting.destination_field == 'PROJECT' and mapping_setting.source_field == 'CUSTOMER') or mapping_setting.source_field == 'CATEGORY':
if (mapping_setting.destination_field == 'CUSTOMER' and mapping_setting.source_field == 'PROJECT') or mapping_setting.source_field == 'CATEGORY':
is_auto_sync_status_allowed = True

return is_auto_sync_status_allowed
return is_auto_sync_status_allowed
55 changes: 21 additions & 34 deletions apps/mappings/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from apps.mappings.models import GeneralMapping
from apps.workspaces.models import WorkspaceGeneralSettings, QBOCredential
from apps.mappings.helpers import get_auto_sync_permission
from fyle_integrations_imports.queues import chain_import_fields_to_fyle
from fyle_integrations_imports.dataclasses import TaskSetting

SYNC_METHODS = {
'ACCOUNT': 'accounts',
Expand Down Expand Up @@ -99,48 +101,33 @@ def async_disable_category_for_items_mapping(workspace_id: int):
async_task('apps.mappings.tasks.disable_category_for_items_mapping', workspace_id)


def construct_task_settings_payload(workspace_id):
def construct_tasks_and_chain_import_fields_to_fyle(workspace_id):
"""
Chain import fields to Fyle
:param workspace_id: Workspace Id
"""
mapping_settings = MappingSetting.objects.filter(workspace_id=workspace_id, import_to_fyle=True)
credentials = QBOCredential.objects.get(workspace_id=workspace_id)

task_settings = {
'import_tax_codes': {
'destination_field': '',
'destination_sync_method': '',
'is_auto_sync_enabled' : False,
'import': False,
},
'import_vendors_as_merchants': {
'destination_field': '',
'destination_sync_method': '',
'is_auto_sync_enabled' : False,
'import': False,
},
'import_categories': {
'destination_field': '',
'destination_sync_method': '',
'is_auto_sync_enabled' : False,
'import': False,
},
task_settings: TaskSetting = {
'import_tax': None,
'import_vendors_as_merchants': None,
'import_categories': None,
'mapping_settings': [],
'credentails': credentials,
'credentials': credentials,
'sdk_connection_string': 'apps.quickbooks_online.utils.QBOConnector',
}

for mapping_setting in mapping_settings:
if mapping_setting.source_field in ['PROJECT']:
task_settings['mapping_settings'].append({
'source_field': mapping_setting.source_field,
'destination_field': mapping_setting.destination_field,
'destination_sync_method': SYNC_METHODS[mapping_setting.destination_field],
'is_auto_sync_enabled' : get_auto_sync_permission(mapping_setting),
'is_custom': False,
})

# Make a call to the SDK
# chain_import_fields_to_fyle(workspace_id, task_settings)
pass
# For now we are only adding PROJECTS support that is why we are hardcoding it
if mapping_settings:
for mapping_setting in mapping_settings:
if mapping_setting.source_field in ['PROJECT']:
task_settings['mapping_settings'].append({
'source_field': mapping_setting.source_field,
'destination_field': mapping_setting.destination_field,
'destination_sync_method': SYNC_METHODS[mapping_setting.destination_field],
'is_auto_sync_enabled': get_auto_sync_permission(mapping_setting),
'is_custom': False,
})

chain_import_fields_to_fyle(workspace_id, task_settings)
6 changes: 3 additions & 3 deletions apps/mappings/schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def schedule_or_delete_fyle_import_tasks(workspace_general_settings: WorkspaceGe

if task_to_be_scheduled:
Schedule.objects.update_or_create(
func='apps.mappings.queues.construct_task_settings_payload',
func='apps.mappings.queues.construct_tasks_and_chain_import_fields_to_fyle',
args='{}'.format(workspace_general_settings.workspace_id),
defaults={
'schedule_type': Schedule.MINUTES,
Expand All @@ -30,13 +30,13 @@ def schedule_or_delete_fyle_import_tasks(workspace_general_settings: WorkspaceGe

import_fields_count = MappingSetting.objects.filter(
import_to_fyle=True,
workspace_id=workspace_general_settings.workspace_id,
workspace_id=workspace_general_settings.workspace_id,
source_field__in=['PROJECT']
).count()

# If the import fields count is 0, delete the schedule
if import_fields_count == 0:
Schedule.objects.filter(
func='apps.mappings.queues.construct_task_settings_payload',
func='apps.mappings.queues.construct_tasks_and_chain_import_fields_to_fyle',
args='{}'.format(workspace_general_settings.workspace_id)
).delete()
1 change: 0 additions & 1 deletion apps/mappings/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from django.dispatch import receiver
from fyle_accounting_mappings.models import EmployeeMapping, Mapping, MappingSetting

from apps.mappings.helpers import schedule_or_delete_fyle_import_tasks
from apps.mappings.queues import (
async_auto_create_expense_field_mapping,
schedule_cost_centers_creation,
Expand Down
8 changes: 7 additions & 1 deletion apps/mappings/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,13 @@ def create_fyle_categories_payload(categories: List[DestinationAttribute], works
if updated_categories:
for category in updated_categories:
destination_id_of_category = category.mapping.first().destination.destination_id
payload.append({'id': category.source_id, 'name': category.value, 'code': destination_id_of_category, 'is_enabled': category.active})
payload.append({
'id': category.source_id,
'name': category.value,
'code': destination_id_of_category,
# Always keep Unspecified category enabled
'is_enabled': category.active if category.value != 'Unspecified' else True
})
else:
existing_category_names = ExpenseAttribute.objects.filter(attribute_type='CATEGORY', workspace_id=workspace_id).values_list('value', flat=True)

Expand Down
2 changes: 1 addition & 1 deletion apps/quickbooks_online/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def format_special_characters(value: str) -> str:
return formatted_string


CHARTS_OF_ACCOUNTS = ['Expense', 'Other Expense', 'Fixed Asset', 'Cost of Goods Sold', 'Current Liability', 'Equity', 'Other Current Asset', 'Other Current Liability', 'Long Term Liability', 'Current Asset', 'Income', 'Other Income']
CHARTS_OF_ACCOUNTS = ['Expense', 'Other Expense', 'Fixed Asset', 'Cost of Goods Sold', 'Current Liability', 'Equity', 'Other Current Asset', 'Other Current Liability', 'Long Term Liability', 'Current Asset', 'Income', 'Other Income', 'Other Asset']


class QBOConnector:
Expand Down
13 changes: 9 additions & 4 deletions apps/workspaces/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,16 +232,21 @@ def post_to_integration_settings(workspace_id: int, active: bool):
logger.error(error)


def export_to_qbo(workspace_id, export_mode=None):
def export_to_qbo(workspace_id, export_mode=None, expense_group_ids=[]):
general_settings = WorkspaceGeneralSettings.objects.get(workspace_id=workspace_id)
last_export_detail = LastExportDetail.objects.get(workspace_id=workspace_id)
last_exported_at = datetime.now()
is_expenses_exported = False
export_mode = export_mode or 'MANUAL'
expense_group_filters = {
'exported_at__isnull': True,
'workspace_id': workspace_id
}
if expense_group_ids:
expense_group_filters['id__in'] = expense_group_ids

if general_settings.reimbursable_expenses_object:

expense_group_ids = ExpenseGroup.objects.filter(fund_source='PERSONAL', exported_at__isnull=True, workspace_id=workspace_id).values_list('id', flat=True)
expense_group_ids = ExpenseGroup.objects.filter(fund_source='PERSONAL', **expense_group_filters).values_list('id', flat=True)

if len(expense_group_ids):
is_expenses_exported = True
Expand Down Expand Up @@ -279,7 +284,7 @@ def export_to_qbo(workspace_id, export_mode=None):
)

if general_settings.corporate_credit_card_expenses_object:
expense_group_ids = ExpenseGroup.objects.filter(fund_source='CCC', exported_at__isnull=True, workspace_id=workspace_id).values_list('id', flat=True)
expense_group_ids = ExpenseGroup.objects.filter(fund_source='CCC', **expense_group_filters).values_list('id', flat=True)

if len(expense_group_ids):
is_expenses_exported = True
Expand Down
1 change: 1 addition & 0 deletions fyle_integrations_imports
1 change: 1 addition & 0 deletions fyle_qbo_api/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
'corsheaders',
'fyle_rest_auth',
'fyle_accounting_mappings',
'fyle_integrations_imports',
'django_q',
'django_filters',
# User Created Apps
Expand Down
6 changes: 6 additions & 0 deletions sql/functions/delete-workspace.sql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ BEGIN
GET DIAGNOSTICS rcount = ROW_COUNT;
RAISE NOTICE 'Deleted % errors', rcount;

DELETE
FROM import_logs il
WHERE il.workspace_id = _workspace_id;
GET DIAGNOSTICS rcount = ROW_COUNT;
RAISE NOTICE 'Deleted % import_logs', rcount;

DELETE
FROM bill_lineitems bl
WHERE bl.bill_id IN (
Expand Down

0 comments on commit d4327f7

Please sign in to comment.