Skip to content

Commit

Permalink
Merge branch 'spotlight-api' into hackathon-base
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashutosh619-sudo committed Sep 13, 2024
2 parents bbc9c7f + 2dce048 commit 5856962
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 3 deletions.
25 changes: 25 additions & 0 deletions apps/spotlight/migrations/0002_copyexportsettings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.1.14 on 2024-09-12 20:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('spotlight', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='CopyExportSettings',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('workspace_id', models.IntegerField(help_text='Workspace id of the organization')),
('reimbursable_export_setting', models.JSONField(null=True)),
('ccc_export_setting', models.JSONField(null=True)),
],
options={
'db_table': 'copy_export_settings',
},
),
]
9 changes: 9 additions & 0 deletions apps/spotlight/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ class Query(models.Model):

class Meta:
db_table = 'queries'

class CopyExportSettings(models.Model):

workspace_id = models.IntegerField(help_text="Workspace id of the organization")
reimbursable_export_setting = models.JSONField(null=True)
ccc_export_setting = models.JSONField(null=True)

class Meta:
db_table = 'copy_export_settings'
175 changes: 175 additions & 0 deletions apps/spotlight/prompts/suggestion_context_page_prompt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
SUGGESTION_PROMPT = """
Objectives:
You are a AI agent that suggests what actions and features
we provide for a specific page. You will get the user input at the end.
Instructions:
These are the pages and their corresponding actions we provide, you will get the
URL as input and you have to reply the actions list:
Output should be in JSON format.
1. For /dashboard
Output:
{{
"suggestions": {{
"actions": [
{{
"code": "trigger_export",
"title": "Export IIF file",
"description": "Export the current data to an IIF file."
}}
]
}}
}}
2. For /export_settings
Output:
{{
"suggestions": {{
"actions": [
{{
"code": "enable_reimbursable_expenses_export",
"title": "Enable reimbursable export settings",
"description": "Enable the option to export reimbursable expenses in Export Configuration."
}},
{{
"code": "disable_reimbursable_expenses_export",
"title": "Disable reimbursable export settings",
"description": "Disable the option to export reimbursable expenses in Export Configuration."
}},
{{
"code": "set_reimbursable_expenses_export_module_bill",
"title": "Select reimbursable export module as bill",
"description": "Choose Bill as the type of transaction in QuickBooks Desktop to export your Fyle expenses."
}},
{{
"code": "set_reimbursable_expenses_export_module_journal_entry",
"title": "Select reimbursable export module as journal entry",
"description": "Choose Journal Entry as the type of transaction in QuickBooks Desktop to export your Fyle expenses."
}},
{{
"code": "set_reimbursable_expenses_export_grouping_expense"
"title": "Group reimbursable expenses export by expense",
"description": "Set grouping to expense, this grouping reflects how the expense entries are posted in QuickBooks Desktop."
}},
{{
"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."
}},
{{
"code": "set_reimbursable_expenses_export_state_processing",
"title": "Set reimbursable expenses export state as processing",
"description": "You could choose to export expenses when they have been approved and are awaiting payment clearance."
}},
{{
"code": "set_reimbursable_expenses_export_state_paid",
"title": "Set reimbursable expenses export state as paid",
"description": "You could choose to export expenses when they have been paid out."
}},
{{
"code": "enable_corporate_card_expenses_export",
"title": "Enable option corporate card expenses export",
"description": "Enable the option to export of credit card expenses from Fyle to QuickBooks Desktop."
}},
{{
"code": "disable_corporate_card_expenses_export",
"title": "Disable reimbursable export settings",
"description": "Disable the option to export of credit card expenses from Fyle to QuickBooks Desktop."
}},
{{
"code": "set_corporate_credit_card_expenses_export_credit_card_purchase",
"title": "Set Credit Card Purchase transaction type to export",
"description": "Credit Card Purchase type of transaction in QuickBooks Desktop to be export as Fyle expenses."
}},
{{
"code": "set_corporate_credit_card_expenses_export_journal_entry",
"title": "Set Journal Entry transaction type to export",
"description": "Journal Entry type of transaction in QuickBooks Desktop to be export as Fyle expenses."
}},
{{
"code": "set_corporate_credit_card_expenses_purchased_from_field_employee",
"title": "Set Purchased From field to Employee",
"description": "Employee field should be represented as Payee for the credit card purchase."
}},
{{
"code": "set_corporate_credit_card_expenses_purchased_from_field_vendor",
"title": "Set Purchased From field to Vendor",
"description": "Vendor field should be represented as Payee for the credit card purchase."
}},
{{
"code": "set_corporate_credit_card_expenses_export_grouping_report",
"title": "Group corporate credit expenses export to report",
"description": "Group reports as the expense entries posted in QuickBooks Desktop."
}},
{{
"code": "set_corporate_credit_card_expenses_export_grouping_expense",
"title": "Group corporate credit expenses export to expenses",
"description": "Group expense as the expense entries posted in QuickBooks Desktop."
}},
{{
"code": "set_corporate_credit_card_expenses_export_state_approved",
"title": "Set corporate credit expenses export to approved state",
"description": "Set corporate credit expenses to export expenses when they have been approved and are awaiting payment clearance"
}},
{{
"code": "set_corporate_credit_card_expenses_export_state_closed",
"title": "Set corporate credit expenses export to closed state",
"description": "Set corporate credit expenses to export expenses when they have been closed"
}}
]
}}
}}
3. /field_mappings
Output:
{{
"suggestions": {{
"actions": [
{{
"code": "set_customer_field_mapping_to_project"
"title": "Map Customer field to Project",
"description": "Set Project field in Fyle mapped to 'Customers' field in QuickBooks Desktops."
}},
{{
"code": "set_customer_field_mapping_to_cost_center",
"title": "Map Customer field to Cost Center",
"description": "Set Cost Center field in Fyle mapped to 'Customers' field in QuickBooks Desktop."
}},
{{
"code" "set_class_field_mapping_to_project",
"title": "Map Class field to Project",
"description": "Set Project field in Fyle mapped to 'Class' field in QuickBooks Desktop."
}},
{{
"code": "set_class_field_mapping_to_cost_center",
"title": "Map Class field to Cost Center",
"description": "Set Cost Center field in Fyle mapped to 'Class' field in QuickBooks Desktop."
}}
]
}}
}}
-----------------------------
Important things to take care:
1. Match the user query and only reply the actions, nothing less nothing more.
2. Dont match the exact URL, it can be a bit different containing things in the beginning
or the end.
3. If the user query doesn't match any of the above provided URL please reply with empty suggestion like this:
{{
"suggestions": {{
"actions": []
}}
}}
---------------------------
User Query: {user_query}
---------------------------
"""
112 changes: 112 additions & 0 deletions apps/spotlight/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import requests

