Skip to content

Commit

Permalink
Merge branch 'master' into xero_merchants
Browse files Browse the repository at this point in the history
  • Loading branch information
ruuushhh committed Aug 29, 2023
2 parents fe6131f + 3a35a6b commit 9217c15
Show file tree
Hide file tree
Showing 9 changed files with 362 additions and 285 deletions.
75 changes: 75 additions & 0 deletions apps/fyle/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from fyle_accounting_mappings.models import ExpenseAttribute
from django.db.models import Q

from apps.tasks.models import TaskLog
from apps.workspaces.models import FyleCredential, WorkspaceGeneralSettings, Workspace
from apps.workspaces.serializers import WorkspaceSerializer
from datetime import datetime, timezone
from .models import Expense, ExpenseGroup, ExpenseGroupSettings

from fyle_integrations_platform_connector import PlatformConnector

def get_expense_field(workspace_id):

default_attributes = ['EMPLOYEE', 'CATEGORY', 'PROJECT', 'COST_CENTER', 'CORPORATE_CARD', 'TAX_GROUP']
attributes = ExpenseAttribute.objects.filter(
~Q(attribute_type__in=default_attributes),
workspace_id=workspace_id
).values('attribute_type', 'display_name').distinct()

expense_fields= [
{'attribute_type': 'COST_CENTER', 'display_name': 'Cost Center'},
{'attribute_type': 'PROJECT', 'display_name': 'Project'}
]

for attribute in attributes:
expense_fields.append(attribute)

return expense_fields


def sync_fyle_dimension(workspace_id):

workspace = Workspace.objects.get(id=workspace_id)
if workspace.source_synced_at:
time_interval = datetime.now(timezone.utc) - workspace.source_synced_at

if workspace.source_synced_at is None or time_interval.days > 0:
fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id)

platform = PlatformConnector(fyle_credentials)
platform.import_fyle_dimensions()

workspace.source_synced_at = datetime.now()
workspace.save(update_fields=['source_synced_at'])


def refresh_fyle_dimension(workspace_id):

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

platform = PlatformConnector(fyle_credentials)
platform.import_fyle_dimensions()

workspace = Workspace.objects.get(id=workspace_id)
workspace.source_synced_at = datetime.now()
workspace.save(update_fields=['source_synced_at'])


def exportable_expense_group(workspace_id):

configuration = WorkspaceGeneralSettings.objects.get(workspace_id=workspace_id)
fund_source = []

if configuration.reimbursable_expenses_object:
fund_source.append('PERSONAL')
if configuration.corporate_credit_card_expenses_object:
fund_source.append('CCC')

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

return expense_group_ids
68 changes: 8 additions & 60 deletions apps/fyle/views.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
from datetime import datetime, timezone
from django.db.models import Q

from rest_framework.views import status
from rest_framework import generics
from rest_framework.response import Response

from fyle_accounting_mappings.models import ExpenseAttribute
from fyle_accounting_mappings.serializers import ExpenseAttributeSerializer

from fyle_integrations_platform_connector import PlatformConnector

from apps.tasks.models import TaskLog
from apps.workspaces.models import FyleCredential, WorkspaceGeneralSettings, Workspace
from apps.workspaces.serializers import WorkspaceSerializer

from fyle_integrations_platform_connector import PlatformConnector
from .tasks import create_expense_groups, get_task_log_and_fund_source, async_create_expense_groups
from .tasks import get_task_log_and_fund_source, async_create_expense_groups
from .models import Expense, ExpenseGroup, ExpenseGroupSettings
from .serializers import ExpenseGroupSerializer, ExpenseSerializer, ExpenseFieldSerializer, \
from .serializers import ExpenseGroupSerializer, ExpenseFieldSerializer, \
ExpenseGroupSettingsSerializer
from apps.exceptions import handle_view_exceptions
from .actions import exportable_expense_group, get_expense_field, refresh_fyle_dimension, sync_fyle_dimension


class ExpenseGroupView(generics.ListCreateAPIView):
Expand Down Expand Up @@ -98,19 +86,8 @@ class ExpenseFieldsView(generics.ListAPIView):
serializer_class = ExpenseFieldSerializer

def get(self, request, *args, **kwargs):
default_attributes = ['EMPLOYEE', 'CATEGORY', 'PROJECT', 'COST_CENTER', 'CORPORATE_CARD', 'TAX_GROUP']
attributes = ExpenseAttribute.objects.filter(
~Q(attribute_type__in=default_attributes),
workspace_id=self.kwargs['workspace_id']
).values('attribute_type', 'display_name').distinct()

expense_fields= [
{'attribute_type': 'COST_CENTER', 'display_name': 'Cost Center'},
{'attribute_type': 'PROJECT', 'display_name': 'Project'}
]

for attribute in attributes:
expense_fields.append(attribute)
expense_fields = get_expense_field(workspace_id=kwargs['workspace_id'])

return Response(
expense_fields,
Expand Down Expand Up @@ -146,18 +123,7 @@ def post(self, request, *args, **kwargs):
Sync Data From Fyle
"""

workspace = Workspace.objects.get(id=kwargs['workspace_id'])
if workspace.source_synced_at:
time_interval = datetime.now(timezone.utc) - workspace.source_synced_at

if workspace.source_synced_at is None or time_interval.days > 0:
fyle_credentials = FyleCredential.objects.get(workspace_id=kwargs['workspace_id'])

platform = PlatformConnector(fyle_credentials)
platform.import_fyle_dimensions()

workspace.source_synced_at = datetime.now()
workspace.save(update_fields=['source_synced_at'])
sync_fyle_dimension(workspace_id=kwargs['workspace_id'])

return Response(
status=status.HTTP_200_OK
Expand All @@ -174,15 +140,8 @@ def post(self, request, *args, **kwargs):
"""
Sync data from Fyle
"""

fyle_credentials = FyleCredential.objects.get(workspace_id=kwargs['workspace_id'])

platform = PlatformConnector(fyle_credentials)
platform.import_fyle_dimensions()

workspace = Workspace.objects.get(id=kwargs['workspace_id'])
workspace.source_synced_at = datetime.now()
workspace.save(update_fields=['source_synced_at'])
refresh_fyle_dimension(workspace_id=kwargs['workspace_id'])

return Response(
status=status.HTTP_200_OK
Expand All @@ -194,19 +153,8 @@ class ExportableExpenseGroupsView(generics.RetrieveAPIView):
List Exportable Expense Groups
"""
def get(self, request, *args, **kwargs):
configuration = WorkspaceGeneralSettings.objects.get(workspace_id=kwargs['workspace_id'])
fund_source = []

if configuration.reimbursable_expenses_object:
fund_source.append('PERSONAL')
if configuration.corporate_credit_card_expenses_object:
fund_source.append('CCC')

expense_group_ids = ExpenseGroup.objects.filter(
workspace_id=self.kwargs['workspace_id'],
exported_at__isnull=True,
fund_source__in=fund_source
).values_list('id', flat=True)

expense_group_ids = exportable_expense_group(workspace_id=kwargs['workspace_id'])

return Response(
data={'exportable_expense_group_ids': expense_group_ids},
Expand Down
48 changes: 48 additions & 0 deletions apps/mappings/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import logging
from .serializers import TenantMappingSerializer, GeneralMappingSerializer
from .models import TenantMapping, GeneralMapping
from apps.workspaces.models import XeroCredentials
from apps.xero.utils import XeroConnector
from apps.workspaces.models import Workspace
from ..workspaces.models import WorkspaceGeneralSettings

from django_q.tasks import Chain

from xerosdk.exceptions import UnsuccessfulAuthentication

from .utils import MappingUtils


logger = logging.getLogger(__name__)

def tenant_mapping_view(workspace_id, tenant_mapping_payload):

mapping_utils = MappingUtils(workspace_id)
tenant_mapping_object = mapping_utils.create_or_update_tenant_mapping(tenant_mapping_payload)
xero_credentials = XeroCredentials.objects.filter(workspace_id=workspace_id).first()
workspace = Workspace.objects.filter(id=workspace_id).first()

try:
xero_connector = XeroConnector(xero_credentials, workspace_id=workspace_id)
tenant_mapping = TenantMapping.objects.filter(workspace_id=workspace_id).first()
company_info = xero_connector.get_organisations()[0]
workspace.xero_currency = company_info['BaseCurrency']
workspace.save()
xero_credentials.country = company_info['CountryCode']
xero_credentials.save()

if tenant_mapping and not tenant_mapping.connection_id:
connections = xero_connector.connection.connections.get_all()
connection = list(filter(lambda connection: connection['tenantId'] == tenant_mapping.tenant_id, connections))

if connection:
tenant_mapping.connection_id = connection[0]['id']
tenant_mapping.save()

except UnsuccessfulAuthentication:
logger.info('Xero refresh token is invalid for workspace_id - %s', workspace_id)

except Exception:
logger.info('Error while fetching company information')

return tenant_mapping_object
39 changes: 4 additions & 35 deletions apps/mappings/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@

from fyle_xero_api.utils import assert_valid

from xerosdk.exceptions import UnsuccessfulAuthentication

from .serializers import TenantMappingSerializer, GeneralMappingSerializer
from .models import TenantMapping, GeneralMapping
from apps.workspaces.models import XeroCredentials
from .utils import MappingUtils
from .serializers import TenantMappingSerializer
from .models import TenantMapping
from ..workspaces.models import WorkspaceGeneralSettings
from apps.xero.utils import XeroConnector
from apps.workspaces.models import Workspace
from apps.exceptions import handle_view_exceptions
from .actions import tenant_mapping_view

logger = logging.getLogger(__name__)

Expand All @@ -35,33 +30,7 @@ def post(self, request, *args, **kwargs):

assert_valid(tenant_mapping_payload is not None, 'Request body is empty')

mapping_utils = MappingUtils(kwargs['workspace_id'])
tenant_mapping_object = mapping_utils.create_or_update_tenant_mapping(tenant_mapping_payload)
xero_credentials = XeroCredentials.objects.filter(workspace_id=kwargs['workspace_id']).first()
workspace = Workspace.objects.filter(id=kwargs['workspace_id']).first()

try:
xero_connector = XeroConnector(xero_credentials, workspace_id=kwargs['workspace_id'])
tenant_mapping = TenantMapping.objects.filter(workspace_id=kwargs['workspace_id']).first()
company_info = xero_connector.get_organisations()[0]
workspace.xero_currency = company_info['BaseCurrency']
workspace.save()
xero_credentials.country = company_info['CountryCode']
xero_credentials.save()

if tenant_mapping and not tenant_mapping.connection_id:
connections = xero_connector.connection.connections.get_all()
connection = list(filter(lambda connection: connection['tenantId'] == tenant_mapping.tenant_id, connections))

if connection:
tenant_mapping.connection_id = connection[0]['id']
tenant_mapping.save()

except UnsuccessfulAuthentication:
logger.info('Xero refresh token is invalid for workspace_id - %s', kwargs['workspace_id'])

except Exception:
logger.info('Error while fetching company information')
tenant_mapping_object = tenant_mapping_view(workspace_id=kwargs['workspace_id'],tenant_mapping_payload=tenant_mapping_payload)

return Response(
data=self.serializer_class(tenant_mapping_object).data,
Expand Down
Loading

0 comments on commit 9217c15

Please sign in to comment.