From c2817bed0b640b5a804af8ccc9faac5f2fd204b1 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 30 Sep 2022 10:13:17 +0530 Subject: [PATCH 01/23] feat: Repayment schedule types for term loans (cherry picked from commit 76c6ccab5d0d518cfc8aacddb72f13f995e8922e) # Conflicts: # erpnext/loan_management/doctype/loan/loan.json # erpnext/loan_management/doctype/loan/loan.py --- .../loan_management/doctype/loan/loan.json | 4 + erpnext/loan_management/doctype/loan/loan.py | 88 +++++++++++++++---- .../doctype/loan_type/loan_type.json | 11 ++- .../quick_stock_balance.py | 1 + 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index 76870aeee89..aa8ab022188 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -424,7 +424,11 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2022-09-13 02:05:25.017190", +======= + "modified": "2022-09-29 11:50:31.957360", +>>>>>>> 76c6ccab5d (feat: Repayment schedule types for term loans) "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index 540330b42b3..ecadd4ac31e 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -7,8 +7,22 @@ import math import frappe from frappe import _ +<<<<<<< HEAD from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate from six import string_types +======= +from frappe.utils import ( + add_days, + add_months, + date_diff, + flt, + get_first_day, + get_last_day, + getdate, + now_datetime, + nowdate, +) +>>>>>>> 76c6ccab5d (feat: Repayment schedule types for term loans) import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry @@ -115,30 +129,66 @@ class Loan(AccountsController): if not self.repayment_start_date: frappe.throw(_("Repayment Start Date is mandatory for term loans")) + schedule_type = frappe.db.get_value("Loan Type", self.loan_type, "repayment_schedule_type") self.repayment_schedule = [] payment_date = self.repayment_start_date balance_amount = self.loan_amount - while balance_amount > 0: - interest_amount = flt(balance_amount * flt(self.rate_of_interest) / (12 * 100)) - principal_amount = self.monthly_repayment_amount - interest_amount - balance_amount = flt(balance_amount + interest_amount - self.monthly_repayment_amount) - if balance_amount < 0: - principal_amount += balance_amount - balance_amount = 0.0 - total_payment = principal_amount + interest_amount - self.append( - "repayment_schedule", - { - "payment_date": payment_date, - "principal_amount": principal_amount, - "interest_amount": interest_amount, - "total_payment": total_payment, - "balance_loan_amount": balance_amount, - }, + while balance_amount > 0: + interest_amount, principal_amount, balance_amount, total_payment = self.get_amounts( + payment_date, balance_amount, schedule_type ) - next_payment_date = add_single_month(payment_date) - payment_date = next_payment_date + + if schedule_type == "Pro-rated calendar months": + next_payment_date = add_days(get_last_day(payment_date), 1) + payment_date = next_payment_date + + self.add_repayment_schedule_row( + payment_date, principal_amount, interest_amount, total_payment, balance_amount + ) + + if schedule_type == "Monthly as per repayment start date": + next_payment_date = add_single_month(payment_date) + payment_date = next_payment_date + + def get_amounts(self, payment_date, balance_amount, schedule_type): + first_day_of_month = get_first_day(payment_date) + + if schedule_type == "Monthly as per repayment start date": + days = 1 + months = 12 + else: + if first_day_of_month == payment_date: + days = 30 + months = 365 + else: + days = date_diff(get_last_day(payment_date), payment_date) + months = 365 + + interest_amount = flt(balance_amount * flt(self.rate_of_interest) * days / (months * 100)) + principal_amount = self.monthly_repayment_amount - interest_amount + balance_amount = flt(balance_amount + interest_amount - self.monthly_repayment_amount) + if balance_amount < 0: + principal_amount += balance_amount + balance_amount = 0.0 + + total_payment = principal_amount + interest_amount + + return interest_amount, principal_amount, balance_amount, total_payment + + def add_repayment_schedule_row( + self, payment_date, principal_amount, interest_amount, total_payment, balance_loan_amount + ): + self.append( + "repayment_schedule", + { + "payment_date": payment_date, + "principal_amount": principal_amount, + "interest_amount": interest_amount, + "total_payment": total_payment, + "balance_loan_amount": balance_loan_amount, + }, + ) def set_repayment_period(self): if self.repayment_method == "Repay Fixed Amount per Period": diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json index 00337e4b4c3..e1ed3caf8f4 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type.json +++ b/erpnext/loan_management/doctype/loan_type/loan_type.json @@ -16,6 +16,7 @@ "company", "is_term_loan", "disabled", + "repayment_schedule_type", "description", "account_details_section", "mode_of_payment", @@ -157,12 +158,20 @@ "label": "Disbursement Account", "options": "Account", "reqd": 1 + }, + { + "depends_on": "is_term_loan", + "fieldname": "repayment_schedule_type", + "fieldtype": "Select", + "label": "Repayment Schedule Type", + "mandatory_depends_on": "is_term_loan", + "options": "\nMonthly as per repayment start date\nPro-rated calendar months" } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-01-25 16:23:57.009349", + "modified": "2022-09-28 21:31:01.278941", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Type", diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py index 846be0b9bdc..403d8746895 100644 --- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py +++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py @@ -15,6 +15,7 @@ class QuickStockBalance(Document): @frappe.whitelist() def get_stock_item_details(warehouse, date, item=None, barcode=None): + print(warehouse, date, item, "########") out = {} if barcode: out["item"] = frappe.db.get_value( From 71b21086b1d249551b4f551c97fd3c64725239e9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 30 Sep 2022 10:19:58 +0530 Subject: [PATCH 02/23] chore: Remove print statements (cherry picked from commit 3466461eb3ec97394a5d1e29f0a5ae1df5987042) --- erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py index 403d8746895..846be0b9bdc 100644 --- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py +++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py @@ -15,7 +15,6 @@ class QuickStockBalance(Document): @frappe.whitelist() def get_stock_item_details(warehouse, date, item=None, barcode=None): - print(warehouse, date, item, "########") out = {} if barcode: out["item"] = frappe.db.get_value( From 3f02059085426fdb72d47df796374e20b0a4c942 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 30 Sep 2022 10:39:45 +0530 Subject: [PATCH 03/23] chore: Update labels as per repayment type (cherry picked from commit 2ddee50f27277fa951a2b236b513f377afdc611a) # Conflicts: # erpnext/loan_management/doctype/loan/loan.json --- erpnext/loan_management/doctype/loan/loan.js | 8 ++++++++ erpnext/loan_management/doctype/loan/loan.json | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js index 38328e69674..c386ce3ac07 100644 --- a/erpnext/loan_management/doctype/loan/loan.js +++ b/erpnext/loan_management/doctype/loan/loan.js @@ -103,6 +103,14 @@ frappe.ui.form.on('Loan', { frm.trigger("toggle_fields"); }, + repayment_schedule_type: function(frm) { + if (frm.doc.repayment_schedule_type == "Pro-rated calendar months") { + frm.set_df_property("repayment_start_date", "label", "Interest Calculation Start Date"); + } else { + frm.set_df_property("repayment_start_date", "label", "Repayment Start Date"); + } + }, + loan_type: function(frm) { frm.toggle_reqd("repayment_method", frm.doc.is_term_loan); frm.toggle_display("repayment_method", frm.doc.is_term_loan); diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index aa8ab022188..86d4bd1b573 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -20,6 +20,7 @@ "manually_update_paid_amount_in_salary_slip", "section_break_8", "loan_type", + "repayment_schedule_type", "loan_amount", "rate_of_interest", "is_secured_loan", @@ -167,7 +168,8 @@ "depends_on": "is_term_loan", "fieldname": "repayment_start_date", "fieldtype": "Date", - "label": "Repayment Start Date" + "label": "Repayment Start Date", + "mandatory_depends_on": "is_term_loan" }, { "fieldname": "column_break_11", @@ -413,22 +415,35 @@ "label": "Is NPA" }, { +<<<<<<< HEAD "allow_on_submit": 1, "default": "0", "depends_on": "repay_from_salary", "fieldname": "manually_update_paid_amount_in_salary_slip", "fieldtype": "Check", "label": "Manually Update Paid Amount in Salary Slip" +======= + "depends_on": "is_term_loan", + "fetch_from": "loan_type.repayment_schedule_type", + "fieldname": "repayment_schedule_type", + "fieldtype": "Data", + "label": "Repayment Schedule Type", + "read_only": 1 +>>>>>>> 2ddee50f27 (chore: Update labels as per repayment type) } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], +<<<<<<< HEAD <<<<<<< HEAD "modified": "2022-09-13 02:05:25.017190", ======= "modified": "2022-09-29 11:50:31.957360", >>>>>>> 76c6ccab5d (feat: Repayment schedule types for term loans) +======= + "modified": "2022-09-30 10:36:47.902903", +>>>>>>> 2ddee50f27 (chore: Update labels as per repayment type) "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", From 7ddcfc00fc86d8eba3c404e4a3c2d4acfecf14c8 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 30 Sep 2022 14:06:06 +0530 Subject: [PATCH 04/23] chore: Add patch to update repayment schedule type in loan documents (cherry picked from commit 679b5ed5514b1fc7ee2840326f073764333fe3b6) # Conflicts: # erpnext/patches.txt --- erpnext/loan_management/doctype/loan/test_loan.py | 1 + erpnext/patches.txt | 9 +++++++++ .../patches/v13_0/update_schedule_type_in_loans.py | 14 ++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 erpnext/patches/v13_0/update_schedule_type_in_loans.py diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index e2b0870c322..11627af53dc 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -1052,6 +1052,7 @@ def create_loan_type( "company": "_Test Company", "loan_name": loan_name, "is_term_loan": is_term_loan, + "repayment_schedule_type": "Monthly as per repayment start date", "maximum_loan_amount": maximum_loan_amount, "rate_of_interest": rate_of_interest, "penalty_interest_rate": penalty_interest_rate, diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b3099644780..dc9e11af6f5 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -370,7 +370,16 @@ erpnext.patches.v13_0.job_card_status_on_hold erpnext.patches.v13_0.add_cost_center_in_loans erpnext.patches.v13_0.show_india_localisation_deprecation_warning erpnext.patches.v13_0.fix_number_and_frequency_for_monthly_depreciation +<<<<<<< HEAD erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair execute:frappe.db.set_value("Naming Series", "Naming Series", {"select_doc_for_series": "", "set_options": "", "prefix": "", "current_value": 0, "user_must_always_select": 0}) +======= +erpnext.patches.v14_0.remove_hr_and_payroll_modules # 20-07-2022 +erpnext.patches.v14_0.fix_crm_no_of_employees +erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes +erpnext.patches.v14_0.fix_subcontracting_receipt_gl_entries +erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger +erpnext.patches.v13_0.update_schedule_type_in_loans +>>>>>>> 679b5ed551 (chore: Add patch to update repayment schedule type in loan documents) diff --git a/erpnext/patches/v13_0/update_schedule_type_in_loans.py b/erpnext/patches/v13_0/update_schedule_type_in_loans.py new file mode 100644 index 00000000000..e5b5f643604 --- /dev/null +++ b/erpnext/patches/v13_0/update_schedule_type_in_loans.py @@ -0,0 +1,14 @@ +import frappe + + +def execute(): + loan = frappe.qb.DocType("Loan") + loan_type = frappe.qb.DocType("Loan Type") + + frappe.qb.update(loan_type).set( + loan_type.repayment_schedule_type, "Monthly as per repayment start date" + ).where(loan_type.is_term_loan == 1).run() + + frappe.qb.update(loan).set( + loan.repayment_schedule_type, "Monthly as per repayment start date" + ).where(loan.is_term_loan == 1).run() From 5fc8d20e962097f9648c6c3dc8ce91946e222e56 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 30 Sep 2022 15:29:07 +0530 Subject: [PATCH 05/23] chore: label post save (cherry picked from commit bf7a51791aec5c1e1c522e5243e391a05b4bf1f7) --- erpnext/loan_management/doctype/loan/loan.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js index c386ce3ac07..20e2b0b2013 100644 --- a/erpnext/loan_management/doctype/loan/loan.js +++ b/erpnext/loan_management/doctype/loan/loan.js @@ -61,6 +61,10 @@ frappe.ui.form.on('Loan', { }, refresh: function (frm) { + if (frm.doc.repayment_schedule_type == "Pro-rated calendar months") { + frm.set_df_property("repayment_start_date", "label", "Interest Calculation Start Date"); + } + if (frm.doc.docstatus == 1) { if (["Disbursed", "Partially Disbursed"].includes(frm.doc.status) && (!frm.doc.repay_from_salary)) { frm.add_custom_button(__('Request Loan Closure'), function() { From fa0a137a3879b3fea69069e35a1e738a7bea0912 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 22 Oct 2022 23:46:01 +0530 Subject: [PATCH 06/23] chore: Add repayment date on option (cherry picked from commit ef0cb17fafce696fff11685a5cf74e936a3f0508) --- erpnext/loan_management/doctype/loan/loan.py | 34 ++++-- .../loan_management/doctype/loan/test_loan.py | 104 +++++++++++++++++- .../doctype/loan_type/loan_type.json | 13 ++- 3 files changed, 138 insertions(+), 13 deletions(-) diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index ecadd4ac31e..417012a8299 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -16,7 +16,6 @@ from frappe.utils import ( add_months, date_diff, flt, - get_first_day, get_last_day, getdate, now_datetime, @@ -129,36 +128,51 @@ class Loan(AccountsController): if not self.repayment_start_date: frappe.throw(_("Repayment Start Date is mandatory for term loans")) - schedule_type = frappe.db.get_value("Loan Type", self.loan_type, "repayment_schedule_type") + schedule_type_details = frappe.db.get_value( + "Loan Type", self.loan_type, ["repayment_schedule_type", "repayment_date_on"], as_dict=1 + ) + self.repayment_schedule = [] payment_date = self.repayment_start_date balance_amount = self.loan_amount while balance_amount > 0: interest_amount, principal_amount, balance_amount, total_payment = self.get_amounts( - payment_date, balance_amount, schedule_type + payment_date, + balance_amount, + schedule_type_details.repayment_schedule_type, + schedule_type_details.repayment_date_on, ) - if schedule_type == "Pro-rated calendar months": - next_payment_date = add_days(get_last_day(payment_date), 1) + if schedule_type_details.repayment_schedule_type == "Pro-rated calendar months": + next_payment_date = get_last_day(payment_date) + if schedule_type_details.repayment_date_on == "Start of the next month": + next_payment_date = add_days(next_payment_date, 1) + payment_date = next_payment_date self.add_repayment_schedule_row( payment_date, principal_amount, interest_amount, total_payment, balance_amount ) - if schedule_type == "Monthly as per repayment start date": + if ( + schedule_type_details.repayment_schedule_type == "Monthly as per repayment start date" + or schedule_type_details.repayment_date_on == "End of the current month" + ): next_payment_date = add_single_month(payment_date) payment_date = next_payment_date - def get_amounts(self, payment_date, balance_amount, schedule_type): - first_day_of_month = get_first_day(payment_date) - + def get_amounts(self, payment_date, balance_amount, schedule_type, repayment_date_on): if schedule_type == "Monthly as per repayment start date": days = 1 months = 12 else: - if first_day_of_month == payment_date: + expected_payment_date = get_last_day(payment_date) + if repayment_date_on == "Start of the next month": + expected_payment_date = add_days(expected_payment_date, 1) + + if expected_payment_date == payment_date: + # using 30 days for calculating interest for all full months days = 30 months = 365 else: diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index 11627af53dc..e9442cebe0f 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -4,7 +4,16 @@ import unittest import frappe -from frappe.utils import add_days, add_months, add_to_date, date_diff, flt, get_datetime, nowdate +from frappe.utils import ( + add_days, + add_months, + add_to_date, + date_diff, + flt, + format_date, + get_datetime, + nowdate, +) from erpnext.loan_management.doctype.loan.loan import ( make_loan_write_off, @@ -52,6 +61,50 @@ class TestLoan(unittest.TestCase): penalty_income_account="Penalty Income Account - _TC", ) + create_loan_type( + "Term Loan Type 1", + 12000, + 7.5, + is_term_loan=1, + mode_of_payment="Cash", + disbursement_account="Disbursement Account - _TC", + payment_account="Payment Account - _TC", + loan_account="Loan Account - _TC", + interest_income_account="Interest Income Account - _TC", + penalty_income_account="Penalty Income Account - _TC", + repayment_schedule_type="Monthly as per repayment start date", + ) + + create_loan_type( + "Term Loan Type 2", + 12000, + 7.5, + is_term_loan=1, + mode_of_payment="Cash", + disbursement_account="Disbursement Account - _TC", + payment_account="Payment Account - _TC", + loan_account="Loan Account - _TC", + interest_income_account="Interest Income Account - _TC", + penalty_income_account="Penalty Income Account - _TC", + repayment_schedule_type="Pro-rated calendar months", + repayment_date_on="Start of the next month", + ) + + create_loan_type( + "Term Loan Type 3", + 12000, + 7.5, + is_term_loan=1, + mode_of_payment="Cash", + disbursement_account="Disbursement Account - _TC", + payment_account="Payment Account - _TC", + loan_account="Loan Account - _TC", + interest_income_account="Interest Income Account - _TC", + penalty_income_account="Penalty Income Account - _TC", + repayment_schedule_type="Pro-rated calendar months", + repayment_date_on="End of the current month", + ) + create_loan_type( "Stock Loan", 2000000, @@ -912,6 +965,45 @@ class TestLoan(unittest.TestCase): amounts = calculate_amounts(loan.name, add_days(last_date, 5)) self.assertEqual(flt(amounts["pending_principal_amount"], 0), 0) + def test_term_loan_schedule_types(self): + loan = create_loan( + self.applicant1, + "Term Loan Type 1", + 12000, + "Repay Over Number of Periods", + 12, + repayment_start_date="2022-10-17", + ) + + # Check for first, second and last installment date + self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "17-10-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "17-11-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "17-09-2023") + + loan.loan_type = "Term Loan Type 2" + loan.save() + + # Check for first, second and last installment date + self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "01-11-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "01-12-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "01-10-2023") + + loan.loan_type = "Term Loan Type 3" + loan.save() + + # Check for first, second and last installment date + self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "31-10-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "30-11-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "30-09-2023") + + loan.repayment_method = "Repay Fixed Amount per Period" + loan.monthly_repayment_amount = 1042 + loan.save() + + self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "31-10-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "30-11-2022") + self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "30-09-2023") + def create_loan_scenario_for_penalty(doc): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] @@ -1043,6 +1135,8 @@ def create_loan_type( penalty_income_account=None, repayment_method=None, repayment_periods=None, + repayment_schedule_type=None, + repayment_date_on=None, ): if not frappe.db.exists("Loan Type", loan_name): @@ -1067,8 +1161,14 @@ def create_loan_type( "repayment_periods": repayment_periods, "write_off_amount": 100, } - ).insert() + ) + if loan_type.is_term_loan: + loan_type.repayment_schedule_type = repayment_schedule_type + if loan_type.repayment_schedule_type != "Monthly as per repayment start date": + loan_type.repayment_date_on = repayment_date_on + + loan_type.insert() loan_type.submit() diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json index e1ed3caf8f4..5cc9464585b 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type.json +++ b/erpnext/loan_management/doctype/loan_type/loan_type.json @@ -17,6 +17,7 @@ "is_term_loan", "disabled", "repayment_schedule_type", + "repayment_date_on", "description", "account_details_section", "mode_of_payment", @@ -161,17 +162,27 @@ }, { "depends_on": "is_term_loan", + "description": "The schedule type that will be used for generating the term loan schedules (will affect the payment date and monthly repayment amount)", "fieldname": "repayment_schedule_type", "fieldtype": "Select", "label": "Repayment Schedule Type", "mandatory_depends_on": "is_term_loan", "options": "\nMonthly as per repayment start date\nPro-rated calendar months" + }, + { + "depends_on": "eval:doc.repayment_schedule_type == \"Pro-rated calendar months\"", + "description": "Select whether the repayment date should be the end of the current month or start of the upcoming month", + "fieldname": "repayment_date_on", + "fieldtype": "Select", + "label": "Repayment Date On", + "mandatory_depends_on": "eval:doc.repayment_schedule_type == \"Pro-rated calendar months\"", + "options": "\nStart of the next month\nEnd of the current month" } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-09-28 21:31:01.278941", + "modified": "2022-10-22 17:43:03.954201", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Type", From 85f48dd6bd76aae983c985f9bf7e6bc7b4253f4c Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 23 Oct 2022 18:51:51 +0530 Subject: [PATCH 07/23] chore: Update tests (cherry picked from commit e59b147a620c45d8727c8a0adf9ea1cd0d57df6f) --- .../loan_management/doctype/loan/test_loan.py | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index e9442cebe0f..276b05baf62 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -59,6 +59,7 @@ class TestLoan(unittest.TestCase): loan_account="Loan Account - _TC", interest_income_account="Interest Income Account - _TC", penalty_income_account="Penalty Income Account - _TC", + repayment_schedule_type="Monthly as per repayment start date", ) create_loan_type( @@ -118,6 +119,7 @@ class TestLoan(unittest.TestCase): "Loan Account - _TC", "Interest Income Account - _TC", "Penalty Income Account - _TC", + repayment_schedule_type="Monthly as per repayment start date", ) create_loan_type( @@ -976,33 +978,57 @@ class TestLoan(unittest.TestCase): ) # Check for first, second and last installment date - self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "17-10-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "17-11-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "17-09-2023") + self.assertEqual( + format_date(loan.get("repayment_schedule")[0].payment_date, "dd-MM-yyyy"), "17-10-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[1].payment_date, "dd-MM-yyyy"), "17-11-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[-1].payment_date, "dd-MM-yyyy"), "17-09-2023" + ) loan.loan_type = "Term Loan Type 2" loan.save() # Check for first, second and last installment date - self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "01-11-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "01-12-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "01-10-2023") + self.assertEqual( + format_date(loan.get("repayment_schedule")[0].payment_date, "dd-MM-yyyy"), "01-11-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[1].payment_date, "dd-MM-yyyy"), "01-12-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[-1].payment_date, "dd-MM-yyyy"), "01-10-2023" + ) loan.loan_type = "Term Loan Type 3" loan.save() # Check for first, second and last installment date - self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "31-10-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "30-11-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "30-09-2023") + self.assertEqual( + format_date(loan.get("repayment_schedule")[0].payment_date, "dd-MM-yyyy"), "31-10-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[1].payment_date, "dd-MM-yyyy"), "30-11-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[-1].payment_date, "dd-MM-yyyy"), "30-09-2023" + ) loan.repayment_method = "Repay Fixed Amount per Period" loan.monthly_repayment_amount = 1042 loan.save() - self.assertEqual(format_date(loan.get("repayment_schedule")[0].payment_date), "31-10-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[1].payment_date), "30-11-2022") - self.assertEqual(format_date(loan.get("repayment_schedule")[-1].payment_date), "30-09-2023") + self.assertEqual( + format_date(loan.get("repayment_schedule")[0].payment_date, "dd-MM-yyyy"), "31-10-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[1].payment_date, "dd-MM-yyyy"), "30-11-2022" + ) + self.assertEqual( + format_date(loan.get("repayment_schedule")[-1].payment_date, "dd-MM-yyyy"), "30-09-2023" + ) def create_loan_scenario_for_penalty(doc): From 804cf40f692afe3dbe41bca0e9bd2e9c703c79fd Mon Sep 17 00:00:00 2001 From: Vishal Date: Fri, 28 Oct 2022 11:36:14 +0530 Subject: [PATCH 08/23] chore: Added Material Request Reference in Purchase Recipt Dashboard for Tracking (cherry picked from commit a04c44fe34845b6e1e254fc86ea452a6ce8f3930) --- .../doctype/purchase_receipt/purchase_receipt_dashboard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py index 06ba9365561..60e5fcffd06 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py @@ -1,6 +1,5 @@ from frappe import _ - def get_data(): return { "fieldname": "purchase_receipt_no", @@ -12,13 +11,14 @@ def get_data(): "Purchase Receipt": "return_against", }, "internal_links": { + "Material Request": ["items", "material_request"], "Purchase Order": ["items", "purchase_order"], "Project": ["items", "project"], "Quality Inspection": ["items", "quality_inspection"], }, "transactions": [ {"label": _("Related"), "items": ["Purchase Invoice", "Landed Cost Voucher", "Asset"]}, - {"label": _("Reference"), "items": ["Purchase Order", "Quality Inspection", "Project"]}, + {"label": _("Reference"), "items": ["Material Request", "Purchase Order", "Quality Inspection", "Project"]}, {"label": _("Returns"), "items": ["Purchase Receipt"]}, {"label": _("Subscription"), "items": ["Auto Repeat"]}, ], From 292ff1bd6b5c507bddc1307d1cd0d585e51906dd Mon Sep 17 00:00:00 2001 From: Vishal Date: Fri, 28 Oct 2022 11:59:10 +0530 Subject: [PATCH 09/23] chore: minor linting issue fixed (cherry picked from commit e8c01570176212322bf7b0688ece2f3fbf98a184) --- .../doctype/purchase_receipt/purchase_receipt_dashboard.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py index 60e5fcffd06..b3ae7b58b49 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py @@ -1,5 +1,6 @@ from frappe import _ + def get_data(): return { "fieldname": "purchase_receipt_no", @@ -18,7 +19,10 @@ def get_data(): }, "transactions": [ {"label": _("Related"), "items": ["Purchase Invoice", "Landed Cost Voucher", "Asset"]}, - {"label": _("Reference"), "items": ["Material Request", "Purchase Order", "Quality Inspection", "Project"]}, + { + "label": _("Reference"), + "items": ["Material Request", "Purchase Order", "Quality Inspection", "Project"], + }, {"label": _("Returns"), "items": ["Purchase Receipt"]}, {"label": _("Subscription"), "items": ["Auto Repeat"]}, ], From d73237e896ee6cfe9f072550882343e833a3e954 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 29 Oct 2022 11:06:53 +0530 Subject: [PATCH 10/23] chore: Resolve conflicts --- erpnext/loan_management/doctype/loan/loan.json | 17 ----------------- erpnext/loan_management/doctype/loan/loan.py | 6 +----- erpnext/patches.txt | 10 +--------- 3 files changed, 2 insertions(+), 31 deletions(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index 86d4bd1b573..6df1b4b7369 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -415,35 +415,18 @@ "label": "Is NPA" }, { -<<<<<<< HEAD - "allow_on_submit": 1, - "default": "0", - "depends_on": "repay_from_salary", - "fieldname": "manually_update_paid_amount_in_salary_slip", - "fieldtype": "Check", - "label": "Manually Update Paid Amount in Salary Slip" -======= "depends_on": "is_term_loan", "fetch_from": "loan_type.repayment_schedule_type", "fieldname": "repayment_schedule_type", "fieldtype": "Data", "label": "Repayment Schedule Type", "read_only": 1 ->>>>>>> 2ddee50f27 (chore: Update labels as per repayment type) } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], -<<<<<<< HEAD -<<<<<<< HEAD - "modified": "2022-09-13 02:05:25.017190", -======= - "modified": "2022-09-29 11:50:31.957360", ->>>>>>> 76c6ccab5d (feat: Repayment schedule types for term loans) -======= "modified": "2022-09-30 10:36:47.902903", ->>>>>>> 2ddee50f27 (chore: Update labels as per repayment type) "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index 417012a8299..cdc693df1f7 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -7,10 +7,6 @@ import math import frappe from frappe import _ -<<<<<<< HEAD -from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate -from six import string_types -======= from frappe.utils import ( add_days, add_months, @@ -21,7 +17,7 @@ from frappe.utils import ( now_datetime, nowdate, ) ->>>>>>> 76c6ccab5d (feat: Repayment schedule types for term loans) +from six import string_types import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry diff --git a/erpnext/patches.txt b/erpnext/patches.txt index dc9e11af6f5..47277cc48ce 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -370,16 +370,8 @@ erpnext.patches.v13_0.job_card_status_on_hold erpnext.patches.v13_0.add_cost_center_in_loans erpnext.patches.v13_0.show_india_localisation_deprecation_warning erpnext.patches.v13_0.fix_number_and_frequency_for_monthly_depreciation -<<<<<<< HEAD erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.show_hr_payroll_deprecation_warning erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair execute:frappe.db.set_value("Naming Series", "Naming Series", {"select_doc_for_series": "", "set_options": "", "prefix": "", "current_value": 0, "user_must_always_select": 0}) -======= -erpnext.patches.v14_0.remove_hr_and_payroll_modules # 20-07-2022 -erpnext.patches.v14_0.fix_crm_no_of_employees -erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes -erpnext.patches.v14_0.fix_subcontracting_receipt_gl_entries -erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger -erpnext.patches.v13_0.update_schedule_type_in_loans ->>>>>>> 679b5ed551 (chore: Add patch to update repayment schedule type in loan documents) +erpnext.patches.v13_0.update_schedule_type_in_loans \ No newline at end of file From cb89dba5ab488a52f56f6f7cf7eb7230b113bc91 Mon Sep 17 00:00:00 2001 From: Sagar Sharma Date: Sat, 29 Oct 2022 11:56:34 +0530 Subject: [PATCH 11/23] fix: add `Sales Order` reference in Material Request Dashboard (cherry picked from commit 15ebf4a0cf87360ce4265014fe23b2a95e171506) --- .../doctype/material_request/material_request_dashboard.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py index b073e6a22ee..691a8b39b1b 100644 --- a/erpnext/stock/doctype/material_request/material_request_dashboard.py +++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py @@ -4,10 +4,13 @@ from frappe import _ def get_data(): return { "fieldname": "material_request", + "internal_links": { + "Sales Order": ["items", "sales_order"], + }, "transactions": [ { "label": _("Reference"), - "items": ["Request for Quotation", "Supplier Quotation", "Purchase Order"], + "items": ["Sales Order", "Request for Quotation", "Supplier Quotation", "Purchase Order"], }, {"label": _("Stock"), "items": ["Stock Entry", "Purchase Receipt", "Pick List"]}, {"label": _("Manufacturing"), "items": ["Work Order"]}, From 65b047c94c71b99b0416423c9b2a2710e1603906 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 30 Oct 2022 10:44:15 +0530 Subject: [PATCH 12/23] chore: Resync Loan Doc --- erpnext/loan_management/doctype/loan/loan.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index 6df1b4b7369..9868b6c25f4 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -426,7 +426,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-09-30 10:36:47.902903", + "modified": "2022-09-31 10:36:47.902903", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", From e9006582fb748edaefb221a1492b3c2b4074104f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 30 Oct 2022 10:48:37 +0530 Subject: [PATCH 13/23] chore: Add removed field --- erpnext/loan_management/doctype/loan/loan.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index 9868b6c25f4..e40976700c9 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -414,6 +414,14 @@ "fieldtype": "Check", "label": "Is NPA" }, + { + "allow_on_submit": 1, + "default": "0", + "depends_on": "repay_from_salary", + "fieldname": "manually_update_paid_amount_in_salary_slip", + "fieldtype": "Check", + "label": "Manually Update Paid Amount in Salary Slip" + }, { "depends_on": "is_term_loan", "fetch_from": "loan_type.repayment_schedule_type", @@ -426,7 +434,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-09-31 10:36:47.902903", + "modified": "2022-09-32 10:36:47.902903", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", From d2aea0cd2ef8abd50ba23a346e037eb8568cedc0 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 30 Oct 2022 11:01:41 +0530 Subject: [PATCH 14/23] chore: fix datetime value --- erpnext/loan_management/doctype/loan/loan.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index e40976700c9..634465db9f0 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -434,7 +434,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-09-32 10:36:47.902903", + "modified": "2022-10-01 10:36:47.902903", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", From 50bc7785f7a3e403e0e2256e696aa2058a420c68 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 31 Oct 2022 10:39:03 +0530 Subject: [PATCH 15/23] chore: reload doctypes --- erpnext/loan_management/doctype/loan/loan.json | 2 +- erpnext/loan_management/doctype/loan_type/loan_type.json | 2 +- erpnext/patches/v13_0/update_schedule_type_in_loans.py | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index 634465db9f0..73bd1c65ffc 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -434,7 +434,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-10-01 10:36:47.902903", + "modified": "2022-11-01 10:36:47.902903", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json index 5cc9464585b..3e784c256e7 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type.json +++ b/erpnext/loan_management/doctype/loan_type/loan_type.json @@ -182,7 +182,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-10-22 17:43:03.954201", + "modified": "2022-11-01 17:43:03.954201", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Type", diff --git a/erpnext/patches/v13_0/update_schedule_type_in_loans.py b/erpnext/patches/v13_0/update_schedule_type_in_loans.py index e5b5f643604..0cff5c5fee9 100644 --- a/erpnext/patches/v13_0/update_schedule_type_in_loans.py +++ b/erpnext/patches/v13_0/update_schedule_type_in_loans.py @@ -2,6 +2,9 @@ import frappe def execute(): + frappe.reload_doc("loan_management", "doctype", "loan") + frappe.reload_doc("loan_management", "doctype", "loan_type") + loan = frappe.qb.DocType("Loan") loan_type = frappe.qb.DocType("Loan Type") From 60fa87751abc24dd676ce9cf112c340b50f2d9c0 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 31 Oct 2022 11:28:32 +0530 Subject: [PATCH 16/23] chore: Update payroll loan tests --- erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py index 35cea017e8c..d94edef1b07 100644 --- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py @@ -295,6 +295,7 @@ class TestPayrollEntry(FrappeTestCase): loan_account="Loan Account - _TC", interest_income_account="Interest Income Account - _TC", penalty_income_account="Penalty Income Account - _TC", + repayment_schedule_type="Monthly as per repayment start date", ) loan = create_loan( From 310e7c522c3462de84415ea0c0825202819c7020 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 31 Oct 2022 23:21:29 +0530 Subject: [PATCH 17/23] fix: group warehouse filter not working for Batch-wise Balance history report --- .../batch_wise_balance_history.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py index 8a13300dc83..949452d43ba 100644 --- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py +++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py @@ -74,10 +74,21 @@ def get_conditions(filters): else: frappe.throw(_("'To Date' is required")) - for field in ["item_code", "warehouse", "batch_no", "company"]: + for field in ["item_code", "batch_no", "company"]: if filters.get(field): conditions += " and {0} = {1}".format(field, frappe.db.escape(filters.get(field))) + if filters.get("warehouse"): + warehouse_details = frappe.db.get_value( + "Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1 + ) + if warehouse_details: + conditions += ( + " and exists (select name from `tabWarehouse` wh \ + where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)" + % (warehouse_details.lft, warehouse_details.rgt) + ) + return conditions @@ -87,7 +98,7 @@ def get_stock_ledger_entries(filters): return frappe.db.sql( """ select item_code, batch_no, warehouse, posting_date, sum(actual_qty) as actual_qty - from `tabStock Ledger Entry` + from `tabStock Ledger Entry` as sle where is_cancelled = 0 and docstatus < 2 and ifnull(batch_no, '') != '' %s group by voucher_no, batch_no, item_code, warehouse order by item_code, warehouse""" From 9dc0edfb8a71204fc9d6b7806fb63c59f2215a26 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Nov 2022 16:03:32 +0530 Subject: [PATCH 18/23] fix: Do not force eligibilgity of itc for reverse charge --- erpnext/regional/india/taxes.js | 6 ++++++ erpnext/regional/india/utils.py | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js index 88973e36b6a..49af669fc3f 100644 --- a/erpnext/regional/india/taxes.js +++ b/erpnext/regional/india/taxes.js @@ -47,6 +47,12 @@ erpnext.setup_auto_gst_taxation = (doctype) => { } } }); + }, + + reverse_charge: function(frm) { + if (frm.doc.reverse_charge == "Y") { + frm.set_value('eligibility_for_itc', 'ITC on Reverse Charge'); + } } }); } diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index e98093bd820..0b61e7faf9b 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -983,8 +983,6 @@ def validate_reverse_charge_transaction(doc, method): frappe.throw(msg) - doc.eligibility_for_itc = "ITC on Reverse Charge" - def update_itc_availed_fields(doc, method): country = frappe.get_cached_value("Company", doc.company, "country") From b877b0d3a2e47a26534b842931288c6405ee5dc6 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 1 Nov 2022 16:56:35 +0530 Subject: [PATCH 19/23] fix: filter return pos in reconciliation tool --- erpnext/accounts/utils.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index c4fafba2669..b0b217684ea 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -835,10 +835,7 @@ def remove_return_pos_invoices(party_type, party, invoice_list): else: return invoice_list - # remove pos return invoices from invoice_list - for idx, inv in enumerate(invoice_list, 0): - if inv.voucher_no in return_pos: - del invoice_list[idx] + invoice_list = [x for x in invoice_list if x.voucher_no not in return_pos] return invoice_list From 88889579529db4f4222125cab1300b463f535d93 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Nov 2022 19:54:41 +0530 Subject: [PATCH 20/23] fix: Issues while cancel/amending Purchase Invoice with TDS enabled (cherry picked from commit f7c9258770a79aff0b951dc18c0b7c39f794b03f) # Conflicts: # erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py --- .../accounts/doctype/purchase_invoice/purchase_invoice.js | 4 ++++ .../accounts/doctype/purchase_invoice/purchase_invoice.py | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 6c37e6c9a3c..0208975513b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -569,6 +569,10 @@ frappe.ui.form.on("Purchase Invoice", { erpnext.queries.setup_queries(frm, "Warehouse", function() { return erpnext.queries.warehouse(frm.doc); }); + + if (frm.is_new()) { + frm.clear_table("tax_withheld_vouchers"); + } }, is_subcontracted: function(frm) { diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index a1a18f0becd..865b0ba2337 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -67,6 +67,9 @@ class PurchaseInvoice(BuyingController): supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category") self.set_onload("supplier_tds", supplier_tds) + if self.is_new(): + self.set("tax_withheld_vouchers", []) + def before_save(self): if not self.on_hold: self.release_date = "" @@ -1373,7 +1376,12 @@ class PurchaseInvoice(BuyingController): "GL Entry", "Stock Ledger Entry", "Repost Item Valuation", +<<<<<<< HEAD "Purchase Invoice", +======= + "Payment Ledger Entry", + "Tax Withheld Vouchers", +>>>>>>> f7c9258770 (fix: Issues while cancel/amending Purchase Invoice with TDS enabled) ) self.update_advance_tax_references(cancel=1) From 9b63a1a2e9716113f266f76977bb6a29e56e1703 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 31 Oct 2022 19:58:46 +0530 Subject: [PATCH 21/23] fix: Mode of payment for returns in POS Sales Invoice (cherry picked from commit 06e8e28531e2584fd5499df1c233082657de12b0) --- erpnext/controllers/taxes_and_totals.py | 41 +++++++++++++++---------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 66d4cad8037..ed95f834379 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -890,24 +890,33 @@ class calculate_taxes_and_totals(object): self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc) def set_total_amount_to_default_mop(self, total_amount_to_pay): - default_mode_of_payment = frappe.db.get_value( - "POS Payment Method", - {"parent": self.doc.pos_profile, "default": 1}, - ["mode_of_payment"], - as_dict=1, - ) - - if default_mode_of_payment: - self.doc.payments = [] - self.doc.append( - "payments", - { - "mode_of_payment": default_mode_of_payment.mode_of_payment, - "amount": total_amount_to_pay, - "default": 1, - }, + total_paid_amount = 0 + for payment in self.doc.get("payments"): + total_paid_amount += ( + payment.amount if self.doc.party_account_currency == self.doc.currency else payment.base_amount ) + pending_amount = total_amount_to_pay - total_paid_amount + + if pending_amount > 0: + default_mode_of_payment = frappe.db.get_value( + "POS Payment Method", + {"parent": self.doc.pos_profile, "default": 1}, + ["mode_of_payment"], + as_dict=1, + ) + + if default_mode_of_payment: + self.doc.payments = [] + self.doc.append( + "payments", + { + "mode_of_payment": default_mode_of_payment.mode_of_payment, + "amount": pending_amount, + "default": 1, + }, + ) + def get_itemised_tax_breakup_html(doc): if not doc.taxes: From 12b15347bce86efec8691d688e4c7794d00d3e94 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Nov 2022 20:17:34 +0530 Subject: [PATCH 22/23] chore: Update tests (cherry picked from commit 5b74161195b3b006d47f29de5a97428effca527e) --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 1106cf01a2b..79a67b83631 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -916,7 +916,8 @@ class TestSalesInvoice(unittest.TestCase): pos_return.insert() pos_return.submit() - self.assertEqual(pos_return.get("payments")[0].amount, -1000) + self.assertEqual(pos_return.get("payments")[0].amount, -500) + self.assertEqual(pos_return.get("payments")[1].amount, -500) def test_pos_change_amount(self): make_pos_profile( From 4a10454d89400720d3d114a9c285acd6b5a007c2 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Nov 2022 21:30:36 +0530 Subject: [PATCH 23/23] chore: Resolve conflicts --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 865b0ba2337..9616e93a020 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1376,12 +1376,7 @@ class PurchaseInvoice(BuyingController): "GL Entry", "Stock Ledger Entry", "Repost Item Valuation", -<<<<<<< HEAD - "Purchase Invoice", -======= - "Payment Ledger Entry", "Tax Withheld Vouchers", ->>>>>>> f7c9258770 (fix: Issues while cancel/amending Purchase Invoice with TDS enabled) ) self.update_advance_tax_references(cancel=1)