Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add exports module base structure #85

Merged
merged 16 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/accounting_exports/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,13 @@ def _group_expenses(expenses: List[Expense], export_setting: ExportSetting, fund
group_by_field = fund_source_data.get('group_by')
date_field = fund_source_data.get('date_field')

default_fields.extend([group_by_field, fund_source])
default_fields.extend(group_by_field)

if date_field:
default_fields.append(date_field)

# Extract expense IDs from the provided expenses
expense_ids = [expense.id for expense in expenses]

# Retrieve expenses from the database
expenses = Expense.objects.filter(id__in=expense_ids).all()

Expand Down Expand Up @@ -109,7 +108,6 @@ def create_accounting_export(expense_objects: List[Expense], fund_source: str, w
"""
Group expenses by report_id and fund_source, format date fields, and create AccountingExport objects.
"""

# Retrieve the ExportSetting for the workspace
export_setting = ExportSetting.objects.get(workspace_id=workspace_id)

Expand Down
22 changes: 11 additions & 11 deletions apps/fyle/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except FyleCredential.DoesNotExist:
logger.info('Fyle credentials not found %s', args[1]) # args[1] is workspace_id
args[2].detail = {'message': 'Fyle credentials do not exist in workspace'}
args[2].status = 'FAILED'
args[2].save()
logger.info('Fyle credentials not found %s', args[0]) # args[1] is workspace_id
args[1].detail = {'message': 'Fyle credentials do not exist in workspace'}
args[1].status = 'FAILED'
args[1].save()

except NoPrivilegeError:
logger.info('Invalid Fyle Credentials / Admin is disabled')
args[2].detail = {'message': 'Invalid Fyle Credentials / Admin is disabled'}
args[2].status = 'FAILED'
args[2].save()
args[1].detail = {'message': 'Invalid Fyle Credentials / Admin is disabled'}
args[1].status = 'FAILED'
args[1].save()

except Exception:
error = traceback.format_exc()
args[2].detail = {'error': error}
args[2].status = 'FATAL'
args[2].save()
logger.exception('Something unexpected happened workspace_id: %s %s', args[1], args[2].detail)
args[1].detail = {'error': error}
args[1].status = 'FATAL'
args[1].save()
logger.exception('Something unexpected happened workspace_id: %s %s', args[0], args[1].detail)

return wrapper
3 changes: 1 addition & 2 deletions apps/fyle/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ def create_expense_objects(expenses: List[Dict], workspace_id: int):

# Create an empty list to store expense objects
expense_objects = []

for expense in expenses:
# Iterate through custom property fields and handle empty values
for custom_property_field in expense['custom_properties']:
Expand Down Expand Up @@ -171,7 +170,7 @@ def create_expense_objects(expenses: List[Dict], workspace_id: int):
)

# Check if an AccountingExport related to the expense object already exists
if not Expense.objects.filter(accountingexport__isnull=False).distinct():
if not expense_object.accountingexport_set.exists():
expense_objects.append(expense_object)

return expense_objects
Expand Down
8 changes: 4 additions & 4 deletions apps/fyle/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@ def import_expenses(workspace_id, accounting_export: AccountingExport, source_ac
}
export_settings = ExportSetting.objects.get(workspace_id=workspace_id)
workspace = Workspace.objects.get(pk=workspace_id)
last_synced_at = getattr(workspace, f"{fund_source_key.lower()}_last_synced_at", None)
last_synced_at = getattr(workspace, f"{fund_source_map.get(fund_source_key)}_last_synced_at", None)
fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id)

platform = PlatformConnector(fyle_credentials)

expenses = platform.expenses.get(
source_account_type=[source_account_type],
state=getattr(export_settings, f"{fund_source_key.lower()}_expense_state"),
state=getattr(export_settings, f"{fund_source_map.get(fund_source_key)}_expense_state"),
settled_at=last_synced_at if getattr(export_settings, f"{fund_source_map.get(fund_source_key)}_expense_state") == 'PAYMENT_PROCESSING' else None,
approved_at=last_synced_at if getattr(export_settings, f"{fund_source_map.get(fund_source_key)}_expense_state") == 'APPROVED' else None,
filter_credit_expenses=(fund_source_key == 'CCC'),
last_paid_at=last_synced_at if getattr(export_settings, f"{fund_source_key.lower()}_expense_state") == 'PAID' else None
last_paid_at=last_synced_at if getattr(export_settings, f"{fund_source_map.get(fund_source_key)}_expense_state") == 'PAID' else None
)

if expenses:
Expand All @@ -59,7 +59,7 @@ def import_expenses(workspace_id, accounting_export: AccountingExport, source_ac

with transaction.atomic():
expenses_object = Expense.create_expense_objects(expenses, workspace_id)
AccountingExport.create_accounting_export_report_id(
AccountingExport.create_accounting_export(
expenses_object,
fund_source=fund_source_key,
workspace_id=workspace_id
Expand Down
Empty file.
4 changes: 4 additions & 0 deletions apps/sage300/exports/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@


def get_sage300_connection_class():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

pass
6 changes: 6 additions & 0 deletions apps/sage300/exports/purchase_invoice/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class PurchaceInvoice():
pass


class PurchaceInvoiceLineitems():
pass
37 changes: 37 additions & 0 deletions apps/sage300/exports/purchase_invoice/queues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from typing import List
from django_q.tasks import Chain

from apps.accounting_exports.models import AccountingExport
from apps.workspaces.models import FyleCredential


def check_accounting_export_and_start_import(self, export_type: str, accounting_exports: List[AccountingExport]):
"""
Check accounting export group and start export
"""

fyle_credentials = FyleCredential.objects.filter(workspace_id=self.workspace_id)

chain = Chain()
chain.append('apps.fyle.helpers.sync_dimensions', fyle_credentials, self.workspace_id)
for index, accounting_export_group in enumerate(accounting_exports):
accounting_export, _ = AccountingExport.objects.get_or_create(
workspace_id=accounting_export_group.workspace_id,
id=accounting_export_group.id,
defaults={
'status': 'ENQUEUED',
'type': export_type
}
)
if accounting_export.status not in ['IN_PROGRESS', 'ENQUEUED']:
accounting_export.status = 'ENQUEUED'
accounting_export.save()

last_export = False
if accounting_export.count() == index + 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wont this condition always be false?

last_export = True

chain.append('apps.sage300.purchace_invoice.queues.create_purchace_invoice', accounting_export, last_export)

if chain.length() > 1:
chain.run()
79 changes: 79 additions & 0 deletions apps/sage300/exports/purchase_invoice/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from datetime import datetime
from django.db import transaction

from apps.accounting_exports.models import AccountingExport
from apps.sage300.exports.purchase_invoice.models import PurchaceInvoice, PurchaceInvoiceLineitems
from apps.workspaces.models import ExportSetting
from apps.sage300.utils import SageDesktopConnector


class ExportPurchaceInvoice:

"""
Class for purchace invoice module
"""

def __init__(
self,
workspace_id: int,
):
self.workspace_id = workspace_id

def trigger_import(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export

"""
Trigger import for Project module
"""
self.check_accounting_export_and_start_import()

def __construct_purchace_invoice(item, lineitem):
pass

def post_purchace_invoice(self, item, lineitem):
"""
Export Purchace Invoice
"""

try:
purchace_invoice_payload = self.__construct_purchace_invoice(item, lineitem)

sage300_connection = SageDesktopConnector()
created_purchace_invoice_ = sage300_connection.connection.documents.post_document(purchace_invoice_payload)
return created_purchace_invoice_

except Exception as e:
print(e)

def create_purchace_invoice(self, accounting_export: AccountingExport):
"""
function to create purchace invoice
"""

export_settings = ExportSetting.objects.filter(workspace_id=accounting_export.workspace_id)

if accounting_export.status not in ['IN_PROGRESS', 'COMPLETE']:
accounting_export.status = 'IN_PROGRESS'
accounting_export.save()
else:
return

try:
with transaction.atomic():
purchace_invoice_object = PurchaceInvoice.create_expense_report(accounting_export)

purchace_invoice_lineitems_objects = PurchaceInvoiceLineitems.create_expense_report_lineitems(
accounting_export, export_settings
)

created_purchace_invoice = self.post_purchace_invoice(
purchace_invoice_object, purchace_invoice_lineitems_objects
)

accounting_export.detail = created_purchace_invoice
accounting_export.status = 'COMPLETE'
accounting_export.exported_at = datetime.now()

accounting_export.save()

except Exception as e:
print(e)
# will add execptions here
21 changes: 21 additions & 0 deletions apps/sage300/exports/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import List

from sage300.exports.purchase_invoice.tasks import PurchaceInvoice
from accounting_exports.models import AccountingExport

EXPORT_CLASS_MAP = {
'PURCHACE_INVOICE': PurchaceInvoice,
}


def trigger_export_via_schedule(workspace_id: int, export_type: str, accounting_exports: List[AccountingExport]):
"""
Trigger import via schedule
:param workspace_id: Workspace id
:param destination_field: Destination field
:param source_field: Type of attribute (e.g., 'PROJECT', 'CATEGORY', 'COST_CENTER')
"""

module_class = EXPORT_CLASS_MAP[export_type]
item = module_class(workspace_id, accounting_exports)
item.trigger_export()
4 changes: 2 additions & 2 deletions apps/workspaces/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class Workspace(models.Model):
name = StringNotNullField(help_text='Name of the workspace')
user = models.ManyToManyField(User, help_text='Reference to users table')
org_id = models.CharField(max_length=255, help_text='org id', unique=True)
last_synced_at = CustomDateTimeField(help_text='Datetime when expenses were pulled last')
ccc_last_synced_at = CustomDateTimeField(help_text='Datetime when ccc expenses were pulled last')
reimbursable_last_synced_at = CustomDateTimeField(help_text='Datetime when expenses were pulled last')
credit_card_last_synced_at = CustomDateTimeField(help_text='Datetime when ccc expenses were pulled last')
source_synced_at = CustomDateTimeField(help_text='Datetime when source dimensions were pulled')
destination_synced_at = CustomDateTimeField(help_text='Datetime when destination dimensions were pulled')
onboarding_state = StringOptionsField(
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ def create_temp_workspace():
id=workspace_id,
name='Fyle For Testing {}'.format(workspace_id),
org_id='riseabovehate{}'.format(workspace_id),
last_synced_at=None,
ccc_last_synced_at=None,
reimbursable_last_synced_at=None,
credit_card_last_synced_at=None,
created_at=datetime.now(tz=timezone.utc),
updated_at=datetime.now(tz=timezone.utc)
)
Expand Down
Loading