From ad04610c94c62de6c54fa05bde2c32331b222af3 Mon Sep 17 00:00:00 2001 From: Vishakh Desai Date: Tue, 1 Oct 2024 12:25:04 +0530 Subject: [PATCH 01/22] fix: get stock accounts from the doc instead of db in validate_stock_accounts (cherry picked from commit 30954586d8d8f63869cce9446b93ba6089ad4899) --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- erpnext/accounts/utils.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index b4fb13e42c3..c1d91c49d8f 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -153,7 +153,7 @@ class JournalEntry(AccountsController): frappe.throw(_("Journal Entry type should be set as Depreciation Entry for asset depreciation")) def validate_stock_accounts(self): - stock_accounts = get_stock_accounts(self.company, self.doctype, self.name) + stock_accounts = get_stock_accounts(self.company, accounts=self.accounts) for account in stock_accounts: account_bal, stock_bal, warehouse_list = get_stock_and_account_balance( account, self.posting_date, self.company diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 10f30512c0b..cb5b4479408 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1524,12 +1524,16 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle, precision): return matched -def get_stock_accounts(company, voucher_type=None, voucher_no=None): +def get_stock_accounts(company, voucher_type=None, voucher_no=None, accounts=None): stock_accounts = [ d.name for d in frappe.db.get_all("Account", {"account_type": "Stock", "company": company, "is_group": 0}) ] - if voucher_type and voucher_no: + + if accounts: + stock_accounts = [row.account for row in accounts if row.account in stock_accounts] + + elif voucher_type and voucher_no: if voucher_type == "Journal Entry": stock_accounts = [ d.account From f5f6c7609a42563df19fa873d19fc6d83c7c10bd Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 22 Oct 2024 20:27:06 +0530 Subject: [PATCH 02/22] test: fix test case --- erpnext/accounts/doctype/journal_entry/test_journal_entry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index 979f964b62a..f219c228421 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -146,12 +146,12 @@ class TestJournalEntry(unittest.TestCase): "credit_in_account_currency": 0 if diff > 0 else abs(diff), }, ) - jv.insert() if account_bal == stock_bal: - self.assertRaises(StockAccountInvalidTransaction, jv.submit) + self.assertRaises(StockAccountInvalidTransaction, jv.insert) frappe.db.rollback() else: + jv.insert() jv.submit() jv.cancel() From d3e29fe828f0956c8d042d734697923557e058a8 Mon Sep 17 00:00:00 2001 From: IamSaiyyamChhetri Date: Mon, 21 Oct 2024 12:28:27 +0530 Subject: [PATCH 03/22] fix: add company filter for project - In Project dt Sales Order field - In Sales Order dt Project field (cherry picked from commit 9909d760a529192e0fe26eeae03ed6c7e1b5375b) --- erpnext/projects/doctype/project/project.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index 6ac6d1f88a6..b5d169f2364 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -47,6 +47,7 @@ frappe.ui.form.on("Project", { frm.set_query("sales_order", function () { var filters = { project: ["in", frm.doc.__islocal ? [""] : [frm.doc.name, ""]], + company: frm.doc.company, }; if (frm.doc.customer) { From 2f3c3d55195497db215c654ac17da5339b6eda4f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 25 Oct 2024 13:30:28 +0530 Subject: [PATCH 04/22] fix: set bill_no before `against_voucher` gets concatenated (cherry picked from commit 7bade7f1fe08370d655e12929b2376814dac018a) --- .../accounts/report/general_ledger/general_ledger.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index b7f035b1e80..0436dc51214 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -337,9 +337,17 @@ def get_accounts_with_children(accounts): return list(set(all_accounts)) if all_accounts else None +def set_bill_no(gl_entries): + inv_details = get_supplier_invoice_details() + for gl in gl_entries: + gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "") + + def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries): data = [] + set_bill_no(gl_entries) + gle_map = initialize_gle_map(gl_entries, filters) totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map) @@ -513,7 +521,6 @@ def get_account_type_map(company): def get_result_as_list(data, filters): balance, _balance_in_account_currency = 0, 0 - inv_details = get_supplier_invoice_details() for d in data: if not d.get("posting_date"): @@ -523,7 +530,6 @@ def get_result_as_list(data, filters): d["balance"] = balance d["account_currency"] = filters.account_currency - d["bill_no"] = inv_details.get(d.get("against_voucher"), "") return data From 895f1bff0135c02338441a0ae29275841252faad Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 26 Oct 2024 19:51:31 +0200 Subject: [PATCH 05/22] fix(RFQ): make strings translatable (backport #43843) (#43847) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> fix(RFQ): make strings translatable (#43843) --- .../request_for_quotation/request_for_quotation.js | 10 ++++++---- erpnext/translations/de.csv | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js index 30abad528bf..fd2af857869 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js @@ -137,8 +137,8 @@ frappe.ui.form.on("Request for Quotation",{ return; } }, - "Download PDF for Supplier", - "Download" + __("Download PDF for Supplier"), + __("Download") ); }, __("Tools") @@ -257,8 +257,10 @@ frappe.ui.form.on("Request for Quotation",{ }); }; - dialog.fields_dict.note.$wrapper.append(`

This is a preview of the email to be sent. A PDF of the document will - automatically be attached with the email.

`); + const msg = __( + "This is a preview of the email to be sent. A PDF of the document will automatically be attached with the email." + ); + dialog.fields_dict.note.$wrapper.append(`

${msg}

`); dialog.show(); } diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 8161e44cb80..adbbabf2a75 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -5268,6 +5268,7 @@ Request for Quotation Supplier,Angebotsanfrage Lieferant, Send Email,E-Mail absenden, Quote Status,Zitat Status, Download PDF,PDF Herunterladen, +Download PDF for Supplier,PDF für Lieferanten herunterladen, Supplier of Goods or Services.,Lieferant von Waren oder Dienstleistungen., Name and Type,Name und Typ, SUP-.YYYY.-,SUP-.YYYY.-, @@ -6624,6 +6625,7 @@ This is a location where operations are executed.,"Dies ist ein Ort, an dem Oper This is a location where final product stored.,"Dies ist ein Ort, an dem das Endprodukt gelagert wird.", Scrap Warehouse,Ausschusslager, This is a location where scraped materials are stored.,"Dies ist ein Ort, an dem abgekratzte Materialien gelagert werden.", +This is a preview of the email to be sent. A PDF of the document will automatically be attached with the email.,Dies ist eine Vorschau der zu sendenden E-Mail. Ein PDF des Dokuments wird automatisch an die E-Mail angehängt., Required Items,Erforderliche Elemente, Actual Start Date,Tatsächliches Startdatum, Planned End Date,Geplantes Enddatum, From 7e7cc807a5ab6ee8b5dcf8e036d60d6181ebdd12 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 25 Oct 2024 17:11:27 +0530 Subject: [PATCH 06/22] refactor: query for expense_account moved to setup hook in purchase invoice (cherry picked from commit a9ac0cc2238d420c518fdcbf69e8ed1defac7f2e) # Conflicts: # erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js --- .../doctype/purchase_invoice/purchase_invoice.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index ff5550489c2..25d0f85ea6e 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -25,6 +25,13 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. } }; }); + + this.frm.set_query("expense_account", "items", function () { + return { + query: "erpnext.controllers.queries.get_expense_account", + filters: { company: doc.company }, + }; + }); } onload() { @@ -469,6 +476,7 @@ cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) } } +<<<<<<< HEAD cur_frm.set_query("expense_account", "items", function(doc) { return { query: "erpnext.controllers.queries.get_expense_account", @@ -477,6 +485,9 @@ cur_frm.set_query("expense_account", "items", function(doc) { }); cur_frm.set_query("wip_composite_asset", "items", function() { +======= +cur_frm.set_query("wip_composite_asset", "items", function () { +>>>>>>> a9ac0cc223 (refactor: query for expense_account moved to setup hook in purchase invoice) return { filters: {'is_composite_asset': 1, 'docstatus': 0 } } From b81dc2bf5eac5e26d9b93dc9ca829f75ccfdcd32 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 28 Oct 2024 09:55:04 +0530 Subject: [PATCH 07/22] chore: resolve conflict --- .../doctype/purchase_invoice/purchase_invoice.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 25d0f85ea6e..503eb751c41 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -476,18 +476,7 @@ cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) } } -<<<<<<< HEAD -cur_frm.set_query("expense_account", "items", function(doc) { - return { - query: "erpnext.controllers.queries.get_expense_account", - filters: {'company': doc.company } - } -}); - cur_frm.set_query("wip_composite_asset", "items", function() { -======= -cur_frm.set_query("wip_composite_asset", "items", function () { ->>>>>>> a9ac0cc223 (refactor: query for expense_account moved to setup hook in purchase invoice) return { filters: {'is_composite_asset': 1, 'docstatus': 0 } } From fd63ace6c785363cbc3431fd54e9739d65873395 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 15 Oct 2024 18:38:42 +0530 Subject: [PATCH 08/22] fix: do not check for payment terms details for return invoices. (cherry picked from commit 6703b7d1aea159d02c4eae6f45e486b27138e29c) --- .../accounts/report/accounts_receivable/accounts_receivable.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 5ef39755ca5..b2a24338cbf 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -500,7 +500,8 @@ class ReceivablePayableReport: from `tab{row.voucher_type}` si, `tabPayment Schedule` ps where si.name = ps.parent and - si.name = %s + si.name = %s and + si.is_return = 0 order by ps.paid_amount desc, due_date """, row.voucher_no, From bd34a6787141c86f5346e8bebfabc88ca7eb0b7d Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 25 Oct 2024 18:09:01 +0530 Subject: [PATCH 09/22] fix: do not set payment terms for return invoices (cherry picked from commit 8b700eadc746698c02573f5af209a962d32be5d6) # Conflicts: # erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js # erpnext/accounts/doctype/sales_invoice/sales_invoice.js --- .../doctype/purchase_invoice/purchase_invoice.js | 8 ++++++++ erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 9 +++++++++ erpnext/controllers/accounts_controller.py | 7 ++++++- erpnext/public/js/controllers/transaction.js | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 503eb751c41..9cfa8930db4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -310,8 +310,16 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. party_type: "Supplier", account: this.frm.doc.credit_to, price_list: this.frm.doc.buying_price_list, +<<<<<<< HEAD fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template) }, function() { +======= + fetch_payment_terms_template: cint( + (this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template + ), + }, + function () { +>>>>>>> 8b700eadc7 (fix: do not set payment terms for return invoices) me.apply_pricing_rule(); me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0; me.frm.doc.tax_withholding_category = me.frm.supplier_tds; diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index bc458ffa272..822b471115e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -280,8 +280,17 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e party_type: "Customer", account: this.frm.doc.debit_to, price_list: this.frm.doc.selling_price_list, +<<<<<<< HEAD pos_profile: pos_profile }, function() { +======= + pos_profile: pos_profile, + fetch_payment_terms_template: cint( + (this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template + ), + }, + function () { +>>>>>>> 8b700eadc7 (fix: do not set payment terms for return invoices) me.apply_pricing_rule(); }); diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index bcdc788df47..4f1e77e72b5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -415,6 +415,11 @@ class AccountsController(TransactionBase): ) def validate_invoice_documents_schedule(self): + if self.is_return: + self.payment_terms_template = "" + self.payment_schedule = [] + return + self.validate_payment_schedule_dates() self.set_due_date() self.set_payment_schedule() @@ -429,7 +434,7 @@ class AccountsController(TransactionBase): self.validate_payment_schedule_amount() def validate_all_documents_schedule(self): - if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.is_return: + if self.doctype in ("Sales Invoice", "Purchase Invoice"): self.validate_invoice_documents_schedule() elif self.doctype in ("Quotation", "Purchase Order", "Sales Order"): self.validate_non_invoice_documents_schedule() diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index f774528ee86..79e14b9eb5b 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -2213,7 +2213,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe payment_terms_template() { var me = this; const doc = this.frm.doc; - if(doc.payment_terms_template && doc.doctype !== 'Delivery Note') { + if(doc.payment_terms_template && doc.doctype !== 'Delivery Note' && doc.is_return == 0) { var posting_date = doc.posting_date || doc.transaction_date; frappe.call({ method: "erpnext.controllers.accounts_controller.get_payment_terms", From 78db8c002989296417aa1ab88b612a2b639e0f40 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 25 Oct 2024 18:14:07 +0530 Subject: [PATCH 10/22] fix: hide payment terms for return and paid purchase invoices (cherry picked from commit 912e1e3f3d3a3e3d8b15fee9dfa1dda7c1922e37) # Conflicts: # erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 3af2617da75..058bcc36f02 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1128,12 +1128,14 @@ "label": "Payment Terms" }, { + "depends_on": "eval:(!doc.is_paid && !doc.is_return)", "fieldname": "payment_terms_template", "fieldtype": "Link", "label": "Payment Terms Template", "options": "Payment Terms Template" }, { + "depends_on": "eval:(!doc.is_paid && !doc.is_return)", "fieldname": "payment_schedule", "fieldtype": "Table", "label": "Payment Schedule", @@ -1611,7 +1613,11 @@ "idx": 204, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2024-09-11 12:59:19.130593", +======= + "modified": "2024-10-25 18:13:01.944477", +>>>>>>> 912e1e3f3d (fix: hide payment terms for return and paid purchase invoices) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", From 627832fe5b173fc33a9b816c4949b4813c6a370e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 28 Oct 2024 10:47:34 +0530 Subject: [PATCH 11/22] refactor: fix garbage title, desc and name in razorpay (cherry picked from commit 7332ec8fbd98585ad3784d6f8fb8fb67ab3aa3fe) --- erpnext/accounts/doctype/payment_request/payment_request.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 47cb3fd812f..628144af638 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -238,12 +238,12 @@ class PaymentRequest(Document): return controller.get_payment_url( **{ "amount": flt(self.grand_total, self.precision("grand_total")), - "title": data.company.encode("utf-8"), - "description": self.subject.encode("utf-8"), + "title": data.company, + "description": self.subject, "reference_doctype": "Payment Request", "reference_docname": self.name, "payer_email": self.email_to or frappe.session.user, - "payer_name": frappe.safe_encode(data.customer_name), + "payer_name": data.customer_name, "order_id": self.name, "currency": self.currency, } From c695959902c59c7a315e2f4519477b1c9a36c0a5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 28 Oct 2024 13:20:07 +0530 Subject: [PATCH 12/22] chore: resolve conflicts --- .../accounts/doctype/purchase_invoice/purchase_invoice.js | 5 ----- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 4 ---- erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 5 ----- 3 files changed, 14 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 9cfa8930db4..dc879cfc1b4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -310,16 +310,11 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. party_type: "Supplier", account: this.frm.doc.credit_to, price_list: this.frm.doc.buying_price_list, -<<<<<<< HEAD - fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template) - }, function() { -======= fetch_payment_terms_template: cint( (this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template ), }, function () { ->>>>>>> 8b700eadc7 (fix: do not set payment terms for return invoices) me.apply_pricing_rule(); me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0; me.frm.doc.tax_withholding_category = me.frm.supplier_tds; diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 058bcc36f02..82c4a224eb4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1613,11 +1613,7 @@ "idx": 204, "is_submittable": 1, "links": [], -<<<<<<< HEAD - "modified": "2024-09-11 12:59:19.130593", -======= "modified": "2024-10-25 18:13:01.944477", ->>>>>>> 912e1e3f3d (fix: hide payment terms for return and paid purchase invoices) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 822b471115e..dffd5d98c4f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -280,17 +280,12 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e party_type: "Customer", account: this.frm.doc.debit_to, price_list: this.frm.doc.selling_price_list, -<<<<<<< HEAD - pos_profile: pos_profile - }, function() { -======= pos_profile: pos_profile, fetch_payment_terms_template: cint( (this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template ), }, function () { ->>>>>>> 8b700eadc7 (fix: do not set payment terms for return invoices) me.apply_pricing_rule(); }); From 51c1d032ba36f081ebd9fc144960f4cd5f8316a0 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:02:23 +0530 Subject: [PATCH 13/22] fix: basic rate not editable in Stock Entry Detail (backport #43837) (#43839) * fix: basic rate not editable in Stock Entry Detail (#43837) (cherry picked from commit 5a967bc868566eae06ce44df894cbb33bc98f869) # Conflicts: # erpnext/stock/doctype/stock_entry/stock_entry.js * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/stock_entry/stock_entry.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index d58361b2d3b..6d18a21fbe3 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -714,7 +714,17 @@ frappe.ui.form.on('Stock Entry', { } }); + frappe.ui.form.on('Stock Entry Detail', { + set_basic_rate_manually(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + frm.fields_dict.items.grid.update_docfield_property( + "basic_rate", + "read_only", + row?.set_basic_rate_manually ? 0 : 1 + ); + }, + qty: function(frm, cdt, cdn) { frm.events.set_serial_no(frm, cdt, cdn, () => { frm.events.set_basic_rate(frm, cdt, cdn); From a7cc7b28c075388b22501d6f68faac3da5a1a20d Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 28 Oct 2024 15:11:07 +0530 Subject: [PATCH 14/22] fix: purchase return validation issue (#43871) --- .../controllers/sales_and_purchase_return.py | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index ba13287ca66..c26644c870b 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -78,6 +78,9 @@ def validate_returned_items(doc): if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]: select_fields += ",rejected_qty, received_qty" + if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]: + select_fields += ",name" + for d in frappe.db.sql( f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""", doc.return_against, @@ -103,15 +106,24 @@ def validate_returned_items(doc): items_returned = False for d in doc.get("items"): + key = d.item_code + raise_exception = False + if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]: + field = frappe.scrub(doc.doctype) + "_item" + if d.get(field): + key = (d.item_code, d.get(field)) + raise_exception = True + if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0): - if d.item_code not in valid_items: - frappe.throw( + if key not in valid_items: + frappe.msgprint( _("Row # {0}: Returned Item {1} does not exist in {2} {3}").format( d.idx, d.item_code, doc.doctype, doc.return_against - ) + ), + raise_exception=raise_exception, ) else: - ref = valid_items.get(d.item_code, frappe._dict()) + ref = valid_items.get(key, frappe._dict()) validate_quantity(doc, d, ref, valid_items, already_returned_items) if ( @@ -206,8 +218,12 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items): def get_ref_item_dict(valid_items, ref_item_row): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + key = ref_item_row.item_code + if ref_item_row.get("name"): + key = (ref_item_row.item_code, ref_item_row.name) + valid_items.setdefault( - ref_item_row.item_code, + key, frappe._dict( { "qty": 0, @@ -221,7 +237,7 @@ def get_ref_item_dict(valid_items, ref_item_row): } ), ) - item_dict = valid_items[ref_item_row.item_code] + item_dict = valid_items[key] item_dict["qty"] += ref_item_row.qty item_dict["stock_qty"] += ref_item_row.get("stock_qty", 0) if ref_item_row.get("rate", 0) > item_dict["rate"]: From aaae81f7e872f6e6fb475ed751212d025c6c6709 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:12:16 +0530 Subject: [PATCH 15/22] fix: added validation for UOM must be whole number (backport #43710) (#43711) * fix: added validation for UOM must be whole number (#43710) (cherry picked from commit 4fd4a37dc931b48526a5e00b0a905a735b435778) # Conflicts: # erpnext/controllers/accounts_controller.py * chore: fix conflicts * chore: fix linters issue --------- Co-authored-by: rohitwaghchaure --- erpnext/controllers/accounts_controller.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index bcdc788df47..ebd6594a2a8 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -3308,6 +3308,9 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil parent.update_billing_percentage() parent.set_status() + parent.validate_uom_is_integer("uom", "qty") + parent.validate_uom_is_integer("stock_uom", "stock_qty") + def check_if_child_table_updated(child_table_before_update, child_table_after_update, fields_to_check): accounting_dimensions = [*get_accounting_dimensions(), "cost_center", "project"] From 3fa392ebdf7009a9137785e24cc3ad964ca1b9a6 Mon Sep 17 00:00:00 2001 From: "lukas.brandhoff" Date: Wed, 16 Oct 2024 13:24:57 +0000 Subject: [PATCH 16/22] refactor: include 'Project Name' in Project summary report Keep name field for backwards compatibility (cherry picked from commit 736d1a1105009c272c6b2ba3cec6b6741c39b62d) --- .../projects/report/project_summary/project_summary.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/projects/report/project_summary/project_summary.py b/erpnext/projects/report/project_summary/project_summary.py index 7a35fd236a0..261517f02c6 100644 --- a/erpnext/projects/report/project_summary/project_summary.py +++ b/erpnext/projects/report/project_summary/project_summary.py @@ -15,6 +15,7 @@ def execute(filters=None): filters=filters, fields=[ "name", + "project_name", "status", "percent_complete", "expected_start_date", @@ -48,6 +49,11 @@ def get_columns(): "options": "Project", "width": 200, }, + { + "fieldname": "project_name", + "label": _("Project Name"), + "width": 200, + }, { "fieldname": "project_type", "label": _("Type"), @@ -82,7 +88,7 @@ def get_chart_data(data): overdue = [] for project in data: - labels.append(project.name) + labels.append(project.project_name) total.append(project.total_tasks) completed.append(project.completed_tasks) overdue.append(project.overdue_tasks) From 0742e6e19389c6883a789ef498bdee82ba930476 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 29 Oct 2024 15:35:19 +0530 Subject: [PATCH 17/22] fix: not able to submit stock entry (#43890) --- erpnext/stock/doctype/serial_no/serial_no.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 25932a3ad04..90d5c3201e6 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -335,11 +335,16 @@ def validate_serial_no(sle, item_det): if sr.work_order and work_order and sr.work_order == work_order: allow_existing_serial_no = True - if not allow_existing_serial_no and sle.voucher_type in [ - "Stock Entry", - "Purchase Receipt", - "Purchase Invoice", - ]: + if ( + not allow_existing_serial_no + and sle.voucher_type + in [ + "Stock Entry", + "Purchase Receipt", + "Purchase Invoice", + ] + and cint(sle.actual_qty) > 0 + ): msg = "" if sle.voucher_type == "Stock Entry": From cbe704c73c9959f80a66acc17ff61126c27fcd50 Mon Sep 17 00:00:00 2001 From: Imesha Sudasingha Date: Mon, 28 Oct 2024 03:43:56 +0000 Subject: [PATCH 18/22] fix: add parenttype clause to invoice tax query in sales_register report (cherry picked from commit e30ab141f4bc51b1378eb80d1bf3885453afbcfe) --- erpnext/accounts/report/sales_register/sales_register.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 3e7ac1a818d..c2c2454dde3 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -522,7 +522,8 @@ def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts, inclu tax_details = frappe.db.sql( """select parent, account_head, sum(base_tax_amount_after_discount_amount) as tax_amount - from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" + from `tabSales Taxes and Charges` where parent in (%s) and parenttype = 'Sales Invoice' + group by parent, account_head""" % ", ".join(["%s"] * len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1, From 76530de786d9a220ca9e59720184b5d5b9328979 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 22:00:36 +0530 Subject: [PATCH 19/22] fix: work order finish button not showing (backport #43875) (#43877) * fix: work order finish button not showing (#43875) (cherry picked from commit 0a70be5b993895dcc888c7418bbd675224554d2b) # Conflicts: # erpnext/manufacturing/doctype/job_card/job_card.js # erpnext/manufacturing/doctype/job_card/job_card.py * chore: fix conflicts * chore: fix conflicts * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- .../doctype/job_card/job_card.py | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index ccabf14cde4..349e7eb4b3f 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -767,26 +767,19 @@ class JobCard(Document): qty = 0 if self.work_order: - doc = frappe.get_doc("Work Order", self.work_order) if doc.transfer_material_against == "Job Card" and not doc.skip_transfer: - completed = True + min_qty = [] for d in doc.operations: - if d.status != "Completed": - completed = False + if d.completed_qty: + min_qty.append(d.completed_qty) + else: + min_qty = [] break - if completed: - job_cards = frappe.get_all( - "Job Card", - filters={"work_order": self.work_order, "docstatus": ("!=", 2)}, - fields="sum(transferred_qty) as qty", - group_by="operation_id", - ) + if min_qty: + qty = min(min_qty) - if job_cards: - qty = min(d.qty for d in job_cards) - - doc.db_set("material_transferred_for_manufacturing", qty) + doc.db_set("material_transferred_for_manufacturing", qty) self.set_status(update_status) From 93243b1d95b7412ea307c16bf63c08193e17d5a2 Mon Sep 17 00:00:00 2001 From: Ahmed Shareef Date: Tue, 29 Oct 2024 11:07:58 +0400 Subject: [PATCH 20/22] fix: remarks field in payment reconciliation (cherry picked from commit 2d5b079949ce13a162686780c2b4cde5c7fb1071) # Conflicts: # erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json # erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py --- .../payment_reconciliation.py | 1 + .../payment_reconciliation_payment.json | 18 ++++++++----- .../payment_reconciliation_payment.py | 27 +++++++++++++++++++ erpnext/accounts/utils.py | 2 ++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 9480aeb7746..218add540d3 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -256,6 +256,7 @@ class PaymentReconciliation(Document): "posting_date": inv.posting_date, "currency": inv.currency, "cost_center": inv.cost_center, + "remarks": inv.remarks, } ) ) diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json index d199236ae99..8e3ff2288aa 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json @@ -14,7 +14,7 @@ "amount", "difference_amount", "sec_break1", - "remark", + "remarks", "currency", "exchange_rate", "cost_center" @@ -74,12 +74,6 @@ "fieldname": "sec_break1", "fieldtype": "Section Break" }, - { - "fieldname": "remark", - "fieldtype": "Small Text", - "label": "Remark", - "read_only": 1 - }, { "fieldname": "currency", "fieldtype": "Link", @@ -105,12 +99,22 @@ "fieldtype": "Link", "label": "Cost Center", "options": "Cost Center" + }, + { + "fieldname": "remarks", + "fieldtype": "Small Text", + "label": "Remarks", + "read_only": 1 } ], "is_virtual": 1, "istable": 1, "links": [], +<<<<<<< HEAD "modified": "2023-11-17 17:33:34.818530", +======= + "modified": "2024-10-29 16:24:43.021230", +>>>>>>> 2d5b079949 (fix: remarks field in payment reconciliation) "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Payment", 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 1c66b9b4cb5..e55d6a717b3 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py @@ -6,6 +6,33 @@ from frappe.model.document import Document class PaymentReconciliationPayment(Document): +<<<<<<< HEAD +======= + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + cost_center: DF.Link | None + currency: DF.Link | None + difference_amount: DF.Currency + exchange_rate: DF.Float + is_advance: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + posting_date: DF.Date | None + reference_name: DF.DynamicLink | None + reference_row: DF.Data | None + reference_type: DF.Link | None + remarks: DF.SmallText | None + # end: auto-generated types + +>>>>>>> 2d5b079949 (fix: remarks field in payment reconciliation) @staticmethod def get_list(args): pass diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index cb5b4479408..5bb453d3491 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1930,6 +1930,7 @@ class QueryPaymentLedger: ple.cost_center.as_("cost_center"), Sum(ple.amount).as_("amount"), Sum(ple.amount_in_account_currency).as_("amount_in_account_currency"), + ple.remarks, ) .where(ple.delinked == 0) .where(Criterion.all(filter_on_voucher_no)) @@ -1992,6 +1993,7 @@ class QueryPaymentLedger: Table("vouchers").due_date, Table("vouchers").currency, Table("vouchers").cost_center.as_("cost_center"), + Table("vouchers").remarks, ) .where(Criterion.all(filter_on_outstanding_amount)) ) From 15881ea71865cab1a4d61dad27df8d6c00b92daa Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 30 Oct 2024 10:28:30 +0530 Subject: [PATCH 21/22] chore: resolve conflicts --- .../payment_reconciliation_payment.json | 4 --- .../payment_reconciliation_payment.py | 27 ------------------- 2 files changed, 31 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json index 8e3ff2288aa..010e93558cf 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json @@ -110,11 +110,7 @@ "is_virtual": 1, "istable": 1, "links": [], -<<<<<<< HEAD - "modified": "2023-11-17 17:33:34.818530", -======= "modified": "2024-10-29 16:24:43.021230", ->>>>>>> 2d5b079949 (fix: remarks field in payment reconciliation) "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Payment", 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 e55d6a717b3..1c66b9b4cb5 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py @@ -6,33 +6,6 @@ from frappe.model.document import Document class PaymentReconciliationPayment(Document): -<<<<<<< HEAD -======= - # begin: auto-generated types - # This code is auto-generated. Do not modify anything in this block. - - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from frappe.types import DF - - amount: DF.Currency - cost_center: DF.Link | None - currency: DF.Link | None - difference_amount: DF.Currency - exchange_rate: DF.Float - is_advance: DF.Data | None - parent: DF.Data - parentfield: DF.Data - parenttype: DF.Data - posting_date: DF.Date | None - reference_name: DF.DynamicLink | None - reference_row: DF.Data | None - reference_type: DF.Link | None - remarks: DF.SmallText | None - # end: auto-generated types - ->>>>>>> 2d5b079949 (fix: remarks field in payment reconciliation) @staticmethod def get_list(args): pass From 55c5f30d5457a0ce19ad2827a97a656211876541 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:26:08 +0530 Subject: [PATCH 22/22] fix: calculate tds with net amount when invoice exceeds single threshold amount (backport #43869) (#43919) * fix: calculate tds with net amount when invoice exceeds single threshold amount (cherry picked from commit ef694a40a1945fb4bd1f56a962a9245a6e76706b) * test: add unit test to validate purchase invoice exceeding single threshold value (cherry picked from commit 94badb464db4e598fd6fec72d3ee4d914d02d87d) --------- Co-authored-by: venkat102 --- .../tax_withholding_category.py | 20 +++++----- .../test_tax_withholding_category.py | 40 +++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index d1bb2461795..187e5026e24 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -482,7 +482,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers): payment_entry_filters.pop("apply_tax_withholding_amount", None) payment_entry_filters.pop("tax_withholding_category", None) - supp_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0 + supp_inv_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0 supp_jv_credit_amt = ( frappe.db.get_value( @@ -506,7 +506,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers): group_by="payment_type", ) - supp_credit_amt += supp_jv_credit_amt + supp_credit_amt = supp_jv_credit_amt supp_credit_amt += inv.tax_withholding_net_total for type in payment_entry_amounts: @@ -524,18 +524,18 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers): tax_withholding_net_total = inv.tax_withholding_net_total if (threshold and tax_withholding_net_total >= threshold) or ( - cumulative_threshold and supp_credit_amt >= cumulative_threshold + cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold ): + # Get net total again as TDS is calculated on net total + # Grand is used to just check for threshold breach + net_total = ( + frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") or 0.0 + ) + supp_credit_amt += net_total + if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint( tax_details.tax_on_excess_amount ): - # Get net total again as TDS is calculated on net total - # Grand is used to just check for threshold breach - net_total = ( - frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") - or 0.0 - ) - net_total += inv.tax_withholding_net_total supp_credit_amt = net_total - cumulative_threshold if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0): diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py index b4550d2bb53..83b53aa7ae6 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py @@ -121,6 +121,46 @@ class TestTaxWithholdingCategory(FrappeTestCase): for d in reversed(invoices): d.cancel() + def test_cumulative_threshold_with_party_ledger_amount_on_net_total(self): + invoices = [] + frappe.db.set_value( + "Supplier", "Test TDS Supplier3", "tax_withholding_category", "Advance TDS Category" + ) + + # Invoice with tax and without exceeding single and cumulative thresholds + for _ in range(2): + pi = create_purchase_invoice(supplier="Test TDS Supplier3", rate=1000, do_not_save=True) + pi.apply_tds = 1 + pi.append( + "taxes", + { + "category": "Total", + "charge_type": "Actual", + "account_head": "_Test Account VAT - _TC", + "cost_center": "Main - _TC", + "tax_amount": 500, + "description": "Test", + "add_deduct_tax": "Add", + }, + ) + pi.save() + pi.submit() + invoices.append(pi) + + # Third Invoice exceeds single threshold and not exceeding cumulative threshold + pi1 = create_purchase_invoice(supplier="Test TDS Supplier3", rate=6000) + pi1.apply_tds = 1 + pi1.save() + pi1.submit() + invoices.append(pi1) + + # Cumulative threshold is 10,000 + # Threshold calculation should be only on the third invoice + self.assertEqual(pi1.taxes[0].tax_amount, 800) + + for d in reversed(invoices): + d.cancel() + def test_cumulative_threshold_tcs(self): frappe.db.set_value( "Customer", "Test TCS Customer", "tax_withholding_category", "Cumulative Threshold TCS"