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: Add Receipt URLs to DB #643

Closed
wants to merge 2 commits into from
Closed

feat: Add Receipt URLs to DB #643

wants to merge 2 commits into from

Conversation

ruuushhh
Copy link
Contributor

@ruuushhh ruuushhh commented Sep 24, 2024

Description

Store receipt URLs to db
And note if failed

Clickup

Add Receipt URLs to DB

Summary by CodeRabbit

  • New Features

    • Added new fields for managing expense receipt URLs and attachment upload status in multiple models.
    • Enhanced attachment upload handling with improved error tracking and URL management for credit card charges.
  • Bug Fixes

    • Improved handling of attachment upload failures to ensure accurate status reporting.
  • Tests

    • Expanded test coverage for receipt URL management and attachment handling across various entities.

@ruuushhh ruuushhh requested a review from ashwin1111 September 24, 2024 04:40
@ruuushhh ruuushhh self-assigned this Sep 24, 2024
@github-actions github-actions bot added the size/S Small PR label Sep 24, 2024
Copy link

coderabbitai bot commented Sep 24, 2024

Walkthrough

The changes introduce new fields to four model classes in the apps/netsuite/models.py file, enhancing their structure to store additional information related to expense receipts and attachment upload status. A new mapping is established in apps/netsuite/tasks.py to associate task types with their corresponding model classes, improving the handling of attachment uploads and failure states. Additionally, modifications to the SQL schema and test cases ensure comprehensive coverage of these new features.

Changes

File Change Summary
apps/netsuite/models.py Added receipt_urls (JSONField) and is_attachment_upload_failed (BooleanField) to Bill, CreditCardCharge, ExpenseReport, and JournalEntry classes.
apps/netsuite/tasks.py Introduced TASK_TYPE_MODEL_MAP for mapping task types to model classes. Updated load_attachments method to accept credit_card_charge_object. Modified upload_attachments_and_update_export to utilize the task model.
tests/sql_fixtures/reset_db_fixtures Added new columns (is_attachment_upload_failed, receipt_urls) to multiple tables in the SQL schema and updated COPY statements accordingly. Added migration entry 0027_auto_20240924_0614.
tests/test_netsuite/test_tasks.py Enhanced assertions for receipt_urls and is_attachment_upload_failed in tests for CreditCardCharge, Bill, JournalEntry, and ExpenseReport. Updated method signatures to include necessary parameters.

Poem

In fields of code, where rabbits play,
New fields emerge to save the day.
With URLs and flags to show,
Attachments dance, as data flows.
A hop, a skip, through tasks we glide,
In the world of netsuite, we take pride! 🐇✨


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
222 0 💤 20 ❌ 15 🔥 25.421s ⏱️

Copy link

Tests Skipped Failures Errors Time
222 0 💤 20 ❌ 15 🔥 24.771s ⏱️

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: 4

Outside diff range and nitpick comments (5)
apps/netsuite/models.py (4)

381-382: LGTM! Consider adding a docstring for the new fields.

The addition of receipt_urls and is_attachment_upload_failed fields aligns well with the PR objectives. The field types and options are appropriate for their intended use.

Consider adding a brief docstring to explain the structure of the receipt_urls JSONField, e.g., what keys and values are expected. This would improve code maintainability.


585-586: LGTM! Consider adding a docstring for consistency.

The addition of receipt_urls and is_attachment_upload_failed fields is consistent with the changes in the Bill class and aligns with the PR objectives.

For consistency with the suggestion for the Bill class, consider adding a brief docstring to explain the structure of the receipt_urls JSONField.


803-804: LGTM! Consider adding a docstring for consistency.

The addition of receipt_urls and is_attachment_upload_failed fields is consistent with the changes in the other classes and aligns with the PR objectives.

For consistency with the suggestions for the other classes, consider adding a brief docstring to explain the structure of the receipt_urls JSONField.


1034-1035: LGTM! Consider adding a docstring for consistency.

The addition of receipt_urls and is_attachment_upload_failed fields is consistent with the changes in the other classes and completes the implementation across all relevant classes.

For consistency with the suggestions for the other classes, consider adding a brief docstring to explain the structure of the receipt_urls JSONField.

