Skip to content

Commit

Permalink
feat: Single credit line for Journal Entry (#655)
Browse files Browse the repository at this point in the history
* feat: Single credit line for Journal Entry

* test: add tests for single credit line <> JE (#656)

* test: add tests for single credit line <> JE

* test: add tests

* API fix

* fix memo

* dummy
  • Loading branch information
ashwin1111 authored Oct 16, 2024
1 parent 5e23d08 commit 054b3c1
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 22 deletions.
2 changes: 1 addition & 1 deletion apps/fyle/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def get_task_log_and_fund_source(workspace_id: int):

configuration = Configuration.objects.get(workspace_id=workspace_id)
fund_source = []

if configuration.reimbursable_expenses_object:
fund_source.append('PERSONAL')
if configuration.corporate_credit_card_expenses_object:
Expand Down
96 changes: 91 additions & 5 deletions apps/netsuite/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
'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:
"""
Create a journal entry report
:return: constructed journal entry
Expand All @@ -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={},
Expand Down Expand Up @@ -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))

Expand All @@ -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)

Expand Down
2 changes: 0 additions & 2 deletions apps/netsuite/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1134,8 +1134,6 @@ def create_journal_entry_lineitems(expense_group: ExpenseGroup, configuration: C
configuration = Configuration.objects.get(workspace_id=expense_group.workspace_id)
employee_field_mapping = configuration.employee_field_mapping

debit_account_id = None

journal_entry_lineitem_objects = []

for lineitem in expenses:
Expand Down
2 changes: 1 addition & 1 deletion apps/netsuite/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
worker_logger.info('Created Journal Entry with Expense Group %s successfully', expense_group.id)

Expand Down
6 changes: 4 additions & 2 deletions apps/workspaces/apis/advanced_settings/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class Meta:
'sync_netsuite_to_fyle_payments',
'auto_create_destination_entity',
'auto_create_merchants',
'memo_structure'
'memo_structure',
'je_single_credit_line'
]


Expand Down Expand Up @@ -153,7 +154,8 @@ def update(self, instance, validated):
'auto_create_destination_entity': configurations.get('auto_create_destination_entity'),
'auto_create_merchants': configurations.get('auto_create_merchants'),
'change_accounting_period': configurations.get('change_accounting_period'),
'memo_structure': configurations.get('memo_structure')
'memo_structure': configurations.get('memo_structure'),
'je_single_credit_line': configurations.get('je_single_credit_line')
}
)

Expand Down
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'),
),
]
1 change: 1 addition & 0 deletions apps/workspaces/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')

class Meta:
db_table = 'configurations'
Expand Down
14 changes: 8 additions & 6 deletions tests/sql_fixtures/reset_db_fixtures/reset_db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ CREATE TABLE public.configurations (
is_simplify_report_closure_enabled boolean NOT NULL,
import_items boolean NOT NULL,
name_in_journal_entry character varying(100) NOT NULL,
allow_intercompany_vendors boolean NOT NULL
allow_intercompany_vendors boolean NOT NULL,
je_single_credit_line boolean NOT NULL
);


Expand Down Expand Up @@ -2691,10 +2692,10 @@ COPY public.category_mappings (id, created_at, updated_at, destination_account_i
-- Data for Name: configurations; Type: TABLE DATA; Schema: public; Owner: postgres
--

COPY public.configurations (id, reimbursable_expenses_object, corporate_credit_card_expenses_object, created_at, updated_at, workspace_id, sync_fyle_to_netsuite_payments, sync_netsuite_to_fyle_payments, import_projects, auto_map_employees, import_categories, auto_create_destination_entity, auto_create_merchants, employee_field_mapping, import_tax_items, change_accounting_period, memo_structure, map_fyle_cards_netsuite_account, skip_cards_mapping, import_vendors_as_merchants, import_netsuite_employees, is_simplify_report_closure_enabled, import_items, name_in_journal_entry, allow_intercompany_vendors) FROM stdin;
1 EXPENSE REPORT BILL 2021-11-15 08:56:07.193743+00 2021-11-15 08:56:07.193795+00 1 f f f \N f f f EMPLOYEE f f {employee_email,category,spent_on,report_number,purpose} t f f f f f MERCHANT f
2 JOURNAL ENTRY CREDIT CARD CHARGE 2021-11-16 04:18:15.836271+00 2021-11-16 04:20:09.969589+00 2 f f f \N f f f EMPLOYEE t f {employee_email,category,spent_on,report_number,purpose} t f f f f f MERCHANT f
3 JOURNAL ENTRY CREDIT CARD CHARGE 2021-12-03 11:04:00.194287+00 2021-12-03 11:04:00.1943+00 49 f f f \N f f f EMPLOYEE f f {employee_email,category,spent_on,report_number,purpose} t f f f f f MERCHANT f
COPY public.configurations (id, reimbursable_expenses_object, corporate_credit_card_expenses_object, created_at, updated_at, workspace_id, sync_fyle_to_netsuite_payments, sync_netsuite_to_fyle_payments, import_projects, auto_map_employees, import_categories, auto_create_destination_entity, auto_create_merchants, employee_field_mapping, import_tax_items, change_accounting_period, memo_structure, map_fyle_cards_netsuite_account, skip_cards_mapping, import_vendors_as_merchants, import_netsuite_employees, is_simplify_report_closure_enabled, import_items, name_in_journal_entry, allow_intercompany_vendors, je_single_credit_line) FROM stdin;
1 EXPENSE REPORT BILL 2021-11-15 08:56:07.193743+00 2021-11-15 08:56:07.193795+00 1 f f f \N f f f EMPLOYEE f f {employee_email,category,spent_on,report_number,purpose} t f f f f f MERCHANT f f
2 JOURNAL ENTRY CREDIT CARD CHARGE 2021-11-16 04:18:15.836271+00 2021-11-16 04:20:09.969589+00 2 f f f \N f f f EMPLOYEE t f {employee_email,category,spent_on,report_number,purpose} t f f f f f MERCHANT f f
3 JOURNAL ENTRY CREDIT CARD CHARGE 2021-12-03 11:04:00.194287+00 2021-12-03 11:04:00.1943+00 49 f f f \N f f f EMPLOYEE f f {employee_email,category,spent_on,report_number,purpose} t f f f f f MERCHANT f f
\.


Expand Down Expand Up @@ -7984,6 +7985,7 @@ COPY public.django_migrations (id, app, name, applied) FROM stdin;
197 netsuite 0026_auto_20240902_1650 2024-09-02 16:50:55.770274+00
198 netsuite 0027_auto_20240924_0820 2024-09-24 08:24:35.223017+00
199 fyle_accounting_mappings 0026_destinationattribute_code 2024-10-01 08:54:06.770864+00
200 workspaces 0039_configuration_je_single_credit_line 2024-10-11 13:43:49.169823+00
\.


Expand Down Expand Up @@ -11895,7 +11897,7 @@ SELECT pg_catalog.setval('public.django_content_type_id_seq', 47, true);
-- Name: django_migrations_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
--

SELECT pg_catalog.setval('public.django_migrations_id_seq', 199, true);
SELECT pg_catalog.setval('public.django_migrations_id_seq', 200, true);


--
Expand Down
58 changes: 57 additions & 1 deletion tests/test_netsuite/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'},
Expand Down
Loading

0 comments on commit 054b3c1

Please sign in to comment.