diff --git a/erpnext/loan_management/doctype/loan_balance_adjustment/__init__.py b/erpnext/loan_management/doctype/loan_balance_adjustment/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.js b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.js new file mode 100644 index 0000000000..8aec63ad75 --- /dev/null +++ b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.js @@ -0,0 +1,8 @@ +// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Loan Balance Adjustment', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.json b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.json new file mode 100644 index 0000000000..5fb25defce --- /dev/null +++ b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.json @@ -0,0 +1,190 @@ +{ + "actions": [], + "autoname": "LM-ADJ-.#####", + "creation": "2022-06-28 14:48:47.736269", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "loan", + "applicant_type", + "applicant", + "column_break_3", + "company", + "posting_date", + "accounting_dimensions_section", + "cost_center", + "section_break_9", + "adjustment_account", + "column_break_11", + "adjustment_type", + "amount", + "reference_number", + "remarks", + "amended_from" + ], + "fields": [ + { + "fieldname": "loan", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Loan", + "options": "Loan", + "reqd": 1 + }, + { + "fetch_from": "loan.applicant_type", + "fieldname": "applicant_type", + "fieldtype": "Select", + "label": "Applicant Type", + "options": "Employee\nMember\nCustomer", + "read_only": 1 + }, + { + "fetch_from": "loan.applicant", + "fieldname": "applicant", + "fieldtype": "Dynamic Link", + "label": "Applicant ", + "options": "applicant_type", + "read_only": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fetch_from": "loan.company", + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "read_only": 1, + "reqd": 1 + }, + { + "default": "Today", + "fieldname": "posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Posting Date", + "reqd": 1 + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center" + }, + { + "fieldname": "section_break_9", + "fieldtype": "Section Break", + "label": "Adjustment Details" + }, + { + "fieldname": "column_break_11", + "fieldtype": "Column Break" + }, + { + "fieldname": "reference_number", + "fieldtype": "Data", + "label": "Reference Number" + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Loan Balance Adjustment", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Loan Balance Adjustment", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "adjustment_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Adjustment Account", + "options": "Account", + "reqd": 1 + }, + { + "fieldname": "amount", + "fieldtype": "Currency", + "label": "Amount", + "options": "Company:company:default_currency", + "reqd": 1 + }, + { + "fieldname": "adjustment_type", + "fieldtype": "Select", + "label": "Adjustment Type", + "options": "Credit Adjustment\nDebit Adjustment", + "reqd": 1 + }, + { + "fieldname": "remarks", + "fieldtype": "Data", + "label": "Remarks" + } + ], + "index_web_pages_for_search": 1, + "is_submittable": 1, + "links": [], + "modified": "2022-06-28 14:54:52.792592", + "modified_by": "Administrator", + "module": "Loan Management", + "name": "Loan Balance Adjustment", + "naming_rule": "Expression (old style)", + "owner": "Administrator", + "permissions": [ + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Loan Manager", + "share": 1, + "submit": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py new file mode 100644 index 0000000000..8f98ce64d8 --- /dev/null +++ b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py @@ -0,0 +1,132 @@ +# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class LoanBalanceAdjustment(Document): + """ + Add credit/debit adjustments to loan ledger. + """ + def validate(self): + self.set_missing_values() + + def on_submit(self): + self.set_status_and_amounts() + self.make_gl_entries() + + def on_cancel(self): + self.set_status_and_amounts(cancel=1) + self.make_gl_entries(cancel=1) + self.ignore_linked_doctypes = ["GL Entry"] + + def set_missing_values(self): + if not self.posting_date: + self.posting_date = nowdate() + + if not self.cost_center: + self.cost_center = erpnext.get_default_cost_center(self.company) + + if not self.posting_date: + self.posting_date = self.posting_date or nowdate() + + def set_status_and_amounts(self, cancel=0): + loan_details = frappe.get_all( + "Loan", + fields=[ + "loan_amount", + "disbursed_amount", + "total_payment", + "total_principal_paid", + "total_interest_payable", + "status", + "is_term_loan", + "is_secured_loan", + ], + filters={"name": self.against_loan}, + )[0] + + if cancel: + disbursed_amount = self.get_values_on_cancel(loan_details) + else: + disbursed_amount = self.get_values_on_submit(loan_details) + + frappe.db.set_value( + "Loan", + self.against_loan, + { + "disbursed_amount": disbursed_amount, + }, + ) + + def get_values_on_cancel(self, loan_details): + if self.adjustment_type == "Credit Adjustment": + disbursed_amount = loan_details.disbursed_amount - self.amount + elif self.adjustment_type == "Debit Adjustment": + disbursed_amount = loan_details.disbursed_amount + self.amount + + return disbursed_amount + + def get_values_on_submit(self, loan_details): + if self.adjustment_type == "Credit": + disbursed_amount = loan_details.disbursed_amount + self.amount + elif self.adjustment_type == "Debit": + disbursed_amount = loan_details.disbursed_amount - self.amount + + total_payment = loan_details.total_payment + + if loan_details.status in ("Disbursed", "Partially Disbursed") and not loan_details.is_term_loan: + process_loan_interest_accrual_for_demand_loans( + posting_date=add_days(self.posting_date, -1), + loan=self.against_loan, + accrual_type=self.adjustment_type, + ) + + return disbursed_amount + + def make_gl_entries(self, cancel=0, adv_adj=0): + gle_map = [] + + loan_entry = { + "account": self.loan_account, + "against": self.adjustment_account, + "against_voucher_type": "Loan", + "against_voucher": self.against_loan, + "remarks": _("{} against loan:".format(self.adjustment_type)) \ + + self.against_loan, + "cost_center": self.cost_center, + "party_type": self.applicant_type, + "party": self.applicant, + "posting_date": self.posting_date, + } + company_entry = { + "account": self.adjustment_account, + "against": self.loan_account, + "against_voucher_type": "Loan", + "against_voucher": self.against_loan, + "remarks": _("{} against loan:".format(self.adjustment_type)) \ + + self.against_loan, + "cost_center": self.cost_center, + "posting_date": self.posting_date, + } + if self.adjustment_type == "Credit Adjustment": + loan_entry["credit"] = self.amount + loan_entry["credit_in_account_currency"] = self.amount + + company_entry["debit"] = self.amount + company_entry["debit_in_account_currency"] = self.amount + + elif self.adjustment_type == "Debit Adjustment": + loan_entry["debit"] = self.amount + loan_entry["debit_in_account_currency"] = self.amount + + company_entry["credit"] = self.amount + company_entry["credit_in_account_currency"] = self.amount + + + gle_map.append(self.get_gl_dict(loan_entry)) + + gle_map.append(self.get_gl_dict(company_entry)) + + if gle_map: + make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj) diff --git a/erpnext/loan_management/doctype/loan_balance_adjustment/test_loan_balance_adjustment.py b/erpnext/loan_management/doctype/loan_balance_adjustment/test_loan_balance_adjustment.py new file mode 100644 index 0000000000..7658d7b215 --- /dev/null +++ b/erpnext/loan_management/doctype/loan_balance_adjustment/test_loan_balance_adjustment.py @@ -0,0 +1,9 @@ +# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestLoanBalanceAdjustment(FrappeTestCase): + pass