from apps.fyle.helpers import get_access_token
from apps.spotlight.models import CopyExportSettings
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 .prompts.suggestion_context_page_prompt import SUGGESTION_PROMPT

from . import llm

Expand Down Expand Up @@ -58,6 +60,14 @@ def get_suggestions(cls, *, user_query: str) -> str:
)
return llm.get_openai_response(system_prompt=formatted_prompt)

class SuggestionService:
@classmethod
def get_suggestions(cls, *, user_query: str) -> str:
formatted_prompt = SUGGESTION_PROMPT.format(
user_query=user_query
)

return llm.get_openai_response(system_prompt=formatted_prompt)

class ActionService:

Expand All @@ -79,6 +89,10 @@ def _get_action_function_from_code(cls, *, code: str) -> Callable:
"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,
"disable_reimbursable_expenses_export": cls.disable_reimbursable_expenses_export,
"enable_reimbursable_expenses_export": cls.enable_reimbursable_expenses_export,
"disable_corporate_card_expenses_export": cls.disable_corporate_card_expenses_export,
"enable_corporate_card_expenses_export": cls.enable_corporate_card_expenses_export
}
return code_to_function_map[code]

Expand Down Expand Up @@ -315,6 +329,104 @@ def set_class_field_mapping_to_cost_center(cls, *, workspace_id: int):
return ActionResponse(message="Field mapping updated successfully", is_success=True)
return ActionResponse(message="Field mapping already exists", is_success=False)

@classmethod
def enable_reimbursable_expenses_export(cls, *, workspace_id: int):
fields_for_reimbursable = ['reimbursable_expenses_export_type', 'reimbursable_expense_state', 'reimbursable_expense_date',
'reimbursable_expense_grouped_by', 'bank_account_name']

with transaction.atomic():
export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first()
if export_settings:
if export_settings.reimbursable_expenses_export_type is None:
copied_export_settings = CopyExportSettings.objects.filter(workspace_id=workspace_id).first()
if copied_export_settings:
for field in fields_for_reimbursable:
setattr(export_settings, field, copied_export_settings.reimbursable_export_setting[field])

