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

feat: Netsuite Tax Override #662

Merged
merged 8 commits into from
Nov 19, 2024
Merged

feat: Netsuite Tax Override #662

merged 8 commits into from
Nov 19, 2024

Conversation

ruuushhh
Copy link
Contributor

@ruuushhh ruuushhh commented Nov 11, 2024

Description

Netsuite Tax Override

Clickup

https://app.clickup.com/1864988/v/l/6-901604646819-1

Summary by CodeRabbit

  • New Features

    • Introduced a new setting to enable tax balancing for general mappings.
    • Enhanced tax handling for line items in the NetSuite integration, allowing for better management of taxed and untaxed entries.
    • Added detailed tax information structures to improve clarity in tax-related data.
  • Bug Fixes

    • Improved accuracy in tax calculations across various transaction types, ensuring correct processing of bills, credit card charges, and journal entries.
    • Enhanced error handling in tests to ensure proper responses to various failure scenarios.

@ruuushhh ruuushhh self-assigned this Nov 11, 2024
@github-actions github-actions bot added the size/L Large PR label Nov 11, 2024
Copy link

coderabbitai bot commented Nov 11, 2024

Walkthrough

This pull request introduces a new Boolean field, is_tax_balancing_enabled, to the GeneralMapping model, allowing for the tracking of tax balancing status. Additionally, it enhances the NetSuiteConnector class by adding methods to manage taxed line items and streamline the preparation of custom segments. The changes also include updates to existing methods for handling line items, ensuring accurate processing of tax-related logic across various financial contexts.

Changes

File Path Change Summary
apps/mappings/migrations/0015_generalmapping_is_tax_balancing_enabled.py Added a migration for a new Boolean field is_tax_balancing_enabled in the generalmapping model.
apps/mappings/models.py Introduced is_tax_balancing_enabled field and updated workspace field with a related_name.
apps/netsuite/connector.py Added handle_taxed_line_items method; refactored existing line item methods for tax handling.
apps/netsuite/tasks.py Updated various functions to include general_mappings parameter for improved tax handling.
tests/sql_fixtures/reset_db_fixtures/reset_db.sql Added is_tax_balancing_enabled column to the public.general_mappings table in the SQL schema.
tests/test_netsuite/conftest.py Modified existing fixtures and added a new fixture for tax destination attributes.
tests/test_netsuite/fixtures.py Enhanced data structures for tax details and updated existing fields for clarity.
tests/test_netsuite/test_connector.py Updated tests to validate tax balancing logic in financial documents.
tests/test_netsuite/test_tasks.py Refined test functions to include new parameters and assertions for improved validation.

Possibly related PRs

  • feat: netsuite tax override tests #667: The changes in this PR enhance the testing of tax-related functionalities, particularly focusing on the is_tax_balancing_enabled flag in the GeneralMapping model, which is directly related to the new field added in the main PR.
  • fix: get tax mapping #669: This PR modifies the logic for retrieving tax item IDs, which is relevant to the new is_tax_balancing_enabled field in the GeneralMapping model, as it may influence how tax mappings are handled based on the state of this field.

Suggested reviewers

  • Hrishabh17
  • ashwin1111

Poem

🐇 In the fields where tax rules play,
A new flag blooms, bright as day.
Balancing ledgers, neat and fine,
With every line, our codes align.
Hopping forward, we embrace the change,
In our code garden, we rearrange! 🌼

Warning

Rate limit exceeded

@ruuushhh has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 49 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 40a2470 and 8c3618e.


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>, please review it.
    • Generate unit testing code 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 testing code 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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 using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • 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/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

Tests Skipped Failures Errors Time
224 0 💤 55 ❌ 17 🔥 32.933s ⏱️

Copy link

Tests Skipped Failures Errors Time
224 0 💤 55 ❌ 17 🔥 32.503s ⏱️

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.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
apps/mappings/models.py (1)

71-71: LGTM! Consider documenting the tax balancing behavior.

The new boolean field aligns well with the existing tax-related fields. However, the help text could be more descriptive about when and why tax balancing would be enabled.

Consider enhancing the help text:

