From 14b672942ba5b7746d5ff3d8cd40d5b41c4f234d Mon Sep 17 00:00:00 2001 From: ruuushhh <66899387+ruuushhh@users.noreply.github.com> Date: Fri, 15 Dec 2023 12:53:54 +0530 Subject: [PATCH] Imports base test cases (#47) * Fix: Import bugs * Imports base test cases * Imports test cases for schedules, categories, cost centers (#48) * Imports test cases for schedules, categories, cost centers * Imports test cases for merchants, projects, expense fields (#49) --- tests/conftest.py | 66 +- tests/test_mappings/__init__.py | 0 tests/test_mappings/test_imports/__init__.py | 0 .../test_imports/test_modules/__init__.py | 0 .../test_imports/test_modules/conftest.py | 170 + .../test_imports/test_modules/fixtures.py | 8175 +++++++++++++++++ .../test_imports/test_modules/helpers.py | 30 + .../test_imports/test_modules/test_base.py | 578 ++ .../test_modules/test_categories.py | 233 + .../test_modules/test_cost_centers.py | 148 + .../test_expense_custom_fields.py | 203 + .../test_modules/test_merchants.py | 217 + .../test_modules/test_projects.py | 293 + .../test_imports/test_schedules.py | 60 + 14 files changed, 10162 insertions(+), 11 deletions(-) create mode 100644 tests/test_mappings/__init__.py create mode 100644 tests/test_mappings/test_imports/__init__.py create mode 100644 tests/test_mappings/test_imports/test_modules/__init__.py create mode 100644 tests/test_mappings/test_imports/test_modules/conftest.py create mode 100644 tests/test_mappings/test_imports/test_modules/fixtures.py create mode 100644 tests/test_mappings/test_imports/test_modules/helpers.py create mode 100644 tests/test_mappings/test_imports/test_modules/test_base.py create mode 100644 tests/test_mappings/test_imports/test_modules/test_categories.py create mode 100644 tests/test_mappings/test_imports/test_modules/test_cost_centers.py create mode 100644 tests/test_mappings/test_imports/test_modules/test_expense_custom_fields.py create mode 100644 tests/test_mappings/test_imports/test_modules/test_merchants.py create mode 100644 tests/test_mappings/test_imports/test_modules/test_projects.py create mode 100644 tests/test_mappings/test_imports/test_schedules.py diff --git a/tests/conftest.py b/tests/conftest.py index 4d359e1..5fdd36f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,14 +6,14 @@ import pytest from fyle.platform.platform import Platform -from fyle_accounting_mappings.models import DestinationAttribute +from fyle_accounting_mappings.models import DestinationAttribute, MappingSetting from fyle_rest_auth.models import AuthToken, User from rest_framework.test import APIClient from apps.accounting_exports.models import AccountingExport, AccountingExportSummary, Error from apps.fyle.helpers import get_access_token from apps.fyle.models import ExpenseFilter -from apps.workspaces.models import BusinessCentralCredentials, ExportSetting, FyleCredential, Workspace +from apps.workspaces.models import BusinessCentralCredentials, ExportSetting, FyleCredential, ImportSetting, Workspace from ms_business_central_api.tests import settings from tests.test_fyle.fixtures import fixtures as fyle_fixtures @@ -68,37 +68,43 @@ def test_connection(db): @pytest.fixture(scope="session", autouse=True) def default_session_fixture(request): patched_1 = mock.patch( - 'fyle_rest_auth.authentication.get_fyle_admin', - return_value=fyle_fixtures['get_my_profile'] + 'dynamics.core.client.Dynamics._Dynamics__refresh_access_token', + return_value="dummy_token" ) patched_1.__enter__() patched_2 = mock.patch( - 'fyle.platform.internals.auth.Auth.update_access_token', - return_value='asnfalsnkflanskflansfklsan' + 'fyle_rest_auth.authentication.get_fyle_admin', + return_value=fyle_fixtures['get_my_profile'] ) patched_2.__enter__() patched_3 = mock.patch( + 'fyle.platform.internals.auth.Auth.update_access_token', + return_value='asnfalsnkflanskflansfklsan' + ) + patched_3.__enter__() + + patched_4 = mock.patch( 'apps.fyle.helpers.post_request', return_value={ 'access_token': 'easnfkjo12233.asnfaosnfa.absfjoabsfjk', 'cluster_domain': 'https://staging.fyle.tech' } ) - patched_3.__enter__() + patched_4.__enter__() - patched_4 = mock.patch( + patched_5 = mock.patch( 'fyle.platform.apis.v1beta.spender.MyProfile.get', return_value=fyle_fixtures['get_my_profile'] ) - patched_4.__enter__() + patched_5.__enter__() - patched_5 = mock.patch( + patched_6 = mock.patch( 'fyle_rest_auth.helpers.get_fyle_admin', return_value=fyle_fixtures['get_my_profile'] ) - patched_5.__enter__() + patched_6.__enter__() @pytest.fixture @@ -316,3 +322,41 @@ def add_export_settings(): credit_card_expense_grouped_by='EXPENSE' if workspace_id == 3 else 'REPORT', credit_card_expense_date='spent_at' ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_import_settings(): + """ + Pytest fixtue to add import_settings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + + for workspace_id in workspace_ids: + ImportSetting.objects.create( + workspace_id=workspace_id, + import_vendors_as_merchants=True, + import_categories=True + ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_mapping_settings(): + """ + Pytest fixtue to add mapping_settings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + + for workspace_id in workspace_ids: + MappingSetting.objects.create( + workspace_id=workspace_id, + source_field='CATEGORY', + destination_field='ACCOUNT', + import_to_fyle=True, + is_custom=False + ) diff --git a/tests/test_mappings/__init__.py b/tests/test_mappings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_mappings/test_imports/__init__.py b/tests/test_mappings/test_imports/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_mappings/test_imports/test_modules/__init__.py b/tests/test_mappings/test_imports/test_modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_mappings/test_imports/test_modules/conftest.py b/tests/test_mappings/test_imports/test_modules/conftest.py new file mode 100644 index 0000000..6a2c1c3 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/conftest.py @@ -0,0 +1,170 @@ +""" +Fixture configuration for import tests +""" +import pytest +from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_project_mappings(): + """ + Pytest fixtue to add project mappings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + for workspace_id in workspace_ids: + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='PROJECT', + display_name='Direct Mail Campaign', + value='Direct Mail Campaign', + destination_id='10064', + detail='Business Central Project - Direct Mail Campaign, Id - 10064', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='PROJECT', + display_name='Platform APIs', + value='Platform APIs', + destination_id='10081', + detail='Business Central Project - Platform APIs, Id - 10081', + active=True + ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_cost_center_mappings(): + """ + Pytest fixtue to add cost center mappings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + for workspace_id in workspace_ids: + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='COST_CENTER', + display_name='Direct Mail Campaign', + value='Direct Mail Campaign', + destination_id='10064', + detail='Cost Center - Direct Mail Campaign, Id - 10064', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='COST_CENTER', + display_name='Platform APIs', + value='Platform APIs', + destination_id='10081', + detail='Cost Center - Platform APIs, Id - 10081', + active=True + ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_merchant_mappings(): + """ + Pytest fixture to add merchant mappings to a workspace + """ + workspace_ids = [ + 1, 2, 3 + ] + for workspace_id in workspace_ids: + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='MERCHANT', + display_name='Direct Mail Campaign', + value='Direct Mail Campaign', + destination_id='10064', + detail='Merchant - Direct Mail Campaign, Id - 10064', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=workspace_id, + attribute_type='MERCHANT', + display_name='Platform APIs', + value='Platform APIs', + destination_id='10081', + detail='Merchant - Platform APIs, Id - 10081', + active=True + ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_project_expense_attributes(): + """ + Pytest fixture to add project expense attributes to a workspace + """ + for i in range(1, 110): + ExpenseAttribute.objects.create( + workspace_id=1, + attribute_type='PROJECT', + display_name='Project', + value='Platform APIs {0}'.format(i), + source_id='1008{0}'.format(i), + detail='Merchant - Platform APIs, Id - 1008{0}'.format(i), + active=True + ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_expense_destination_attributes(): + """ + Pytest fixture to add expense & destination attributes to a workspace + """ + ExpenseAttribute.objects.create( + workspace_id=1, + attribute_type='CATEGORY', + display_name='Category', + value='Test Dynamics', + source_id='1008', + detail='Merchant - Platform APIs, Id - 1008', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=1, + attribute_type='ACCOUNT', + display_name='Account', + value='Test Dynamics', + destination_id='10081', + detail='Merchant - Platform APIs, Id - 10081', + active=True + ) + + +@pytest.fixture() +@pytest.mark.django_db(databases=['default']) +def add_expense_destination_attributes_1(): + """ + Pytest fixture to add expense & destination attributes to a workspace + """ + values = ['Internet','Meals'] + count = 0 + + for value in values: + count += 1 + ExpenseAttribute.objects.create( + workspace_id=1, + attribute_type='CATEGORY', + display_name='Category', + value= value, + source_id='1009{0}'.format(count), + detail='Merchant - Platform APIs, Id - 1008', + active=True + ) + DestinationAttribute.objects.create( + workspace_id=1, + attribute_type='ACCOUNT', + display_name='Account', + value= value, + destination_id=value, + detail='Merchant - Platform APIs, Id - 10081', + active=True + ) diff --git a/tests/test_mappings/test_imports/test_modules/fixtures.py b/tests/test_mappings/test_imports/test_modules/fixtures.py new file mode 100644 index 0000000..f5c56c0 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/fixtures.py @@ -0,0 +1,8175 @@ +data = { + "get_account_destination_attributes": [ + { + "@odata.etag": 'W/"JzE5OzQxNTc0MzQxMTUzMjE1OTAxMTcxOzAwOyc="', + "id": "7d943839-4319-ee11-9cc4-6045bdc8dcac", + "number": "9510", + "displayName": "Corporate Tax", + "category": "Expense", + "subCategory": "Tax Expense", + "blocked": False, + "accountType": "Posting", + "directPosting": True, + "netChange": 0, + "lastModifiedDateTime": "2023-07-03T01:45:41.137Z", + }, + { + "@odata.etag": 'W/"JzE5OzQxNTc0MzQxMTUzMjE1OTAxMTcxOzAwOyc="', + "id": "7d943839-4319-ee11-9cc4-6045bdc8dcad", + "number": "9511", + "displayName": "Corporate Tax 1", + "category": "Expense", + "subCategory": "Tax Expense", + "blocked": False, + "accountType": "Posting", + "directPosting": True, + "netChange": 0, + "lastModifiedDateTime": "2023-07-03T01:45:41.137Z", + }, + ], + "get_vendors_destination_attributes": [ + { + "@odata.etag": 'W/"JzE5Ozc0MTk4OTU2MjA2MzYyNjkwOTkxOzAwOyc="', + "id": "84943839-4319-ee11-9cc4-6045bdc8dcac", + "number": "10000", + "displayName": "London Postmaster", + "addressLine1": "10 North Lake Avenue", + "addressLine2": "", + "city": "New Delhi", + "state": "", + "country": "IN", + "postalCode": "110001", + "phoneNumber": "", + "email": "mrs.carol.philips@contoso.com", + "website": "", + "taxRegistrationNumber": "895741963", + "currencyId": "00000000-0000-0000-0000-000000000000", + "currencyCode": "INR", + "irs1099Code": "", + "paymentTermsId": "68923839-4319-ee11-9cc4-6045bdc8dcac", + "paymentMethodId": "00000000-0000-0000-0000-000000000000", + "taxLiable": False, + "blocked": "_x0020_", + "balance": 88010, + "lastModifiedDateTime": "2023-07-03T01:45:45.427Z", + }, + { + "@odata.etag": 'W/"JzE5OzE2NjkzNDgxNjg2OTU0Njk0MDgxOzAwOyc="', + "id": "e7b80674-ca5d-ee11-8df1-6045bd725f7d", + "number": "10040", + "displayName": "Fabrikam, Inc.", + "addressLine1": "10 North Lake Avenue", + "addressLine2": "", + "city": "Atlanta", + "state": "GA", + "country": "US", + "postalCode": "31772", + "phoneNumber": "4255550101", + "email": "krystal.york@contoso.com", + "website": "www.royalmail.co.uk", + "taxRegistrationNumber": "", + "currencyId": "94923839-4319-ee11-9cc4-6045bdc8dcac", + "currencyCode": "USD", + "irs1099Code": "", + "paymentTermsId": "69923839-4319-ee11-9cc4-6045bdc8dcac", + "paymentMethodId": "d6bb303f-4319-ee11-9cc4-6045bdc8dcac", + "taxLiable": False, + "blocked": "_x0020_", + "balance": 0, + "lastModifiedDateTime": "2023-09-28T06:44:24.85Z", + }, + ], + "get_vendors_destination_attributes_subsequent_run": [ + { + "@odata.etag": 'W/"JzE5OzY5NDE2OTUxNzEzNjA0NzY2MTAxOzAwOyc="', + "id": "85943839-4319-ee11-9cc4-6045bdc8dcac", + "number": "20000", + "displayName": "AR Day Property Management", + "addressLine1": "100 Day Drive", + "addressLine2": "", + "city": "Chicago", + "state": "", + "country": "US", + "postalCode": "US-IL 61236", + "phoneNumber": "", + "email": "mr.frank.lee@contoso.com", + "website": "", + "taxRegistrationNumber": "274863274", + "currencyId": "00000000-0000-0000-0000-000000000000", + "currencyCode": "INR", + "irs1099Code": "", + "paymentTermsId": "68923839-4319-ee11-9cc4-6045bdc8dcac", + "paymentMethodId": "00000000-0000-0000-0000-000000000000", + "taxLiable": False, + "blocked": "_x0020_", + "balance": 253422.43, + "lastModifiedDateTime": "2023-07-03T01:45:45.447Z", + }, + { + "@odata.etag": 'W/"JzE5OzE3OTYxNzMyOTgzNDIyNTQyNTUxOzAwOyc="', + "id": "86943839-4319-ee11-9cc4-6045bdc8dcac", + "number": "30000", + "displayName": "CoolWood Technologies", + "addressLine1": "33 Hitech Drive", + "addressLine2": "", + "city": "New Delhi", + "state": "", + "country": "IN", + "postalCode": "110001", + "phoneNumber": "", + "email": "mr.richard.bready@contoso.com", + "website": "", + "taxRegistrationNumber": "697528465", + "currencyId": "00000000-0000-0000-0000-000000000000", + "currencyCode": "INR", + "irs1099Code": "", + "paymentTermsId": "68923839-4319-ee11-9cc4-6045bdc8dcac", + "paymentMethodId": "00000000-0000-0000-0000-000000000000", + "taxLiable": False, + "blocked": "_x0020_", + "balance": 370837.5, + "lastModifiedDateTime": "2023-07-03T01:45:45.437Z", + }, + ], + "get_account_destination_attributes_1": [ + { + "@odata.etag": 'W/"JzE5OzQxNTc0MzQxMTUzMjE1OTAxMTcxOzAwOyc="', + "id": "7d943839-4319-ee11-9cc4-6045bdc8dcac", + "number": "9510", + "displayName": "Train", + "category": "Expense", + "subCategory": "Tax Expense", + "blocked": False, + "accountType": "Posting", + "directPosting": True, + "netChange": 0, + "lastModifiedDateTime": "2023-07-03T01:45:41.137Z", + }, + { + "@odata.etag": 'W/"JzE5OzQxNTc0MzQxMTUzMjE1OTAxMTcxOzAwOyc="', + "id": "7d943839-4319-ee11-9cc4-6045bdc8dcad", + "number": "9511", + "displayName": "Internet", + "category": "Expense", + "subCategory": "Tax Expense", + "blocked": False, + "accountType": "Posting", + "directPosting": True, + "netChange": 0, + "lastModifiedDateTime": "2023-07-03T01:45:41.137Z", + }, + ], + "create_fyle_expense_custom_fields_payload_create_new_case": { + "field_name": "Luke", + "type": "SELECT", + "is_enabled": True, + "is_mandatory": False, + "placeholder": "Select Luke", + "options": [], + "code": None, + }, + "get_location_destination_attributes_2": [ + { + "@odata.etag": 'W/"JzIwOzE3ODYzMDUwMTE2MDYwNzQyOTk3MTswMDsn"', + "id": "2a933839-4319-ee11-9cc4-6045bdc8dcac", + "code": "BLUE", + "displayName": "Testing Ash", + "contact": "Jeff Smith", + "addressLine1": "South East Street, 3", + "addressLine2": "", + "city": "NEW DELHI", + "state": "", + "country": "IN", + "postalCode": "IN-110001", + "phoneNumber": "+44-(0)20 8207 4533", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + { + "@odata.etag": 'W/"JzIwOzE2NDkzOTMzMzk0MjQ1NTk4NjAxMTswMDsn"', + "id": "2b933839-4319-ee11-9cc4-6045bdc8dcac", + "code": "EAST", + "displayName": "Australia", + "contact": "Jack Potter", + "addressLine1": "Great Eastern Street, 80", + "addressLine2": "", + "city": "London", + "state": "", + "country": "GB", + "postalCode": "GB-EC2A 3JL", + "phoneNumber": "+44-(0)30 9874 1299", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + ], + "get_location_destination_attributes_3": [ + { + "@odata.etag": 'W/"JzIwOzE3ODYzMDUwMTE2MDYwNzQyOTk3MTswMDsn"', + "id": "2a933839-4319-ee11-9cc4-6045bdc8dca4", + "code": "BLUE", + "displayName": "USA 1", + "contact": "Jeff Smith", + "addressLine1": "South East Street, 3", + "addressLine2": "", + "city": "NEW DELHI", + "state": "", + "country": "IN", + "postalCode": "IN-110001", + "phoneNumber": "+44-(0)20 8207 4533", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + { + "@odata.etag": 'W/"JzIwOzE2NDkzOTMzMzk0MjQ1NTk4NjAxMTswMDsn"', + "id": "2b933839-4319-ee11-9cc4-6045bdc8dca3", + "code": "EAST", + "displayName": "USA 2", + "contact": "Jack Potter", + "addressLine1": "Great Eastern Street, 80", + "addressLine2": "", + "city": "London", + "state": "", + "country": "GB", + "postalCode": "GB-EC2A 3JL", + "phoneNumber": "+44-(0)30 9874 1299", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + ], + "get_location_destination_attributes_1": [ + { + "@odata.etag": 'W/"JzE5OzMzOTk1NjQxNzI1Mjg0MzMxMzAxOzAwOyc="', + "id": "2c933839-4319-ee11-9cc4-6045bdc8dcac", + "code": "MAIN", + "displayName": "Main Warehouse", + "contact": "Eleanor Parkes", + "addressLine1": "UK Campus Bldg 5", + "addressLine2": "Thames Valley Park", + "city": "Reading", + "state": "", + "country": "GB", + "postalCode": "GB-RG6 1WG", + "phoneNumber": "+44-(0)10 5214 4987", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + { + "@odata.etag": 'W/"JzIwOzE0Njc3NjkzNzg4OTE5MjQ1MDg1MTswMDsn"', + "id": "2d933839-4319-ee11-9cc4-6045bdc8dcac", + "code": "OUT. LOG.", + "displayName": "Outsourced Logistics", + "contact": "", + "addressLine1": "", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + ], + "get_employee_destination_attributes_0": [ + { + "@odata.etag": 'W/"JzE5OzcxODU5NjM0ODcxNDY4NDkzMTIxOzAwOyc="', + "id": "d82d092b-ca5d-ee11-8def-6045bde811d8", + "number": "AH", + "displayName": "Annette Hill", + "givenName": "Annette", + "middleName": "", + "surname": "Hill", + "jobTitle": "Secretary", + "addressLine1": "677 Fifth Avenue", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "4465-4899-4643", + "mobilePhone": "4564-4564-7831", + "email": "", + "personalEmail": "ah@contoso.com", + "employmentDate": "2001-06-01", + "terminationDate": "0001-01-01", + "status": "Active", + "birthDate": "1973-12-12", + "statisticsGroupCode": "", + "lastModifiedDateTime": "2023-09-28T06:42:27.733Z", + }, + { + "@odata.etag": 'W/"JzIwOzE0MzMyODYwNzA4NTA0MDIyMjY4MTswMDsn"', + "id": "e85d0165-4319-ee11-9cc4-6045bdc8dcac", + "number": "EH", + "displayName": "Ester Henderson", + "givenName": "Ester", + "middleName": "", + "surname": "Henderson", + "jobTitle": "Secretary", + "addressLine1": "5 Russel Street", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "4465-4899-4643", + "mobilePhone": "4564-4564-7831", + "email": "", + "personalEmail": "eh@cronus-demosite.com", + "employmentDate": "1996-06-01", + "terminationDate": "0001-01-01", + "status": "Active", + "birthDate": "1963-12-12", + "statisticsGroupCode": "", + "lastModifiedDateTime": "2023-07-03T01:46:22.747Z", + }, + ], + "create_new_auto_create_expense_custom_fields_get_by_id": { + "category_ids": [ + 259385, + 259386, + 259387, + 259388, + 259389, + 259390, + 259391, + 259392, + 259393, + 259394, + 259395, + 259396, + 259397, + 259398, + 259399, + ], + "code": None, + "column_name": "text_column3", + "created_at": "2023-10-10T11:06:12.906551+00:00", + "default_value": None, + "field_name": "Luke", + "id": 229506, + "is_custom": True, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "Australia", + "Bangalore", + "Canada", + "Elimination - Global", + "Elimination - NA", + "Elimination - Sub", + "Holding Company", + "Inactive loc", + "India", + "Leaf Village", + "London", + "Mist Village", + "New South Wales", + "Prod test", + "Sand village", + "South Africa", + "Testing", + "Testing Ash", + "United Kingdom", + "USA 1", + "USA 2", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "Select Luke", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-11T07:42:24.133074+00:00", + }, + "create_new_auto_create_employee_destination_attributes_disable_case": [ + { + "@odata.etag": 'W/"JzE5OzcxODU5NjM0ODcxNDY4NDkzMTIxOzAwOyc="', + "id": "d82d092b-ca5d-ee11-8def-6045bde811d8", + "number": "AH", + "displayName": "Annette Hill", + "givenName": "Annette", + "middleName": "", + "surname": "Hill", + "jobTitle": "Secretary", + "addressLine1": "677 Fifth Avenue", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "4465-4899-4643", + "mobilePhone": "4564-4564-7831", + "email": "", + "personalEmail": "ah@contoso.com", + "employmentDate": "2001-06-01", + "terminationDate": "0001-01-01", + "status": "Inactive", + "birthDate": "1973-12-12", + "statisticsGroupCode": "", + "lastModifiedDateTime": "2023-09-28T06:42:27.733Z", + }, + { + "@odata.etag": 'W/"JzIwOzE0MzMyODYwNzA4NTA0MDIyMjY4MTswMDsn"', + "id": "e85d0165-4319-ee11-9cc4-6045bdc8dcac", + "number": "EH", + "displayName": "Ester Henderson", + "givenName": "Ester", + "middleName": "", + "surname": "Henderson", + "jobTitle": "Secretary", + "addressLine1": "5 Russel Street", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "4465-4899-4643", + "mobilePhone": "4564-4564-7831", + "email": "", + "personalEmail": "eh@cronus-demosite.com", + "employmentDate": "1996-06-01", + "terminationDate": "0001-01-01", + "status": "Active", + "birthDate": "1963-12-12", + "statisticsGroupCode": "", + "lastModifiedDateTime": "2023-07-03T01:46:22.747Z", + }, + ], + "create_new_auto_create_projects_destination_attributes_re_enable_case": [ + { + "@odata.etag": 'W/"JzE5OzcxODU5NjM0ODcxNDY4NDkzMTIxOzAwOyc="', + "id": "d82d092b-ca5d-ee11-8def-6045bde811d8", + "number": "AH", + "displayName": "Annette Hill", + "givenName": "Annette", + "middleName": "", + "surname": "Hill", + "jobTitle": "Secretary", + "addressLine1": "677 Fifth Avenue", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "4465-4899-4643", + "mobilePhone": "4564-4564-7831", + "email": "", + "personalEmail": "ah@contoso.com", + "employmentDate": "2001-06-01", + "terminationDate": "0001-01-01", + "status": "Active", + "birthDate": "1973-12-12", + "statisticsGroupCode": "", + "lastModifiedDateTime": "2023-09-28T06:42:27.733Z", + }, + { + "@odata.etag": 'W/"JzIwOzE0MzMyODYwNzA4NTA0MDIyMjY4MTswMDsn"', + "id": "e85d0165-4319-ee11-9cc4-6045bdc8dcac", + "number": "EH", + "displayName": "Ester Henderson", + "givenName": "Ester", + "middleName": "", + "surname": "Henderson", + "jobTitle": "Secretary", + "addressLine1": "5 Russel Street", + "addressLine2": "", + "city": "", + "state": "", + "country": "", + "postalCode": "", + "phoneNumber": "4465-4899-4643", + "mobilePhone": "4564-4564-7831", + "email": "", + "personalEmail": "eh@cronus-demosite.com", + "employmentDate": "1996-06-01", + "terminationDate": "0001-01-01", + "status": "Active", + "birthDate": "1963-12-12", + "statisticsGroupCode": "", + "lastModifiedDateTime": "2023-07-03T01:46:22.747Z", + }, + ], + "get_location_destination_attributes_0": [ + { + "@odata.etag": 'W/"JzIwOzE3ODYzMDUwMTE2MDYwNzQyOTk3MTswMDsn"', + "id": "2a933839-4319-ee11-9cc4-6045bdc8dcac", + "code": "BLUE", + "displayName": "Enterprise", + "contact": "Jeff Smith", + "addressLine1": "South East Street, 3", + "addressLine2": "", + "city": "NEW DELHI", + "state": "", + "country": "IN", + "postalCode": "IN-110001", + "phoneNumber": "+44-(0)20 8207 4533", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + { + "@odata.etag": 'W/"JzIwOzE2NDkzOTMzMzk0MjQ1NTk4NjAxMTswMDsn"', + "id": "2b933839-4319-ee11-9cc4-6045bdc8dcac", + "code": "EAST", + "displayName": "Midsize Business", + "contact": "Jack Potter", + "addressLine1": "Great Eastern Street, 80", + "addressLine2": "", + "city": "London", + "state": "", + "country": "GB", + "postalCode": "GB-EC2A 3JL", + "phoneNumber": "+44-(0)30 9874 1299", + "email": "", + "website": "", + "lastModifiedDateTime": "2023-12-07T14:51:19.873Z", + }, + ], + "create_fyle_project_payload_create_new_case": [ + { + "name": "Direct Mail Campaign", + "code": "10064", + "description": "Business Central Project - Direct Mail Campaign, Id - 10064", + "is_enabled": True, + }, + { + "name": "Platform APIs", + "code": "10081", + "description": "Business Central Project - Platform APIs, Id - 10081", + "is_enabled": True, + }, + ], + "create_fyle_project_payload_create_disable_case": [ + { + "code": "10064", + "description": "Business Central Project - Direct Mail Campaign, Id - 10064", + "is_enabled": True, + "name": "Direct Mail Campaign", + }, + { + "code": "10081", + "description": "Business Central Project - Platform APIs, Id - 10081", + "is_enabled": False, + "name": "Platform APIs", + }, + ], + "create_fyle_cost_center_payload_create_new_case": [ + { + "code": "10064", + "description": "Cost Center - Direct Mail Campaign, Id - 10064", + "is_enabled": True, + "name": "Direct Mail Campaign", + }, + { + "description": "Cost Center - Platform APIs, Id - 10081", + "is_enabled": True, + "name": "Platform APIs", + "code": "10081", + }, + ], + "create_new_auto_create_expense_custom_fields_expense_attributes_0": [ + { + "count": 2, + "data": [ + { + "category_ids": [259385], + "code": None, + "column_name": "text_column3", + "created_at": "2023-10-10T11:06:12.906551+00:00", + "default_value": None, + "field_name": "Luke", + "id": 229506, + "is_custom": True, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "Australia", + "Bangalore", + "Canada", + "Elimination - Global", + "Elimination - NA", + "Elimination - Sub", + "Holding Company", + "Inactive loc", + "India", + "Leaf Village", + "London", + "Mist Village", + "New South Wales", + "Prod test", + "Sand village", + "South Africa", + "Testing", + "Testing Ash", + "United Kingdom", + "USA 1", + "USA 2", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "Select Luke", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-10T13:24:33.787371+00:00", + }, + { + "category_ids": [ + 259385, + ], + "code": None, + "column_name": "text_column4", + "created_at": "2023-10-10T11:07:08.534779+00:00", + "default_value": None, + "field_name": "Cube", + "id": 229507, + "is_custom": True, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "Butter Cookies 1", + "Butter Cookies 2", + "Enterprise", + "Killua Class", + "Midsize Business", + "Naruto test 1", + "Serizawa test 1", + "Serizawa test 2", + "Service Line 1", + "Service Line 2", + "Service Line 3", + "Small Business", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "Select Cube", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-10T13:24:33.787371+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_expense_custom_fields_expense_attributes_1": [ + { + "count": 2, + "data": [ + { + "category_ids": [259385], + "code": None, + "column_name": "text_column3", + "created_at": "2023-10-10T11:06:12.906551+00:00", + "default_value": None, + "field_name": "Luke", + "id": 229506, + "is_custom": True, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "Australia", + "Bangalore", + "Canada", + "Elimination - Global", + "Elimination - NA", + "Elimination - Sub", + "Holding Company", + "Inactive loc", + "India", + "Leaf Village", + "London", + "Mist Village", + "New South Wales", + "Prod test", + "Sand village", + "South Africa", + "Testing", + "Testing Ash", + "United Kingdom", + "USA 1", + "USA 2", + "USA 3", + "USA 4", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "Select Luke", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-10T13:24:33.787371+00:00", + }, + { + "category_ids": [ + 259385, + ], + "code": None, + "column_name": "text_column4", + "created_at": "2023-10-10T11:07:08.534779+00:00", + "default_value": None, + "field_name": "Cube", + "id": 229507, + "is_custom": True, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "Butter Cookies 1", + "Butter Cookies 2", + "Enterprise", + "Killua Class", + "Midsize Business", + "Naruto test 1", + "Serizawa test 1", + "Serizawa test 2", + "Service Line 1", + "Service Line 2", + "Service Line 3", + "Small Business", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "Select Cube", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-10T13:24:33.787371+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_categories_expense_attributes_0": [ + { + "count": 20, + "data": [ + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Train", + "id": 268774, + "is_enabled": True, + "name": "Train", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323490, 323492, 323493, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Train", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Fuel", + "id": 268775, + "is_enabled": True, + "name": "Fuel", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489, 323491, 323492], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Fuel", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Office Supplies", + "id": 268776, + "is_enabled": True, + "name": "Office Supplies", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323487, 323488, 323490, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Office Supplies", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Utility", + "id": 268777, + "is_enabled": True, + "name": "Utility", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323490, 323491], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Utility", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Entertainment", + "id": 268778, + "is_enabled": True, + "name": "Entertainment", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323488, 323490], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Entertainment", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Others", + "id": 268779, + "is_enabled": True, + "name": "Others", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323490, 323493, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Others", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Mileage", + "id": 268780, + "is_enabled": True, + "name": "Mileage", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323485, 323490, 323491], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Mileage", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Food", + "id": 268781, + "is_enabled": True, + "name": "Food", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489, 323492], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Food", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Bus", + "id": 268782, + "is_enabled": True, + "name": "Bus", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323490, 323492, 323493], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Bus", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Taxi", + "id": 268783, + "is_enabled": True, + "name": "Taxi", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323490, 323491], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Taxi", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Mail", + "id": 268784, + "is_enabled": True, + "name": "Mail", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323490, 323492, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Mail", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Lodging", + "id": 268785, + "is_enabled": True, + "name": "Lodging", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Lodging", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Airlines", + "id": 268786, + "is_enabled": True, + "name": "Airlines", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323490, 323491, 323492], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Airlines", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Software", + "id": 268787, + "is_enabled": True, + "name": "Software", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323488, 323489, 323493], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Software", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Parking", + "id": 268788, + "is_enabled": True, + "name": "Parking", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323491, 323493], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Parking", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Unspecified", + "id": 268789, + "is_enabled": True, + "name": "Unspecified", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Unspecified", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Per Diem", + "id": 268790, + "is_enabled": True, + "name": "Per Diem", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Per Diem", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Professional Services", + "id": 268791, + "is_enabled": True, + "name": "Professional Services", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Professional Services", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Groceries", + "id": 268792, + "is_enabled": True, + "name": "Groceries", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323487, 323488, 323489, 323491, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Groceries", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Rental", + "id": 268793, + "is_enabled": True, + "name": "Rental", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Rental", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + ], + "offset": 0, + } + ], + "create_fyle_category_payload_create_new_case": [ + {"name": "Internet", "code": "Internet", "is_enabled": True}, + {"name": "Meals", "code": "Meals", "is_enabled": True}, + ], + "create_fyle_category_payload_create_disable_case": [ + {"name": "Internet", "code": "Internet", "is_enabled": False, "id": "10091"}, + {"name": "Meals", "code": "Meals", "is_enabled": False, "id": "10092"}, + ], + "create_new_auto_create_categories_expense_attributes_1": [ + { + "count": 31, + "data": [ + { + "code": "Airfare", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Airfare", + "id": 269476, + "is_enabled": True, + "name": "Airfare", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Cell Phone", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Cell Phone", + "id": 269477, + "is_enabled": True, + "name": "Cell Phone", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Ground Transportation/Parking", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Ground Transportation-Parking", + "id": 269478, + "is_enabled": True, + "name": "Ground Transportation-Parking", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Hotel/Lodging", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Hotel-Lodging", + "id": 269479, + "is_enabled": True, + "name": "Hotel-Lodging", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Internet", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Internet", + "id": 269480, + "is_enabled": True, + "name": "Internet", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "labhvam", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "labhvam", + "id": 269481, + "is_enabled": True, + "name": "labhvam", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Meals", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Meals", + "id": 269482, + "is_enabled": True, + "name": "Meals", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Naruto", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Naruto", + "id": 269483, + "is_enabled": True, + "name": "Naruto", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "Sasuke", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "Sasuke", + "id": 269484, + "is_enabled": True, + "name": "Sasuke", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": "subham", + "created_at": "2023-09-04T10:17:24.971507+00:00", + "display_name": "subham", + "id": 269485, + "is_enabled": True, + "name": "subham", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": None, + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": None, + "updated_at": "2023-09-04T10:17:24.971507+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Train", + "id": 268774, + "is_enabled": True, + "name": "Train", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323490, 323492, 323493, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Train", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Fuel", + "id": 268775, + "is_enabled": True, + "name": "Fuel", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489, 323491, 323492], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Fuel", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Office Supplies", + "id": 268776, + "is_enabled": True, + "name": "Office Supplies", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323487, 323488, 323490, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Office Supplies", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Utility", + "id": 268777, + "is_enabled": True, + "name": "Utility", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323490, 323491], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Utility", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Entertainment", + "id": 268778, + "is_enabled": True, + "name": "Entertainment", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323488, 323490], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Entertainment", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Others", + "id": 268779, + "is_enabled": True, + "name": "Others", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323490, 323493, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Others", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Mileage", + "id": 268780, + "is_enabled": True, + "name": "Mileage", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323485, 323490, 323491], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Mileage", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Food", + "id": 268781, + "is_enabled": True, + "name": "Food", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489, 323492], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Food", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Bus", + "id": 268782, + "is_enabled": True, + "name": "Bus", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323490, 323492, 323493], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Bus", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Taxi", + "id": 268783, + "is_enabled": True, + "name": "Taxi", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323490, 323491], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Taxi", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Mail", + "id": 268784, + "is_enabled": True, + "name": "Mail", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323490, 323492, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Mail", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Lodging", + "id": 268785, + "is_enabled": True, + "name": "Lodging", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Lodging", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Airlines", + "id": 268786, + "is_enabled": True, + "name": "Airlines", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323490, 323491, 323492], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Airlines", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Software", + "id": 268787, + "is_enabled": True, + "name": "Software", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323488, 323489, 323493], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Software", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Parking", + "id": 268788, + "is_enabled": True, + "name": "Parking", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323491, 323493], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Parking", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Unspecified", + "id": 268789, + "is_enabled": True, + "name": "Unspecified", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Unspecified", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Per Diem", + "id": 268790, + "is_enabled": True, + "name": "Per Diem", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Per Diem", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Professional Services", + "id": 268791, + "is_enabled": True, + "name": "Professional Services", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323488, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Professional Services", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Groceries", + "id": 268792, + "is_enabled": True, + "name": "Groceries", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323487, 323488, 323489, 323491, 323494], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Groceries", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + { + "code": None, + "created_at": "2023-08-30T18:58:09.203161+00:00", + "display_name": "Rental", + "id": 268793, + "is_enabled": True, + "name": "Rental", + "org_id": "orwimNcVyYsp", + "restricted_project_ids": [323486, 323489], + "restricted_spender_user_ids": [], + "sub_category": None, + "system_category": "Rental", + "updated_at": "2023-08-30T18:58:09.203161+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_cost_centers_expense_attributes_0": [ + { + "count": 6, + "data": [ + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Enterprise, Id - 600", + "id": 19728, + "is_enabled": True, + "name": "Enterprise", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Midsize Business, Id - 500", + "id": 19730, + "is_enabled": True, + "name": "Midsize Business", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 1, Id - 100", + "id": 19731, + "is_enabled": True, + "name": "Service Line 1", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 2, Id - 200", + "id": 19732, + "is_enabled": True, + "name": "Ester Henderson", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 3, Id - 300", + "id": 19733, + "is_enabled": True, + "name": "Annette Hill", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Small Business, Id - 400", + "id": 19734, + "is_enabled": True, + "name": "Small Business", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_cost_centers_expense_attributes_disable": [ + { + "count": 2, + "data": [ + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 3, Id - 300", + "id": 19733, + "is_enabled": False, + "name": "Annette Hill", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Small Business, Id - 400", + "id": 19734, + "is_enabled": False, + "name": "Small Business", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_merchants_expense_attributes_0": [ + { + "count": 1, + "data": [ + { + "category_ids": [259385, 259386, 259387, 259388, 259389, 273385], + "code": None, + "column_name": "merchant", + "created_at": "2023-06-01T04:46:25.644307+00:00", + "default_value": "", + "field_name": "Merchant", + "id": 225221, + "is_custom": False, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "ADP", + "Advisor Printing", + "akavuluru", + "American Express", + "Ashwin", + "Boardwalk Post", + "Brian Foster", + "Canyon CPA", + "Chris Curtis", + "Citi Bank", + "Consulting Grid", + "Cornerstone", + "Credit Card Misc", + "Entity V100", + "Entity V200", + "Entity V300", + "Entity V400", + "Entity V500", + "Entity V600", + "Entity V700", + "Global Printing", + "Global Properties Inc.", + "gokul", + "Green Team Waste Management", + "Hanson Learning Solutions", + "HC Equipment Repair", + "Investor CPA", + "James Taylor", + "Jessica Lane", + "Joshua Wood", + "Justin Glass", + "Kaufman & Langer LLP", + "Kristofferson Consulting", + "Lee Thomas", + "Lenovo", + "Linda Hicks", + "Magnolia CPA", + "Massachusetts Department of Revenue", + "Matthew Estrada", + "Microns Consulting", + "Natalie Pope", + "National Grid", + "National Insurance", + "Neighborhood Printers", + "Nilesh, Dhoni", + "Paramount Consulting", + "Prima Printing", + "Prosper Post", + "Quali Consultants", + "Quick Post", + "River Glen Insurance", + "Sachin, Saran", + "Samantha Washington", + "Scribe Post", + "Singleton Brothers CPA", + "Srav", + "State Bank", + "The Nonprofit Alliance", + "The Post Company", + "Theresa Brown", + "Vaishnavi Primary", + "Victor Martinez", + "Vision Post", + "VM", + "Worldwide Commercial", + "Yash", + "Baki Hanma", + "Labhvam", + "Fyle For Intacct Ref", + "Goner", + "Keventers", + "Whirpool", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "E.g. Uber", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-23T12:20:00.035384+00:00", + } + ], + "offset": 0, + } + ], + "create_new_auto_create_merchants_expense_attributes_1": [ + { + "count": 1, + "data": [ + { + "category_ids": [259385, 259386, 259387, 259388, 259389, 273385], + "code": None, + "column_name": "merchant", + "created_at": "2023-06-01T04:46:25.644307+00:00", + "default_value": "", + "field_name": "Merchant", + "id": 225221, + "is_custom": False, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "ADP", + "Advisor Printing", + "akavuluru", + "American Express", + "Ashwin", + "Boardwalk Post", + "Brian Foster", + "Canyon CPA", + "Chris Curtis", + "Citi Bank", + "Consulting Grid", + "Cornerstone", + "Credit Card Misc", + "Entity V100", + "Entity V200", + "Entity V300", + "Entity V400", + "Entity V500", + "Entity V600", + "Entity V700", + "Global Printing", + "Global Properties Inc.", + "gokul", + "Green Team Waste Management", + "Hanson Learning Solutions", + "HC Equipment Repair", + "Investor CPA", + "James Taylor", + "Jessica Lane", + "Joshua Wood", + "Justin Glass", + "Kaufman & Langer LLP", + "Kristofferson Consulting", + "Lee Thomas", + "Lenovo", + "Linda Hicks", + "Magnolia CPA", + "Massachusetts Department of Revenue", + "Matthew Estrada", + "Microns Consulting", + "Natalie Pope", + "National Grid", + "National Insurance", + "Neighborhood Printers", + "Nilesh, Dhoni", + "Paramount Consulting", + "Prima Printing", + "Prosper Post", + "Quali Consultants", + "Quick Post", + "River Glen Insurance", + "Sachin, Saran", + "Samantha Washington", + "Scribe Post", + "Singleton Brothers CPA", + "Srav", + "State Bank", + "The Nonprofit Alliance", + "The Post Company", + "Theresa Brown", + "Vaishnavi Primary", + "Victor Martinez", + "Vision Post", + "VM", + "Worldwide Commercial", + "Yash", + "Baki Hanma", + "Labhvam", + "Fyle For Intacct Ref", + "Goner", + "Keventers", + "Whirpool", + "Uvuv", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "E.g. Uber", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-23T12:20:00.035384+00:00", + } + ], + "offset": 0, + } + ], + "create_new_auto_create_merchants_expense_attributes_2": [ + { + "count": 1, + "data": [ + { + "category_ids": [259385, 259386, 259387, 259388, 259389, 273385], + "code": None, + "column_name": "merchant", + "created_at": "2023-06-01T04:46:25.644307+00:00", + "default_value": "", + "field_name": "Merchant", + "id": 225221, + "is_custom": False, + "is_enabled": True, + "is_mandatory": False, + "options": [ + "ADP", + "Advisor Printing", + "akavuluru", + "American Express", + "Ashwin", + "Boardwalk Post", + "Brian Foster", + "Canyon CPA", + "Chris Curtis", + "Citi Bank", + "Consulting Grid", + "Cornerstone", + "Credit Card Misc", + "Entity V100", + "Entity V200", + "Entity V300", + "Entity V400", + "Entity V500", + "Entity V600", + "Entity V700", + "Global Printing", + "Global Properties Inc.", + "gokul", + "Green Team Waste Management", + "Hanson Learning Solutions", + "HC Equipment Repair", + "Investor CPA", + "James Taylor", + "Jessica Lane", + "Joshua Wood", + "Justin Glass", + "Kaufman & Langer LLP", + "Kristofferson Consulting", + "Lee Thomas", + "Lenovo", + "Linda Hicks", + "Magnolia CPA", + "Massachusetts Department of Revenue", + "Matthew Estrada", + "Microns Consulting", + "Natalie Pope", + "National Grid", + "National Insurance", + "Neighborhood Printers", + "Nilesh, Dhoni", + "Paramount Consulting", + "Prima Printing", + "Prosper Post", + "Quali Consultants", + "Quick Post", + "River Glen Insurance", + "Sachin, Saran", + "Samantha Washington", + "Scribe Post", + "Singleton Brothers CPA", + "Srav", + "State Bank", + "The Nonprofit Alliance", + "The Post Company", + "Theresa Brown", + "Vaishnavi Primary", + "Victor Martinez", + "Vision Post", + "VM", + "Worldwide Commercial", + "Yash", + "Baki Hanma", + "Labhvam", + "Fyle For Intacct Ref", + "Goner", + "Keventers", + "Whirpool", + "Uvuv", + "Eminem", + "Logic", + ], + "org_id": "orqjgyJ21uge", + "parent_field_id": None, + "placeholder": "E.g. Uber", + "seq": 1, + "type": "SELECT", + "updated_at": "2023-10-23T12:20:00.035384+00:00", + } + ], + "offset": 0, + } + ], + "create_new_auto_create_cost_centers_expense_attributes_1": [ + { + "count": 7, + "data": [ + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Enterprise, Id - 600", + "id": 19728, + "is_enabled": True, + "name": "Enterprise", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Killua Class, Id - 9903", + "id": 19729, + "is_enabled": True, + "name": "Killua Class", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Midsize Business, Id - 500", + "id": 19730, + "is_enabled": True, + "name": "Midsize Business", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 1, Id - 100", + "id": 19731, + "is_enabled": True, + "name": "Service Line 1", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 2, Id - 200", + "id": 19732, + "is_enabled": True, + "name": "Service Line 2", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Service Line 3, Id - 300", + "id": 19733, + "is_enabled": True, + "name": "Service Line 3", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + { + "code": None, + "created_at": "2023-09-15T06:06:10.923262+00:00", + "description": "Cost Center - Small Business, Id - 400", + "id": 19734, + "is_enabled": True, + "name": "Small Business", + "org_id": "ortL3T2BabCW", + "restricted_spender_user_ids": None, + "updated_at": "2023-09-15T06:06:10.923262+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_projects_expense_attributes_0": [ + { + "count": 28, + "data": [ + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10086", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - openheimer, Id - 10086", + "display_name": "openheimer", + "id": 322907, + "is_enabled": False, + "name": "openheimer", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-08-01T12:47:24.128675+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10088", + "created_at": "2023-08-01T12:47:24.128675+00:00", + "description": "Sage Intacct Project - Yujiro, Id - 10088", + "display_name": "Annette Hill", + "id": 322927, + "is_enabled": True, + "name": "Annette Hill", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-08-01T12:47:24.128675+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10087", + "created_at": "2023-08-01T12:38:20.406828+00:00", + "description": "Sage Intacct Project - Pickle, Id - 10087", + "display_name": "Ester Henderson", + "id": 322926, + "is_enabled": True, + "name": "Ester Henderson", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-08-01T12:38:20.406828+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10083", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - labhvam, Id - 10083", + "display_name": "labhvam", + "id": 322905, + "is_enabled": False, + "name": "labhvam", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-08-01T09:41:10.913084+00:00", + }, + { + "approver_user_ids": ["None", "None"], + "approver_users": [], + "category_ids": [ + 259385, + 259386, + 259387, + 259388, + 259389, + 259390, + 259391, + 259392, + 259393, + 259394, + 259395, + 259396, + 259397, + 259398, + 259399, + 259401, + 259402, + 259403, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "None", + "created_at": "2023-07-31T14:13:44.016925+00:00", + "description": "None", + "display_name": "Fyle proj 3", + "id": 322924, + "is_enabled": True, + "name": "Fyle proj 3", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T14:13:44.016925+00:00", + }, + { + "approver_user_ids": ["None", "None"], + "approver_users": [], + "category_ids": [ + 259385, + 259386, + 259387, + 259388, + 259389, + 259390, + 259391, + 259392, + 259393, + 259394, + 259395, + 259396, + 259397, + 259398, + 259399, + 259401, + 259402, + 259403, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "None", + "created_at": "2023-07-31T14:13:22.031233+00:00", + "description": "None", + "display_name": "Fyle proj 2", + "id": 322923, + "is_enabled": True, + "name": "Fyle proj 2", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T14:13:22.031233+00:00", + }, + { + "approver_user_ids": ["None", "None"], + "approver_users": [], + "category_ids": [ + 259385, + 259386, + 259387, + 259388, + 259389, + 259390, + 259391, + 259392, + 259393, + 259394, + 259395, + 259396, + 259397, + 259398, + 259399, + 259401, + 259402, + 259403, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "None", + "created_at": "2023-07-31T13:59:57.718713+00:00", + "description": "None", + "display_name": "Fyle proj 1", + "id": 322922, + "is_enabled": True, + "name": "Fyle proj 1", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T13:59:57.718713+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "Template-FF", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Fixed Fee Project with Five Tasks, Id - Template-FF", + "display_name": "Fixed Fee Project with Five Tasks", + "id": 322899, + "is_enabled": True, + "name": "Fixed Fee Project with Five Tasks", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10078", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Fyle NetSuite Integration, Id - 10078", + "display_name": "Fyle NetSuite Integration", + "id": 322900, + "is_enabled": True, + "name": "Fyle NetSuite Integration", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10077", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Fyle Sage Intacct Integration, Id - 10077", + "display_name": "Fyle Sage Intacct Integration", + "id": 322901, + "is_enabled": True, + "name": "Fyle Sage Intacct Integration", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10000", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - General Overhead, Id - 10000", + "display_name": "General Overhead", + "id": 322902, + "is_enabled": True, + "name": "General Overhead", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10025", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - General Overhead-Current, Id - 10025", + "display_name": "General Overhead-Current", + "id": 322903, + "is_enabled": True, + "name": "General Overhead-Current", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10076", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Integrations, Id - 10076", + "display_name": "Integrations", + "id": 322904, + "is_enabled": True, + "name": "Integrations", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10080", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Mobile App Redesign, Id - 10080", + "display_name": "Mobile App Redesign", + "id": 322906, + "is_enabled": True, + "name": "Mobile App Redesign", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10081", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Platform APIs, Id - 10081", + "display_name": "Platform APIs", + "id": 322908, + "is_enabled": True, + "name": "Platform APIs", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10082", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Support Taxes, Id - 10082", + "display_name": "Support Taxes", + "id": 322909, + "is_enabled": True, + "name": "Support Taxes", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "Template-TM", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - T&M Project with Five Tasks, Id - Template-TM", + "display_name": "T&M Project with Five Tasks", + "id": 322910, + "is_enabled": True, + "name": "T&M Project with Five Tasks", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": "None", + "code": "10085", + "created_at": "2023-07-31T10:52:39.443516+00:00", + "description": "Sage Intacct Project - Youtube proj, Id - 10085", + "display_name": "Youtube proj", + "id": 322911, + "is_enabled": True, + "name": "Youtube proj", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-07-31T10:52:39.443516+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259386, + 259388, + 259389, + 259390, + 259391, + 259394, + 259395, + 259396, + 259397, + 259400, + 259401, + 259402, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "7OUXCF0XJ0", + "created_at": "2023-06-01T04:48:20.729481+00:00", + "description": "KSFYP9KOIE", + "display_name": "Project 10", + "id": 320663, + "is_enabled": True, + "name": "Project 10", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.636962+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259387, + 259389, + 259392, + 259396, + 259399, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "7070DYRG0R", + "created_at": "2023-06-01T04:48:19.896375+00:00", + "description": "JO38LCLK45", + "display_name": "Project 9", + "id": 320662, + "is_enabled": True, + "name": "Project 9", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.635301+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259388, + 259390, + 259392, + 259393, + 259395, + 259397, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "NMPHRP9IH5", + "created_at": "2023-06-01T04:48:19.043469+00:00", + "description": "YE8SLNWO5L", + "display_name": "Project 8", + "id": 320661, + "is_enabled": True, + "name": "Project 8", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.633920+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259386, + 259387, + 259392, + 259395, + 259399, + 259402, + 259403, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "77UQ8NI3XZ", + "created_at": "2023-06-01T04:48:18.209488+00:00", + "description": "R8MNK74OL5", + "display_name": "Project 7", + "id": 320660, + "is_enabled": True, + "name": "Project 7", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.632360+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259390, + 259400, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "43L0CC24Y7", + "created_at": "2023-06-01T04:48:17.374612+00:00", + "description": "EWUD1LI1IO", + "display_name": "Project 6", + "id": 320659, + "is_enabled": True, + "name": "Project 6", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.629026+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259390, + 259391, + 259393, + 259394, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "J7TVHSYQDY", + "created_at": "2023-06-01T04:48:16.538603+00:00", + "description": "EIRFULTGYD", + "display_name": "Project 5", + "id": 320658, + "is_enabled": True, + "name": "Project 5", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.627150+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259388, + 259389, + 259390, + 259391, + 259392, + 259393, + 259396, + 259397, + 259399, + 259401, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "1IUZDMVXTR", + "created_at": "2023-06-01T04:48:15.710357+00:00", + "description": "Z9SG2RTNX7", + "display_name": "Project 4", + "id": 320657, + "is_enabled": True, + "name": "Project 4", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.625882+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259387, + 259389, + 259393, + 259394, + 259395, + 259398, + 259399, + 259401, + 259402, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "D5DW3ZN81B", + "created_at": "2023-06-01T04:48:14.910874+00:00", + "description": "OMH2VEMBPY", + "display_name": "Project 3", + "id": 320656, + "is_enabled": True, + "name": "Project 3", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.623804+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259385, + 259387, + 259388, + 259390, + 259391, + 259392, + 259393, + 259395, + 259396, + 259398, + 259400, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "02B5XR6PGR", + "created_at": "2023-06-01T04:48:14.001968+00:00", + "description": "FQJJMFWQ41", + "display_name": "Project 2", + "id": 320655, + "is_enabled": True, + "name": "Project 2", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.621249+00:00", + }, + { + "approver_user_ids": ["usyp58biP7hS", "None"], + "approver_users": [ + { + "email": "approver1@fyleforbcaa.in", + "full_name": "Ryan Gallagher", + "id": "usyp58biP7hS", + } + ], + "category_ids": [ + 259386, + 259387, + 259388, + 259389, + 259390, + 259393, + 259395, + 259397, + 259400, + 259403, + 259404, + 259405, + 259406, + 259407, + 259408, + 259409, + 259410, + 259411, + 259412, + 259413, + 259414, + 259415, + 259416, + 259417, + 259418, + 259419, + 259420, + 259421, + 259422, + 259423, + 259424, + 259425, + 259426, + 259427, + 259428, + 259429, + 259430, + 259431, + 259432, + 259433, + 259434, + 259435, + 259436, + 259437, + 259438, + 259439, + 259440, + 259441, + 259442, + 259443, + 259444, + 259445, + 259446, + 259447, + 259448, + 259449, + 259450, + 259451, + 259452, + 259453, + 259454, + 259455, + 259456, + 259457, + 259458, + 259459, + 259460, + 259461, + 259462, + 259463, + 259464, + 259465, + 259466, + 259467, + 259468, + 259469, + 259470, + 259471, + 259472, + 259473, + 259474, + 259475, + 259476, + 259477, + 259478, + 259479, + 259480, + 259481, + 259482, + 259483, + 259484, + 259485, + 259486, + 259487, + 259488, + 259489, + 259490, + 259491, + 259492, + 259493, + 259494, + 259495, + 259496, + 259497, + 259498, + 259499, + 259500, + 259501, + 259502, + 259503, + 259504, + 259505, + 259506, + 259507, + 259508, + 259509, + 259510, + 259511, + 259512, + 259513, + 259514, + 259515, + 259516, + 259517, + 259518, + 259519, + 259520, + 259521, + 259522, + 259523, + 259524, + 259525, + 259526, + 259527, + 259528, + 259529, + 259530, + 259531, + 259532, + 259533, + 259534, + 259535, + 259536, + 259537, + 259538, + 259539, + 259540, + 259541, + 259542, + 259543, + 259544, + 259545, + 259546, + 259547, + 259548, + 259549, + 259550, + 259551, + 259552, + 259553, + 259554, + 259555, + 259556, + 259557, + 259558, + 259559, + 259560, + 259561, + 259562, + 259563, + 259564, + 259565, + 259566, + 259567, + 259568, + 259569, + 259570, + 259571, + 259572, + 259573, + 259574, + 259575, + 259576, + 259577, + 259578, + 259579, + 259580, + 259581, + 259582, + 259583, + 259584, + 259585, + 259586, + 259587, + 259588, + 259589, + 259590, + 259591, + 259592, + 259593, + 259594, + 259595, + 259596, + 259597, + 259598, + 259599, + 259600, + 259601, + 259602, + 259603, + 259604, + 259605, + 259606, + 259607, + 259608, + 259609, + 259610, + 259611, + 259612, + 259613, + 259614, + 259615, + 259616, + 259617, + 259618, + 259619, + 259620, + 259621, + 259622, + 259623, + 259624, + 259625, + 259626, + 259627, + 259628, + 259629, + 259630, + 259631, + 259632, + 259633, + 259634, + 260161, + 260162, + 260165, + 260166, + 260167, + 260168, + 260169, + 260170, + 260171, + 260172, + 260173, + 260174, + 260175, + 260176, + 260177, + 260178, + 260179, + 260180, + 260181, + 260182, + 260183, + 260184, + 260185, + 260186, + 260187, + 260188, + 260189, + 260190, + 260191, + 260192, + 260193, + 260194, + 260195, + 260196, + 260197, + 260198, + 260199, + 260200, + 260201, + 260202, + 260203, + 260204, + 260205, + 260206, + 260207, + 260208, + 260209, + 260210, + 260211, + 260212, + 260213, + 260214, + 260215, + 260216, + 260217, + 260218, + 260219, + 260220, + 260221, + 260222, + 260223, + 260224, + 260225, + 260226, + 260227, + 260228, + 260229, + 260230, + 260231, + 260232, + 260233, + 260234, + 260235, + 260236, + 260237, + 260238, + 260239, + 260240, + 260241, + 260242, + 260243, + 260244, + 260245, + 260246, + 260247, + 260248, + 260249, + 260250, + 260251, + 260252, + 260253, + 260254, + 260255, + 260256, + 260257, + 260258, + 260259, + 260260, + 260261, + 260262, + 260263, + 260264, + 260265, + 260266, + 260267, + 260268, + 260269, + 260270, + 260271, + 260272, + 260273, + 260274, + 260275, + 260276, + 260277, + 260278, + 260279, + 260280, + 260281, + 260282, + 260283, + 260284, + 260285, + 260286, + 260287, + 260288, + 260289, + 260290, + 260291, + 260292, + 260293, + 260294, + 260295, + 260296, + 260297, + 260298, + 260299, + 260300, + 260301, + 260302, + 260303, + 260304, + 260305, + 260306, + 260307, + 260308, + 260309, + 260310, + 260311, + 260312, + 260313, + 260314, + 260315, + 260316, + 260317, + 260318, + 260319, + 260320, + 260321, + 260322, + 260323, + 260324, + 260325, + 260326, + 260327, + 260328, + 260329, + 261448, + 261449, + 261450, + 261451, + 261452, + 261749, + 261750, + 261824, + 261825, + 262290, + ], + "code": "C1ZQT5UGZA", + "created_at": "2023-06-01T04:48:13.075889+00:00", + "description": "3BOU91E9P3", + "display_name": "Project 1", + "id": 320654, + "is_enabled": True, + "name": "Project 1", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": "None", + "sub_project": "", + "updated_at": "2023-06-16T07:45:29.607863+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_projects_expense_attributes_1": [ + { + "count": 13, + "data": [ + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10089", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Electro wizard, Id - 10089", + "display_name": "Electro wizard", + "id": 323014, + "is_enabled": True, + "name": "Electro wizard", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10090", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Yujiro, Id - 10090", + "display_name": "Yujiro", + "id": 323015, + "is_enabled": True, + "name": "Yujiro", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10091", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Fixed Fee Project with Five Tasks, Id - 10091", + "display_name": "Fixed Fee Project with Five Tasks", + "id": 323015, + "is_enabled": True, + "name": "Fixed Fee Project with Five Tasks", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10092", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Fyle NetSuite Integration, Id - 10092", + "display_name": "Fyle NetSuite Integration", + "id": 323015, + "is_enabled": True, + "name": "Fyle NetSuite Integration", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10093", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Fyle Sage Intacct Integration, Id - 10093", + "display_name": "Fyle Sage Intacct Integration", + "id": 323015, + "is_enabled": True, + "name": "Fyle Sage Intacct Integration", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10094", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - General Overhead, Id - 10094", + "display_name": "General Overhead", + "id": 323015, + "is_enabled": True, + "name": "General Overhead", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10095", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - General Overhead-Current, Id - 10095", + "display_name": "General Overhead-Current", + "id": 323015, + "is_enabled": True, + "name": "General Overhead-Current", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10096", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Integrations, Id - 10096", + "display_name": "Integrations", + "id": 323015, + "is_enabled": True, + "name": "Integrations", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10097", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Mobile App Redesign, Id - 10097", + "display_name": "Mobile App Redesign", + "id": 323015, + "is_enabled": True, + "name": "Mobile App Redesign", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10098", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Platform APIs, Id - 10098", + "display_name": "Platform APIs", + "id": 323015, + "is_enabled": True, + "name": "Platform APIs", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10099", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Support Taxes, Id - 10099", + "display_name": "Support Taxes", + "id": 323015, + "is_enabled": True, + "name": "Support Taxes", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "100100", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - T&M Project with Five Tasks, Id - 100100", + "display_name": "T&M Project with Five Tasks", + "id": 323015, + "is_enabled": True, + "name": "T&M Project with Five Tasks", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "100101", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Youtube proj, Id - 100101", + "display_name": "Youtube proj", + "id": 323015, + "is_enabled": True, + "name": "Youtube proj", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + ], + "offset": 0, + } + ], + "create_new_auto_create_projects_expense_attributes_3": [ + {"count": 0, "data": [], "offset": 0} + ], + "create_new_auto_create_projects_expense_attributes_4": [ + { + "count": 2, + "data": [ + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10089", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Electro wizard, Id - 10089", + "display_name": "Annette Hill", + "id": 323014, + "is_enabled": False, + "name": "Annette Hill", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + { + "approver_user_ids": [], + "approver_users": [], + "category_ids": None, + "code": "10090", + "created_at": "2023-08-08T11:01:16.347801+00:00", + "description": "Sage Intacct Project - Yujiro, Id - 10090", + "display_name": "Yujiro", + "id": 323015, + "is_enabled": False, + "name": "Yujiro", + "org_id": "orqjgyJ21uge", + "restricted_spender_user_ids": None, + "sub_project": None, + "updated_at": "2023-08-08T11:01:16.347801+00:00", + }, + ], + "offset": 0, + } + ], +} diff --git a/tests/test_mappings/test_imports/test_modules/helpers.py b/tests/test_mappings/test_imports/test_modules/helpers.py new file mode 100644 index 0000000..9243928 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/helpers.py @@ -0,0 +1,30 @@ +from fyle_integrations_platform_connector import PlatformConnector + +from apps.mappings.imports.modules.base import Base +from apps.workspaces.models import FyleCredential + + +def get_base_class_instance( + workspace_id: int = 1, + source_field: str = "COST_CENTER", + destination_field: str = "COST_CENTER", + platform_class_name: str = "cost_centers", + sync_after: str = None, +): + + base = Base( + workspace_id=workspace_id, + source_field=source_field, + destination_field=destination_field, + platform_class_name=platform_class_name, + sync_after=sync_after, + ) + + return base + + +def get_platform_connection(workspace_id): + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + return platform diff --git a/tests/test_mappings/test_imports/test_modules/test_base.py b/tests/test_mappings/test_imports/test_modules/test_base.py new file mode 100644 index 0000000..3a21e7e --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_base.py @@ -0,0 +1,578 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from fyle_accounting_mappings.models import CategoryMapping, DestinationAttribute, ExpenseAttribute, Mapping +from fyle_integrations_platform_connector import PlatformConnector + +from apps.accounting_exports.models import Error +from apps.mappings.imports.modules.categories import Category +from apps.mappings.imports.modules.projects import Project +from apps.mappings.models import ImportLog +from apps.workspaces.models import FyleCredential, Workspace +from tests.test_mappings.test_imports.test_modules.fixtures import data as destination_attributes_data +from tests.test_mappings.test_imports.test_modules.helpers import get_base_class_instance, get_platform_connection + + +def test_sync_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + + mocker.patch( + "dynamics.apis.Accounts.get_all", + return_value=destination_attributes_data["get_account_destination_attributes"], + ) + + account_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="ACCOUNT" + ).count() + assert account_count == 0 + + account = Category(workspace_id, "ACCOUNT", None) + account.sync_destination_attributes("ACCOUNT") + + new_account_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="ACCOUNT" + ).count() + assert new_account_count == 2 + + +def test_sync_expense_atrributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + fyle_credentials.workspace.org_id = "orwimNcVyYsp" + fyle_credentials.workspace.save() + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + mocker.patch("fyle.platform.apis.v1beta.admin.Categories.list_all", return_value=[]) + + category_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="CATEGORY" + ).count() + assert category_count == 0 + + category = Category(workspace_id, "ACCOUNT", None) + category.sync_expense_attributes(platform) + + category_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="CATEGORY" + ).count() + assert category_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.Categories.list_all", + return_value=destination_attributes_data[ + "create_new_auto_create_categories_expense_attributes_0" + ], + ) + category.sync_expense_attributes(platform) + + category_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="CATEGORY" + ).count() + assert ( + category_count + == destination_attributes_data[ + "create_new_auto_create_categories_expense_attributes_0" + ][0]["count"] + ) + + +def test_remove_duplicates( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + add_cost_center_mappings, +): + attributes = DestinationAttribute.objects.filter(attribute_type="COST_CENTER") + + assert len(attributes) == 6 + + for attribute in attributes: + DestinationAttribute.objects.create( + attribute_type="COST_CENTER", + workspace_id=attribute.workspace_id, + value=attribute.value, + destination_id="010{0}".format(attribute.destination_id), + ) + + attributes = DestinationAttribute.objects.filter(attribute_type="COST_CENTER") + + assert len(attributes) == 12 + + base = get_base_class_instance() + + attributes = base.remove_duplicate_attributes(attributes) + assert len(attributes) == 2 + + +def test_get_platform_class( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, +): + base = get_base_class_instance() + platform = get_platform_connection(1) + + assert base.get_platform_class(platform) == platform.cost_centers + + base = get_base_class_instance( + workspace_id=1, + source_field="CATEGORY", + destination_field="ACCOUNT", + platform_class_name="categories", + ) + assert base.get_platform_class(platform) == platform.categories + + base = get_base_class_instance( + workspace_id=1, + source_field="COST_CENTER", + destination_field="DEPARTMENT", + platform_class_name="cost_centers", + ) + assert base.get_platform_class(platform) == platform.cost_centers + + +def test_get_auto_sync_permission( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, +): + base = get_base_class_instance() + + assert base.get_auto_sync_permission() == False + + base = get_base_class_instance( + workspace_id=1, + source_field="CATEGORY", + destination_field="ACCOUNT", + platform_class_name="categories", + ) + + assert base.get_auto_sync_permission() == True + + base = get_base_class_instance( + workspace_id=1, + source_field="PROJECT", + destination_field="DEPARTMENT", + platform_class_name="projects", + ) + + assert base.get_auto_sync_permission() == False + + +def test_construct_attributes_filter( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + add_cost_center_mappings, +): + base = get_base_class_instance() + + assert base.construct_attributes_filter("PROJECT") == { + "attribute_type": "PROJECT", + "workspace_id": 1, + } + + date_string = "2023-08-06 12:50:05.875029" + sync_after = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S.%f") + + base = get_base_class_instance( + workspace_id=1, + source_field="CATEGORY", + destination_field="ACCOUNT", + platform_class_name="categories", + sync_after=sync_after, + ) + + assert base.construct_attributes_filter("CATEGORY") == { + "attribute_type": "CATEGORY", + "workspace_id": 1, + "updated_at__gte": sync_after, + } + + paginated_destination_attribute_values = [ + "Mobile App Redesign", + "Platform APIs", + "Fyle NetSuite Integration", + "Fyle Sage Intacct Integration", + "Support Taxes", + "T&M Project with Five Tasks", + "Fixed Fee Project with Five Tasks", + "General Overhead", + "General Overhead-Current", + "Youtube proj", + "Integrations", + "Yujiro", + "Pickle", + ] + + assert base.construct_attributes_filter( + "COST_CENTER", paginated_destination_attribute_values + ) == { + "attribute_type": "COST_CENTER", + "workspace_id": 1, + "updated_at__gte": sync_after, + "value__in": paginated_destination_attribute_values, + } + + +def test_auto_create_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + project = Project(1, "EMPLOYEE", None) + project.sync_after = None + + Workspace.objects.filter(id=1).update(org_id="orqjgyJ21uge") + # delete all destination attributes, expense attributes and mappings + Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE" + ).delete() + ExpenseAttribute.objects.filter(workspace_id=1, attribute_type="PROJECT").delete() + + # create new case for account import + with mock.patch("fyle.platform.apis.v1beta.admin.Projects.list_all") as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.Projects.post_bulk", + return_value=[], + ) + mocker.patch( + "dynamics.apis.Employees.get_all", + return_value=destination_attributes_data[ + "get_employee_destination_attributes_0" + ], + ) + mock_call.side_effect = [ + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_0" + ], + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_1" + ], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ).count() + + assert expense_attributes_count == 0 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).count() + + assert mappings_count == 0 + + project.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ).count() + + assert expense_attributes_count == 30 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).count() + + assert mappings_count == 2 + + # disable case for employee import + with mock.patch("fyle.platform.apis.v1beta.admin.Projects.list_all") as mock_call: + mocker.patch( + "dynamics.apis.Employees.get_all", + return_value=destination_attributes_data[ + "create_new_auto_create_employee_destination_attributes_disable_case" + ], + ) + mocker.patch( + "fyle_integrations_platform_connector.apis.Projects.post_bulk", + return_value=[], + ) + mock_call.side_effect = [ + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_3" + ], + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_4" + ], + ] + + destination_attribute = DestinationAttribute.objects.filter( + workspace_id=1, value="Ester Henderson" + ).first() + + assert destination_attribute.active == True + + expense_attribute = ExpenseAttribute.objects.filter( + workspace_id=1, value="Ester Henderson" + ).first() + + assert expense_attribute.active == True + + mapping = Mapping.objects.filter( + destination_id=destination_attribute.id + ).first() + + pre_run_expense_attribute_disabled_count = ExpenseAttribute.objects.filter( + workspace_id=1, active=False, attribute_type="PROJECT" + ).count() + + assert pre_run_expense_attribute_disabled_count == 2 + + # This confirms that mapping is present and both expense_attribute and destination_attribute are active + assert mapping.source_id == expense_attribute.id + + project.trigger_import() + + destination_attribute = DestinationAttribute.objects.filter( + workspace_id=1, value="Annette Hill" + ).first() + + assert destination_attribute.active == False + + expense_attribute = ExpenseAttribute.objects.filter( + workspace_id=1, value="Annette Hill" + ).first() + + assert expense_attribute.active == False + + post_run_expense_attribute_disabled_count = ExpenseAttribute.objects.filter( + workspace_id=1, active=False, attribute_type="PROJECT" + ).count() + + assert ( + post_run_expense_attribute_disabled_count + == pre_run_expense_attribute_disabled_count + + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_4" + ][0]["count"] + ) + + # not re-enable case for project import + with mock.patch("fyle.platform.apis.v1beta.admin.Projects.list_all") as mock_call: + mocker.patch( + "dynamics.apis.Employees.get_all", + return_value=destination_attributes_data[ + "create_new_auto_create_projects_destination_attributes_re_enable_case" + ], + ) + mocker.patch( + "fyle_integrations_platform_connector.apis.Projects.post_bulk", + return_value=[], + ) + mock_call.side_effect = [ + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_3" + ], + destination_attributes_data[ + "create_new_auto_create_projects_expense_attributes_3" + ], + ] + + pre_run_destination_attribute_count = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE", active=False + ).count() + + assert pre_run_destination_attribute_count == 1 + + pre_run_expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT", active=False + ).count() + + assert pre_run_expense_attribute_count == 4 + + project.trigger_import() + + post_run_destination_attribute_count = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE", active=False + ).count() + + assert post_run_destination_attribute_count == 0 + + post_run_expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT", active=False + ).count() + + assert pre_run_expense_attribute_count == post_run_expense_attribute_count + + # Not creating the schedule part due to time diff + current_time = datetime.now() + sync_after = current_time.replace(tzinfo=timezone.utc) + project.sync_after = sync_after + + import_log = ImportLog.objects.filter(workspace_id=1).first() + import_log.status = "COMPLETE" + import_log.attribute_type = "PROJECT" + import_log.total_batches_count = 10 + import_log.processed_batches_count = 10 + import_log.error_log = [] + import_log.save() + + import_log = ImportLog.objects.filter(workspace_id=1).first() + + response = project.trigger_import() + + import_log_post_run = ImportLog.objects.filter(workspace_id=1).first() + + assert response == None + assert import_log.status == import_log_post_run.status + assert import_log.total_batches_count == import_log_post_run.total_batches_count + + # not creating the schedule due to a schedule running already + project.sync_after = None + + import_log = ImportLog.objects.filter(workspace_id=1).first() + import_log.status = "IN_PORGRESS" + import_log.total_batches_count = 8 + import_log.processed_batches_count = 3 + import_log.save() + + response = project.trigger_import() + + assert response == None + assert import_log.status == "IN_PORGRESS" + assert import_log.total_batches_count != 0 + assert import_log.processed_batches_count != 0 + + # Setting import_log to COMPLETE since there are no destination_attributes + mocker.patch("fyle.platform.apis.v1beta.admin.Projects.list_all", return_value=[]) + mocker.patch("dynamics.apis.Employees.get_all", return_value=[]) + + Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE" + ).delete() + project.sync_after = None + + response = project.trigger_import() + + import_log = ImportLog.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ).first() + assert import_log.status == "COMPLETE" + assert import_log.total_batches_count == 0 + assert import_log.processed_batches_count == 0 + assert response == None + + +def test_expense_attributes_sync_after( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + add_project_expense_attributes, +): + project = Project(1, "EMPLOYEE", None) + + current_time = datetime.now() - timedelta(minutes=300) + sync_after = current_time.replace(tzinfo=timezone.utc) + project.sync_after = sync_after + + expense_attributes = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + )[0:100] + + assert expense_attributes.count() == 100 + + paginated_expense_attribute_values = [] + + for expense_attribute in expense_attributes: + expense_attribute.updated_at = datetime.now().replace(tzinfo=timezone.utc) + expense_attribute.save() + paginated_expense_attribute_values.append(expense_attribute.value) + + filters = project.construct_attributes_filter( + "PROJECT", paginated_expense_attribute_values + ) + + expense_attributes = ExpenseAttribute.objects.filter(**filters) + + assert expense_attributes.count() == 100 + + +def test_resolve_expense_attribute_errors( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + add_expense_destination_attributes, +): + workspace_id = 1 + category = Category(1, "ACCOUNT", None) + + # deleting all the Error objects + Error.objects.filter(workspace_id=workspace_id).delete() + + # getting the expense_attribute + source_category = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="CATEGORY" + ).first() + + category_mapping_count = CategoryMapping.objects.filter( + workspace_id=1, source_category_id=source_category.id + ).count() + + # category mapping is not present + assert category_mapping_count == 0 + + error = Error.objects.create( + workspace_id=workspace_id, + expense_attribute=source_category, + type="CATEGORY_MAPPING", + error_title=source_category.value, + error_detail="Category mapping is missing", + is_resolved=False, + ) + + assert Error.objects.get(id=error.id).is_resolved == False + + destination_attribute = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="ACCOUNT" + ).first() + + # creating the category mapping in bulk mode to avoid setting the is_resolved flag to true by signal + category_list = [] + category_list.append( + CategoryMapping( + workspace_id=1, + source_category_id=source_category.id, + destination_account_id=destination_attribute.id, + ) + ) + CategoryMapping.objects.bulk_create(category_list) + + category.resolve_expense_attribute_errors() + assert Error.objects.get(id=error.id).is_resolved == True diff --git a/tests/test_mappings/test_imports/test_modules/test_categories.py b/tests/test_mappings/test_imports/test_modules/test_categories.py new file mode 100644 index 0000000..8dbadae --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_categories.py @@ -0,0 +1,233 @@ +from unittest import mock + +from fyle_accounting_mappings.models import CategoryMapping, DestinationAttribute, ExpenseAttribute, Mapping +from fyle_integrations_platform_connector import PlatformConnector + +from apps.mappings.imports.modules.categories import Category +from apps.workspaces.models import FyleCredential, Workspace +from tests.test_mappings.test_imports.test_modules.fixtures import data as destination_attributes_data + + +def test_sync_destination_attributes_categories( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + + mocker.patch( + "dynamics.apis.Accounts.get_all", + return_value=destination_attributes_data["get_account_destination_attributes"], + ) + + account_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="ACCOUNT" + ).count() + assert account_count == 0 + + category = Category(workspace_id, "ACCOUNT", None) + category.sync_destination_attributes("ACCOUNT") + + new_account_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="ACCOUNT" + ).count() + assert new_account_count == 2 + + mocker.patch( + "dynamics.apis.Locations.get_all", + return_value=destination_attributes_data[ + "get_location_destination_attributes_0" + ], + ) + + expense_type_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="LOCATION" + ).count() + assert expense_type_count == 0 + + category = Category(workspace_id, "LOCATION", None) + category.sync_destination_attributes("LOCATION") + + new_expense_type_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="LOCATION" + ).count() + assert new_expense_type_count == 2 + + +def test_sync_expense_atrributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + fyle_credentials.workspace.org_id = "orwimNcVyYsp" + fyle_credentials.workspace.save() + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + mocker.patch("fyle.platform.apis.v1beta.admin.Categories.list_all", return_value=[]) + + category_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="CATEGORY" + ).count() + assert category_count == 0 + + category = Category(workspace_id, "ACCOUNT", None) + category.sync_expense_attributes(platform) + + category_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="CATEGORY" + ).count() + assert category_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.Categories.list_all", + return_value=destination_attributes_data[ + "create_new_auto_create_categories_expense_attributes_0" + ], + ) + category.sync_expense_attributes(platform) + + category_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="CATEGORY" + ).count() + assert ( + category_count + == destination_attributes_data[ + "create_new_auto_create_categories_expense_attributes_0" + ][0]["count"] + ) + + +def test_auto_create_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + category = Category(1, "ACCOUNT", None) + category.sync_after = None + + Workspace.objects.filter(id=1).update(org_id="orwimNcVyYsp") + # delete all destination attributes, expense attributes and mappings + Mapping.objects.filter( + workspace_id=1, source_type="CATEGORY", destination_type="ACCOUNT" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="ACCOUNT" + ).delete() + ExpenseAttribute.objects.filter(workspace_id=1, attribute_type="CATEGORY").delete() + + # create new case for account import + with mock.patch("fyle.platform.apis.v1beta.admin.Categories.list_all") as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.Categories.post_bulk", + return_value=[], + ) + mocker.patch( + "dynamics.apis.Accounts.get_all", + return_value=destination_attributes_data[ + "get_account_destination_attributes_1" + ], + ) + mock_call.side_effect = [ + destination_attributes_data[ + "create_new_auto_create_categories_expense_attributes_0" + ], + destination_attributes_data[ + "create_new_auto_create_categories_expense_attributes_1" + ], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="CATEGORY" + ).count() + + assert expense_attributes_count == 0 + + mappings_count = CategoryMapping.objects.filter(workspace_id=1).count() + + assert mappings_count == 0 + + category.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="CATEGORY" + ).count() + + assert expense_attributes_count == 30 + + mappings_count = CategoryMapping.objects.filter(workspace_id=1).count() + + assert mappings_count == 2 + + +def test_construct_fyle_payload( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + add_expense_destination_attributes_1, + mocker, +): + category = Category(1, "ACCOUNT", None) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="ACCOUNT" + ) + existing_fyle_attributes_map = {} + is_auto_sync_status_allowed = category.get_auto_sync_permission() + + fyle_payload = category.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed, + ) + + assert ( + fyle_payload + == destination_attributes_data["create_fyle_category_payload_create_new_case"] + ) + + # disable case + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="ACCOUNT", value__in=["Internet", "Meals"] + ).update(active=False) + + ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="ACCOUNT", value__in=["Internet", "Meals"] + ).update(active=True) + + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="ACCOUNT" + ) + + paginated_destination_attribute_values = [ + attribute.value for attribute in paginated_destination_attributes + ] + existing_fyle_attributes_map = category.get_existing_fyle_attributes( + paginated_destination_attribute_values + ) + + fyle_payload = category.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed, + ) + + assert ( + fyle_payload + == destination_attributes_data[ + "create_fyle_category_payload_create_disable_case" + ] + ) diff --git a/tests/test_mappings/test_imports/test_modules/test_cost_centers.py b/tests/test_mappings/test_imports/test_modules/test_cost_centers.py new file mode 100644 index 0000000..4c05831 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_cost_centers.py @@ -0,0 +1,148 @@ +from unittest import mock + +from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute, Mapping +from fyle_integrations_platform_connector import PlatformConnector + +from apps.mappings.imports.modules.cost_centers import CostCenter +from apps.workspaces.models import FyleCredential, Workspace +from tests.test_mappings.test_imports.test_modules.fixtures import data + + +def test_sync_expense_atrributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + fyle_credentials.workspace.org_id = "ortL3T2BabCW" + fyle_credentials.workspace.save() + + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + mocker.patch( + "fyle.platform.apis.v1beta.admin.CostCenters.list_all", return_value=[] + ) + + cost_center_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="COST_CENTER" + ).count() + assert cost_center_count == 0 + + category = CostCenter(workspace_id, "LOCATION", None) + category.sync_expense_attributes(platform) + + cost_center_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="COST_CENTER" + ).count() + assert cost_center_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.CostCenters.list_all", + return_value=data["create_new_auto_create_cost_centers_expense_attributes_1"], + ) + + category.sync_expense_attributes(platform) + + cost_center_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="COST_CENTER" + ).count() + assert cost_center_count == 7 + + +def test_auto_create_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + cost_center = CostCenter(1, "LOCATION", None) + cost_center.sync_after = None + + Workspace.objects.filter(id=1).update(org_id="ortL3T2BabCW") + # delete all destination attributes, expense attributes and mappings + Mapping.objects.filter( + workspace_id=1, source_type="COST_CENTER", destination_type="LOCATION" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="LOCATION" + ).delete() + ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="COST_CENTER" + ).delete() + + # create new case for account import + with mock.patch( + "fyle.platform.apis.v1beta.admin.CostCenters.list_all" + ) as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.CostCenters.post_bulk", + return_value=[], + ) + mocker.patch( + "dynamics.apis.Locations.get_all", + return_value=data["get_location_destination_attributes_0"], + ) + mock_call.side_effect = [ + data["create_new_auto_create_cost_centers_expense_attributes_0"], + data["create_new_auto_create_cost_centers_expense_attributes_1"], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="COST_CENTER" + ).count() + + assert expense_attributes_count == 0 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="COST_CENTER", destination_type="LOCATION" + ).count() + + assert mappings_count == 0 + + cost_center.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="COST_CENTER" + ).count() + + assert expense_attributes_count == 9 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="COST_CENTER", destination_type="LOCATION" + ).count() + + assert mappings_count == 2 + + +def test_construct_fyle_payload( + api_client, + test_connection, + mocker, + create_temp_workspace, + add_business_central_creds, + add_fyle_credentials, + add_cost_center_mappings, +): + cost_center = CostCenter(1, "COST_CENTER", None) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="COST_CENTER" + ) + + existing_fyle_attributes_map = {} + is_auto_sync_status_allowed = cost_center.get_auto_sync_permission() + + fyle_payload = cost_center.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed, + ) + + assert fyle_payload == data["create_fyle_cost_center_payload_create_new_case"] diff --git a/tests/test_mappings/test_imports/test_modules/test_expense_custom_fields.py b/tests/test_mappings/test_imports/test_modules/test_expense_custom_fields.py new file mode 100644 index 0000000..c2bd5a1 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_expense_custom_fields.py @@ -0,0 +1,203 @@ +from unittest import mock + +from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute, Mapping +from fyle_integrations_platform_connector import PlatformConnector + +from apps.mappings.imports.modules.expense_custom_fields import ExpenseCustomField +from apps.workspaces.models import FyleCredential +from tests.test_mappings.test_imports.test_modules.fixtures import data + + +def test_sync_expense_atrributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + fyle_credentials.workspace.org_id = "orqjgyJ21uge" + fyle_credentials.workspace.save() + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="LUKE" + ).count() + assert expense_attribute_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all", return_value=[] + ) + + expense_custom_field = ExpenseCustomField(workspace_id, "LUKE", "CLASS", None) + expense_custom_field.sync_expense_attributes(platform) + + expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="LUKE" + ).count() + assert expense_attribute_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all", + return_value=data[ + "create_new_auto_create_expense_custom_fields_expense_attributes_0" + ], + ) + + expense_custom_field.sync_expense_attributes(platform) + + expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="LUKE" + ).count() + assert expense_attribute_count == 21 + + +def test_auto_create_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + fyle_credentials.workspace.org_id = "orqjgyJ21uge" + fyle_credentials.workspace.save() + + expense_custom_field = ExpenseCustomField(1, "LUKE", "LOCATION", None) + expense_custom_field.sync_after = None + + # delete all destination attributes, expense attributes and mappings + Mapping.objects.filter( + workspace_id=1, source_type="LUKE", destination_type="LOCATION" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="LOCATION" + ).delete() + ExpenseAttribute.objects.filter(workspace_id=1, attribute_type="LUKE").delete() + + # create new case for projects import + with mock.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all" + ) as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.ExpenseCustomFields.post", + return_value=[], + ) + mocker.patch( + "dynamics.apis.Locations.get_all", + return_value=data["get_location_destination_attributes_2"], + ) + mock_call.side_effect = [ + data["create_new_auto_create_expense_custom_fields_expense_attributes_0"], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="LUKE" + ).count() + + assert expense_attributes_count == 0 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="LUKE", destination_type="LOCATION" + ).count() + + assert mappings_count == 0 + + expense_custom_field.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="LUKE" + ).count() + + assert expense_attributes_count == 21 + + destination_attributes_count = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="LOCATION" + ).count() + + assert destination_attributes_count == 2 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="LUKE", destination_type="LOCATION" + ).count() + + assert mappings_count == 2 + + # create new expense_custom_field mapping for sub-sequent run (we will be adding 2 new LOCATION) + with mock.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all" + ) as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.ExpenseCustomFields.post", + return_value=[], + ) + mocker.patch( + "fyle_integrations_platform_connector.apis.ExpenseCustomFields.get_by_id", + return_value=data["create_new_auto_create_expense_custom_fields_get_by_id"], + ) + mocker.patch( + "dynamics.apis.Locations.get_all", + return_value=data["get_location_destination_attributes_3"], + ) + mock_call.side_effect = [ + data["create_new_auto_create_expense_custom_fields_expense_attributes_1"], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="LUKE" + ).count() + + assert expense_attributes_count == 21 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="LUKE", destination_type="LOCATION" + ).count() + + assert mappings_count == 2 + + expense_custom_field.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="LUKE" + ).count() + + assert expense_attributes_count == 21 + 2 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="LUKE", destination_type="LOCATION" + ).count() + + assert mappings_count == 4 + + +def test_construct_fyle_expense_custom_field_payload( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + expense_custom_field = ExpenseCustomField(1, "LUKE", "LOCATION", None) + expense_custom_field.sync_after = None + fyle_credentials = FyleCredential.objects.get(workspace_id=1) + platform = PlatformConnector(fyle_credentials=fyle_credentials) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="LOCATION" + ) + + fyle_payload = expense_custom_field.construct_fyle_expense_custom_field_payload( + paginated_destination_attributes, platform + ) + print(fyle_payload, "fyle_payload") + + assert ( + fyle_payload + == data["create_fyle_expense_custom_fields_payload_create_new_case"] + ) diff --git a/tests/test_mappings/test_imports/test_modules/test_merchants.py b/tests/test_mappings/test_imports/test_modules/test_merchants.py new file mode 100644 index 0000000..dccd091 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_merchants.py @@ -0,0 +1,217 @@ +from unittest import mock + +from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute, Mapping +from fyle_integrations_platform_connector import PlatformConnector + +from apps.mappings.imports.modules.merchants import Merchant +from apps.workspaces.models import FyleCredential +from tests.test_mappings.test_imports.test_modules.fixtures import data + + +def test_sync_expense_atrributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id) + platform = PlatformConnector(fyle_credentials=fyle_credentials) + ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="MERCHANT" + ).delete() + + merchants_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="MERCHANT" + ).count() + assert merchants_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all", return_value=[] + ) + + merchant = Merchant(workspace_id, "VENDOR", None) + merchant.sync_expense_attributes(platform) + + merchants_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="MERCHANT" + ).count() + assert merchants_count == 0 + + mocker.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all", + return_value=data["create_new_auto_create_merchants_expense_attributes_0"], + ) + + merchant.sync_expense_attributes(platform) + + merchants_count = ExpenseAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="MERCHANT" + ).count() + assert merchants_count == 72 + + +def test_sync_destination_atrributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + mocker.patch( + "dynamics.apis.Vendors.get_all", + return_value=data["get_vendors_destination_attributes"], + ) + workspace_id = 1 + + vendors_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="VENDOR" + ).count() + assert vendors_count == 0 + + tax_group = Merchant(workspace_id, "VENDOR", None) + tax_group.sync_destination_attributes("VENDOR") + + vendors_count = DestinationAttribute.objects.filter( + workspace_id=workspace_id, attribute_type="VENDOR" + ).count() + assert vendors_count == 2 + + +def test_auto_create_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + workspace_id = 1 + merchant = Merchant(workspace_id, "VENDOR", None) + merchant.sync_after = None + + # delete all destination attributes, expense attributes and mappings + Mapping.objects.filter( + workspace_id=1, source_type="MERCHANT", destination_type="VENDOR" + ).delete() + # DestinationAttribute.objects.filter(workspace_id=1, attribute_type='VENDOR').delete() + ExpenseAttribute.objects.filter(workspace_id=1, attribute_type="MERCHANT").delete() + + # create new case for tax-groups import + with mock.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all" + ) as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.Merchants.post", return_value=[] + ) + mocker.patch( + "dynamics.apis.Vendors.get_all", + return_value=data["get_vendors_destination_attributes"], + ) + + mock_call.side_effect = [ + data["create_new_auto_create_merchants_expense_attributes_0"], + data["create_new_auto_create_merchants_expense_attributes_1"], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="MERCHANT" + ).count() + + assert expense_attributes_count == 0 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="MERCHANT", destination_type="VENDOR" + ).count() + + assert mappings_count == 0 + + merchant.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="MERCHANT" + ).count() + + assert expense_attributes_count == 73 + + # We dont create any mapping for VENDOR and MERCHANT, so this should be 0 + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="MERCHANT", destination_type="VENDOR" + ).count() + + assert mappings_count == 0 + + # create new tax-groups sub-sequent run (we will be adding 2 new tax-details) + with mock.patch( + "fyle.platform.apis.v1beta.admin.ExpenseFields.list_all" + ) as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.Merchants.post", return_value=[] + ) + mocker.patch( + "dynamics.apis.Vendors.get_all", + return_value=data["get_vendors_destination_attributes_subsequent_run"], + ) + + mock_call.side_effect = [ + data["create_new_auto_create_merchants_expense_attributes_1"], + data["create_new_auto_create_merchants_expense_attributes_2"], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="MERCHANT" + ).count() + + assert expense_attributes_count == 73 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="MERCHANT", destination_type="VENDOR" + ).count() + + assert mappings_count == 0 + + merchant.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="MERCHANT" + ).count() + + assert expense_attributes_count == 73 + 2 + + # We dont create any mapping for VENDOR and MERCHANT, so this should be 0 + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="MERCHANT", destination_type="VENDOR" + ).count() + + assert mappings_count == 0 + + +def test_construct_fyle_payload( + api_client, + test_connection, + mocker, + create_temp_workspace, + add_business_central_creds, + add_fyle_credentials, + add_merchant_mappings, +): + merchant = Merchant(1, "MERCHANT", None) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="MERCHANT" + ) + + existing_fyle_attributes_map = {} + is_auto_sync_status_allowed = merchant.get_auto_sync_permission() + + fyle_payload = merchant.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed, + ) + + assert fyle_payload == ["Direct Mail Campaign", "Platform APIs"] diff --git a/tests/test_mappings/test_imports/test_modules/test_projects.py b/tests/test_mappings/test_imports/test_modules/test_projects.py new file mode 100644 index 0000000..f994c96 --- /dev/null +++ b/tests/test_mappings/test_imports/test_modules/test_projects.py @@ -0,0 +1,293 @@ +from datetime import datetime, timezone +from unittest import mock + +from fyle_accounting_mappings.models import DestinationAttribute, ExpenseAttribute, Mapping + +from apps.mappings.imports.modules.projects import Project +from apps.mappings.models import ImportLog +from apps.workspaces.models import Workspace +from tests.test_mappings.test_imports.test_modules.fixtures import data + + +def test_auto_create_destination_attributes( + api_client, + test_connection, + create_temp_workspace, + add_fyle_credentials, + add_business_central_creds, + mocker, +): + project = Project(1, "EMPLOYEE", None) + project.sync_after = None + + Workspace.objects.filter(id=1).update(org_id="orqjgyJ21uge") + # delete all destination attributes, expense attributes and mappings + Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE" + ).delete() + ExpenseAttribute.objects.filter(workspace_id=1, attribute_type="PROJECT").delete() + + # create new case for account import + with mock.patch("fyle.platform.apis.v1beta.admin.Projects.list_all") as mock_call: + mocker.patch( + "fyle_integrations_platform_connector.apis.Projects.post_bulk", + return_value=[], + ) + mocker.patch( + "dynamics.apis.Employees.get_all", + return_value=data["get_employee_destination_attributes_0"], + ) + mock_call.side_effect = [ + data["create_new_auto_create_projects_expense_attributes_0"], + data["create_new_auto_create_projects_expense_attributes_1"], + ] + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ).count() + + assert expense_attributes_count == 0 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).count() + + assert mappings_count == 0 + + project.trigger_import() + + expense_attributes_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ).count() + + assert expense_attributes_count == 30 + + mappings_count = Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).count() + + assert mappings_count == 2 + + # disable case for employee import + with mock.patch("fyle.platform.apis.v1beta.admin.Projects.list_all") as mock_call: + mocker.patch( + "dynamics.apis.Employees.get_all", + return_value=data[ + "create_new_auto_create_employee_destination_attributes_disable_case" + ], + ) + mocker.patch( + "fyle_integrations_platform_connector.apis.Projects.post_bulk", + return_value=[], + ) + mock_call.side_effect = [ + data["create_new_auto_create_projects_expense_attributes_3"], + data["create_new_auto_create_projects_expense_attributes_4"], + ] + + destination_attribute = DestinationAttribute.objects.filter( + workspace_id=1, value="Ester Henderson" + ).first() + + assert destination_attribute.active == True + + expense_attribute = ExpenseAttribute.objects.filter( + workspace_id=1, value="Ester Henderson" + ).first() + + assert expense_attribute.active == True + + mapping = Mapping.objects.filter( + destination_id=destination_attribute.id + ).first() + + pre_run_expense_attribute_disabled_count = ExpenseAttribute.objects.filter( + workspace_id=1, active=False, attribute_type="PROJECT" + ).count() + + assert pre_run_expense_attribute_disabled_count == 2 + + # This confirms that mapping is present and both expense_attribute and destination_attribute are active + assert mapping.source_id == expense_attribute.id + + project.trigger_import() + + destination_attribute = DestinationAttribute.objects.filter( + workspace_id=1, value="Annette Hill" + ).first() + + assert destination_attribute.active == False + + expense_attribute = ExpenseAttribute.objects.filter( + workspace_id=1, value="Annette Hill" + ).first() + + assert expense_attribute.active == False + + post_run_expense_attribute_disabled_count = ExpenseAttribute.objects.filter( + workspace_id=1, active=False, attribute_type="PROJECT" + ).count() + + assert ( + post_run_expense_attribute_disabled_count + == pre_run_expense_attribute_disabled_count + + data["create_new_auto_create_projects_expense_attributes_4"][0]["count"] + ) + + # not re-enable case for project import + with mock.patch("fyle.platform.apis.v1beta.admin.Projects.list_all") as mock_call: + mocker.patch( + "dynamics.apis.Employees.get_all", + return_value=data[ + "create_new_auto_create_projects_destination_attributes_re_enable_case" + ], + ) + mocker.patch( + "fyle_integrations_platform_connector.apis.Projects.post_bulk", + return_value=[], + ) + mock_call.side_effect = [ + data["create_new_auto_create_projects_expense_attributes_3"], + data["create_new_auto_create_projects_expense_attributes_3"], + ] + + pre_run_destination_attribute_count = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE", active=False + ).count() + + assert pre_run_destination_attribute_count == 1 + + pre_run_expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT", active=False + ).count() + + assert pre_run_expense_attribute_count == 4 + + project.trigger_import() + + post_run_destination_attribute_count = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE", active=False + ).count() + + assert post_run_destination_attribute_count == 0 + + post_run_expense_attribute_count = ExpenseAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT", active=False + ).count() + + assert pre_run_expense_attribute_count == post_run_expense_attribute_count + + # Not creating the schedule part due to time diff + current_time = datetime.now() + sync_after = current_time.replace(tzinfo=timezone.utc) + project.sync_after = sync_after + + import_log = ImportLog.objects.filter(workspace_id=1).first() + import_log.status = "COMPLETE" + import_log.attribute_type = "PROJECT" + import_log.total_batches_count = 10 + import_log.processed_batches_count = 10 + import_log.error_log = [] + import_log.save() + + import_log = ImportLog.objects.filter(workspace_id=1).first() + + response = project.trigger_import() + + import_log_post_run = ImportLog.objects.filter(workspace_id=1).first() + + assert response == None + assert import_log.status == import_log_post_run.status + assert import_log.total_batches_count == import_log_post_run.total_batches_count + + # not creating the schedule due to a schedule running already + project.sync_after = None + + import_log = ImportLog.objects.filter(workspace_id=1).first() + import_log.status = "IN_PORGRESS" + import_log.total_batches_count = 8 + import_log.processed_batches_count = 3 + import_log.save() + + response = project.trigger_import() + + assert response == None + assert import_log.status == "IN_PORGRESS" + assert import_log.total_batches_count != 0 + assert import_log.processed_batches_count != 0 + + # Setting import_log to COMPLETE since there are no destination_attributes + mocker.patch("fyle.platform.apis.v1beta.admin.Projects.list_all", return_value=[]) + mocker.patch("dynamics.apis.Employees.get_all", return_value=[]) + + Mapping.objects.filter( + workspace_id=1, source_type="PROJECT", destination_type="EMPLOYEE" + ).delete() + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="EMPLOYEE" + ).delete() + project.sync_after = None + + response = project.trigger_import() + + import_log = ImportLog.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ).first() + assert import_log.status == "COMPLETE" + assert import_log.total_batches_count == 0 + assert import_log.processed_batches_count == 0 + assert response == None + + +def test_construct_fyle_payload( + api_client, + test_connection, + mocker, + create_temp_workspace, + add_business_central_creds, + add_fyle_credentials, + add_project_mappings, +): + project = Project(1, "PROJECT", None) + + # create new case + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ) + + existing_fyle_attributes_map = {} + is_auto_sync_status_allowed = project.get_auto_sync_permission() + + fyle_payload = project.construct_fyle_payload( + paginated_destination_attributes, + existing_fyle_attributes_map, + is_auto_sync_status_allowed, + ) + + assert fyle_payload == data["create_fyle_project_payload_create_new_case"] + + # disable case + DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT", value__in=["Platform APIs"] + ).update(active=False) + + paginated_destination_attributes = DestinationAttribute.objects.filter( + workspace_id=1, attribute_type="PROJECT" + ) + + paginated_destination_attribute_values = [ + attribute.value for attribute in paginated_destination_attributes + ] + + existing_fyle_attributes_map = project.get_existing_fyle_attributes( + paginated_destination_attribute_values + ) + + fyle_payload = project.construct_fyle_payload( + paginated_destination_attributes, existing_fyle_attributes_map, True + ) + + assert fyle_payload == data["create_fyle_project_payload_create_disable_case"] diff --git a/tests/test_mappings/test_imports/test_schedules.py b/tests/test_mappings/test_imports/test_schedules.py new file mode 100644 index 0000000..e3d0e3a --- /dev/null +++ b/tests/test_mappings/test_imports/test_schedules.py @@ -0,0 +1,60 @@ +from django_q.models import Schedule +from fyle_accounting_mappings.models import MappingSetting + +from apps.mappings.imports.schedules import schedule_or_delete_fyle_import_tasks +from apps.workspaces.models import ImportSetting + + +def test_schedule_projects_creation(api_client, test_connection, create_temp_workspace, add_fyle_credentials, add_import_settings, add_mapping_settings): + workspace_id = 1 + + # Test schedule projects creation + import_setting = ImportSetting.objects.get(workspace_id=workspace_id) + import_setting.import_categories = True + import_setting.import_vendors_as_merchants = True + import_setting.save() + + mapping_setting = MappingSetting.objects.filter(workspace_id=workspace_id, source_field='CATEGORY', destination_field='ACCOUNT', import_to_fyle=True).first() + + schedule_or_delete_fyle_import_tasks(import_setting, mapping_setting) + + schedule = Schedule.objects.filter( + func='apps.mappings.imports.queues.chain_import_fields_to_fyle', + args='{}'.format(workspace_id), + ).first() + + assert schedule.func == 'apps.mappings.imports.queues.chain_import_fields_to_fyle' + + # Test delete schedule projects creation + import_setting = ImportSetting.objects.get(workspace_id=workspace_id) + import_setting.import_categories = False + import_setting.import_vendors_as_merchants = False + import_setting.save() + + mapping_setting = MappingSetting.objects.filter(workspace_id=workspace_id, source_field='CATEGORY', destination_field='ACCOUNT', import_to_fyle=True).first() + mapping_setting.import_to_fyle = False + mapping_setting.save() + + schedule_or_delete_fyle_import_tasks(import_setting, mapping_setting) + + schedule = Schedule.objects.filter( + func='apps.mappings.imports.queues.chain_import_fields_to_fyle', + args='{}'.format(workspace_id), + ).first() + + assert schedule == None + + # Test schedule categories creation adding the new schedule and not adding the old one + import_setting = ImportSetting.objects.get(workspace_id=workspace_id) + import_setting.import_categories = True + import_setting.import_vendors_as_merchants = False + import_setting.save() + + schedule_or_delete_fyle_import_tasks(import_setting, mapping_setting) + + schedule = Schedule.objects.filter( + func='apps.mappings.imports.queues.chain_import_fields_to_fyle', + args='{}'.format(workspace_id), + ).first() + + assert schedule.func == 'apps.mappings.imports.queues.chain_import_fields_to_fyle'