Skip to content

Commit

Permalink
Update base model methods (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
NileshPant1999 authored Nov 27, 2023
1 parent 0840c89 commit 75a246c
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 43 deletions.
17 changes: 9 additions & 8 deletions apps/sage300/exports/accounting_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.db import transaction

from apps.accounting_exports.models import AccountingExport
from apps.workspaces.models import ExportSetting
from apps.workspaces.models import AdvancedSetting


class AccountingDataExporter:
Expand All @@ -11,10 +11,11 @@ class AccountingDataExporter:
Subclasses should implement the 'post' method for posting data.
"""

body_model = None
lineitem_model = None
def __init__(self):
self.body_model = None
self.lineitem_model = None

def post(self, body, lineitems):
def post(self, workspace_id, body, lineitems):
"""
Implement this method to post data to the external accounting system.
"""
Expand All @@ -31,8 +32,8 @@ def create_sage300_object(self, accounting_export: AccountingExport):
NotImplementedError: If the method is not implemented in the subclass.
"""

# Retrieve export settings for the current workspace
export_settings = ExportSetting.objects.filter(workspace_id=accounting_export.workspace_id)
# Retrieve advance settings for the current workspace
advance_settings = AdvancedSetting.objects.filter(workspace_id=accounting_export.workspace_id).first()

# Check and update the status of the accounting export
if accounting_export.status not in ['IN_PROGRESS', 'COMPLETE']:
Expand All @@ -49,11 +50,11 @@ def create_sage300_object(self, accounting_export: AccountingExport):

# Create or update line items for the accounting object
lineitems_model_objects = self.lineitem_model.create_or_update_object(
accounting_export, export_settings
accounting_export, advance_settings
)

# Post the data to the external accounting system
created_object = self.post(body_model_object, lineitems_model_objects)
created_object = self.post(accounting_export.workspace_id, body_model_object, lineitems_model_objects)

# Update the accounting export details
accounting_export.detail = created_object
Expand Down
254 changes: 242 additions & 12 deletions apps/sage300/exports/base_model.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
from typing import Optional
from datetime import datetime
from django.db import models
from django.db.models import Sum

from fyle_accounting_mappings.models import MappingSetting, ExpenseAttribute, Mapping

from apps.accounting_exports.models import AccountingExport
from apps.fyle.models import Expense
from apps.fyle.models import Expense, DependentFieldSetting
from apps.workspaces.models import Workspace, FyleCredential, AdvancedSetting

from apps.sage300.exports.helpers import get_filtered_mapping


class BaseExportModel(models.Model):
"""
Base Model for Sage300 Export
"""
created_at = models.DateTimeField(auto_now_add=True, help_text='Created at')
updated_at = models.DateTimeField(auto_now=True, help_text='Updated at')
workspace = models.ForeignKey(Workspace, on_delete=models.PROTECT, help_text='Reference to Workspace model')

class Meta:
abstract = True

def get_expense_purpose(workspace_id, lineitem: Expense, category: str, advance_setting: AdvancedSetting) -> str:
workspace = Workspace.objects.get(id=workspace_id)
Expand Down Expand Up @@ -49,25 +59,245 @@ def get_expense_purpose(workspace_id, lineitem: Expense, category: str, advance_
return purpose

def get_vendor_id(accounting_export: AccountingExport):
return '124'
return '3a3485d9-5cc7-4668-9557-b06100a3e8c9'

def get_total_amount(accounting_export: AccountingExport):
return '123123'
"""
Calculate the total amount of expenses associated with a given AccountingExport
Parameters:
- accounting_export (AccountingExport): The AccountingExport instance for which to calculate the total amount.
Returns:
- float: The total amount of expenses associated with the provided AccountingExport.
"""

def get_invoice_date(accounting_export: AccountingExport):
return datetime.now()
# Using the related name 'expenses' to access the expenses associated with the given AccountingExport
total_amount = accounting_export.expenses.aggregate(Sum('amount'))['amount__sum']

# If there are no expenses for the given AccountingExport, 'total_amount' will be None
# Handle this case by returning 0 or handling it as appropriate for your application
return total_amount or 0.0

def get_invoice_date(accounting_export: AccountingExport) -> str:
"""
Get the invoice date from the provided AccountingExport.
Parameters:
- accounting_export (AccountingExport): The AccountingExport instance containing the description field.
Returns:
- str: The invoice date as a string in the format '%Y-%m-%dT%H:%M:%S'.
"""
# Check for specific keys in the 'description' field and return the corresponding value
if 'spent_at' in accounting_export.description and accounting_export.description['spent_at']:
return accounting_export.description['spent_at']
elif 'approved_at' in accounting_export.description and accounting_export.description['approved_at']:
return accounting_export.description['approved_at']
elif 'verified_at' in accounting_export.description and accounting_export.description['verified_at']:
return accounting_export.description['verified_at']
elif 'last_spent_at' in accounting_export.description and accounting_export.description['last_spent_at']:
return accounting_export.description['last_spent_at']
elif 'posted_at' in accounting_export.description and accounting_export.description['posted_at']:
return accounting_export.description['posted_at']

# If none of the expected keys are present or if the values are empty, return the current date and time
return datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

def get_job_id(accounting_export: AccountingExport, expense: Expense):
return '2312'
"""
Get the job ID based on the provided AccountingExport and Expense.
Parameters:
- accounting_export (AccountingExport): The AccountingExport instance containing workspace information.
- expense (Expense): The Expense instance containing information for job ID retrieval.
Returns:
- Optional[str]: The job ID as a string if found, otherwise None.
"""

job_id = None

# Retrieve mapping settings for job
job_settings: MappingSetting = MappingSetting.objects.filter(
workspace_id=accounting_export.workspace_id,
destination_field='JOB'
).first()

if job_settings:
# Determine the source value based on the configured source field
if job_settings.source_field == 'PROJECT':
source_value = expense.project
elif job_settings.source_field == 'COST_CENTER':
source_value = expense.cost_center
else:
attribute = ExpenseAttribute.objects.filter(attribute_type=job_settings.source_field).first()
source_value = expense.custom_properties.get(attribute.display_name, None)

# Check for a mapping based on the source value
mapping: Mapping = Mapping.objects.filter(
source_type=job_settings.source_field,
destination_type='JOB',
source__value=source_value,
workspace_id=accounting_export.workspace_id
).first()

# If a mapping is found, retrieve the destination job ID
if mapping:
job_id = mapping.destination.destination_id

return job_id

def get_commitment_id(accounting_export: AccountingExport, expense: Expense):
return '12312'
"""
Get the commitment ID based on the provided AccountingExport and Expense.
Parameters:
- accounting_export (AccountingExport): The AccountingExport instance containing workspace information.
- expense (Expense): The Expense instance containing information for job ID retrieval.
Returns:
- Optional[str]: The commitment ID as a string if found, otherwise None.
"""

commitment_setting: MappingSetting = MappingSetting.objects.filter(
workspace_id=accounting_export.workspace_id,
destination_field='COMMITMENT'
).first()

commitment_id = None
source_id = None

if accounting_export and commitment_setting:
if expense:
if commitment_setting.source_field == 'PROJECT':
source_id = expense.project_id
source_value = expense.project
elif commitment_setting.source_field == 'COST_CENTER':
source_value = expense.cost_center
else:
attribute = ExpenseAttribute.objects.filter(attribute_type=expense.source_field).first()
source_value = expense.custom_properties.get(attribute.display_name, None)
else:
source_value = accounting_export.description[accounting_export.source_field.lower()]

mapping: Mapping = get_filtered_mapping(
commitment_setting.source_field, 'COMMITMENT', accounting_export.workspace_id, source_value, source_id
)

def get_standard_category_id(accounting_export: AccountingExport, expense: Expense):
return '123123'
if mapping:
commitment_id = mapping.destination.destination_id
return commitment_id

def get_cost_code_id(accounting_export: AccountingExport, lineitem: Expense, dependent_field_setting: DependentFieldSetting, job_id: str):
from apps.sage300.models import CostCategory
cost_code_id = None

selected_cost_code = lineitem.custom_properties.get(dependent_field_setting.cost_code_field_name, None)
cost_code = CostCategory.objects.filter(
workspace_id=accounting_export.workspace_id,
cost_code_name=selected_cost_code,
project_id=job_id
).first()

if cost_code:
cost_code_id = cost_code.cost_code_id

return cost_code_id

def get_cost_category_id(expense_group: AccountingExport, lineitem: Expense, dependent_field_setting: DependentFieldSetting, project_id: str, cost_code_id: str):
from apps.sage300.models import CostCategory
cost_category_id = None

selected_cost_category = lineitem.custom_properties.get(dependent_field_setting.cost_type_field_name, None)
cost_category = CostCategory.objects.filter(
workspace_id=expense_group.workspace_id,
cost_code_id=cost_code_id,
project_id=project_id,
name=selected_cost_category
).first()

if cost_category:
cost_category_id = cost_category.cost_category_id

return cost_category_id

def get_standard_category_id(accounting_export: AccountingExport, expense: Expense) -> Optional[str]:
"""
Get the standard category ID based on the provided AccountingExport and Expense.
Parameters:
- accounting_export (AccountingExport): The AccountingExport instance containing workspace information.
- expense (Expense): The Expense instance containing information for standard category ID retrieval.
Returns:
- Optional[str]: The standard category ID as a string if found, otherwise None.
"""
standard_category_id = None

# Retrieve mapping settings for standard category
standard_category_setting: MappingSetting = MappingSetting.objects.filter(
workspace_id=accounting_export.workspace_id,
destination_field='STANDARD_CATEGORY'
).first()

if standard_category_setting:
# Retrieve the attribute corresponding to the source field
attribute = ExpenseAttribute.objects.filter(attribute_type=standard_category_setting.source_field).first()

# Determine the source value based on the configured source field
source_value = expense.custom_properties.get(attribute.display_name, None)

# Check for a mapping based on the source value
mapping: Mapping = Mapping.objects.filter(
source_type=standard_category_setting.source_field,
destination_type='STANDARD_CATEGORY',
source__value=source_value,
workspace_id=accounting_export.workspace_id
).first()

# If a mapping is found, retrieve the destination standard category ID
if mapping:
standard_category_id = mapping.destination.destination_id

return standard_category_id

def get_standard_cost_code_id(accounting_export: AccountingExport, expense: Expense):
return '123123'
"""
Get the standard cost code ID based on the provided AccountingExport and Expense.
class Meta:
abstract = True
Parameters:
- accounting_export (AccountingExport): The AccountingExport instance containing workspace information.
- expense (Expense): The Expense instance containing information for standard category ID retrieval.
Returns:
- Optional[str]: The standard cost code ID as a string if found, otherwise None.
"""
standard_cost_code_id = None

# Retrieve mapping settings for standard cost code
standard_cost_code_setting: MappingSetting = MappingSetting.objects.filter(
workspace_id=accounting_export.workspace_id,
destination_field='STANDARD_COST_CODE'
).first()

if standard_cost_code_setting:
# Retrieve the attribute corresponding to the source field
attribute = ExpenseAttribute.objects.filter(attribute_type=standard_cost_code_setting.source_field).first()

# Determine the source value based on the configured source field
source_value = expense.custom_properties.get(attribute.display_name, None)

# Check for a mapping based on the source value
mapping: Mapping = Mapping.objects.filter(
source_type=standard_cost_code_setting.source_field,
destination_type='STANDARD_COST_CODE',
source__value=source_value,
workspace_id=accounting_export.workspace_id
).first()

# If a mapping is found, retrieve the destination standard cost code ID
if mapping:
standard_cost_code_id = mapping.destination.destination_id

return standard_cost_code_id
17 changes: 17 additions & 0 deletions apps/sage300/exports/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from fyle_accounting_mappings.models import Mapping


def get_filtered_mapping(
source_field: str, destination_type: str, workspace_id: int, source_value: str, source_id: str) -> Mapping:
filters = {
'source_type': source_field,
'destination_type': destination_type,
'workspace_id': workspace_id
}

if source_id:
filters['source__source_id'] = source_id
else:
filters['source__value'] = source_value

return Mapping.objects.filter(**filters).first()
Loading

0 comments on commit 75a246c

Please sign in to comment.