From cbe15e159a3f97f2e057df74370dbd35b0c661b1 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 4 Dec 2023 16:47:28 +0530 Subject: [PATCH 01/14] fix: limit end date to current date (cherry picked from commit ab6e92aae129653f13e54728d8d3a8c88dcda6cb) --- erpnext/accounts/report/financial_statements.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 096bb107069a..7355c4b8a165 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -8,7 +8,17 @@ import frappe from frappe import _ -from frappe.utils import add_days, add_months, cint, cstr, flt, formatdate, get_first_day, getdate +from frappe.utils import ( + add_days, + add_months, + cint, + cstr, + flt, + formatdate, + get_first_day, + getdate, + today, +) from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_accounting_dimensions, @@ -43,6 +53,8 @@ def get_period_list( year_start_date = getdate(period_start_date) year_end_date = getdate(period_end_date) + year_end_date = getdate(today()) if year_end_date > getdate(today()) else year_end_date + months_to_add = {"Yearly": 12, "Half-Yearly": 6, "Quarterly": 3, "Monthly": 1}[periodicity] period_list = [] From c2a137f0fb48e9322436ada3e3cce849a236d231 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 20:55:06 +0530 Subject: [PATCH 02/14] feat: add employee number to client user bootinfo (backport #38477) (#38602) feat: add employee number to client user bootinfo (#38477) (cherry picked from commit 525f656cc111f6225b44e1211dc5726d311a120b) Co-authored-by: Richard Case <110036763+casesolved-co-uk@users.noreply.github.com> --- erpnext/hooks.py | 1 + erpnext/startup/boot.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index dad12c4d591b..054f9dedabe7 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -638,4 +638,5 @@ extend_bootinfo = [ "erpnext.support.doctype.service_level_agreement.service_level_agreement.add_sla_doctypes", + "erpnext.startup.boot.bootinfo", ] diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index db1cc494e0ba..db1d7846195d 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -73,3 +73,11 @@ def update_page_info(bootinfo): "Sales Person Tree": {"title": "Sales Person Tree", "route": "Tree/Sales Person"}, } ) + + +def bootinfo(bootinfo): + if bootinfo.get("user") and bootinfo["user"].get("name"): + bootinfo["user"]["employee"] = "" + employee = frappe.db.get_value("Employee", {"user_id": bootinfo["user"]["name"]}, "name", cache=True) + if employee: + bootinfo["user"]["employee"] = employee From 4e6b8ead8fd4ed720eecd021707c47225e8c15fa Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 6 Dec 2023 20:53:55 +0530 Subject: [PATCH 03/14] chore: remove unused cache=True (cherry picked from commit 6a47a2ceaf20572e143ab12ff76cfd9c54f509d6) --- erpnext/startup/boot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index db1d7846195d..bc4b6141bf06 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -78,6 +78,6 @@ def update_page_info(bootinfo): def bootinfo(bootinfo): if bootinfo.get("user") and bootinfo["user"].get("name"): bootinfo["user"]["employee"] = "" - employee = frappe.db.get_value("Employee", {"user_id": bootinfo["user"]["name"]}, "name", cache=True) + employee = frappe.db.get_value("Employee", {"user_id": bootinfo["user"]["name"]}, "name") if employee: bootinfo["user"]["employee"] = employee From b28deaae2c0e3784c7cbe585ded11d5354d65c9c Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Thu, 7 Dec 2023 19:39:24 +0530 Subject: [PATCH 04/14] fix: format only if searched text contain link value text (cherry picked from commit 08ed3cd31394eb1108dc29a7a5b3f6ded85e3656) --- erpnext/public/js/financial_statements.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 907a775bfa53..5e1974299ee1 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -2,10 +2,16 @@ frappe.provide("erpnext.financial_statements"); erpnext.financial_statements = { "filters": get_filters(), - "formatter": function(value, row, column, data, default_formatter) { + "formatter": function(value, row, column, data, default_formatter, filter) { if (data && column.fieldname=="account") { value = data.account_name || value; + if (filter && filter?.text && filter?.type == "contains") { + if (!value.toLowerCase().includes(filter.text)) { + return value; + } + } + if (data.account) { column.link_onclick = "erpnext.financial_statements.open_general_ledger(" + JSON.stringify(data) + ")"; From 008400d287c26f78909abb1b09bb52a5ea94c1b3 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Fri, 8 Dec 2023 16:34:29 +0530 Subject: [PATCH 05/14] fix: calc monthly_repayment_amount correctly in regenerate_repayment_schedule (#38636) --- .../loan_management/doctype/loan_repayment/loan_repayment.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index 0d16c7f0c50c..0b057f85aa38 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -599,6 +599,8 @@ def regenerate_repayment_schedule(loan, cancel=0): last_repayment_amount = None last_balance_amount = None + original_repayment_schedule_len = len(loan_doc.get("repayment_schedule")) + for term in reversed(loan_doc.get("repayment_schedule")): if not term.is_accrued: next_accrual_date = term.payment_date @@ -616,7 +618,7 @@ def regenerate_repayment_schedule(loan, cancel=0): if loan_doc.repayment_method == "Repay Fixed Amount per Period": monthly_repayment_amount = flt( - balance_amount / len(loan_doc.get("repayment_schedule")) - accrued_entries + balance_amount / (original_repayment_schedule_len - accrued_entries) ) else: repayment_period = loan_doc.repayment_periods - accrued_entries From 29cd474f44844ace9409cf4f304ef950a84f5616 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:59:46 +0530 Subject: [PATCH 06/14] fix(ux): don't update qty blindly (backport #38608) (#38638) fix(ux): don't update qty blindly (cherry picked from commit 0156339f3433f1a3ddb08885d2b85902c1114345) Co-authored-by: s-aga-r --- erpnext/public/js/controllers/transaction.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 050b9dcd3db4..ff00a3ade163 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -441,7 +441,6 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe item.pricing_rules = '' return this.frm.call({ method: "erpnext.stock.get_item_details.get_item_details", - child: item, args: { doc: me.frm.doc, args: { @@ -490,6 +489,19 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe callback: function(r) { if(!r.exc) { frappe.run_serially([ + () => { + var child = locals[cdt][cdn]; + var std_field_list = ["doctype"] + .concat(frappe.model.std_fields_list) + .concat(frappe.model.child_table_field_list); + + for (var key in r.message) { + if (std_field_list.indexOf(key) === -1) { + if (key === "qty" && child[key]) continue; + child[key] = r.message[key]; + } + } + }, () => { var d = locals[cdt][cdn]; me.add_taxes_from_item_tax_template(d.item_tax_rate); From 7813efad356a56de595f887896562818f43cae23 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 10 Dec 2023 16:29:27 +0530 Subject: [PATCH 07/14] Revert "refactor: bank transaction (backport #38182)" (#38653) Revert "refactor: bank transaction (#38182)" This reverts commit a4b5fc81008a9f730ce512dc2a8419967d835f84. --- .../bank_reconciliation_tool.py | 4 +- .../bank_transaction/bank_transaction.json | 17 +-- .../bank_transaction/bank_transaction.py | 139 ++++++++++-------- 3 files changed, 83 insertions(+), 77 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 8cc3bc3bf47b..6017c5a491da 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -423,9 +423,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers): vouchers = json.loads(vouchers) transaction = frappe.get_doc("Bank Transaction", bank_transaction_name) transaction.add_payment_entries(vouchers) - transaction.save() - - return transaction + return frappe.get_doc("Bank Transaction", bank_transaction_name) @frappe.whitelist() diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json index 8c5a5eaef5dc..bb7a4771b2da 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json @@ -13,7 +13,6 @@ "status", "bank_account", "company", - "amended_from", "section_break_4", "deposit", "withdrawal", @@ -26,10 +25,10 @@ "transaction_id", "transaction_type", "section_break_14", - "column_break_oufv", "payment_entries", "section_break_18", "allocated_amount", + "amended_from", "column_break_17", "unallocated_amount", "party_section", @@ -139,12 +138,10 @@ "fieldtype": "Section Break" }, { - "allow_on_submit": 1, "fieldname": "allocated_amount", "fieldtype": "Currency", "label": "Allocated Amount", - "options": "currency", - "read_only": 1 + "options": "currency" }, { "fieldname": "amended_from", @@ -160,12 +157,10 @@ "fieldtype": "Column Break" }, { - "allow_on_submit": 1, "fieldname": "unallocated_amount", "fieldtype": "Currency", "label": "Unallocated Amount", - "options": "currency", - "read_only": 1 + "options": "currency" }, { "fieldname": "party_section", @@ -230,15 +225,11 @@ "fieldname": "bank_party_account_number", "fieldtype": "Data", "label": "Party Account No. (Bank Statement)" - }, - { - "fieldname": "column_break_oufv", - "fieldtype": "Column Break" } ], "is_submittable": 1, "links": [], - "modified": "2023-11-18 18:32:47.203694", + "modified": "2023-06-06 13:58:12.821411", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Transaction", diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index a9a8b1599502..256bde5c7199 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -2,73 +2,78 @@ # For license information, please see license.txt import frappe -from frappe import _ from frappe.utils import flt from erpnext.controllers.status_updater import StatusUpdater class BankTransaction(StatusUpdater): - def before_validate(self): - self.update_allocated_amount() + def after_insert(self): + self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - def validate(self): - self.validate_duplicate_references() - - def validate_duplicate_references(self): - """Make sure the same voucher is not allocated twice within the same Bank Transaction""" - if not self.payment_entries: - return - - pe = [] - for row in self.payment_entries: - reference = (row.payment_document, row.payment_entry) - if reference in pe: - frappe.throw( - _("{0} {1} is allocated twice in this Bank Transaction").format( - row.payment_document, row.payment_entry - ) - ) - pe.append(reference) - - def update_allocated_amount(self): - self.allocated_amount = ( - sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0 - ) - self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount - - def before_submit(self): - self.allocate_payment_entries() + def on_submit(self): + self.clear_linked_payment_entries() self.set_status() if frappe.db.get_single_value("Accounts Settings", "enable_party_matching"): self.auto_set_party() - def before_update_after_submit(self): - self.validate_duplicate_references() - self.allocate_payment_entries() - self.update_allocated_amount() + _saving_flag = False + + # nosemgrep: frappe-semgrep-rules.rules.frappe-modifying-but-not-comitting + def on_update_after_submit(self): + "Run on save(). Avoid recursion caused by multiple saves" + if not self._saving_flag: + self._saving_flag = True + self.clear_linked_payment_entries() + self.update_allocations() + self._saving_flag = False def on_cancel(self): - for payment_entry in self.payment_entries: - self.clear_linked_payment_entry(payment_entry, for_cancel=True) + self.clear_linked_payment_entries(for_cancel=True) + self.set_status(update=True) + + def update_allocations(self): + "The doctype does not allow modifications after submission, so write to the db direct" + if self.payment_entries: + allocated_amount = sum(p.allocated_amount for p in self.payment_entries) + else: + allocated_amount = 0.0 + amount = abs(flt(self.withdrawal) - flt(self.deposit)) + self.db_set("allocated_amount", flt(allocated_amount)) + self.db_set("unallocated_amount", amount - flt(allocated_amount)) + self.reload() self.set_status(update=True) def add_payment_entries(self, vouchers): "Add the vouchers with zero allocation. Save() will perform the allocations and clearance" if 0.0 >= self.unallocated_amount: - frappe.throw(_("Bank Transaction {0} is already fully reconciled").format(self.name)) + frappe.throw(frappe._("Bank Transaction {0} is already fully reconciled").format(self.name)) + added = False for voucher in vouchers: - self.append( - "payment_entries", - { + # Can't add same voucher twice + found = False + for pe in self.payment_entries: + if ( + pe.payment_document == voucher["payment_doctype"] + and pe.payment_entry == voucher["payment_name"] + ): + found = True + + if not found: + pe = { "payment_document": voucher["payment_doctype"], "payment_entry": voucher["payment_name"], "allocated_amount": 0.0, # Temporary - }, - ) + } + child = self.append("payment_entries", pe) + added = True + + # runs on_update_after_submit + if added: + self.save() def allocate_payment_entries(self): """Refactored from bank reconciliation tool. @@ -85,7 +90,6 @@ def allocate_payment_entries(self): - clear means: set the latest transaction date as clearance date """ remaining_amount = self.unallocated_amount - to_remove = [] for payment_entry in self.payment_entries: if payment_entry.allocated_amount == 0.0: unallocated_amount, should_clear, latest_transaction = get_clearance_details( @@ -95,39 +99,49 @@ def allocate_payment_entries(self): if 0.0 == unallocated_amount: if should_clear: latest_transaction.clear_linked_payment_entry(payment_entry) - to_remove.append(payment_entry) + self.db_delete_payment_entry(payment_entry) elif remaining_amount <= 0.0: - to_remove.append(payment_entry) + self.db_delete_payment_entry(payment_entry) - elif 0.0 < unallocated_amount <= remaining_amount: - payment_entry.allocated_amount = unallocated_amount + elif 0.0 < unallocated_amount and unallocated_amount <= remaining_amount: + payment_entry.db_set("allocated_amount", unallocated_amount) remaining_amount -= unallocated_amount if should_clear: latest_transaction.clear_linked_payment_entry(payment_entry) - elif 0.0 < unallocated_amount: - payment_entry.allocated_amount = remaining_amount + elif 0.0 < unallocated_amount and unallocated_amount > remaining_amount: + payment_entry.db_set("allocated_amount", remaining_amount) remaining_amount = 0.0 elif 0.0 > unallocated_amount: - frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount)) + self.db_delete_payment_entry(payment_entry) + frappe.throw(frappe._("Voucher {0} is over-allocated by {1}").format(unallocated_amount)) + + self.reload() - for payment_entry in to_remove: - self.remove(to_remove) + def db_delete_payment_entry(self, payment_entry): + frappe.db.delete("Bank Transaction Payments", {"name": payment_entry.name}) @frappe.whitelist() def remove_payment_entries(self): for payment_entry in self.payment_entries: self.remove_payment_entry(payment_entry) - - self.save() # runs before_update_after_submit + # runs on_update_after_submit + self.save() def remove_payment_entry(self, payment_entry): "Clear payment entry and clearance" self.clear_linked_payment_entry(payment_entry, for_cancel=True) self.remove(payment_entry) + def clear_linked_payment_entries(self, for_cancel=False): + if for_cancel: + for payment_entry in self.payment_entries: + self.clear_linked_payment_entry(payment_entry, for_cancel) + else: + self.allocate_payment_entries() + def clear_linked_payment_entry(self, payment_entry, for_cancel=False): clearance_date = None if for_cancel else self.date set_voucher_clearance( @@ -148,10 +162,11 @@ def auto_set_party(self): deposit=self.deposit, ).match() - if not result: - return - - self.party_type, self.party = result + if result: + party_type, party = result + frappe.db.set_value( + "Bank Transaction", self.name, field={"party_type": party_type, "party": party} + ) @frappe.whitelist() @@ -183,7 +198,9 @@ def get_clearance_details(transaction, payment_entry): if gle["gl_account"] == gl_bank_account: if gle["amount"] <= 0.0: frappe.throw( - _("Voucher {0} value is broken: {1}").format(payment_entry.payment_entry, gle["amount"]) + frappe._("Voucher {0} value is broken: {1}").format( + payment_entry.payment_entry, gle["amount"] + ) ) unmatched_gles -= 1 @@ -204,7 +221,7 @@ def get_clearance_details(transaction, payment_entry): def get_related_bank_gl_entries(doctype, docname): # nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql - return frappe.db.sql( + result = frappe.db.sql( """ SELECT ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount, @@ -222,6 +239,7 @@ def get_related_bank_gl_entries(doctype, docname): dict(doctype=doctype, docname=docname), as_dict=True, ) + return result def get_total_allocated_amount(doctype, docname): @@ -354,7 +372,6 @@ def set_voucher_clearance(doctype, docname, clearance_date, self): if clearance_date: vouchers = [{"payment_doctype": "Bank Transaction", "payment_name": self.name}] bt.add_payment_entries(vouchers) - bt.save() else: for pe in bt.payment_entries: if pe.payment_document == self.doctype and pe.payment_entry == self.name: From c87a3c7793d577a6544b65148f59899a14e19b8b Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Tue, 12 Dec 2023 05:25:15 +0100 Subject: [PATCH 08/14] fix: typo in unittest (#38673) (cherry picked from commit 6ad298adfcac1932a7e0b37b8cab3bfdfcffd32a) --- .../repost_accounting_ledger/test_repost_accounting_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py index dda0ec778f65..1bce1a619941 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py @@ -22,7 +22,7 @@ def setUp(self): self.create_item() self.update_repost_settings() - def teadDown(self): + def tearDown(self): frappe.db.rollback() def update_repost_settings(self): From 7c080bd60c3c88b2530f3fcf1a71e990937de597 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 12 Dec 2023 10:20:26 +0530 Subject: [PATCH 09/14] refactor(test): repost utility deletion flag test (cherry picked from commit cc15f695b428945fa1e3d3f29a3e9cbdb46853d4) --- .../test_repost_accounting_ledger.py | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py index dda0ec778f65..2c24b760f2f2 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py @@ -177,34 +177,40 @@ def test_03_deletion_flag_and_preview_function(self): pe = get_payment_entry(si.doctype, si.name) pe.save().submit() - # without deletion flag set + # with deletion flag set ral = frappe.new_doc("Repost Accounting Ledger") ral.company = self.company - ral.delete_cancelled_entries = False + ral.delete_cancelled_entries = True ral.append("vouchers", {"voucher_type": si.doctype, "voucher_no": si.name}) ral.append("vouchers", {"voucher_type": pe.doctype, "voucher_no": pe.name}) - ral.save() - - # assert preview data is generated - preview = ral.generate_preview() - self.assertIsNotNone(preview) - ral.save().submit() - # background jobs don't run on test cases. Manually triggering repost function. start_repost(ral.name) + self.assertIsNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) + self.assertIsNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) - self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) - self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) + def test_05_without_deletion_flag(self): + si = create_sales_invoice( + item=self.item, + company=self.company, + customer=self.customer, + debit_to=self.debit_to, + parent_cost_center=self.cost_center, + cost_center=self.cost_center, + rate=100, + ) - # with deletion flag set + pe = get_payment_entry(si.doctype, si.name) + pe.save().submit() + + # without deletion flag set ral = frappe.new_doc("Repost Accounting Ledger") ral.company = self.company - ral.delete_cancelled_entries = True + ral.delete_cancelled_entries = False ral.append("vouchers", {"voucher_type": si.doctype, "voucher_no": si.name}) ral.append("vouchers", {"voucher_type": pe.doctype, "voucher_no": pe.name}) ral.save().submit() start_repost(ral.name) - self.assertIsNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) - self.assertIsNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) + self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) + self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) From f0408c89cee20dd3e15cdce804254b61eead4909 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 12 Dec 2023 10:34:51 +0530 Subject: [PATCH 10/14] refactor: remove explicit commit on repost (cherry picked from commit a97b3db749b2850659c733d0cddebfc92fb38cb8) --- .../repost_accounting_ledger/repost_accounting_ledger.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py index 1d72a46c12f4..df4a066f4c83 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -152,8 +152,6 @@ def start_repost(account_repost_doc=str) -> None: doc.make_gl_entries(1) doc.make_gl_entries() - frappe.db.commit() - def get_allowed_types_from_settings(): return [ From 4542a12787f41a8c781497cb344b7fffbbcf3c17 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 12 Dec 2023 11:30:33 +0530 Subject: [PATCH 11/14] refactor: increase limit and remove explicit call to start_repost (cherry picked from commit ccff58856390aa56e1ae104a9c53712fb774b704) --- .../repost_accounting_ledger/repost_accounting_ledger.py | 2 +- .../test_repost_accounting_ledger.py | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py index df4a066f4c83..9211b286c7d4 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -108,7 +108,7 @@ def generate_preview(self): return rendered_page def on_submit(self): - if len(self.vouchers) > 1: + if len(self.vouchers) > 5: job_name = "repost_accounting_ledger_" + self.name frappe.enqueue( method="erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.start_repost", diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py index 2c24b760f2f2..4caefadb1013 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py @@ -90,9 +90,6 @@ def test_01_basic_functions(self): # Submit repost document ral.save().submit() - # background jobs don't run on test cases. Manually triggering repost function. - start_repost(ral.name) - res = ( qb.from_(gl) .select(gl.voucher_no, Sum(gl.debit).as_("debit"), Sum(gl.credit).as_("credit")) @@ -185,7 +182,6 @@ def test_03_deletion_flag_and_preview_function(self): ral.append("vouchers", {"voucher_type": pe.doctype, "voucher_no": pe.name}) ral.save().submit() - start_repost(ral.name) self.assertIsNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) self.assertIsNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) @@ -211,6 +207,5 @@ def test_05_without_deletion_flag(self): ral.append("vouchers", {"voucher_type": pe.doctype, "voucher_no": pe.name}) ral.save().submit() - start_repost(ral.name) self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) From e61a12b4cbf8b3c1fda9ba88b9541a5e7352c98e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 12 Dec 2023 11:37:06 +0530 Subject: [PATCH 12/14] refactor(test): update repost settings before test case (cherry picked from commit acb6e8e1209b7ac97e0503ad89d9f52b8a8e28d5) --- .../test_repost_accounting_ledger.py | 17 +++++++++-------- .../doctype/sales_invoice/test_sales_invoice.py | 6 ++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py index 4caefadb1013..471a463d9580 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py @@ -20,18 +20,11 @@ def setUp(self): self.create_company() self.create_customer() self.create_item() - self.update_repost_settings() + update_repost_settings() def teadDown(self): frappe.db.rollback() - def update_repost_settings(self): - allowed_types = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"] - repost_settings = frappe.get_doc("Repost Accounting Ledger Settings") - for x in allowed_types: - repost_settings.append("allowed_types", {"document_type": x, "allowed": True}) - repost_settings.save() - def test_01_basic_functions(self): si = create_sales_invoice( item=self.item, @@ -209,3 +202,11 @@ def test_05_without_deletion_flag(self): self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1})) self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1})) + + +def update_repost_settings(): + allowed_types = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"] + repost_settings = frappe.get_doc("Repost Accounting Ledger Settings") + for x in allowed_types: + repost_settings.append("allowed_types", {"document_type": x, "allowed": True}) + repost_settings.save() diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 584f297c904c..d050299912db 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2791,6 +2791,12 @@ def test_sales_invoice_with_discount_accounting_enabled(self): @change_settings("Selling Settings", {"enable_discount_accounting": 1}) def test_additional_discount_for_sales_invoice_with_discount_accounting_enabled(self): + from erpnext.accounts.doctype.repost_accounting_ledger.test_repost_accounting_ledger import ( + update_repost_settings, + ) + + update_repost_settings() + additional_discount_account = create_account( account_name="Discount Account", parent_account="Indirect Expenses - _TC", From fa79a7cdab742603fdc26708a4b887de0be88581 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 12 Dec 2023 13:35:41 +0530 Subject: [PATCH 13/14] refactor: add `get_list` for virtual child doctypes (cherry picked from commit 15c90551b68f5cee549a1b53e564012b394e37cb) --- .../payment_reconciliation_allocation.py | 4 +++- .../payment_reconciliation_invoice.py | 4 +++- .../payment_reconciliation_payment.py | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py index 9db8e62af08b..d7b457a83a78 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py @@ -6,4 +6,6 @@ class PaymentReconciliationAllocation(Document): - pass + @staticmethod + def get_list(args): + pass diff --git a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py index 7665b75ff0fd..eb7e4a5ad172 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py +++ b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py @@ -6,4 +6,6 @@ class PaymentReconciliationInvoice(Document): - pass + @staticmethod + def get_list(args): + pass diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py index c0e3fd641ad3..1c66b9b4cb58 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py @@ -6,4 +6,6 @@ class PaymentReconciliationPayment(Document): - pass + @staticmethod + def get_list(args): + pass From 753a1b511d2696d241625f285a7db59e29092bd3 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Tue, 12 Dec 2023 20:53:44 +0530 Subject: [PATCH 14/14] fix: 1st row depr. sch. value of asset put to less than 180 days acc. to I.T. S. 32 (#38697) fix: 1st row value of asset put to less than 180 days acc. to IT S. 32 --- erpnext/assets/doctype/asset/asset.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index e9c1e14b94cd..92a349abb3e2 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -427,6 +427,10 @@ def _make_depreciation_schedule( n == 0 and (has_pro_rata or has_wdv_or_dd_non_yearly_pro_rata) and not self.opening_accumulated_depreciation + and get_updated_rate_of_depreciation_for_wdv_and_dd( + self, value_after_depreciation, finance_book, False + ) + == finance_book.rate_of_depreciation ): from_date = add_days( self.available_for_use_date, -1 @@ -1387,7 +1391,9 @@ def get_depreciation_amount( @erpnext.allow_regional -def get_updated_rate_of_depreciation_for_wdv_and_dd(asset, depreciable_value, fb_row): +def get_updated_rate_of_depreciation_for_wdv_and_dd( + asset, depreciable_value, fb_row, show_msg=True +): return fb_row.rate_of_depreciation