Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imports refactor master #322

Merged
merged 14 commits into from
Mar 12, 2024
Merged

Imports refactor master #322

merged 14 commits into from
Mar 12, 2024

Conversation

Hrishabh17
Copy link
Contributor

@Hrishabh17 Hrishabh17 commented Mar 8, 2024

Summary by CodeRabbit

  • New Features
    • Introduced a submodule for integration imports.
    • Added functionality to manage import schedules and automate sync settings based on workspace configurations.
    • Enhanced import tasks with new settings for tax codes, categories, and suppliers.
  • Improvements
    • Streamlined the process for handling import exceptions and logging.
    • Optimized synchronization methods and mappings for various entities.
    • Refactored code to improve maintainability and simplify task scheduling.
  • Bug Fixes
    • Corrected error handling in mappings and import processes.
  • Tests
    • Added extensive test cases for new functionalities and refactored code paths.
  • Documentation
    • Updated settings to include new integrations and configurations.
  • Chores
    • Removed obsolete functions and calls to streamline operations.

Hrishabh17 and others added 12 commits February 28, 2024 21:01
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Project: added cluster import, fixed minor typo, added new supplier field
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Project: added cluster import, fixed minor typo, added new supplier field

* Refactor imports costcenter (#312)

* Resource Cost_Center: refactored imports

* Refactor imports for Project resource (#311)

* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Project: added cluster import, fixed minor typo, added new supplier field
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Cost_Center: refactored imports

* Resource Custom Expense Field: refactored imports

* Resource Project: added cluster import, fixed minor typo, added new supplier field
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Cost_Center: refactored imports

* Resource Custom Expense Field: refactored imports

* Resource Project: added cluster import, fixed minor typo, added new supplier field

* Resource Tax Group: refactored imports

* Resource Tax Group: changed to is_auto_sync to False by default
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Cost_Center: refactored imports

* Resource Custom Expense Field: refactored imports

* Resource Tax Group: refactored imports

* Resource Category: refactored imports

* Resource Category: changed is_auto_sync_enabled to True by default
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Cost_Center: refactored imports

* Resource Custom Expense Field: refactored imports

* Resource Tax Group: refactored imports

* Resource Category: refactored imports

* Added RetryException handler and bumped the sdk versions (#306)

* Set tasks limit to 1L (#317)

* Set tasks limit to 1L

* set timeout

* Modified the import schedule creation condition

---------

Co-authored-by: ruuushhh <[email protected]>
* Added integrations_imports submodule, made changes in settings

* Resource Project: Added new flow for the Project Import

* Typo Fix

* Resource Project: removed old import logic for Project

* Resource Cost_Center: refactored imports

* Resource Custom Expense Field: refactored imports

* Resource Tax Group: refactored imports

* Resource Category: refactored imports

* Added RetryException handler and bumped the sdk versions (#306)

* Set tasks limit to 1L (#317)

* Set tasks limit to 1L

* set timeout

* Modified the import schedule creation condition

* Removed dead code, add few test cases, added script for adding new schedule for different workspaces

* Added post deploy sql script to dump old schedules and delete

---------

Co-authored-by: ruuushhh <[email protected]>
* Update delete workspace func

* Fix comments
Copy link

coderabbitai bot commented Mar 8, 2024

Walkthrough

The recent updates introduce a series of enhancements and optimizations across the project, focusing on improving the integration and synchronization of data with Fyle. Key changes include the introduction of a submodule, the consolidation of task scheduling and exception handling, and the refactoring of various functions to streamline operations. These modifications aim to simplify the codebase, improve maintainability, and enhance the efficiency of data import and mapping processes.

Changes

Files Change Summary
.gitmodules Introduced a submodule entry for "fyle_integrations_imports".
apps/mappings/constants.py, apps/xero/actions.py Added new constants and mappings.
apps/mappings/exceptions.py, tests/test_mappings/test_exceptions.py Enhanced exception handling and logging.
apps/mappings/helpers.py, apps/mappings/queue.py, apps/mappings/schedules.py, apps/mappings/signals.py, apps/mappings/tasks.py, apps/workspaces/apis/import_settings/triggers.py, apps/workspaces/utils.py, tests/test_mappings/test_helpers.py, tests/test_mappings/test_queues.py, tests/test_mappings/test_signals.py, tests/test_mappings/test_tasks.py Refactored and optimized task scheduling, data import, and mapping functionalities.
apps/workspaces/apis/import_settings/serializers.py Modified serializer update method.
fyle_integrations_imports, fyle_xero_api/settings.py, fyle_xero_api/tests/settings.py Added new submodule and updated settings.
scripts/python/add_new_import_schedule.py, sql/scripts/024-dump-schedules-to-csv-and-delete.sql Introduced new scripts for managing import schedules and data handling.
tests/test_fyle_integrations_imports/... Added new tests for integration functionalities.

🐇✨
In the land of code where the data streams flow,
A rabbit hopped in, with changes in tow.
"Refactor, streamline," it said with a cheer,
"For efficiency and clarity, the path is now clear!"
With a wiggle of nose and a flick of the ear,
It danced away, leaving improvements so dear.
🌟🐾

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 16

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 60ccb7e and 0b32cd6.
Files selected for processing (28)
  • .gitmodules (1 hunks)
  • apps/mappings/constants.py (1 hunks)
  • apps/mappings/exceptions.py (2 hunks)
  • apps/mappings/helpers.py (1 hunks)
  • apps/mappings/queue.py (2 hunks)
  • apps/mappings/schedules.py (1 hunks)
  • apps/mappings/signals.py (3 hunks)
  • apps/mappings/tasks.py (4 hunks)
  • apps/workspaces/apis/import_settings/serializers.py (1 hunks)
  • apps/workspaces/apis/import_settings/triggers.py (3 hunks)
  • apps/workspaces/utils.py (2 hunks)
  • apps/xero/actions.py (3 hunks)
  • fyle_integrations_imports (1 hunks)
  • fyle_xero_api/settings.py (2 hunks)
  • fyle_xero_api/tests/settings.py (2 hunks)
  • scripts/python/add_new_import_schedule.py (1 hunks)
  • sql/scripts/024-dump-schedules-to-csv-and-delete.sql (1 hunks)
  • tests/test_fyle_integrations_imports/conftest.py (1 hunks)
  • tests/test_fyle_integrations_imports/helpers.py (1 hunks)
  • tests/test_fyle_integrations_imports/test_modules/test_base.py (1 hunks)
  • tests/test_fyle_integrations_imports/test_queue.py (1 hunks)
  • tests/test_mappings/conftest.py (2 hunks)
  • tests/test_mappings/test_exceptions.py (1 hunks)
  • tests/test_mappings/test_helpers.py (2 hunks)
  • tests/test_mappings/test_queues.py (1 hunks)
  • tests/test_mappings/test_signals.py (4 hunks)
  • tests/test_mappings/test_tasks.py (3 hunks)
  • tests/test_xero/test_views.py (1 hunks)
Files skipped from review due to trivial changes (1)
  • fyle_integrations_imports
Additional comments: 24
.gitmodules (1)
  • 1-3: The addition of the fyle_integrations_imports submodule is correctly implemented. Ensure that the submodule repository is accessible and consider the implications of this integration on the project's build and deployment processes.
apps/mappings/helpers.py (1)
  • 5-14: The is_auto_sync_allowed function is implemented correctly and efficiently uses short-circuit evaluation. Consider adding type checks or using Python's type annotations for the function parameters to ensure they are always of the expected types (WorkspaceGeneralSettings and MappingSetting). This can enhance maintainability and reduce the risk of runtime errors.
sql/scripts/024-dump-schedules-to-csv-and-delete.sql (1)
  • 16-22: Ensure the deletion of schedules does not adversely affect the application's functionality. Review the impact of removing these specific schedules on the system's behavior and document any necessary precautions or adjustments.
apps/mappings/constants.py (1)
  • 47-53: The addition of the SYNC_METHODS dictionary centralizes sync method definitions, improving maintainability. Ensure that the keys and values accurately reflect the application's requirements and sync methods.
tests/test_fyle_integrations_imports/helpers.py (1)
  • 8-37: The helper functions get_base_class_instance and get_platform_connection are well-implemented, enhancing test setup reusability. Consider implementing teardown procedures or using context managers in tests to ensure proper cleanup of resources created by these functions.
scripts/python/add_new_import_schedule.py (1)
  • 16-39: The script correctly handles the addition and verification of import schedules using Django's ORM. Consider using logging instead of printing errors directly to the console to improve error visibility and management in production environments.
tests/test_mappings/conftest.py (1)
  • 32-65: The new fixtures for creating a temporary workspace and adding Xero and Fyle credentials are well-implemented, enhancing test setup reusability. Consider implementing teardown procedures or using context managers in tests to ensure proper cleanup of resources created by these fixtures.
apps/mappings/schedules.py (1)
  • 8-50: The new_schedule_or_delete_fyle_import_tasks function is correctly implemented, using conditions to determine whether to schedule or delete tasks. Consider parameterizing the scheduling interval and using timezone-aware datetime objects for next_run to enhance flexibility and correctness in different environments.
apps/workspaces/apis/import_settings/triggers.py (1)
  • 28-44: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [7-75]

The refactoring in triggers.py to use new_schedule_or_delete_fyle_import_tasks for handling tax groups creation and mapping settings is a positive change towards simplifying the code structure and improving maintainability. However, there are a few considerations:

  • Ensure that new_schedule_or_delete_fyle_import_tasks adequately handles all scenarios previously covered by individual scheduling functions. This includes edge cases and error handling.

  • Verify that the new function is thoroughly tested, especially since it centralizes important logic. Consider adding or updating tests in the test suite to cover the new functionality and any edge cases that may arise from the consolidation of logic.

  • Review the documentation and comments to ensure they are updated to reflect the new logic. Clear documentation is crucial for maintainability, especially when refactoring critical parts of the system.

  • Verify that all scenarios previously covered by individual functions are adequately handled by new_schedule_or_delete_fyle_import_tasks.

  • Ensure that the new function is thoroughly tested, including edge cases.

  • Update documentation and comments to reflect the new logic and improve maintainability.

tests/test_xero/test_views.py (1)
  • 121-122: The addition of a mock for ExpenseCustomField and its method sync_expense_attributes in the test_post_refresh_dimensions function is a good practice for isolating the test environment from external dependencies. However, ensure that the mock accurately reflects the behavior of the real ExpenseCustomField to maintain the validity of the test.
apps/mappings/signals.py (3)
  • 5-25: The addition of imports and the reorganization of function calls and imports are generally positive changes that can enhance the readability and maintainability of the code. However, ensure that all newly added imports are used within the file to avoid unnecessary dependencies.
  • 58-64: The logic within run_post_mapping_settings_triggers for determining when to call new_schedule_or_delete_fyle_import_tasks is clear and concise. However, consider adding a comment explaining the significance of ALLOWED_SOURCE_FIELDS and the condition instance.is_custom for future maintainability.
  • 86-142: The error handling and logging within run_pre_mapping_settings_triggers are commendable for robustness. However, ensure that the ValidationError raised in case of a WrongParamsError is caught and handled appropriately upstream to prevent unintended interruptions in the application flow.
apps/workspaces/apis/import_settings/serializers.py (1)
  • 154-159: > 📝 NOTE

This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]

The removal of the call to trigger.pre_save_mapping_settings() in the update method of the serializer could have implications on the application's behavior, particularly in how mapping settings are processed before saving. Ensure that this change is intentional and that any necessary logic has been relocated or accounted for elsewhere in the application to maintain the desired functionality.

fyle_xero_api/tests/settings.py (2)
  • 47-47: Adding fyle_integrations_imports to the installed apps is a necessary step to ensure that its models and functionalities are available during testing. This aligns with the PR's objective of enhancing modular integration capabilities.
  • 189-192: The configuration of logging for fyle_integrations_imports is appropriate and follows the established pattern for other components. Ensure that the log level and propagation settings are consistent with the application's logging strategy to maintain a coherent log output.
fyle_xero_api/settings.py (2)
  • 49-49: The inclusion of fyle_integrations_imports in the list of installed apps is crucial for enabling its functionalities within the application. This change supports the PR's objective of enhancing modular integration capabilities.
  • 199-202: The logging configuration for fyle_integrations_imports is set up correctly, following the established logging pattern. This ensures that logs from this module are captured consistently with the rest of the application.
apps/workspaces/utils.py (1)
  • 225-230: The addition of new_schedule_or_delete_fyle_import_tasks introduces a more flexible approach to handling Fyle import tasks based on workspace settings. However, ensure that the removal of schedule_tax_groups_creation (not shown in the provided code but mentioned in the summary) does not impact any dependent functionalities or leave orphaned tasks that were previously scheduled by it.
  • Consider verifying the impact of removing schedule_tax_groups_creation on the overall task scheduling logic and ensure that any tasks previously scheduled by it are either migrated or appropriately handled.
tests/test_fyle_integrations_imports/test_modules/test_base.py (5)
  • 26-46: The test test_remove_duplicates effectively checks the removal of duplicate DestinationAttribute entries. However, it's important to ensure that the logic for removing duplicates is robust and handles all edge cases, such as case sensitivity and trimming whitespace.
  • Consider adding more test cases to cover edge cases like case sensitivity and whitespace in attribute values to ensure the duplicate removal logic is comprehensive.
  • 62-79: The test test_construct_attributes_filter verifies the construction of attribute filters based on various conditions. It's well-structured and covers different scenarios, including filtering by attribute type, workspace ID, and value inclusion.
  • Good coverage of different filtering scenarios ensures that the attribute filter construction logic is thoroughly tested.
  • 82-104: The test test_expense_attributes_sync_after checks the functionality of syncing expense attributes based on a specific timestamp (sync_after). This test ensures that only attributes updated after the specified timestamp are considered.
  • This test is crucial for verifying that the syncing logic respects the sync_after timestamp, ensuring that only relevant updates are processed.
  • 107-173: The test test_auto_create_destination_attributes covers the auto-creation of destination attributes based on data from Fyle and Xero. It mocks external API calls and verifies that the import logic behaves as expected under various conditions.
  • Comprehensive testing of the auto-creation logic with mocked external dependencies ensures that the import functionality is robust and behaves correctly under different scenarios.
  • 228-273: The test test_resolve_expense_attribute_errors verifies the resolution of expense attribute errors upon successful mapping creation. It ensures that errors are marked as resolved when the underlying issue is addressed.
  • This test is important for ensuring that the system correctly identifies and resolves mapping errors, improving data integrity and user experience.

Comment on lines 12 to 22

from apps.fyle.enums import FyleAttributeEnum
from apps.fyle.models import ExpenseGroupSettings
from apps.mappings.queue import schedule_auto_map_employees, schedule_tax_groups_creation
from apps.mappings.queue import schedule_auto_map_employees
from apps.workspaces.models import Workspace, WorkspaceGeneralSettings
from apps.xero.queue import schedule_payment_creation, schedule_reimbursements_sync, schedule_xero_objects_status_sync
from fyle_xero_api.utils import assert_valid
from apps.mappings.schedules import new_schedule_or_delete_fyle_import_tasks


def generate_token(authorization_code: str, redirect_uri: str = None) -> str:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [245-245]

Decoding a JWT token with verify=False bypasses integrity checks, which could potentially allow tampered tokens to be accepted. This is a security risk as it makes the application vulnerable to token tampering attacks.

Consider verifying the JWT token to ensure its integrity. If the token's signature cannot be verified in this context due to missing keys or other reasons, document the rationale and assess the risk. Implement additional security measures if necessary to mitigate potential threats.

- decoded_jwt = jwt.decode(successful_response["id_token"], options={"verify_signature": False})
+ decoded_jwt = jwt.decode(successful_response["id_token"], options={"verify_signature": True})

Comment on lines +5 to +24
def test_construct_tasks_and_chain_import_fields_to_fyle(
db,
mocker,
create_temp_workspace,
add_xero_credentials,
create_mapping_setting
):
workspace_id = 3
mocker.patch('apps.mappings.queue.chain_import_fields_to_fyle')

WorkspaceGeneralSettings.objects.create(
workspace_id=workspace_id,
import_suppliers_as_merchants=True,
import_categories=True,
import_tax_codes=True,
charts_of_accounts=['Income'],
import_customers=True
)

construct_tasks_and_chain_import_fields_to_fyle(workspace_id)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test setup for construct_tasks_and_chain_import_fields_to_fyle is well-implemented, but the test lacks assertions to verify the outcome of the function call. Consider adding assertions to ensure the test effectively validates the function's behavior under the given conditions.

@@ -0,0 +1,22 @@
rollback;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial rollback; statement might be unnecessary or a mistake unless it serves a specific, undocumented purpose. Consider removing it or documenting its necessity.

)
);

\copy (select * from old_schedules) to '/tmp/django_q_schedule.csv' with csv header;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file path /tmp/django_q_schedule.csv is hard-coded, which could lead to issues in different environments or if the script is run by multiple instances simultaneously. Consider parameterizing the file path or implementing a mechanism to handle potential conflicts.

Comment on lines +31 to +45
def test_schedule_or_delete_fyle_import_tasks_with_no_configuration(configuration, mapping_settings):
new_schedule_or_delete_fyle_import_tasks(configuration, mapping_settings)


def test_schedule_or_delete_fyle_import_tasks_with_import_categories(configuration, db):
def test_schedule_or_delete_fyle_import_tasks_with_import_categories(configuration, mapping_settings):
configuration.import_categories = True
schedule_or_delete_fyle_import_tasks(configuration)
new_schedule_or_delete_fyle_import_tasks(configuration, mapping_settings)


def test_schedule_or_delete_fyle_import_tasks_with_project_mapping(configuration, db):
def test_schedule_or_delete_fyle_import_tasks_with_project_mapping(configuration, mapping_settings):
project_mapping = MappingSetting.objects.create(
source_field="PROJECT", workspace_id=1, import_to_fyle=True
)
configuration.import_categories = False
schedule_or_delete_fyle_import_tasks(configuration)
new_schedule_or_delete_fyle_import_tasks(configuration, mapping_settings)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests and the new mapping_settings fixture are well-implemented, enhancing test flexibility and readability. Ensure that assertions are added to verify the expected outcomes of new_schedule_or_delete_fyle_import_tasks based on the configurations and mapping settings.

Comment on lines 64 to 98
workspace_id,
mapping_setting.destination_field,
mapping_setting.source_field,
mapping_setting.source_placeholder,
)


def upload_tax_groups_to_fyle(
platform_connection: PlatformConnector, workspace_id: int
):
existing_tax_codes_name = ExpenseAttribute.objects.filter(
attribute_type=FyleAttributeEnum.TAX_GROUP, workspace_id=workspace_id
).values_list("value", flat=True)

xero_attributes = DestinationAttribute.objects.filter(
attribute_type="TAX_CODE", workspace_id=workspace_id
).order_by("value", "id")

xero_attributes = remove_duplicates(xero_attributes)

fyle_payload: List[Dict] = create_fyle_tax_group_payload(
xero_attributes, existing_tax_codes_name
attribute_type="MERCHANT",
defaults={
'status': 'IN_PROGRESS'
}
)

if fyle_payload:
platform_connection.tax_groups.post_bulk(fyle_payload)

platform_connection.tax_groups.sync()
Mapping.bulk_create_mappings(xero_attributes, FyleAttributeEnum.TAX_GROUP, "TAX_CODE", workspace_id)
sync_after = None

if not is_created:
sync_after = import_log.last_successful_run_at if import_log.last_successful_run_at else None

def create_fyle_tax_group_payload(
xero_attributes: List[DestinationAttribute], existing_fyle_tax_groups: list
):
"""
Create Fyle tax Group Payload from Xero Objects
:param existing_fyle_tax_groups: Existing tax groups names
:param xero_attributes: Xero Objects
:return: Fyle tax Group Payload
"""

existing_fyle_tax_groups = [
tax_group.lower() for tax_group in existing_fyle_tax_groups
]

fyle_tax_group_payload = []
for xero_attribute in xero_attributes:
if xero_attribute.value.lower() not in existing_fyle_tax_groups:
fyle_tax_group_payload.append(
{
"name": xero_attribute.value,
"is_enabled": True,
"percentage": round((xero_attribute.detail["tax_rate"] / 100), 2),
}
)

logger.info("| Importing Tax Groups to Fyle | Content: {{Fyle Payload count: {}}}".format(len(fyle_tax_group_payload)))
return fyle_tax_group_payload

time_difference = datetime.now() - timedelta(minutes=30)
offset_aware_time_difference = time_difference.replace(tzinfo=timezone.utc)

@handle_import_exceptions(task_name="auto create tax codes_mappings")
def auto_create_tax_codes_mappings(workspace_id: int):
"""
Create Tax Codes Mappings
:return: None
"""

fyle_credentials: FyleCredential = FyleCredential.objects.get(
workspace_id=workspace_id
)

platform = PlatformConnector(fyle_credentials=fyle_credentials)
platform.tax_groups.sync()

sync_xero_attributes("TAX_CODE", workspace_id)

upload_tax_groups_to_fyle(platform, workspace_id)
if (import_log.status == 'IN_PROGRESS' and not is_created) \
or (sync_after and (sync_after > offset_aware_time_difference)):
return

else:
import_log.status = 'IN_PROGRESS'
import_log.processed_batches_count = 0
import_log.total_batches_count = 0
import_log.save()

def auto_create_suppliers_as_merchants(workspace_id):
fyle_credentials: FyleCredential = FyleCredential.objects.get(
workspace_id=workspace_id
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [67-114]

The refactoring in apps/mappings/tasks.py, including the introduction of auto_create_suppliers_as_merchants, is a significant improvement towards simplifying the codebase. However, there are a few points to consider:

  • Ensure that the removal of functions related to managing expense attributes, categories, projects, etc., does not remove any critical functionality or leave parts of the system unable to handle certain scenarios.

  • The new auto_create_suppliers_as_merchants function should be thoroughly tested, especially since it interacts with external systems (Fyle and Xero). Consider adding tests that cover successful cases, error handling, and edge cases.

  • The use of ImportLog to track the import status and log errors is a good practice. Ensure that the error logging is comprehensive and useful for debugging issues.

  • The handling of time comparisons and status checks in auto_create_suppliers_as_merchants (lines 83-88) is crucial for avoiding unnecessary imports. Verify that the logic correctly handles time zones and edge cases related to timing.

  • Verify that no critical functionality is lost due to the removal of functions.

  • Thoroughly test auto_create_suppliers_as_merchants, including error handling and edge cases.

  • Ensure comprehensive and useful error logging in ImportLog.

  • Verify the correctness of time comparisons and status checks to avoid unnecessary imports.

Comment on lines 1 to 29
Mapping.objects.create(
destination_type="ACCOUNT",
destination=da_instance,
workspace_id=workspace_id,
source=ea_instance,
)

ea_instance.save()

xero_attributes = upload_categories_to_fyle(workspace_id=workspace_id)
assert len(xero_attributes) == 29

xero_credentials = XeroCredentials.objects.get(workspace_id=workspace_id)
xero_credentials.delete()

# Expect XeroCredentials.DoesNotExist exception since we've deleted the credentials
with pytest.raises(XeroCredentials.DoesNotExist):
xero_attributes = upload_categories_to_fyle(workspace_id=workspace_id)


def test_create_fyle_category_payload(mocker, db):
workspace_id = 1
qbo_attributes = DestinationAttribute.objects.filter(
workspace_id=1, attribute_type="ACCOUNT"
)

mocker.patch(
"fyle.platform.apis.v1beta.admin.Categories.list_all",
return_value=fyle_data["get_all_categories"],
)

qbo_attributes = remove_duplicates(qbo_attributes)

fyle_credentials: FyleCredential = FyleCredential.objects.get(
workspace_id=workspace_id
)
platform = PlatformConnector(fyle_credentials)

category_map = get_all_categories_from_fyle(platform=platform)
fyle_category_payload = create_fyle_categories_payload(
qbo_attributes, 2, category_map
)

assert (
dict_compare_keys(fyle_category_payload[0], data["fyle_category_payload"][0])
== []
), "category upload api return diffs in keys"


def test_auto_create_category_mappings(db, mocker):
workspace_id = 1
mocker.patch(
"fyle_integrations_platform_connector.apis.Categories.post_bulk",
return_value=[],
)

mocker.patch(
"xerosdk.apis.Accounts.get_all", return_value=xero_data["get_all_accounts"]
)

mocker.patch(
"fyle.platform.apis.v1beta.admin.Categories.list_all",
return_value=fyle_data["get_all_categories"],
)

response = auto_create_category_mappings(workspace_id=workspace_id)
assert response == []

mappings = CategoryMapping.objects.filter(workspace_id=workspace_id)

assert len(mappings) == 0

with mock.patch("apps.mappings.tasks.upload_categories_to_fyle") as mock_call:
mock_call.side_effect = WrongParamsError(
msg="wrong parameter error", response="wrong parameter error"
)
response = auto_create_category_mappings(workspace_id=workspace_id)

mock_call.side_effect = FyleInvalidTokenError(
msg="Invalid Token for Fyle", response="Invalid Token for Fyle"
)
response = auto_create_category_mappings(workspace_id=workspace_id)

mock_call.side_effect = InternalServerError(
msg="Internal server error while importing to Fyle",
response="Internal server error while importing to Fyle",
)
response = auto_create_category_mappings(workspace_id=workspace_id)

fyle_credentials = FyleCredential.objects.get(workspace_id=workspace_id)
fyle_credentials.delete()

response = auto_create_category_mappings(workspace_id=workspace_id)

assert response == None


def test_async_auto_map_employees(mocker, db):
workspace_id = 1

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-111]

The changes in tests/test_mappings/test_tasks.py reflect the refactoring in the tasks module. However, to ensure the tests are effective and maintainable, consider the following:

  • Verify that all new functions introduced in the tasks module, such as auto_create_suppliers_as_merchants, are covered by tests. This includes testing for success scenarios, error handling, and edge cases.

  • For removed functions, ensure that their corresponding tests are either removed or updated to reflect the new logic in the tasks module.

  • The use of mocks and patching should be carefully reviewed to ensure that they accurately represent the dependencies and interactions of the functions under test. This is particularly important for functions that interact with external systems.

  • Consider adding comments or documentation to the tests to explain the purpose and expected behavior of each test case. This can improve maintainability and make it easier for future contributors to understand the test suite.

  • Ensure coverage for all new functions in the tasks module.

  • Update or remove tests corresponding to removed functions.

  • Review the use of mocks and patching for accuracy.

  • Add comments or documentation to improve the understandability of the test suite.

Comment on lines +35 to +108
)

# import_vendors_as_merchants is not used in xero, placeholder to avoid KeyError
task_settings: TaskSetting = {
'import_tax': None,
'import_vendors_as_merchants': None,
'import_suppliers_as_merchants': None,
'import_categories': None,
'import_items': None,
'mapping_settings': [],
'credentials': credentials,
'sdk_connection_string': 'apps.xero.utils.XeroConnector',
'custom_properties': None
}

def schedule_tax_groups_creation(import_tax_codes, workspace_id):
if import_tax_codes:
schedule, _ = Schedule.objects.update_or_create(
func="apps.mappings.tasks.auto_create_tax_codes_mappings",
cluster='import',
args="{}".format(workspace_id),
defaults={
"schedule_type": Schedule.MINUTES,
"minutes": 24 * 60,
"next_run": datetime.now(),
},
)
else:
schedule: Schedule = Schedule.objects.filter(
func="apps.mappings.tasks.auto_create_tax_codes_mappings",
args="{}".format(workspace_id),
).first()
# For now adding only for PROJECT
ALLOWED_SOURCE_FIELDS = [
FyleAttributeEnum.PROJECT,
FyleAttributeEnum.COST_CENTER,
]

if schedule:
schedule.delete()
if workspace_general_settings.import_tax_codes:
task_settings['import_tax'] = {
'destination_field': 'TAX_CODE',
'destination_sync_methods': [SYNC_METHODS['TAX_CODE']],
'is_auto_sync_enabled': False,
'is_3d_mapping': False
}

if workspace_general_settings.import_categories:
task_settings['import_categories'] = {
'destination_field': 'ACCOUNT',
'destination_sync_methods': [SYNC_METHODS['ACCOUNT']],
'is_auto_sync_enabled': True,
'is_3d_mapping': False,
'charts_of_accounts': workspace_general_settings.charts_of_accounts
}

def schedule_fyle_attributes_creation(workspace_id: int):
mapping_settings = MappingSetting.objects.filter(
is_custom=True, import_to_fyle=True, workspace_id=workspace_id
).all()
if workspace_general_settings.import_suppliers_as_merchants:
task_settings['custom_properties'] = {
'func': 'apps.mappings.tasks.auto_create_suppliers_as_merchants',
'args': {
'workspace_id': workspace_id
}
}

if mapping_settings:
schedule, _ = Schedule.objects.get_or_create(
func="apps.mappings.tasks.async_auto_create_custom_field_mappings",
cluster='import',
args="{0}".format(workspace_id),
defaults={
"schedule_type": Schedule.MINUTES,
"minutes": 24 * 60,
"next_run": datetime.now() + timedelta(hours=24),
},
)
else:
schedule: Schedule = Schedule.objects.filter(
func="apps.mappings.tasks.async_auto_create_custom_field_mappings",
args=workspace_id,
).first()
for mapping_setting in mapping_settings:
if mapping_setting.source_field in ALLOWED_SOURCE_FIELDS or mapping_setting.is_custom:
task_settings['mapping_settings'].append(
{
'source_field': mapping_setting.source_field,
'destination_field': mapping_setting.destination_field,
'is_custom': mapping_setting.is_custom,
'destination_sync_methods': [SYNC_METHODS.get(mapping_setting.destination_field.upper(), 'tracking_categories')],
'is_auto_sync_enabled': is_auto_sync_allowed(workspace_general_settings, mapping_setting)
}
)

if schedule:
schedule.delete()
chain_import_fields_to_fyle(workspace_id, task_settings)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactoring in apps/mappings/queue.py to construct_tasks_and_chain_import_fields_to_fyle is a significant improvement in terms of clarity and functionality. However, there are a few areas that could be further refined:

  • The function now handles a broader range of tasks, which is a positive change. Ensure that the function's documentation is updated to accurately describe its new responsibilities and the parameters it accepts.

  • The construction of task_settings is a critical part of this function. Consider breaking down this construction into smaller, more focused functions or methods to improve readability and maintainability.

  • The use of hard-coded values and conditions (e.g., ALLOWED_SOURCE_FIELDS, import_tax, import_categories) should be carefully reviewed to ensure they are flexible and maintainable. Where possible, consider externalizing these configurations or making them more dynamic.

  • Ensure comprehensive testing of this function, particularly because it now encompasses a wider range of functionality. This includes testing for correct task construction, handling of various settings, and interaction with the chain_import_fields_to_fyle function.

  • Update the function's documentation to reflect its expanded responsibilities.

  • Consider refactoring the construction of task_settings to improve readability.

  • Review and possibly externalize hard-coded values and conditions for better flexibility.

  • Ensure comprehensive testing of the function's expanded functionality.

Comment on lines +83 to +132
def handle_import_exceptions_v2(func):
def new_fn(expense_attribute_instance, *args):
import_log: ImportLog = args[0]
workspace_id = import_log.workspace_id
attribute_type = import_log.attribute_type
error = {
'task': 'Import {0} to Fyle and Auto Create Mappings'.format(attribute_type),
'workspace_id': workspace_id,
'message': None,
'response': None
}
try:
return func(expense_attribute_instance, *args)
except WrongParamsError as exception:
error['message'] = exception.message
error['response'] = exception.response
error['alert'] = True
import_log.status = 'FAILED'

except InvalidTokenError:
error['message'] = 'Invalid Token for fyle'
error['alert'] = False
import_log.status = 'FAILED'

except InternalServerError:
error['message'] = 'Internal server error while importing to Fyle'
error['alert'] = True
import_log.status = 'FAILED'

except (XeroWrongParamsError, XeroInvalidTokenError, XeroCredentials.DoesNotExist) as exception:
error['message'] = 'Invalid Token or Xero credentials does not exist workspace_id - {0}'.format(workspace_id)
error['alert'] = False
error['response'] = exception.__dict__
import_log.status = 'FAILED'

except Exception:
response = traceback.format_exc()
error['message'] = 'Something went wrong'
error['response'] = response
error['alert'] = False
import_log.status = 'FATAL'

if error['alert']:
logger.error(error)
else:
logger.info(error)

import_log.error_log = error
import_log.save()

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introduction of handle_import_exceptions_v2 in apps/mappings/exceptions.py is a valuable addition for handling and logging errors during the import process. A few suggestions for improvement:

  • The function does a good job of handling various exceptions and updating the ImportLog status accordingly. Ensure that all relevant exceptions are covered and that the error messages are clear and informative.

  • The use of error['alert'] to determine whether to log an error as info or error is a good practice. However, consider standardizing the conditions under which error['alert'] is set to True or False to ensure consistency across different types of errors.

  • The function updates the ImportLog with error details, which is crucial for debugging. Ensure that the ImportLog model has appropriate fields to store all necessary error information and that this information is easily accessible for troubleshooting.

  • Consider adding unit tests specifically for handle_import_exceptions_v2 to verify that it behaves as expected for different types of exceptions. This can help ensure robustness and ease future maintenance.

  • Verify coverage of all relevant exceptions and clarity of error messages.

  • Standardize conditions for setting error['alert'].

  • Ensure the ImportLog model adequately supports error logging.

  • Add unit tests for handle_import_exceptions_v2.

Comment on lines 66 to 77
mapping_setting.save()

schedule = Schedule.objects.filter(
func="apps.mappings.tasks.async_auto_create_custom_field_mappings",
func="apps.mappings.queue.construct_tasks_and_chain_import_fields_to_fyle",
args="{}".format(workspace_id),
).first()

assert (
schedule.func == "apps.mappings.tasks.async_auto_create_custom_field_mappings"
schedule.func == "apps.mappings.queue.construct_tasks_and_chain_import_fields_to_fyle"
)
assert schedule.args == "1"

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-102]

The updates in tests/test_mappings/test_signals.py to use construct_tasks_and_chain_import_fields_to_fyle are appropriate given the changes in the queue module. However, to ensure the tests are effective:

  • Verify that the test cases adequately cover the scenarios that construct_tasks_and_chain_import_fields_to_fyle is expected to handle. This includes different configurations of workspace settings and mapping settings.

  • Ensure that the assertions in the test cases are meaningful and accurately reflect the expected outcomes of calling construct_tasks_and_chain_import_fields_to_fyle. For example, verifying that the correct tasks are constructed and chained based on the provided settings.

  • Consider adding more detailed comments or documentation within the test cases to explain the setup and expected outcomes. This can improve maintainability and make it easier for future contributors to understand the purpose of each test case.

  • Ensure comprehensive coverage of scenarios for construct_tasks_and_chain_import_fields_to_fyle.

  • Review and enhance assertions to accurately reflect expected outcomes.

  • Add detailed comments or documentation within the test cases for better understandability.

@Hrishabh17 Hrishabh17 added the deploy Triggers deployment of active branch to Staging label Mar 8, 2024
@Hrishabh17 Hrishabh17 added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Mar 8, 2024
@Hrishabh17 Hrishabh17 added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Mar 8, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 0b32cd6 and 55d9050.
Files selected for processing (5)
  • .github/workflows/codecov.yml (1 hunks)
  • .github/workflows/production_deployment.yml (1 hunks)
  • .github/workflows/pytest.yml (1 hunks)
  • .github/workflows/staging_deployment.yml (1 hunks)
  • scripts/python/add_new_import_schedule.py (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • scripts/python/add_new_import_schedule.py
Additional comments: 4
.github/workflows/codecov.yml (1)
  • 16-17: The addition of submodules: recursive under the actions/checkout@v2 step is a good practice for ensuring that all submodules are checked out before proceeding with the CI steps. This is particularly important for projects that rely on submodules for critical functionality or dependencies. This change aligns with the PR objectives of enhancing modularity and improving maintainability by ensuring that all necessary code, including that in submodules, is available for testing and coverage analysis.
.github/workflows/pytest.yml (1)
  • 18-19: The addition of submodules: recursive under the actions/checkout@v2 step in the CI workflow for running pytest and testing for token health is essential. This ensures that all submodules are properly checked out before the services are brought up and tests are run. Given the project's focus on improving integration capabilities and streamlining task scheduling, having access to the complete codebase, including submodules, is crucial for accurate testing and coverage reporting.
.github/workflows/staging_deployment.yml (1)
  • 17-18: Adding submodules: recursive under the actions/checkout@v2 step in the staging deployment workflow is a prudent decision. This ensures that all submodules, which might contain necessary configurations or dependencies, are available during the deployment process. This change supports the PR's goal of optimizing code structure and improving error handling by ensuring that the deployment process has access to the full, intended codebase, including any submodules.
.github/workflows/production_deployment.yml (1)
  • 13-14: Incorporating submodules: recursive under the actions/checkout@v2 step for the production deployment workflow is a critical improvement. This ensures that all necessary submodules are checked out and available during the deployment process, which is vital for a successful and error-free deployment to production. This adjustment aligns with the PR's objectives of enhancing modularity and ensuring that the deployment process is robust and reliable by including all necessary code components.

Copy link

github-actions bot commented Mar 8, 2024

Tests Skipped Failures Errors Time
157 0 💤 0 ❌ 0 🔥 1m 3s ⏱️

Copy link

codecov bot commented Mar 8, 2024

Codecov Report

Attention: Patch coverage is 78.88199% with 34 lines in your changes are missing coverage. Please review.

Project coverage is 93.14%. Comparing base (60ccb7e) to head (af10b05).

Files Patch % Lines
apps/mappings/tasks.py 20.83% 19 Missing ⚠️
apps/mappings/signals.py 76.08% 11 Missing ⚠️
apps/mappings/queue.py 86.95% 3 Missing ⚠️
apps/workspaces/utils.py 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #322      +/-   ##
==========================================
- Coverage   94.54%   93.14%   -1.40%     
==========================================
  Files          60       61       +1     
  Lines        3627     3470     -157     
==========================================
- Hits         3429     3232     -197     
- Misses        198      238      +40     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 55d9050 and af10b05.
Files selected for processing (1)
  • .github/workflows/codecov.yml (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/codecov.yml

Copy link

Tests Skipped Failures Errors Time
157 0 💤 0 ❌ 0 🔥 1m 3s ⏱️

@Hrishabh17 Hrishabh17 merged commit 7702403 into master Mar 12, 2024
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy Triggers deployment of active branch to Staging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants