Skip to content

Commit 44c267e

Browse files
authored
Add support for editing expenses (#87)
1 parent 16ba287 commit 44c267e

File tree

8 files changed

+379
-11
lines changed

8 files changed

+379
-11
lines changed

apps/fyle/exceptions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from fyle.platform.exceptions import NoPrivilegeError, RetryException, InvalidTokenError as FyleInvalidTokenError
44
from rest_framework.response import Response
55
from rest_framework.views import status
6+
from rest_framework.exceptions import ValidationError
67

78
from apps.workspaces.models import FyleCredential, Workspace, ExportSettings, AdvancedSetting
89
from apps.tasks.models import AccountingExport
@@ -43,6 +44,10 @@ def new_fn(*args, **kwargs):
4344
except ExportSettings.DoesNotExist:
4445
return Response({'message': 'Export Settings does not exist in workspace'}, status=status.HTTP_400_BAD_REQUEST)
4546

47+
except ValidationError as e:
48+
logger.exception(e)
49+
return Response({"message": e.detail}, status=status.HTTP_400_BAD_REQUEST)
50+
4651
except Exception as exception:
4752
logger.exception(exception)
4853
return Response(data={'message': 'An unhandled error has occurred, please re-try later'}, status=status.HTTP_400_BAD_REQUEST)

apps/fyle/helpers.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55

66
from django.conf import settings
77
from fyle.platform import Platform
8+
from rest_framework.exceptions import ValidationError
89

9-
from apps.workspaces.models import FyleCredential
10+
from apps.workspaces.models import Workspace, FyleCredential
1011

1112

1213
def post_request(url, body, refresh_token=None):
@@ -142,3 +143,13 @@ def download_iif_file(file_id: str, workspace_id: int):
142143
)['data'][0]['download_url']
143144

144145
return download_url
146+
147+
148+
def assert_valid_request(workspace_id:int, org_id:str):
149+
"""
150+
Assert if the request is valid by checking
151+
the url_workspace_id and fyle_org_id workspace
152+
"""
153+
workspace = Workspace.objects.get(org_id=org_id)
154+
if workspace.id != workspace_id:
155+
raise ValidationError('Workspace mismatch')

apps/fyle/queue.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
* User Triggered Async Tasks
44
* Schedule Triggered Async Tasks
55
"""
6+
import logging
67
from django_q.tasks import async_task
78
from apps.fyle.tasks import (
89
import_credit_card_expenses,
910
import_reimbursable_expenses
1011
)
1112
from apps.workspaces.models import Workspace
1213
from apps.tasks.models import AccountingExport
14+
from apps.fyle.helpers import assert_valid_request
15+
16+
logger = logging.getLogger(__name__)
17+
logger.level = logging.INFO
1318

1419

1520
def queue_import_reimbursable_expenses(workspace_id: int, synchronous: bool = False):
@@ -60,14 +65,20 @@ def queue_import_credit_card_expenses(workspace_id: int, synchronous: bool = Fal
6065
import_credit_card_expenses(workspace_id, accounting_export)
6166

6267

63-
def async_handle_webhook_callback(body: dict) -> None:
68+
def async_handle_webhook_callback(body: dict, workspace_id: int) -> None:
6469
"""
6570
Async'ly import and export expenses
66-
:param body: bodys
71+
:param body: body
6772
:return: None
6873
"""
6974
if body.get('action') == 'ACCOUNTING_EXPORT_INITIATED' and body.get('data'):
7075
org_id = body['data']['org_id']
71-
76+
assert_valid_request(workspace_id=workspace_id, org_id=org_id)
7277
workspace = Workspace.objects.get(org_id=org_id)
7378
async_task('apps.workspaces.tasks.run_import_export', workspace.id)
79+
80+
elif body.get('action') == 'UPDATED_AFTER_APPROVAL' and body.get('data') and body.get('resource') == 'EXPENSE':
81+
org_id = body['data']['org_id']
82+
logger.info("| Updating non-exported expenses through webhook | Content: {{WORKSPACE_ID: {} Payload: {}}}".format(workspace_id, body.get('data')))
83+
assert_valid_request(workspace_id=workspace_id, org_id=org_id)
84+
async_task('apps.fyle.tasks.update_non_exported_expenses', body['data'])

apps/fyle/tasks.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
2. Import Credit Card Expenses from Fyle
66
"""
77
import logging
8+
from typing import Dict
89
from datetime import datetime
910
import traceback
1011

1112
from django.db import transaction
1213

1314
from fyle_integrations_platform_connector import PlatformConnector
1415
from fyle.platform.exceptions import RetryException, NoPrivilegeError
16+
from fyle_integrations_platform_connector.apis.expenses import Expenses as FyleExpenses
1517

1618
from apps.tasks.models import AccountingExport
1719
from apps.workspaces.models import Workspace, ExportSettings, FyleCredential
@@ -151,3 +153,21 @@ def import_credit_card_expenses(workspace_id, accounting_export: AccountingExpor
151153
accounting_export.status = 'FATAL'
152154
accounting_export.save()
153155
logger.exception('Something unexpected happened workspace_id: %s %s', accounting_export.workspace_id, accounting_export.errors)
156+
157+
158+
def update_non_exported_expenses(data: Dict) -> None:
159+
"""
160+
To update expenses not in COMPLETE, IN_PROGRESS state
161+
"""
162+
org_id = data['org_id']
163+
expense_id = data['id']
164+
workspace = Workspace.objects.get(org_id=org_id)
165+
expense = Expense.objects.filter(workspace_id=workspace.id, expense_id=expense_id).first()
166+
167+
if expense and not expense.exported:
168+
expense_obj = []
169+
expense_obj.append(data)
170+
expense_objects = FyleExpenses().construct_expense_object(expense_obj, expense.workspace_id)
171+
Expense.create_expense_objects(
172+
expense_objects, expense.workspace_id
173+
)

apps/fyle/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ class WebhookCallbackView(generics.CreateAPIView):
3131

3232
@handle_view_exceptions()
3333
def post(self, request, *args, **kwargs):
34-
async_handle_webhook_callback(request.data)
34+
async_handle_webhook_callback(request.data, int(kwargs['workspace_id']))
3535

3636
return Response(data={}, status=status.HTTP_200_OK)

requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ gevent==23.9.1
2424
gunicorn==20.1.0
2525

2626
# Platform SDK
27-
fyle==0.36.1
27+
fyle==0.37.0
2828

2929
# Reusable Fyle Packages
3030
fyle-rest-auth==1.7.2
31-
fyle-accounting-mappings==1.32.3
32-
fyle-integrations-platform-connector==1.37.4
31+
fyle-accounting-mappings==1.33.1
32+
fyle-integrations-platform-connector==1.38.1
3333

3434
# Postgres Dependincies
3535
psycopg2-binary==2.8.4

0 commit comments

Comments
 (0)