apps/netsuite/tasks.py (1)

566-567: Check for empty attachment_links before saving

attachment_links might be empty if no attachments were uploaded. Saving an empty JSON may not be necessary.

Consider adding a condition:

if attachment_links:
    credit_card_charge_object.receipt_urls = json.dumps(attachment_links)
    credit_card_charge_object.save()
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5777049 and 952a06a.

Files selected for processing (2)
  • apps/netsuite/models.py (4 hunks)
  • apps/netsuite/tasks.py (6 hunks)
Additional comments not posted (1)
apps/netsuite/models.py (1)

381-382: Verify usage of new fields in related code.

The addition of receipt_urls and is_attachment_upload_failed fields is consistent across all modified classes (Bill, CreditCardCharge, ExpenseReport, and JournalEntry) and aligns well with the PR objectives.

To ensure these new fields are properly utilized, please verify that related parts of the codebase (e.g., views, serializers, and any business logic handling these models) are updated to work with these new fields. Run the following script to check for potential usage:

Also applies to: 585-586, 803-804, 1034-1035

Comment on lines +154 to +155
credit_card_charge_object.is_attachment_upload_failed = True
credit_card_charge_object.save()
Copy link

Choose a reason for hiding this comment

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

Refactor duplicate code in exception handlers

The lines setting credit_card_charge_object.is_attachment_upload_failed = True and saving the object are duplicated in both exception handlers. This violates the DRY (Don't Repeat Yourself) principle.

Consider refactoring the code to reduce duplication. One approach is to handle both exceptions together:

except (InvalidTokenError, Exception) as e:
    logger.info(
        'Attachment failed for expense group id %s / workspace id %s Error: %s',
        expense.expense_id, workspace_id, {'error': str(e)}
    )
    credit_card_charge_object.is_attachment_upload_failed = True
    credit_card_charge_object.save()

Also applies to: 163-164

Comment on lines +429 to +430
task_model.is_attachment_upload_failed = True
task_model.save()
Copy link

Choose a reason for hiding this comment

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

Consolidate duplicated exception handling code

The code setting task_model.is_attachment_upload_failed = True and saving it is duplicated in multiple exceptions. This can be refactored to improve maintainability.

You could set the flag once after the exceptions:

try:
    # Existing code
except (NetSuiteRateLimitError, NetSuiteRequestError, NetSuiteLoginError, InvalidTokenError) as exception:
    logger.info('Error while uploading attachments to NetSuite workspace_id - %s %s', workspace_id, exception.__dict__)
    error_occurred = True
except Exception as exception:
    logger.error(
        'Error while uploading attachments to NetSuite workspace_id - %s %s %s',
        workspace_id, exception, traceback.format_exc()
    )
    error_occurred = True

if error_occurred:
    task_model.is_attachment_upload_failed = True
    task_model.save()

Also applies to: 437-438

Comment on lines 381 to 383
task_model = TASK_TYPE_MODEL_MAP[task_log.type]
task_model = task_model.objects.get(expense_group_id=task_log.expense_group_id)

Copy link

Choose a reason for hiding this comment

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

Avoid variable shadowing for better readability

At line 381, task_model is assigned a model class, and then at line 382, it's reassigned to an instance of that model. This shadowing can be confusing.

Consider using distinct variable names:

-task_model = TASK_TYPE_MODEL_MAP[task_log.type]
-task_model = task_model.objects.get(expense_group_id=task_log.expense_group_id)
+task_model_class = TASK_TYPE_MODEL_MAP[task_log.type]
+task_model = task_model_class.objects.get(expense_group_id=task_log.expense_group_id)
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
task_model = TASK_TYPE_MODEL_MAP[task_log.type]
task_model = task_model.objects.get(expense_group_id=task_log.expense_group_id)
task_model_class = TASK_TYPE_MODEL_MAP[task_log.type]
task_model = task_model_class.objects.get(expense_group_id=task_log.expense_group_id)

Comment on lines +53 to +58
TASK_TYPE_MODEL_MAP = {
'CREATING_EXPENSE_REPORT': ExpenseReport,
'CREATING_BILL': Bill,
'CREATING_JOURNAL_ENTRY': JournalEntry
}

Copy link

Choose a reason for hiding this comment

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

Potential KeyError due to missing 'CREATING_CREDIT_CARD_CHARGE' in TASK_TYPE_MODEL_MAP

The TASK_TYPE_MODEL_MAP dictionary does not include the 'CREATING_CREDIT_CARD_CHARGE' key, which is used elsewhere and could lead to a KeyError when task_log.type is 'CREATING_CREDIT_CARD_CHARGE'.

Consider adding the missing key to TASK_TYPE_MODEL_MAP:

 TASK_TYPE_MODEL_MAP = {
     'CREATING_EXPENSE_REPORT': ExpenseReport,
     'CREATING_BILL': Bill,
     'CREATING_JOURNAL_ENTRY': JournalEntry,
+    'CREATING_CREDIT_CARD_CHARGE': CreditCardCharge
 }

Committable suggestion was skipped due to low confidence.

apps/netsuite/tasks.py Outdated Show resolved Hide resolved
apps/netsuite/tasks.py Outdated Show resolved Hide resolved
apps/netsuite/tasks.py Outdated Show resolved Hide resolved
@github-actions github-actions bot added size/M Medium PR and removed size/S Small PR labels Sep 24, 2024
Copy link

Tests Skipped Failures Errors Time
222 0 💤 0 ❌ 0 🔥 24.912s ⏱️

@ruuushhh ruuushhh requested a review from ashwin1111 September 24, 2024 06:57
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: 2

Outside diff range and nitpick comments (1)
tests/test_netsuite/test_tasks.py (1)

827-827: Improve test_load_attachments function

The changes to the test_load_attachments function look good overall. However, there are a few minor improvements we can make:

  1. On line 863-864, we're creating a credit_card_charge_object but not using it immediately. Consider moving this closer to where it's first used.

  2. The assertion on line 888 uses == for comparison with True. It's generally preferred to use is for boolean comparisons.

Here's a suggested refactor for the boolean comparison:

-    assert credit_card_charge_object.is_attachment_upload_failed == True
+    assert credit_card_charge_object.is_attachment_upload_failed is True

Also, consider moving the credit_card_charge_object creation closer to its first usage for better readability.

Also applies to: 863-864, 868-868, 882-882, 887-888

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 952a06a and e94720e.

Files selected for processing (4)
  • apps/netsuite/migrations/0027_auto_20240924_0614.py (1 hunks)
  • apps/netsuite/tasks.py (6 hunks)
  • tests/sql_fixtures/reset_db_fixtures/reset_db.sql (10 hunks)
  • tests/test_netsuite/test_tasks.py (7 hunks)
Files skipped from review as they are similar to previous changes (1)
  • apps/netsuite/tasks.py
Additional context used
Ruff
tests/test_netsuite/test_tasks.py

883-883: Comparison to None should be cond is None

Replace with cond is None

(E711)


888-888: Avoid equality comparisons to True; use if ...: for truth checks

Replace comparison

(E712)

Additional comments not posted (15)
tests/sql_fixtures/reset_db_fixtures/reset_db.sql (11)

228-230: LGTM: New columns added to 'bills' table

The addition of is_attachment_upload_failed (boolean) and receipt_urls (jsonb) columns to the 'bills' table aligns well with the PR objectives. The data types are appropriate, and the NOT NULL constraint on is_attachment_upload_failed ensures data integrity.


399-401: LGTM: Consistent changes applied to 'credit_card_charges' table

The addition of is_attachment_upload_failed (boolean) and receipt_urls (jsonb) columns to the 'credit_card_charges' table is consistent with the changes made to the 'bills' table. This consistency in schema changes across related tables is commendable.


1073-1075: LGTM: Consistent schema changes in 'expense_reports' table

The addition of is_attachment_upload_failed (boolean) and receipt_urls (jsonb) columns to the 'expense_reports' table maintains consistency with the changes made to the 'bills' and 'credit_card_charges' tables. This uniform approach across tables is good for maintaining a coherent database schema.


1529-1531: LGTM: Consistent schema changes maintained across all tables

The addition of is_attachment_upload_failed (boolean) and receipt_urls (jsonb) columns to the 'journal_entries' table completes the consistent application of these changes across all relevant tables (bills, credit_card_charges, expense_reports, and journal_entries). This uniformity in schema modifications is excellent for maintaining a coherent and easily understandable database structure.


2675-2675: LGTM: COPY statement updated for 'bills' table

The COPY statement for the 'bills' table has been correctly updated to include the newly added columns is_attachment_upload_failed and receipt_urls. This ensures that these new fields will be properly handled in any data import or export operations.


2715-2715: LGTM: COPY statement consistently updated for 'credit_card_charges' table

The COPY statement for the 'credit_card_charges' table has been correctly updated to include the newly added columns is_attachment_upload_failed and receipt_urls. This change is consistent with the update made to the 'bills' table COPY statement, maintaining uniformity in data handling across tables.


7987-7987: LGTM: Migration entry added for schema changes

A new migration entry has been added for 'netsuite' with the identifier '0027_auto_20240924_0614'. This entry corresponds to the schema changes made in this PR, and the timestamp in the identifier (20240924) is consistent with the expected timeframe for these modifications. This ensures proper tracking and versioning of the database schema changes.


11621-11621: LGTM: COPY statement consistently updated for 'expense_reports' table

The COPY statement for the 'expense_reports' table has been correctly updated to include the newly added columns is_attachment_upload_failed and receipt_urls. This change maintains consistency with the updates made to the 'bills' and 'credit_card_charges' COPY statements, ensuring uniform data handling across all affected tables.


11672-11672: LGTM: Consistent COPY statement updates across all affected tables

The COPY statement for the 'journal_entries' table has been correctly updated to include the newly added columns is_attachment_upload_failed and receipt_urls. This change completes the consistent update of COPY statements across all affected tables (bills, credit_card_charges, expense_reports, and journal_entries). The uniformity in these changes is commendable and ensures consistent data handling throughout the database.


11899-11899: LGTM: Migration sequence updated correctly

The sequence for 'django_migrations_id_seq' has been properly updated to 198. This update corresponds to the new migration entry (0027_auto_20240924_0614) added earlier and ensures that future migrations will have correct, incremental IDs. This is crucial for maintaining the integrity of the migration history and preventing potential conflicts in future database schema updates.


Line range hint 228-11899: Summary: Comprehensive and consistent schema updates for receipt URL storage and upload failure tracking

This PR implements a set of well-structured and consistent changes across the database schema to support the storage of receipt URLs and tracking of attachment upload failures. Key points:

  1. New columns (is_attachment_upload_failed and receipt_urls) added consistently to bills, credit_card_charges, expense_reports, and journal_entries tables.
  2. COPY statements for all affected tables updated to include the new columns, ensuring proper data handling in import/export operations.
  3. A new migration (0027_auto_20240924_0614) added and the migration sequence updated accordingly.

These changes effectively fulfill the PR objectives while maintaining data integrity and consistency across the schema. The uniform approach to these modifications will facilitate easier maintenance and understanding of the database structure in the future.

apps/netsuite/migrations/0027_auto_20240924_0614.py (2)

1-12: LGTM: Migration structure is correct

The migration file is properly structured with the correct Django version, dependencies, and migration class definition. This follows Django's migration conventions.


1-53: Consider data migration and indexing

While the schema changes look good, there are two additional points to consider:

  1. Data Migration: This migration adds new fields but doesn't include any data migration. Depending on your application logic, you might need to populate these fields with appropriate default values for existing records.

  2. Indexing: If you expect to frequently query on the is_attachment_upload_failed field, consider adding an index to improve query performance.

To help assess the need for these changes, you can run the following commands:

Based on the results, consider if a data migration is necessary and if adding an index would be beneficial.

tests/test_netsuite/test_tasks.py (2)

638-638: LGTM: Added assertion for receipt_urls in CreditCardCharge object

The added assertion checks if the receipt_urls attribute of the CreditCardCharge object is correctly set. This is a good addition to ensure that the attachment URL is properly associated with the credit card charge.


1628-1629: LGTM: Added assertions for receipt_urls in Bill, JournalEntry, and ExpenseReport objects

These additions are good. They ensure that the receipt_urls attribute is correctly set for Bill, JournalEntry, and ExpenseReport objects after the attachment upload process. This helps verify that the attachment URLs are properly associated with their respective objects.

Also applies to: 1666-1667, 1704-1705

Comment on lines +13 to +22
migrations.AddField(
model_name='bill',
name='is_attachment_upload_failed',
field=models.BooleanField(default=False, help_text='Is Attachment Upload Failed'),
),
migrations.AddField(
model_name='bill',
name='receipt_urls',
field=models.JSONField(help_text='Expense Receipt URL Map', null=True),
),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider refining field definitions

While the new fields align with the PR objectives, consider the following suggestions:

  1. The is_attachment_upload_failed field could be more specific. Consider renaming it to has_receipt_upload_failed for clarity.

  2. The receipt_urls field is defined as nullable (null=True). Consider if this is intentional, as it might lead to inconsistencies in data representation. If an empty state is needed, an empty JSON object ({}) might be more appropriate than null.

Here's a suggested improvement for the bill model (apply similar changes to other models):

 migrations.AddField(
     model_name='bill',
-    name='is_attachment_upload_failed',
+    name='has_receipt_upload_failed',
     field=models.BooleanField(default=False, help_text='Is Attachment Upload Failed'),
 ),
 migrations.AddField(
     model_name='bill',
     name='receipt_urls',
-    field=models.JSONField(help_text='Expense Receipt URL Map', null=True),
+    field=models.JSONField(help_text='Expense Receipt URL Map', default=dict),
 ),

Also applies to: 23-32, 33-42, 43-52

Comment on lines +13 to +52
migrations.AddField(
model_name='bill',
name='is_attachment_upload_failed',
field=models.BooleanField(default=False, help_text='Is Attachment Upload Failed'),
),
migrations.AddField(
model_name='bill',
name='receipt_urls',
field=models.JSONField(help_text='Expense Receipt URL Map', null=True),
),
migrations.AddField(
model_name='creditcardcharge',
name='is_attachment_upload_failed',
field=models.BooleanField(default=False, help_text='Is Attachment Upload Failed'),
),
migrations.AddField(
model_name='creditcardcharge',
name='receipt_urls',
field=models.JSONField(help_text='Expense Receipt URL Map', null=True),
),
migrations.AddField(
model_name='expensereport',
name='is_attachment_upload_failed',
field=models.BooleanField(default=False, help_text='Is Attachment Upload Failed'),
),
migrations.AddField(
model_name='expensereport',
name='receipt_urls',
field=models.JSONField(help_text='Expense Receipt URL Map', null=True),
),
migrations.AddField(
model_name='journalentry',
name='is_attachment_upload_failed',
field=models.BooleanField(default=False, help_text='Is Attachment Upload Failed'),
),
migrations.AddField(
model_name='journalentry',
name='receipt_urls',
field=models.JSONField(help_text='Expense Receipt URL Map', null=True),
),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider optimizing for code reuse

The changes are consistent across all four models ('bill', 'creditcardcharge', 'expensereport', and 'journalentry'), which is good for maintainability. However, this repetition might indicate an opportunity for a more DRY (Don't Repeat Yourself) approach.

Consider creating a mixin or abstract base class that includes these fields, and then inherit from it in your models. This would centralize the field definitions and make future changes easier. For example:

from django.db import models

class ReceiptTrackingMixin(models.Model):
    has_receipt_upload_failed = models.BooleanField(default=False, help_text='Is Attachment Upload Failed')
    receipt_urls = models.JSONField(help_text='Expense Receipt URL Map', default=dict)

    class Meta:
        abstract = True

# In your models.py
class Bill(ReceiptTrackingMixin, models.Model):
    # other fields...

class CreditCardCharge(ReceiptTrackingMixin, models.Model):
    # other fields...

# Apply to other models similarly

This approach would require modifying your models and creating a new migration, but it could simplify future changes and maintain consistency.

@ruuushhh ruuushhh closed this Sep 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/M Medium PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants