-
Notifications
You must be signed in to change notification settings - Fork 3
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: Single credit line for Journal Entry #655
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2085,8 +2085,90 @@ def construct_journal_entry_lineitems(self, journal_entry_lineitems: List[Journa | |||||||||||||||||||
|
||||||||||||||||||||
return lines | ||||||||||||||||||||
|
||||||||||||||||||||
@staticmethod | ||||||||||||||||||||
def __construct_single_itemized_credit_line(journal_entry_lineitems: List[JournalEntryLineItem]): | ||||||||||||||||||||
""" | ||||||||||||||||||||
Create journal entry line items for single credit line | ||||||||||||||||||||
:return: constructed line items | ||||||||||||||||||||
""" | ||||||||||||||||||||
lines = [] | ||||||||||||||||||||
distinct_line_ids = {} | ||||||||||||||||||||
|
||||||||||||||||||||
for line in journal_entry_lineitems: | ||||||||||||||||||||
account_ref = line.debit_account_id | ||||||||||||||||||||
entity_id = line.entity_id | ||||||||||||||||||||
line_id = '{account_ref}::::{entity_id}'.format(account_ref=account_ref, entity_id=entity_id) | ||||||||||||||||||||
|
||||||||||||||||||||
if line_id in distinct_line_ids: | ||||||||||||||||||||
distinct_line_ids[line_id] += line.amount | ||||||||||||||||||||
else: | ||||||||||||||||||||
distinct_line_ids[line_id] = line.amount | ||||||||||||||||||||
|
||||||||||||||||||||
for line_id, amount in distinct_line_ids.items(): | ||||||||||||||||||||
account_ref, entity_id = line_id.split('::::') | ||||||||||||||||||||
lineitem = { | ||||||||||||||||||||
'account': { | ||||||||||||||||||||
'name': None, | ||||||||||||||||||||
Comment on lines
+2107
to
+2111
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Unpack Tuple Keys Without String Splitting Since tuples are used as keys, updating the unpacking logic improves clarity and efficiency by avoiding string manipulation. Apply this diff to refactor the code: - for line_id, amount in distinct_line_ids.items():
- account_ref, entity_id = line_id.split('::::')
+ for (account_ref, entity_id), amount in distinct_line_ids.items(): 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||
'internalId': account_ref, | ||||||||||||||||||||
'externalId': None, | ||||||||||||||||||||
'type': 'account' | ||||||||||||||||||||
}, | ||||||||||||||||||||
'department': { | ||||||||||||||||||||
'name': None, | ||||||||||||||||||||
'internalId': None, | ||||||||||||||||||||
'externalId': None, | ||||||||||||||||||||
'type': 'department' | ||||||||||||||||||||
}, | ||||||||||||||||||||
'location': { | ||||||||||||||||||||
'name': None, | ||||||||||||||||||||
'internalId': None, | ||||||||||||||||||||
'externalId': None, | ||||||||||||||||||||
'type': 'location' | ||||||||||||||||||||
}, | ||||||||||||||||||||
'class': { | ||||||||||||||||||||
'name': None, | ||||||||||||||||||||
'internalId': None, | ||||||||||||||||||||
'externalId': None, | ||||||||||||||||||||
'type': 'classification' | ||||||||||||||||||||
}, | ||||||||||||||||||||
'entity': { | ||||||||||||||||||||
'name': None, | ||||||||||||||||||||
'internalId': entity_id, | ||||||||||||||||||||
'externalId': None, | ||||||||||||||||||||
'type': 'vendor' | ||||||||||||||||||||
}, | ||||||||||||||||||||
'credit': amount, | ||||||||||||||||||||
'creditTax': None, | ||||||||||||||||||||
'customFieldList': [], | ||||||||||||||||||||
'debit': None, | ||||||||||||||||||||
'debitTax': None, | ||||||||||||||||||||
'eliminate': None, | ||||||||||||||||||||
'endDate': None, | ||||||||||||||||||||
'grossAmt': None, | ||||||||||||||||||||
'line': None, | ||||||||||||||||||||
'lineTaxCode': None, | ||||||||||||||||||||
'lineTaxRate': None, | ||||||||||||||||||||
'memo': 'Total Amount', | ||||||||||||||||||||
'residual': None, | ||||||||||||||||||||
'revenueRecognitionRule': None, | ||||||||||||||||||||
'schedule': None, | ||||||||||||||||||||
'scheduleNum': None, | ||||||||||||||||||||
'startDate': None, | ||||||||||||||||||||
'tax1Acct': None, | ||||||||||||||||||||
'taxAccount': None, | ||||||||||||||||||||
'taxBasis': None, | ||||||||||||||||||||
'tax1Amt': None, | ||||||||||||||||||||
'taxCode': None, | ||||||||||||||||||||
'taxRate1': None, | ||||||||||||||||||||
'totalAmount': None, | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
lines.append(lineitem) | ||||||||||||||||||||
|
||||||||||||||||||||
return lines | ||||||||||||||||||||
|
||||||||||||||||||||
def __construct_journal_entry(self, journal_entry: JournalEntry, | ||||||||||||||||||||
journal_entry_lineitems: List[JournalEntryLineItem]) -> Dict: | ||||||||||||||||||||
journal_entry_lineitems: List[JournalEntryLineItem], configuration: Configuration) -> Dict: | ||||||||||||||||||||
ruuushhh marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||
""" | ||||||||||||||||||||
Create a journal entry report | ||||||||||||||||||||
:return: constructed journal entry | ||||||||||||||||||||
|
@@ -2096,7 +2178,11 @@ def __construct_journal_entry(self, journal_entry: JournalEntry, | |||||||||||||||||||
cluster_domain = fyle_credentials.cluster_domain | ||||||||||||||||||||
org_id = Workspace.objects.get(id=journal_entry.expense_group.workspace_id).fyle_org_id | ||||||||||||||||||||
|
||||||||||||||||||||
credit_line = self.construct_journal_entry_lineitems(journal_entry_lineitems, credit='Credit', org_id=org_id) | ||||||||||||||||||||
if configuration.je_single_credit_line: | ||||||||||||||||||||
credit_line = self.__construct_single_itemized_credit_line(journal_entry_lineitems) | ||||||||||||||||||||
else: | ||||||||||||||||||||
credit_line = self.construct_journal_entry_lineitems(journal_entry_lineitems, credit='Credit', org_id=org_id) | ||||||||||||||||||||
|
||||||||||||||||||||
debit_line = self.construct_journal_entry_lineitems( | ||||||||||||||||||||
journal_entry_lineitems, | ||||||||||||||||||||
debit='Debit', attachment_links={}, | ||||||||||||||||||||
|
@@ -2166,13 +2252,13 @@ def __construct_journal_entry(self, journal_entry: JournalEntry, | |||||||||||||||||||
return journal_entry_payload | ||||||||||||||||||||
|
||||||||||||||||||||
def post_journal_entry(self, journal_entry: JournalEntry, | ||||||||||||||||||||
journal_entry_lineitems: List[JournalEntryLineItem]): | ||||||||||||||||||||
journal_entry_lineitems: List[JournalEntryLineItem], configuration: Configuration): | ||||||||||||||||||||
""" | ||||||||||||||||||||
Post journal entries to NetSuite | ||||||||||||||||||||
""" | ||||||||||||||||||||
configuration = Configuration.objects.get(workspace_id=self.workspace_id) | ||||||||||||||||||||
try: | ||||||||||||||||||||
journal_entry_payload = self.__construct_journal_entry(journal_entry, journal_entry_lineitems) | ||||||||||||||||||||
journal_entry_payload = self.__construct_journal_entry(journal_entry, journal_entry_lineitems, configuration) | ||||||||||||||||||||
|
||||||||||||||||||||
logger.info("| Payload for Journal Entry creation | Content: {{WORKSPACE_ID: {} EXPENSE_GROUP_ID: {} JOURNAL_ENTRY_PAYLOAD: {}}}".format(self.workspace_id, journal_entry.expense_group.id, journal_entry_payload)) | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -2186,7 +2272,7 @@ def post_journal_entry(self, journal_entry: JournalEntry, | |||||||||||||||||||
|
||||||||||||||||||||
if configuration.change_accounting_period and detail['message'] == message: | ||||||||||||||||||||
first_day_of_month = datetime.today().date().replace(day=1) | ||||||||||||||||||||
journal_entry_payload = self.__construct_journal_entry(journal_entry, journal_entry_lineitems) | ||||||||||||||||||||
journal_entry_payload = self.__construct_journal_entry(journal_entry, journal_entry_lineitems, configuration) | ||||||||||||||||||||
journal_entry_payload['tranDate'] = first_day_of_month | ||||||||||||||||||||
created_journal_entry = self.connection.journal_entries.post(journal_entry_payload) | ||||||||||||||||||||
|
||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -698,7 +698,7 @@ def create_journal_entry(expense_group, task_log_id, last_export): | |
) | ||
|
||
created_journal_entry = netsuite_connection.post_journal_entry( | ||
journal_entry_object, journal_entry_lineitems_objects | ||
journal_entry_object, journal_entry_lineitems_objects, configuration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Inconsistent Use of The
🔗 Analysis chainVerify the impact of the new The To ensure this change doesn't break existing functionality and is properly implemented throughout the codebase, please run the following checks: 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check if the configuration parameter is properly passed in all calls to create_journal_entry
rg "create_journal_entry\(" --type py
# Verify if the post_journal_entry method in the NetSuiteConnector class accepts the new configuration parameter
rg "def post_journal_entry" --type py
# Check for any tests that need to be updated due to this change
rg "test.*create_journal_entry" --type py
Length of output: 1868 |
||
) | ||
worker_logger.info('Created Journal Entry with Expense Group %s successfully', expense_group.id) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 3.2.14 on 2024-10-09 12:10 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('workspaces', '0038_configuration_allow_intercompany_vendors'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='configuration', | ||
name='je_single_credit_line', | ||
field=models.BooleanField(default=False, help_text='Journal Entry Single Credit Line'), | ||
), | ||
] | ||
Comment on lines
+12
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding an explicit reverse migration. While Django automatically handles reverse migrations for field additions, it's a good practice to explicitly define them for clarity and to ensure proper rollback functionality. Consider updating the operations = [
migrations.AddField(
model_name='configuration',
name='je_single_credit_line',
field=models.BooleanField(default=False, help_text='Enable single credit line for journal entries instead of multiple lines'),
),
]
# Add this method to the Migration class
def reverse_migration(apps, schema_editor):
Configuration = apps.get_model('workspaces', 'Configuration')
Configuration.objects.all().update(je_single_credit_line=False)
operations.append(migrations.RunPython(migrations.noop, reverse_migration)) This ensures that if the migration needs to be reversed, the field will be properly removed and any data cleaned up. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -180,6 +180,7 @@ class Configuration(models.Model): | |
updated_at = models.DateTimeField(auto_now=True, help_text='Updated at') | ||
name_in_journal_entry = models.CharField(max_length=100, help_text='Name in jounral entry for ccc expense only', default='MERCHANT',choices=NAME_IN_JOURNAL_ENTRY) | ||
allow_intercompany_vendors = models.BooleanField(default=False, help_text='Allow intercompany vendors') | ||
je_single_credit_line = models.BooleanField(default=False, help_text='Journal Entry Single Credit Line') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Update all affected files to handle the new The addition of the
Ensure that each of these files properly references and handles the new 🔗 Analysis chainVerify related code for consistency with the new field. While the addition of the Please run the following script to identify areas of the codebase that might need updates: Review the output and update any relevant code to handle the new 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Find potential areas that might need updates due to the new je_single_credit_line field.
# Search for uses of the Configuration model
echo "Files referencing the Configuration model:"
rg "from .+models import .+Configuration" --type python
# Search for journal entry creation or processing
echo "\nFiles potentially involved in journal entry processing:"
rg "journal.+entr(y|ies)" --type python
# Search for existing uses of configuration fields related to journal entries
echo "\nExisting uses of configuration fields for journal entries:"
rg "configuration\..+journal" --type python
Length of output: 589 Script: #!/bin/bash
# Description: Find potential areas that might need updates due to the new je_single_credit_line field.
# Search for uses of the Configuration model
echo "Files referencing the Configuration model:"
rg "from .+models import .+Configuration" --type py
# Search for journal entry creation or processing
echo "\nFiles potentially involved in journal entry processing:"
rg "journal.+entr(y|ies)" --type py
# Search for existing uses of configuration fields related to journal entries
echo "\nExisting uses of configuration fields for journal entries:"
rg "configuration\..+journal" --type py
Length of output: 18413 |
||
|
||
class Meta: | ||
db_table = 'configurations' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1053,8 +1053,64 @@ | |
'tranDate': '2021-12-08T10:33:44', | ||
'tranId': None, | ||
'externalId': 'journal 47 - [email protected]', | ||
} | ||
}, | ||
], | ||
'journal_entry_clubbed_lines': [{ | ||
'account': { | ||
'name': None, | ||
'internalId': '228', | ||
'externalId': None, | ||
'type': 'account', | ||
}, | ||
'department': { | ||
'name': None, | ||
'internalId': None, | ||
'externalId': None, | ||
'type': 'department', | ||
}, | ||
'location': { | ||
'name': None, | ||
'internalId': None, | ||
'externalId': None, | ||
'type': 'location', | ||
}, | ||
'class': { | ||
'name': None, | ||
'internalId': None, | ||
'externalId': None, | ||
'type': 'classification', | ||
}, | ||
'entity': { | ||
'name': None, | ||
'internalId': '10491', | ||
'externalId': None, | ||
'type': 'vendor', | ||
}, | ||
'credit': 120.0, | ||
'creditTax': None, | ||
'customFieldList': [], | ||
'debit': None, | ||
'debitTax': None, | ||
'eliminate': None, | ||
'endDate': None, | ||
'grossAmt': None, | ||
'line': None, | ||
'lineTaxCode': None, | ||
'lineTaxRate': None, | ||
'memo': 'Total Amount', | ||
'residual': None, | ||
'revenueRecognitionRule': None, | ||
'schedule': None, | ||
'scheduleNum': None, | ||
'startDate': None, | ||
'tax1Acct': None, | ||
'taxAccount': None, | ||
'taxBasis': None, | ||
'tax1Amt': None, | ||
'taxCode': None, | ||
'taxRate1': None, | ||
'totalAmount': None, | ||
}], | ||
'credit_card_charge': [ | ||
{ | ||
'account': {'internalId': '228'}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Tuples Instead of String Concatenation for Dictionary Keys
Using string concatenation with separators for dictionary keys can lead to potential issues if the
account_ref
orentity_id
contain the separator string'::::'
. Consider using tuples as dictionary keys to avoid this problem.Apply this diff to fix the issue: