Skip to content

Commit

Permalink
add support for export of expenses from fyle to sage300 (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
NileshPant1999 authored Dec 11, 2023
1 parent 809effe commit 7a17ba8
Show file tree
Hide file tree
Showing 10 changed files with 421 additions and 8 deletions.
3 changes: 3 additions & 0 deletions apps/accounting_exports/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ def create_accounting_export(expense_objects: List[Expense], fund_source: str, w
if date_field:
date_field = date_field.lower()

if date_field:
date_field = date_field.lower()

# Calculate and assign 'last_spent_at' based on the chosen date field
if date_field == 'last_spent_at':
latest_expense = Expense.objects.filter(id__in=accounting_export['expense_ids']).order_by('-spent_at').first()
Expand Down
4 changes: 2 additions & 2 deletions apps/fyle/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
FyleFieldsView,
DependentFieldSettingView,
ExportableAccountingExportView,
AccoutingExportSyncView
AccountingExportSyncView
)


accounting_exports_path = [
path('exportable_accounting_exports/', ExportableAccountingExportView.as_view(), name='exportable-accounting-exports'),
path('accounting_exports/sync/', AccoutingExportSyncView.as_view(), name='sync-accounting-exports'),
path('accounting_exports/sync/', AccountingExportSyncView.as_view(), name='sync-accounting-exports'),
]

other_paths = [
Expand Down
2 changes: 1 addition & 1 deletion apps/fyle/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def get(self, request, *args, **kwargs):
)


class AccoutingExportSyncView(generics.CreateAPIView):
class AccountingExportSyncView(generics.CreateAPIView):
"""
Create expense groups
"""
Expand Down
55 changes: 55 additions & 0 deletions apps/workspaces/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,58 @@ def schedule_sync(workspace_id: int, schedule_enabled: bool, hours: int, email_a
schedule.delete()

return advance_settings


def export_to_sage300(workspace_id: int):
"""
Function to export expenses to Sage 300
"""
# Retrieve export settings for the given workspace
export_settings = ExportSetting.objects.get(workspace_id=workspace_id)

# Update or create an AccountingExportSummary for the workspace
accounting_summary, _ = AccountingExportSummary.objects.update_or_create(workspace_id=workspace_id)

# Set the timestamp for the last export
last_exported_at = datetime.now()

# Flag to track if expenses are exported
is_expenses_exported = False

# Dictionary mapping export types to their corresponding export classes
export_map = {
'PURCHASE_INVOICE': ExportPurchaseInvoice(),
'DIRECT_COST': ExportDirectCost()
}

# Check and export reimbursable expenses if configured
if export_settings.reimbursable_expenses_export_type:
# Get IDs of unreexported accounting exports for personal fund source
accounting_export_ids = AccountingExport.objects.filter(
fund_source='PERSONAL', exported_at__isnull=True).values_list('id', flat=True)

if len(accounting_export_ids):
# Set the flag indicating expenses are exported
is_expenses_exported = True
# Get the appropriate export class and trigger the export
export = export_map[export_settings.reimbursable_expenses_export_type]
export.trigger_export(workspace_id=workspace_id, accounting_export_ids=accounting_export_ids)

# Check and export credit card expenses if configured
if export_settings.credit_card_expense_export_type:
# Get IDs of unreexported accounting exports for credit card fund source
accounting_export_ids = AccountingExport.objects.filter(
fund_source='CCC', exported_at__isnull=True).values_list('id', flat=True)

if len(accounting_export_ids):
# Set the flag indicating expenses are exported
is_expenses_exported = True
# Get the appropriate export class and trigger the export
export = export_map[export_settings.credit_card_expense_export_type]
export.trigger_export(workspace_id=workspace_id, accounting_export_ids=accounting_export_ids)

# Update the accounting summary if expenses are exported
if is_expenses_exported:
accounting_summary.last_exported_at = last_exported_at
accounting_summary.export_mode = 'MANUAL'
accounting_summary.save()
4 changes: 3 additions & 1 deletion apps/workspaces/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@
ImportSettingView,
ExportSettingView,
AdvancedSettingView,
WorkspaceAdminsView
WorkspaceAdminsView,
TriggerExportsView
)


workspace_app_paths = [
path('', WorkspaceView.as_view(), name='workspaces'),
path('ready/', ReadyView.as_view(), name='ready'),
path('<int:workspace_id>/credentials/sage300/', Sage300CredsView.as_view(), name='sage300-creds'),
path('<int:workspace_id>/exports/trigger/', TriggerExportsView.as_view(), name='trigger-exports'),
path('<int:workspace_id>/export_settings/', ExportSettingView.as_view(), name='export-settings'),
path('<int:workspace_id>/import_settings/', ImportSettingView.as_view(), name='import-settings'),
path('<int:workspace_id>/advanced_settings/', AdvancedSettingView.as_view(), name='advanced-settings'),
Expand Down
17 changes: 15 additions & 2 deletions apps/workspaces/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import logging
from django.contrib.auth import get_user_model

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

from fyle_rest_auth.utils import AuthUtils


from sage_desktop_api.utils import assert_valid

from apps.workspaces.tasks import export_to_sage300
from apps.workspaces.models import (
Workspace,
Sage300Credential,
Expand Down Expand Up @@ -124,3 +124,16 @@ class WorkspaceAdminsView(generics.ListAPIView):
"""
serializer_class = WorkspaceAdminSerializer
queryset = Workspace.objects.all()


class TriggerExportsView(generics.GenericAPIView):
"""
Trigger exports creation
"""

def post(self, request, *args, **kwargs):
export_to_sage300(workspace_id=kwargs['workspace_id'])

return Response(
status=status.HTTP_200_OK
)
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,14 +378,14 @@ def add_export_settings():
default_bank_account_name='Accounts Payable',
default_back_account_id='1',
reimbursable_expense_state='PAYMENT_PROCESSING',
reimbursable_expense_date='current_date' if workspace_id == 1 else 'last_spent_at',
reimbursable_expense_date='SPENT_AT' if workspace_id == 1 else 'LAST_SPENT_AT',
reimbursable_expense_grouped_by='REPORT' if workspace_id == 1 else 'EXPENSE',
credit_card_expense_export_type='DIRECT_COST' if workspace_id in [1, 2] else 'PURCHASE_INVOICE',
credit_card_expense_state='PAYMENT_PROCESSING',
default_ccc_credit_card_account_name='Visa',
default_ccc_credit_card_account_id='12',
credit_card_expense_grouped_by='EXPENSE' if workspace_id == 3 else 'REPORT',
credit_card_expense_date='spent_at'
credit_card_expense_date='SPENT_AT'
)


Expand Down
Loading

0 comments on commit 7a17ba8

Please sign in to comment.