-    is_tax_balancing_enabled = models.BooleanField(default=False, help_text='Is tax balancing enabled')
+    is_tax_balancing_enabled = models.BooleanField(
+        default=False,
+        help_text='Enable this to balance tax amounts between Fyle and NetSuite transactions'
+    )
apps/netsuite/connector.py (2)

1166-1173: Mismatch between docstring and function parameters

The docstring mentions a parameter is_credit_card_charge which is not present in the function signature. Please update the docstring to reflect the correct parameters.


1364-1375: Refactor duplicated code blocks to improve maintainability

The code handling tax overrides in both AccountBasedExpenseLineDetail and ItemBasedExpenseLineDetail sections appears similar. Consider refactoring this logic into a separate method to reduce duplication and enhance code readability.

Also applies to: 1397-1406

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 96c13db and 9dac1c5.

📒 Files selected for processing (3)
  • apps/mappings/migrations/0015_generalmapping_is_tax_balancing_enabled.py (1 hunks)
  • apps/mappings/models.py (1 hunks)
  • apps/netsuite/connector.py (12 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/mappings/migrations/0015_generalmapping_is_tax_balancing_enabled.py
🔇 Additional comments (3)
apps/mappings/models.py (1)

73-73: LGTM! Good addition of related_name.

The addition of related_name='general_mappings' to the workspace relationship is a good practice. It provides a clear and intuitive way to access GeneralMapping from a Workspace instance.

Let's verify this doesn't conflict with any existing related names:

✅ Verification successful

Let me search for any other relationships to Workspace model to ensure there are no conflicts.


✓ The related_name='general_mappings' is unique and doesn't conflict

The verification shows that there are only two related_name fields referencing the Workspace model:

  • workspace_schedules in workspaces app
  • general_mappings in mappings app (the one we're reviewing)

These names are distinct and won't cause any conflicts.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any other models with relationships to Workspace
# that might conflict with 'general_mappings'
rg "models\..*Field.*Workspace.*related_name.*general_mappings" --type py

Length of output: 487


Script:

#!/bin/bash
# Search for all relationships to Workspace model
rg "models\..*Field.*Workspace.*related_name" --type py -A 1

Length of output: 1222

apps/netsuite/connector.py (2)

1253-1257: Verify the use of duplicate custom fields

The custom fields custcolfyle_receipt_link_2 and custcolfyle_expense_url_2 are being added alongside custcolfyle_receipt_link and custcolfyle_expense_url. Please verify if both sets of fields are necessary, or if this is a redundancy.

If only one set of custom fields is required, consider removing the duplicates to streamline the data.

Also applies to: 1271-1277


1285-1291: Ensure all calls to construct_bill_lineitems include the new parameter override_tax_details

The method construct_bill_lineitems has been updated with a new parameter override_tax_details. Please verify that all calls to this method have been updated to pass this parameter to prevent any unexpected behavior.

Run the following script to identify calls to construct_bill_lineitems without the required parameter:

✅ Verification successful

Let me verify the actual content of the call to understand why we're seeing 6 arguments when splitting by comma.


The method call has been properly updated with all required parameters

The verification shows that the only call to construct_bill_lineitems in the codebase is correctly passing all five required parameters:

  1. bill_lineitems
  2. {} (empty dictionary for attachment_links)
  3. cluster_domain
  4. org_id
  5. bill.override_tax_details

The false positive in the argument count (showing 6) was due to the comma within the tuple unpacking expense_list, item_list = being counted by the awk command.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all calls to `construct_bill_lineitems` include the new parameter `override_tax_details`.

# Search for all function calls to `construct_bill_lineitems`
rg 'self\.construct_bill_lineitems\(' --no-heading --line-number

# Check if the number of arguments matches the updated signature (should be 5 arguments)
# This is a simplified check assuming arguments are not spread over multiple lines
rg 'self\.construct_bill_lineitems\([^)]{0,}\)' --no-heading --line-number | \
  awk -F',' '{if (NF != 5) print "Line "$1": Incorrect number of arguments ("NF")"}'

Length of output: 486


Script:

#!/bin/bash
# Get the context of the function call
rg 'self\.construct_bill_lineitems\(' -A 1 -B 1

Length of output: 299


if general_mapping.is_tax_balancing_enabled and round(line.tax_amount, 2) != expected_tax_amount:
# Recalculate the net amount based on the modified tax
recalculated_net_amount = round((line.tax_amount * 100) / tax_item_rate, 2)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential division by zero when tax_item_rate is zero

In line 1188, the calculation (line.tax_amount * 100) / tax_item_rate could result in a division by zero error if tax_item_rate is zero. Please add a check to ensure that tax_item_rate is not zero before performing the division.

Apply this diff to handle the division by zero:

+ if tax_item_rate == 0:
+     raise ValueError("Tax item rate cannot be zero")
  recalculated_net_amount = round((line.tax_amount * 100) / tax_item_rate, 2)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
recalculated_net_amount = round((line.tax_amount * 100) / tax_item_rate, 2)
if tax_item_rate == 0:
raise ValueError("Tax item rate cannot be zero")
recalculated_net_amount = round((line.tax_amount * 100) / tax_item_rate, 2)

@ruuushhh ruuushhh requested a review from ashwin1111 November 12, 2024 05:37
apps/netsuite/connector.py Show resolved Hide resolved
apps/netsuite/connector.py Show resolved Hide resolved
apps/netsuite/connector.py Show resolved Hide resolved
apps/netsuite/connector.py Outdated Show resolved Hide resolved
apps/netsuite/connector.py Outdated Show resolved Hide resolved
Copy link

Tests Skipped Failures Errors Time
224 0 💤 55 ❌ 17 🔥 32.994s ⏱️

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.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
apps/netsuite/connector.py (3)

1166-1235: Consider extracting module-specific logic into separate methods.

The method handles different export modules (BILL, JOURNAL_ENTRY, EXPENSE_REPORT) with module-specific logic scattered throughout. This makes the code harder to maintain and test.

Consider refactoring into separate methods for each module:

+ def _handle_journal_entry_tax(self, line, tax_amount):
+     line['grossAmt'] = None
+     line['debit'] = round(tax_amount, 2)
+     line.pop('amount', None)
+     return line

  def handle_taxed_line_items(self, base_line, line, workspace_id, export_module):
      # ... existing code ...
      if export_module == 'JOURNAL_ENTRY':
-         taxable_line['grossAmt'] = None
-         taxable_line['debit'] = recalculated_net_amount
-         taxable_line.pop('amount', None)
+         taxable_line = self._handle_journal_entry_tax(taxable_line, recalculated_net_amount)

Line range hint 1237-1283: Reduce code duplication in URL generation.

The method duplicates the expense URL generation logic. Also, consider adding validation for required parameters.

Consider refactoring:

+ def _generate_expense_url(self, expense_id, org_id):
+     if not expense_id or not org_id:
+         raise ValueError("expense_id and org_id are required")
+     return '{}/app/admin/#/enterprise/view_expense/{}?org_id={}'.format(
+         settings.FYLE_EXPENSE_URL,
+         expense_id,
+         org_id
+     )

  def prepare_custom_segments(self, line_netsuite_custom_segments, attachment_links, expense, org_id, is_credit=False):
      # ... existing code ...
      if not is_credit:
+         expense_url = self._generate_expense_url(expense.expense_id, org_id)
          netsuite_custom_segments.append({
              'scriptId': 'custcolfyle_expense_url',
              'type': 'String',
-             'value': '{}/app/admin/#/enterprise/view_expense/{}?org_id={}'.format(
-                 settings.FYLE_EXPENSE_URL,
-                 expense.expense_id,
-                 org_id
-             )
+             'value': expense_url
          })

Line range hint 1285-1407: Consider adding validation for tax override scenarios.

The method handles tax overrides but could benefit from additional validation and error handling for edge cases.

Add validation:

  def construct_bill_lineitems(self, bill_lineitems: List[BillLineitem], attachment_links: Dict,
          cluster_domain: str, org_id: str, override_tax_details: bool) -> List[Dict]:
+     if override_tax_details and not hasattr(bill_lineitems[0], 'tax_item_id'):
+         raise ValueError("Tax item ID is required when override_tax_details is True")
      
      # ... rest of the method
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9dac1c5 and 59dfb62.

📒 Files selected for processing (1)
  • apps/netsuite/connector.py (12 hunks)
🔇 Additional comments (1)
apps/netsuite/connector.py (1)

1188-1188: ⚠️ Potential issue

Add protection against division by zero.

The calculation (line.tax_amount * 100) / tax_item_rate could result in a division by zero error if tax_item_rate is zero.

Add a check before the division:

+ if tax_item_rate == 0:
+     raise ValueError("Tax item rate cannot be zero")
  recalculated_net_amount = round((line.tax_amount * 100) / tax_item_rate, 2)

Likely invalid or redundant comment.

Copy link

Tests Skipped Failures Errors Time
224 0 💤 0 ❌ 0 🔥 24.886s ⏱️

Copy link

Tests Skipped Failures Errors Time
224 0 💤 0 ❌ 0 🔥 25.146s ⏱️

* feat: netsuite tax override tests

* increase cov

---------

Co-authored-by: GitHub Actions <[email protected]>
@github-actions github-actions bot added size/XL Extra Large PR and removed size/L Large PR labels Nov 18, 2024
Copy link

Tests Skipped Failures Errors Time
229 0 💤 0 ❌ 0 🔥 26.299s ⏱️

Copy link

Tests Skipped Failures Errors Time
229 0 💤 0 ❌ 0 🔥 27.072s ⏱️

Copy link

codecov bot commented Nov 18, 2024

Codecov Report

Attention: Patch coverage is 90.47619% with 12 lines in your changes missing coverage. Please review.

Project coverage is 88.40%. Comparing base (f3b599b) to head (40a2470).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
apps/netsuite/connector.py 89.91% 12 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #662      +/-   ##
==========================================
- Coverage   88.44%   88.40%   -0.05%     
==========================================
  Files          59       59              
  Lines        5444     5501      +57     
==========================================
+ Hits         4815     4863      +48     
- Misses        629      638       +9     
Files with missing lines Coverage Δ
apps/mappings/models.py 100.00% <100.00%> (ø)
apps/netsuite/tasks.py 84.69% <100.00%> (+0.04%) ⬆️
apps/netsuite/connector.py 87.87% <89.91%> (-1.30%) ⬇️

... and 1 file with indirect coverage changes

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.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (14)
tests/sql_fixtures/reset_db_fixtures/reset_db.sql (1)

11656-11659: Consider documenting the default value choice

The default value of false for is_tax_balancing_enabled implies this is an opt-in feature. This looks correct, but consider documenting this decision in the code comments or documentation for future reference.

tests/test_netsuite/conftest.py (1)

306-322: Consider enhancing tax destination attributes test coverage.

While the fixture correctly creates tax items for each workspace, consider these improvements:

  1. Using sequential IDs (98765+i) might cause conflicts with other test data
  2. A fixed tax_rate of 5.0% may not cover all test scenarios
  3. Using the same destination_id ('103578') across workspaces may not reflect real-world scenarios

Consider this enhanced implementation:

 @pytest.fixture
 def add_tax_destination_attributes(db):
-    for i in(1, 2, 49):
+    test_data = [
+        {'workspace_id': 1, 'tax_rate': 5.0, 'destination_id': '103578'},
+        {'workspace_id': 2, 'tax_rate': 10.0, 'destination_id': '103579'},
+        {'workspace_id': 49, 'tax_rate': 7.5, 'destination_id': '103580'}
+    ]
+    
+    for data in test_data:
         DestinationAttribute.objects.create(
-            id = 98765+i,
             attribute_type='TAX_ITEM',
             value='Rushikesh',
-            destination_id = '103578',
+            destination_id=data['destination_id'],
             active = True,
             detail = {
-                'tax_rate': 5.0
+                'tax_rate': data['tax_rate']
             },
-            workspace_id = i,
+            workspace_id=data['workspace_id'],
             created_at = datetime.now(),
             updated_at = datetime.now(),
         )

This provides:

  • Different tax rates to test various scenarios
  • Unique destination IDs per workspace
  • Removed explicit ID setting to prevent conflicts
apps/netsuite/connector.py (1)

Line range hint 1236-1282: Apply DRY principle to URL construction.

The expense URL construction is duplicated for both custom fields. Consider extracting it to a variable.

  if not is_credit:
+     expense_url = '{}/app/admin/#/enterprise/view_expense/{}?org_id={}'.format(
+         settings.FYLE_EXPENSE_URL,
+         expense.expense_id,
+         org_id
+     )
      netsuite_custom_segments.append(
          {
              'scriptId': 'custcolfyle_expense_url',
              'type': 'String',
-             'value': '{}/app/admin/#/enterprise/view_expense/{}?org_id={}'.format(
-                 settings.FYLE_EXPENSE_URL,
-                 expense.expense_id,
-                 org_id
-             )
+             'value': expense_url
          }
      )
      netsuite_custom_segments.append(
          {
              'scriptId': 'custcolfyle_expense_url_2',
              'type': 'String',
-             'value': '{}/app/admin/#/enterprise/view_expense/{}?org_id={}'.format(
-                 settings.FYLE_EXPENSE_URL,
-                 expense.expense_id,
-                 org_id
-             )
+             'value': expense_url
          }
      )
tests/test_netsuite/test_connector.py (5)

22-22: Avoid hardcoding workspace_id in test functions

Throughout the test functions, general_mapping and other objects are retrieved using hardcoded workspace_id values (e.g., workspace_id=1). Consider parameterizing the workspace_id or using a fixture variable to enhance flexibility and maintainability of the tests.

Also applies to: 33-35, 82-82, 96-96, 108-108, 115-118, 235-238, 302-305, 853-853, 871-871, 889-889, 1024-1025


26-26: Accessing private methods using name mangling

The test code is accessing private methods of NetSuiteConnector using name mangling (e.g., netsuite_connection._NetSuiteConnector__construct_expense_report). While this approach works, it's better to test through the public interface or refactor these methods to be protected (single underscore) if they need to be accessed for testing purposes.

Also applies to: 43-43, 54-54, 70-70, 85-85, 99-99, 111-111, 127-127, 137-137, 149-149, 165-165, 174-174, 246-246, 258-258, 274-274, 313-313, 323-323, 336-336


47-47: Replace magic numbers with descriptive constants

Hardcoded values like '103578' for taxCode['internalId'] are used in multiple assertions. Defining these values as descriptive constants (e.g., TEST_TAX_CODE_INTERNAL_ID) would improve readability and maintainability.

Also applies to: 59-59, 73-73, 130-130, 141-141, 152-152, 251-251, 263-263, 278-278, 317-317, 327-327, 339-339


32-75: Parameterize test cases to reduce duplication

The test functions related to tax balancing (test_construct_expense_report_with_tax_balancing, test_construct_bill_item_for_tax_balancing, test_construct_journal_entry_with_tax_balancing, test_contruct_credit_card_charge_with_tax_balancing) share similar structures and code. Consider using parameterized tests or fixtures to eliminate duplication and enhance maintainability.

Also applies to: 115-156, 234-284, 301-341


899-899: Unused variable configuration

In the test_post_journal_entry_exception function, the variable configuration is assigned but not used afterward. If it's unnecessary, consider removing it to keep the code clean.

apps/netsuite/tasks.py (3)

329-332: Inconsistent Variable Naming: 'general_mapping' vs 'general_mappings'

The variable general_mappings is used here, while in other parts of the code, general_mapping is used. For consistency and to avoid confusion, it's recommended to use a consistent variable name throughout the codebase.

Consider standardizing the variable name to general_mapping:

- credit_line = construct_lines(export_line_items, general_mappings, credit='Credit', org_id=workspace.fyle_org_id)
+ credit_line = construct_lines(export_line_items, general_mapping, credit='Credit', org_id=workspace.fyle_org_id)

- debit_line = construct_lines(
-     export_line_items, general_mappings, debit='Debit', attachment_links=expense_id_receipt_url_map,
-     cluster_domain=cluster_domain, org_id=workspace.fyle_org_id
- )
+ debit_line = construct_lines(
+     export_line_items, general_mapping, debit='Debit', attachment_links=expense_id_receipt_url_map,
+     cluster_domain=cluster_domain, org_id=workspace.fyle_org_id
+ )

615-615: Optimize Retrieval of general_mapping

The general_mapping object is retrieved multiple times in different functions. To improve performance, consider retrieving it once and passing it as an argument where necessary.

Apply this change to reduce redundant database queries:

# Retrieve `general_mapping` at the beginning
+ general_mapping = GeneralMapping.objects.get(workspace_id=expense_group.workspace_id)

def create_expense_report(expense_group, task_log_id, last_export):
-     general_mapping = GeneralMapping.objects.get(workspace_id=expense_group.workspace_id)

680-680: Consistent Use of general_mapping

As previously noted, ensure consistent retrieval and usage of the general_mapping object throughout the code to maintain clarity and improve maintainability.

Consider passing general_mapping as an argument to functions that require it, rather than retrieving it multiple times.

tests/test_netsuite/test_tasks.py (3)

178-178: Unused parameter add_tax_destination_attributes in test_post_bill_success

The parameter add_tax_destination_attributes appears to be unused within the test_post_bill_success function. Removing it can simplify the test and avoid confusion.


210-212: Variable naming: Use expense instead of expenses

Within the loop, expenses represents a single expense in each iteration. Renaming it to expense improves clarity and adheres to standard naming conventions.

Apply this change:

-for expenses in expense_group.expenses.all():
-    expenses.workspace_id = 2
-    expenses.save()
+for expense in expense_group.expenses.all():
+    expense.workspace_id = 2
+    expense.save()

210-212: Avoid hard-coded workspace_id values in tests

Assigning expenses.workspace_id = 2 directly may lead to fragile tests if the workspace ID changes. Consider using a variable or fixture to obtain the workspace ID dynamically.

Example:

-    expenses.workspace_id = 2
+    expenses.workspace_id = workspace_id

Ensure workspace_id is defined or passed appropriately in your test setup.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 59dfb62 and 62f5d0e.

📒 Files selected for processing (7)
  • apps/netsuite/connector.py (28 hunks)
  • apps/netsuite/tasks.py (8 hunks)
  • tests/sql_fixtures/reset_db_fixtures/reset_db.sql (4 hunks)
  • tests/test_netsuite/conftest.py (5 hunks)
  • tests/test_netsuite/fixtures.py (3 hunks)
  • tests/test_netsuite/test_connector.py (11 hunks)
  • tests/test_netsuite/test_tasks.py (2 hunks)
🔇 Additional comments (19)
tests/sql_fixtures/reset_db_fixtures/reset_db.sql (3)

7990-7990: LGTM!

The migration record is properly sequenced and timestamped.


11902-11902: LGTM!

The sequence value is correctly updated to match the new migration number.


1442-1443: Verify migration handling for NOT NULL constraint

The new is_tax_balancing_enabled column is marked as NOT NULL without a default value. While this is reflected correctly in the test fixtures, ensure that the corresponding migration handles existing rows appropriately.

✅ Verification successful

Migration safely handles NOT NULL constraint with default value

The migration file shows that is_tax_balancing_enabled column is added with default=False, which safely handles existing rows in the database. This aligns with the test fixture changes and ensures data consistency.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check migration file to verify handling of existing rows

# Look for the migration file that adds this column
fd --type f "0015_generalmapping_is_tax_balancing_enabled.py" | xargs cat

Length of output: 526

tests/test_netsuite/conftest.py (1)

79-81: LGTM! Verify workspace ID consistency across fixtures.

The workspace ID updates are correctly implemented across fixtures. Note that most fixtures use workspace_id=1 except create_credit_card_charge which uses workspace_id=49.

Let's verify the workspace ID usage pattern:

Also applies to: 93-95, 250-252, 264-266

✅ Verification successful

Based on the search results, I can now verify the workspace ID usage pattern across the test fixtures. The results show:

  1. Most test fixtures use workspace_id=1 consistently, including:

    • Configuration objects
    • General mappings
    • Task logs
    • Expense groups
    • Various destination attributes
  2. workspace_id=49 is used specifically for:

    • Credit card charge related tests
    • Custom segments/lists tests
    • Currency tests
    • Department tests
    • Location tests
  3. workspace_id=2 is used occasionally for:

    • Some task logs
    • Specific mapping tests
    • Payment trigger tests

Workspace IDs are consistently used across test fixtures for their specific test scenarios

The different workspace IDs (1, 2, and 49) are intentionally used to isolate different test scenarios and maintain test data separation. This is a good testing practice to prevent test interference.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify workspace ID usage consistency across test files

# Check for workspace ID references in test files
rg -A 2 "workspace_id\s*=\s*(?:1|2|49)" tests/test_netsuite/

Length of output: 72680

apps/netsuite/connector.py (3)

Line range hint 1284-1406: LGTM! Well-structured tax handling implementation.

The changes properly integrate tax handling with clear separation between expense and item lists. The code:

  • Correctly checks for presence of tax information
  • Handles tax overrides appropriately
  • Uses the new handle_taxed_line_items method effectively

Line range hint 1584-1622: LGTM! Consistent implementation across different transaction types.

The tax handling changes are consistently implemented across credit card charges, expense reports, and journal entries. The code maintains a uniform approach to:

  • Tax validation
  • Line item generation
  • Integration with the new handle_taxed_line_items method

Also applies to: 1757-1846, 1988-2080


1166-1234: 🛠️ Refactor suggestion

⚠️ Potential issue

Add safeguards against division by zero and improve documentation.

The tax calculation logic needs additional safeguards and documentation:

  1. The division by tax_item_rate on line 1187 could cause a division by zero error
  2. The complex tax calculation logic would benefit from detailed documentation explaining the business rules and edge cases

Add a check for zero tax rate:

  tax_item_rate = tax_item.detail['tax_rate']
+ if tax_item_rate == 0:
+     raise ValueError("Tax item rate cannot be zero")
  recalculated_net_amount = round((line.tax_amount * 100) / tax_item_rate, 2)

Add detailed documentation:

  def handle_taxed_line_items(self, base_line, line, workspace_id, export_module, general_mapping: GeneralMapping):
      """
      Handle line items where tax is applied or modified by the user.
+     
+     Business Rules:
+     1. When tax balancing is enabled and actual tax differs from expected:
+        - Split into taxable and untaxed line items
+        - Recalculate net amount based on actual tax
+     2. When tax matches expected or balancing is disabled:
+        - Create single line item with tax
+     
      :param base_line: The base line item template that will be modified.
      :param line: The original line with tax and amount information.
-     :param is_credit_card_charge: Boolean flag to differentiate between credit card charges and other transactions.
+     :param workspace_id: The workspace ID for retrieving tax items
+     :param export_module: The type of export (BILL, EXPENSE_REPORT, JOURNAL_ENTRY)
+     :param general_mapping: General mapping configuration containing tax settings
      :return: List of lines (taxed and/or untaxed).
      """

Likely invalid or redundant comment.

tests/test_netsuite/fixtures.py (3)

5-31: LGTM! Well-structured tax details test data

The new tax_list_detail structure provides comprehensive test coverage for tax scenarios with all required fields.


1205-1208: LGTM! Proper custom field type additions

The addition of the 'type' field to customFieldList entries aligns with NetSuite API requirements.


994-999: LGTM! Consistent taxCode structure updates

The taxCode structure updates are consistent across both occurrences and match NetSuite API requirements.

Also applies to: 1215-1217

tests/test_netsuite/test_connector.py (3)

1028-1031: Ensure mock objects are fully configured

When setting up the mock Mapping object, verify that all required attributes and methods are correctly mocked. For instance, confirm that mock_mapping.destination.detail.get.return_value and mock_mapping.destination.detail.all.return_value are providing the expected values for the test.


242-245: Validate tax calculations with given inputs

In the tests involving tax amounts and items, ensure that the amount, tax_amount, and tax_item_id values are consistent and lead to accurate tax calculations. This will help verify that tax balancing is functioning as intended.

Also applies to: 271-273, 308-311, 331-334


1022-1070: Confirm correctness of construct_tax_details_list method

The test_constructs_tax_details_list_for_multiple_items function sets up mocks to test construct_tax_details_list. Ensure that the method handles multiple items correctly and the test accurately reflects realistic scenarios.

apps/netsuite/tasks.py (6)

570-570: Confirm post_credit_card_charge Method Parameters

Ensure that the post_credit_card_charge method accepts general_mappings as a parameter and handles it appropriately.

Run the following script to check the method definition:

#!/bin/bash
# Description: Verify `post_credit_card_charge` method parameters

rg -A 2 "def post_credit_card_charge\(self, credit_card_charge_object, credit_card_charge_lineitems_object, general_mappings, attachment_links, refund\):"

637-637: Verify post_expense_report Method Accepts general_mapping

Check that the post_expense_report method includes general_mapping as a parameter and uses it correctly.

Run the following script to confirm:

#!/bin/bash
# Description: Verify `post_expense_report` method parameters

rg -A 2 "def post_expense_report\(self, expense_report_object, expense_report_lineitems_objects, general_mapping\):"

344-344: Confirm Function Signature Matches in construct_lines Call

Verify that the function construct_lines is defined to accept general_mappings as a parameter in this context.

Run the following script to confirm the function definition:

#!/bin/bash
# Description: Check definition of `construct_lines` function for matching parameters

# Locate the definition of `construct_lines` related to this call
rg -A 2 "def construct_credit_card_charge_lineitems\("
rg -A 2 "def construct_expense_report_lineitems\("

703-703: Ensure post_journal_entry Method Receives Correct Parameters

Confirm that the post_journal_entry method in NetSuiteConnector accepts configuration and general_mapping as parameters and that they are utilized properly within the method.

Run the following script to verify the method signature:

#!/bin/bash
# Description: Verify `post_journal_entry` method parameters

rg -A 2 "def post_journal_entry\(self, journal_entry_object, journal_entry_lineitems_objects, configuration, general_mapping\):"

490-490: Ensure post_bill Method Accepts general_mappings Parameter

Confirm that the post_bill method in NetSuiteConnector accepts general_mappings as a parameter and utilizes it correctly within the method.

Run the following script to verify the method signature:

#!/bin/bash
# Description: Verify `post_bill` method accepts `general_mappings`

rg -A 2 "def post_bill\(self, bill_object, bill_lineitems_objects, general_mappings\):"

340-340: Verify Parameters in Function Call to construct_lines

Ensure that the parameters passed to construct_lines match its definition. Specifically, confirm that general_mappings.override_tax_details is a valid attribute and that general_mappings is an accepted parameter.

Run the following script to check if construct_lines accepts general_mappings and if override_tax_details exists:

@ruuushhh ruuushhh added the deploy Triggers deployment of active branch to Staging label Nov 18, 2024
@ruuushhh ruuushhh added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Nov 18, 2024
Copy link

Tests Skipped Failures Errors Time
229 0 💤 0 ❌ 0 🔥 25.905s ⏱️

* fix: Get Tax Mapping

* fix tests

---------

Co-authored-by: GitHub Actions <[email protected]>
@ruuushhh ruuushhh added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Nov 18, 2024
Copy link

Tests Skipped Failures Errors Time
229 0 💤 0 ❌ 0 🔥 25.631s ⏱️

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.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
apps/netsuite/models.py (1)

118-129: LGTM! Consider adding type hints and docstring.

The changes improve the tax code determination logic by first checking for tax settings existence. This is a good optimization that prevents unnecessary database queries.

Consider these improvements:

  1. Add type hints and docstring:
-def get_tax_item_id_or_none(expense_group: ExpenseGroup, general_mapping: GeneralMapping, lineitem: Expense = None):
+def get_tax_item_id_or_none(expense_group: ExpenseGroup, general_mapping: GeneralMapping, lineitem: Expense = None) -> Optional[str]:
+    """
+    Get tax item ID based on tax group mapping or default tax code.
+    
+    Args:
+        expense_group: The expense group containing the expense
+        general_mapping: General mapping settings
+        lineitem: Optional expense line item
+        
+    Returns:
+        str: Tax item ID if found, None otherwise
+    """
  1. Remove extra blank line after line 121:
     ).first()
-    
     if tax_setting:
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 40a2470 and 8c3618e.

📒 Files selected for processing (1)
  • apps/netsuite/models.py (1 hunks)

@ruuushhh ruuushhh merged commit 3e83358 into master Nov 19, 2024
6 checks passed
ruuushhh added a commit that referenced this pull request Nov 20, 2024
* feat: Netsuite Tax Override

* fix comments

* Fix tests

* feat: netsuite tax override tests (#667)

* feat: netsuite tax override tests

* increase cov

---------

Co-authored-by: GitHub Actions <[email protected]>

* fix: get tax mapping (#669)

* fix: Get Tax Mapping

* fix tests

---------

Co-authored-by: GitHub Actions <[email protected]>

---------

Co-authored-by: GitHub Actions <[email protected]>
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 size/XL Extra Large PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants