diff --git a/apps/spotlight/prompts/spotlight_prompt.py b/apps/spotlight/prompts/spotlight_prompt.py index 3c00bd6..ee38ca7 100644 --- a/apps/spotlight/prompts/spotlight_prompt.py +++ b/apps/spotlight/prompts/spotlight_prompt.py @@ -88,8 +88,8 @@ "description": "Set grouping to expense, this grouping reflects how the expense entries are posted in QuickBooks Desktop." }}, {{ - "code": "set_reimbursable_expenses_export_grouping_expense_report", - "title": "Group reimbursable expenses export by expense report", + "code": "set_reimbursable_expenses_export_grouping_report", + "title": "Group reimbursable expenses export by report", "description": "Set grouping to expense_report, this grouping reflects how the expense entries are posted in QuickBooks Desktop." }}, {{ diff --git a/apps/spotlight/service.py b/apps/spotlight/service.py index bfaff04..6cf0528 100644 --- a/apps/spotlight/service.py +++ b/apps/spotlight/service.py @@ -1,17 +1,22 @@ +from dataclasses import dataclass from typing import Callable, Dict +from django.db import transaction +import json import requests from apps.fyle.helpers import get_access_token -from apps.workspaces.models import FyleCredential +from apps.workspaces.models import ExportSettings, FyleCredential from .prompts.support_genie import PROMPT as SUPPORT_GENIE_PROMPT from .prompts.spotlight_prompt import PROMPT as SPOTLIGHT_PROMPT from . import llm -code_action_map = { - "trigger_export": 'http://localhost:8000/api/workspaces/2/trigger_export/' -} + +@dataclass +class ActionResponse: + message: str = None + is_success: bool = None class HelpService: @@ -59,7 +64,21 @@ class ActionService: @classmethod def _get_action_function_from_code(cls, *, code: str) -> Callable: code_to_function_map = { - "trigger_export": cls.trigger_export + "trigger_export": cls.trigger_export, + "set_reimbursable_expenses_export_module_bill": cls.set_reimbursable_expenses_export_module_bill, + "set_reimbursable_expenses_export_module_journal_entry": cls.set_reimbursable_expenses_export_module_journal_entry, + "set_reimbursable_expenses_export_grouping_expense": cls.set_reimbursable_expenses_export_grouping_expense, + "set_reimbursable_expenses_export_grouping_report": cls.set_reimbursable_expenses_export_grouping_report, + "set_reimbursable_expenses_export_state_processing": cls.set_reimbursable_expenses_export_state_processing, + "set_reimbursable_expenses_export_state_paid": cls.set_reimbursable_expenses_export_state_paid, + "set_customer_field_mapping_to_project": cls.set_customer_field_mapping_to_project, + "set_customer_field_mapping_to_cost_center": cls.set_customer_field_mapping_to_cost_center, + "set_class_field_mapping_to_project": cls.set_class_field_mapping_to_project, + "set_class_field_mapping_to_cost_center": cls.set_class_field_mapping_to_cost_center, + "set_corporate_credit_card_expenses_export_credit_card_purchase": cls.set_cc_export_to_corporate_card_purchase, + "set_corporate_credit_card_expenses_export_journal_entry": cls.set_cc_export_to_journal_entry, + "set_corporate_credit_card_expenses_export_grouping_report": cls.set_cc_grouping_to_report, + "set_corporate_credit_card_expenses_export_grouping_expense": cls.set_cc_grouping_to_expense, } return code_to_function_map[code] @@ -75,6 +94,84 @@ def get_access_token(cls, *, workspace_id: int) -> str: creds = FyleCredential.objects.get(workspace_id=workspace_id) return get_access_token(creds.refresh_token) + @classmethod + def set_reimbursable_expenses_export_module_bill(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter( + workspace_id=workspace_id + ).first() + if export_settings is None: + return ActionResponse(message="Failed to set reimbursable expense export type set to Bill", is_success=False) + else: + export_settings.reimbursable_expenses_export_type = 'BILL' + export_settings.save() + return ActionResponse(message="Reimbursable expense export type set to Bill", is_success=True) + + @classmethod + def set_reimbursable_expenses_export_module_journal_entry(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter( + workspace_id=workspace_id + ).first() + if export_settings is None: + return ActionResponse(message="Failed to set reimbursable expense export type set to Journal Entry", is_success=False) + else: + export_settings.reimbursable_expenses_export_type = 'JOURNAL_ENTRY' + export_settings.save() + return ActionResponse(message="Reimbursable expense export type set to Journal Entry", is_success=True) + + @classmethod + def set_reimbursable_expenses_export_grouping_expense(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter( + workspace_id=workspace_id + ).first() + if export_settings is None: + return ActionResponse(message="Failed to set reimbursable expense export grouping to Expenses", is_success=False) + else: + export_settings.reimbursable_expense_grouped_by = 'EXPENSE' + export_settings.save() + return ActionResponse(message="Reimbursable expense export group set to Expenses", is_success=True) + + @classmethod + def set_reimbursable_expenses_export_grouping_report(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter( + workspace_id=workspace_id + ).first() + if export_settings is None: + return ActionResponse(message="Failed to set reimbursable expense export grouping to Report", is_success=False) + else: + export_settings.reimbursable_expense_grouped_by = 'REPORT' + export_settings.save() + return ActionResponse(message="Reimbursable expense export group set to Report", is_success=True) + + @classmethod + def set_reimbursable_expenses_export_state_processing(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter( + workspace_id=workspace_id + ).first() + if export_settings is None: + return ActionResponse(message="Failed to set reimbursable expense export state to Processing", is_success=False) + else: + export_settings.reimbursable_expense_state = 'PAYMENT_PROCESSING' + export_settings.save() + return ActionResponse(message="Reimbursable expense export state set to Processing", is_success=True) + + @classmethod + def set_reimbursable_expenses_export_state_paid(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter( + workspace_id=workspace_id + ).first() + if export_settings is None: + return ActionResponse(message="Failed to set reimbursable expense export state to Paid", is_success=False) + else: + export_settings.reimbursable_expense_state = 'PAID' + export_settings.save() + return ActionResponse(message="Reimbursable expense export state set to Paid", is_success=True) + @classmethod def trigger_export(cls, *, workspace_id: int): access_token = cls.get_access_token(workspace_id=workspace_id) @@ -85,8 +182,140 @@ def trigger_export(cls, *, workspace_id: int): } url = f'http://localhost:8000/api/workspaces/{workspace_id}/trigger_export/' action_response = requests.post(url, json={}, headers=headers) + if action_response.status_code == 200: + return ActionResponse(message="Export triggered successfully", is_success=True) + return ActionResponse(message="Export triggered failed", is_success=False) + + + @classmethod + def set_cc_export_to_corporate_card_purchase(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first() + if export_settings: + export_settings.credit_card_expense_export_type = 'CREDIT_CARD_PURCHASE' + export_settings.save() + return ActionResponse(message="Successfully set corporate card expense as Credit Card Purchase", is_success=True) + + return ActionResponse(message="Export settings doesn't exists!", is_success=False) + + + @classmethod + def set_cc_export_to_journal_entry(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first() + if export_settings: + export_settings.credit_card_expense_export_type = 'JOURNAL_ENTRY' + export_settings.save() + return ActionResponse(message="Successfully set corporate card expense as JOURNAL ENTRY", is_success=True) + + return ActionResponse(message="Export settings doesn't exists!", is_success=False) + + @classmethod + def set_cc_grouping_to_report(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first() + if export_settings: + if export_settings.credit_card_expense_export_type == 'CREDIT_CARD_PURCHASE': + return ActionResponse(message='For Corporate Credit Purchase Export type expenses cannot be grouped by report', is_success=False) + else: + export_settings.credit_card_expense_grouped_by = 'REPORT' + export_settings.save() + return ActionResponse(message='Succesfully set corporate card group by to Report', is_success=True) + + return ActionResponse(message="Export settings doesn't exists!", is_success=False) + + + @classmethod + def set_cc_grouping_to_expense(cls, *, workspace_id: int): + with transaction.atomic(): + export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first() + if export_settings: + if export_settings.credit_card_expense_export_type == 'CREDIT_CARD_PURCHASE': + return ActionResponse(message='Already set to expense', is_success=True) + else: + export_settings.credit_card_expense_grouped_by = 'EXPENSE' + export_settings.save() + return ActionResponse(message='Succesfully set corporate card group by to EXPENSE', is_success=True) + + return ActionResponse(message="Export settings doesn't exists!", is_success=False) + + + @classmethod + def set_customer_field_mapping_to_project(cls, *, workspace_id: int): + access_token = cls.get_access_token(workspace_id=workspace_id) + headers = cls.get_headers(access_token=access_token) + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + url = f'http://localhost:8000/api/workspaces/{workspace_id}/field_mappings/' + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + action_response = requests.get(url, headers=headers) + action_response= action_response.json() + if action_response.get('project_type') != 'PROJECT' and action_response.get('class_type') != 'COST_CENTER': + action_response['project_type'] = 'PROJECT' + post_response = requests.post(url, headers=headers, data=json.dumps(action_response)) + return ActionResponse(message="Field mapping updated successfully", is_success=True) + return ActionResponse(message="Field mapping already exists", is_success=False) + + @classmethod + def set_customer_field_mapping_to_cost_center(cls, *, workspace_id: int): + access_token = cls.get_access_token(workspace_id=workspace_id) + headers = cls.get_headers(access_token=access_token) + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + url = f'http://localhost:8000/api/workspaces/{workspace_id}/field_mappings/' + + action_response = requests.get(url, headers=headers) + action_response= action_response.json() + if action_response.get('project_type') != 'COST_CENTER' and action_response.get('class_type') != 'PROJECT': + action_response['project_type'] = 'COST_CENTER' + post_response = requests.post(url, headers=headers, data=json.dumps(action_response)) + return ActionResponse(message="Field mapping updated successfully", is_success=True) + return ActionResponse(message="Field mapping already exists", is_success=False) + + @classmethod + def set_class_field_mapping_to_project(cls, *, workspace_id: int): + access_token = cls.get_access_token(workspace_id=workspace_id) + headers = cls.get_headers(access_token=access_token) + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + url = f'http://localhost:8000/api/workspaces/{workspace_id}/field_mappings/' + + action_response = requests.get(url, headers=headers) + action_response= action_response.json() + if action_response.get('project_type') != 'PROJECT' and action_response.get('class_type') != 'COST_CENTER': + action_response['class_type'] = 'PROJECT' + post_response = requests.post(url, headers=headers, data=json.dumps(action_response)) + return ActionResponse(message="Field mapping updated successfully", is_success=True) + return ActionResponse(message="Field mapping already exists", is_success=False) + + @classmethod + def set_class_field_mapping_to_cost_center(cls, *, workspace_id: int): + access_token = cls.get_access_token(workspace_id=workspace_id) + headers = cls.get_headers(access_token=access_token) + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + url = f'http://localhost:8000/api/workspaces/{workspace_id}/field_mappings/' + + action_response = requests.get(url, headers=headers) + action_response= action_response.json() + if action_response.get('project_type') != 'COST_CENTER' and action_response.get('class_type') != 'PROJECT': + action_response['class_type'] = 'COST_CENTER' + post_response = requests.post(url, headers=headers, data=json.dumps(action_response)) + return ActionResponse(message="Field mapping updated successfully", is_success=True) + return ActionResponse(message="Field mapping already exists", is_success=False) @classmethod def action(cls, *, code: str, workspace_id: str): action_function = cls._get_action_function_from_code(code=code) - action_function(workspace_id=workspace_id) + return action_function(workspace_id=workspace_id) diff --git a/apps/spotlight/views.py b/apps/spotlight/views.py index ad6511f..87f5355 100644 --- a/apps/spotlight/views.py +++ b/apps/spotlight/views.py @@ -93,8 +93,11 @@ def post(self, request, *args, **kwargs): code = payload["code"] try: - ActionService.action(code=code, workspace_id=workspace_id) - return JsonResponse(data={"message": "Action triggered successfully"}, status=200) + action_response = ActionService.action(code=code, workspace_id=workspace_id) + if action_response.is_success is True: + return JsonResponse(data={"message": action_response.message}, status=200) + else: + return JsonResponse(data={"message": action_response.message}, status=500) except Exception as e: print(e) return JsonResponse(data={"message": "Action failed"}, status=500)