export_settings.save()
return ActionResponse(message='Successfully enabled reimbursable expense', is_success=True)
else:
return ActionResponse(message='Reimbursable Expense is already enabled', is_success=True)

return ActionResponse(message="Export settings doesn't exists", is_success=False)

@classmethod
def disable_reimbursable_expenses_export(cls, *, workspace_id: int):
fields_for_reimbursable = ['reimbursable_expenses_export_type', 'reimbursable_expense_state', 'reimbursable_expense_date',
'reimbursable_expense_grouped_by', 'bank_account_name']
with transaction.atomic():
export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first()
if export_settings:
if export_settings.reimbursable_expenses_export_type is not None:
copied_export_settings, _ = CopyExportSettings.objects.get_or_create(workspace_id=workspace_id,
defaults={'reimbursable_export_setting': {}, 'ccc_export_setting': {}})
reimbursable_export_setting = copied_export_settings.reimbursable_export_setting or {}

for field in fields_for_reimbursable:
reimbursable_export_setting[field] = getattr(export_settings, field, None)
setattr(export_settings, field, None)

copied_export_settings.reimbursable_export_setting = reimbursable_export_setting

export_settings.save()
copied_export_settings.save()

return ActionResponse(message='Reimbursable Expense successfully disabled!', is_success=True)

else:
return ActionResponse(message='Reimbursable Expense is already disabled', is_success=True)

return ActionResponse(message="Export settings doesn't exists", is_success=False)

@classmethod
def enable_corporate_card_expenses_export(cls, *, workspace_id: int):
fields_for_ccc = ['credit_card_expense_export_type', 'credit_card_expense_state', 'credit_card_entity_name_preference',
'credit_card_account_name', 'credit_card_expense_grouped_by', 'credit_card_expense_date']

with transaction.atomic():
export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first()
if export_settings:
if export_settings.credit_card_expense_export_type is None:
copied_export_settings = CopyExportSettings.objects.filter(workspace_id=workspace_id).first()
if copied_export_settings:
for field in fields_for_ccc:
setattr(export_settings, field, copied_export_settings.ccc_export_setting[field])

export_settings.save()
return ActionResponse(message='Successfully enabled Corporate expense', is_success=True)
else:
return ActionResponse(message='Corporate Expense is already enabled', is_success=True)

return ActionResponse(message="Export settings doesn't exists", is_success=False)

@classmethod
def disable_corporate_card_expenses_export(cls, *, workspace_id: int):
fields_for_ccc = ['credit_card_expense_export_type', 'credit_card_expense_state', 'credit_card_entity_name_preference',
'credit_card_account_name', 'credit_card_expense_grouped_by', 'credit_card_expense_date']
with transaction.atomic():
export_settings = ExportSettings.objects.filter(workspace_id=workspace_id).first()
if export_settings:
if export_settings.credit_card_expense_export_type is not None:
copied_export_settings, _ = CopyExportSettings.objects.get_or_create(workspace_id=workspace_id,
defaults={'reimbursable_export_setting': {}, 'ccc_export_setting': {}})
ccc_export_setting = copied_export_settings.ccc_export_setting or {}

for field in fields_for_ccc:
ccc_export_setting[field] = getattr(export_settings, field, None)
setattr(export_settings, field, None)

copied_export_settings.ccc_export_setting = ccc_export_setting

export_settings.save()
copied_export_settings.save()

return ActionResponse(message='Corporate Expense successfully disabled!', is_success=True)

else:
return ActionResponse(message='Corporate Expense is already disabled', is_success=True)

return ActionResponse(message="Export settings doesn't exists", is_success=False)

@classmethod
def action(cls, *, code: str, workspace_id: str):
action_function = cls._get_action_function_from_code(code=code)
Expand Down
6 changes: 4 additions & 2 deletions apps/spotlight/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
"""
from django.urls import path

from apps.spotlight.views import HelpQueryView, QueryView, RecentQueryView, ActionQueryView
from apps.spotlight.views import HelpQueryView, \
QueryView, RecentQueryView, ActionQueryView, SuggestionForPage



urlpatterns = [
path('recent_queries/', RecentQueryView.as_view(), name='recent-queries'),
path('query/', QueryView.as_view(), name='query'),
path('help/', HelpQueryView.as_view(), name='help'),
path('action/', ActionQueryView.as_view(), name='action')
path('action/', ActionQueryView.as_view(), name='action'),
path('suggest_actions/', SuggestionForPage.as_view(), name='suggestion')
]
Loading

0 comments on commit 5856962

Please sign in to comment.