From f654c2d156e9fab1c74683fc264ab72d14cf0c88 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan <67804911+iamejaaz@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:17:59 +0530 Subject: [PATCH 1/7] refactor: change sales invoice button position (#45130) (cherry picked from commit a0f17f8e7381c31dc2f704ecc238983179ef4c5f) --- .../doctype/sales_invoice/sales_invoice.js | 84 ++++++++++--------- erpnext/public/js/controllers/transaction.js | 3 +- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 75c71ef6eb3..c07e2a392ae 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -994,47 +994,51 @@ frappe.ui.form.on("Sales Invoice", { refresh: function (frm) { if (frm.doc.docstatus === 0 && !frm.doc.is_return) { - frm.add_custom_button(__("Fetch Timesheet"), function () { - let d = new frappe.ui.Dialog({ - title: __("Fetch Timesheet"), - fields: [ - { - label: __("From"), - fieldname: "from_time", - fieldtype: "Date", - reqd: 1, + frm.add_custom_button( + __("Timesheet"), + function () { + let d = new frappe.ui.Dialog({ + title: __("Fetch Timesheet"), + fields: [ + { + label: __("From"), + fieldname: "from_time", + fieldtype: "Date", + reqd: 1, + }, + { + fieldtype: "Column Break", + fieldname: "col_break_1", + }, + { + label: __("To"), + fieldname: "to_time", + fieldtype: "Date", + reqd: 1, + }, + { + label: __("Project"), + fieldname: "project", + fieldtype: "Link", + options: "Project", + default: frm.doc.project, + }, + ], + primary_action: function () { + const data = d.get_values(); + frm.events.add_timesheet_data(frm, { + from_time: data.from_time, + to_time: data.to_time, + project: data.project, + }); + d.hide(); }, - { - fieldtype: "Column Break", - fieldname: "col_break_1", - }, - { - label: __("To"), - fieldname: "to_time", - fieldtype: "Date", - reqd: 1, - }, - { - label: __("Project"), - fieldname: "project", - fieldtype: "Link", - options: "Project", - default: frm.doc.project, - }, - ], - primary_action: function () { - const data = d.get_values(); - frm.events.add_timesheet_data(frm, { - from_time: data.from_time, - to_time: data.to_time, - project: data.project, - }); - d.hide(); - }, - primary_action_label: __("Get Timesheets"), - }); - d.show(); - }); + primary_action_label: __("Get Timesheets"), + }); + d.show(); + }, + __("Get Items From") + ); } if (frm.doc.is_debit_note) { diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index b3389b27e84..9e3a76b12ca 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -303,11 +303,10 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } const me = this; - if (!this.frm.is_new() && this.frm.doc.docstatus === 0 && frappe.model.can_create("Quality Inspection")) { + if (!this.frm.is_new() && this.frm.doc.docstatus === 0 && frappe.model.can_create("Quality Inspection") && this.frm.doc.update_stock) { this.frm.add_custom_button(__("Quality Inspection(s)"), () => { me.make_quality_inspection(); }, __("Create")); - this.frm.page.set_inner_btn_group_as_primary(__('Create')); } const inspection_type = ["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"].includes(this.frm.doc.doctype) From 54e3a749365c6979fb83b2cb962fd4db8f04cd60 Mon Sep 17 00:00:00 2001 From: Diptanil Saha Date: Tue, 7 Jan 2025 18:06:02 +0530 Subject: [PATCH 2/7] fix: serial and batch no. buttons on pos (#45048) (cherry picked from commit 31dd32dcdfcb054595cfa04ad1efa43377783656) --- .../page/point_of_sale/pos_item_details.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js index 2c93a0d546b..333b50810c9 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_details.js +++ b/erpnext/selling/page/point_of_sale/pos_item_details.js @@ -210,10 +210,21 @@ erpnext.PointOfSale.ItemDetails = class { make_auto_serial_selection_btn(item) { if (item.has_serial_no || item.has_batch_no) { - const label = item.has_serial_no ? __("Select Serial No") : __("Select Batch No"); - this.$form_container.append( - `
${label}
` - ); + if (item.has_serial_no && item.has_batch_no) { + this.$form_container.append( + `
${__( + "Select Serial No / Batch No" + )}
` + ); + } else { + const classname = item.has_serial_no ? ".serial_no-control" : ".batch_no-control"; + const label = item.has_serial_no ? __("Select Serial No") : __("Select Batch No"); + this.$form_container + .find(classname) + .append( + `
${label}
` + ); + } this.$form_container.find(".serial_no-control").find("textarea").css("height", "6rem"); } } From 87405f0753d78655d621f3324003ac2b3ee743ca Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 7 Jan 2025 17:29:35 +0530 Subject: [PATCH 3/7] fix: issue in returning components against the SCO (cherry picked from commit 729ce1dc50a408a6eea74fefd80ecf4cb4b5c8e5) --- .../controllers/subcontracting_controller.py | 6 +- .../tests/test_subcontracting_controller.py | 73 +++++++++++++++++++ .../serial_and_batch_bundle.py | 2 +- .../report/stock_balance/stock_balance.py | 1 - 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index 0f9431ab440..349a15703fb 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -1257,6 +1257,7 @@ def add_items_in_ste(ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_deta "item_code": row.item_details["rm_item_code"], "subcontracted_item": row.item_details["main_item_code"], "serial_no": "\n".join(row.serial_no) if row.serial_no else "", + "use_serial_batch_fields": 1, } ) @@ -1297,10 +1298,13 @@ def make_return_stock_entry_for_subcontract( if not value.qty: continue + if item_details := value.get("item_details"): + item_details["serial_and_batch_bundle"] = None + if value.batch_no: for batch_no, qty in value.batch_no.items(): if qty > 0: - add_items_in_ste(ste_doc, value, value.qty, rm_details, rm_detail_field, batch_no) + add_items_in_ste(ste_doc, value, qty, rm_details, rm_detail_field, batch_no) else: add_items_in_ste(ste_doc, value, value.qty, rm_details, rm_detail_field) diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py index 0bc348e8876..3b11a0f8029 100644 --- a/erpnext/controllers/tests/test_subcontracting_controller.py +++ b/erpnext/controllers/tests/test_subcontracting_controller.py @@ -282,6 +282,79 @@ class TestSubcontractingController(FrappeTestCase): frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 1) + def test_return_non_consumed_batch_materials(self): + """ + - Set backflush based on Material Transfer. + - Create SCO for item Subcontracted Item SA2. + - Transfer the batched components from Stores to Supplier warehouse with serial nos. + - Transfer extra qty of component for the subcontracted item Subcontracted Item SA2. + - Create SCR for full qty against the SCO and change the qty of raw material. + - After that return the non consumed material back to the store from supplier's warehouse. + """ + + frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 0) + set_backflush_based_on("Material Transferred for Subcontract") + service_item = make_item("Subcontracted Service FG Item A", properties={"is_stock_item": 0}).name + fg_item = make_item( + "Subcontracted FG Item SA2", properties={"is_stock_item": 1, "is_sub_contracted_item": 1} + ).name + rm_item = make_item( + "Subcontracted Batch RM Item SA2", + properties={ + "is_stock_item": 1, + "create_new_batch": 1, + "has_batch_no": 1, + "batch_number_series": "BATCH-RM-IRM-.####", + }, + ).name + + make_bom(item=fg_item, raw_materials=[rm_item], rate=100, currency="INR") + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": service_item, + "qty": 5, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 5, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + rm_items = get_rm_items(sco.supplied_items) + rm_items[0]["qty"] += 1 + itemwise_details = make_stock_in_entry(rm_items=rm_items) + + for item in rm_items: + item["sco_rm_detail"] = sco.items[0].name + + make_stock_transfer_entry( + sco_no=sco.name, + rm_items=rm_items, + itemwise_details=copy.deepcopy(itemwise_details), + ) + + scr1 = make_subcontracting_receipt(sco.name) + scr1.save() + scr1.supplied_items[0].consumed_qty = 5 + scr1.submit() + + for key, value in get_supplied_items(scr1).items(): + transferred_detais = itemwise_details.get(key) + self.assertEqual(value.qty, 5) + self.assertEqual(sorted(value.serial_no), sorted(transferred_detais.get("serial_no")[0:5])) + + sco.load_from_db() + self.assertEqual(sco.supplied_items[0].consumed_qty, 5) + doc = get_materials_from_supplier(sco.name, [d.name for d in sco.supplied_items]) + doc.save() + self.assertEqual(doc.items[0].qty, 1) + self.assertEqual(doc.items[0].s_warehouse, "_Test Warehouse 1 - _TC") + self.assertEqual(doc.items[0].t_warehouse, "_Test Warehouse - _TC") + self.assertTrue(doc.items[0].batch_no) + self.assertTrue(doc.items[0].use_serial_batch_fields) + frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 1) + def test_return_non_consumed_materials(self): """ - Set backflush based on Material Transfer. diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index af378ca2f0b..00076e8ca16 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1557,7 +1557,7 @@ def get_type_of_transaction(parent_doc, child_row): elif parent_doc.get("doctype") == "Stock Reconciliation": type_of_transaction = "Inward" - if parent_doc.get("is_return"): + if parent_doc.get("is_return") and parent_doc.get("doctype") != "Stock Entry": type_of_transaction = "Inward" if ( parent_doc.get("doctype") in ["Purchase Receipt", "Purchase Invoice"] diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 8ea07338cf1..6b5a3661a37 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -317,7 +317,6 @@ class StockBalanceReport: .where((sle.docstatus < 2) & (sle.is_cancelled == 0)) .orderby(sle.posting_datetime) .orderby(sle.creation) - .orderby(sle.actual_qty) ) query = self.apply_inventory_dimensions_filters(query, sle) From 931b5166a86d235e709734f79065d6cab57c8547 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 6 Jan 2025 20:27:06 +0530 Subject: [PATCH 4/7] fix: Missing company filter breaks `get_account_balance` in Bank Reco (cherry picked from commit 8de0fe78eaa3c6798a9fa002513ee912852f661c) --- .../bank_reconciliation_tool.js | 2 ++ .../bank_reconciliation_tool.py | 26 ++++++++++--------- .../data_table_manager.js | 3 ++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js index b15745d834c..7a653e12c72 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js @@ -120,6 +120,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", { args: { bank_account: frm.doc.bank_account, till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1), + company: frm.doc.company, }, callback: (response) => { frm.set_value("account_opening_balance", response.message); @@ -135,6 +136,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", { args: { bank_account: frm.doc.bank_account, till_date: frm.doc.bank_statement_to_date, + company: frm.doc.company, }, callback: (response) => { frm.cleared_balance = response.message; 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 ce7e9436ad5..4b677d56f1f 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -5,11 +5,6 @@ import json import frappe -from frappe import _ -from frappe.model.document import Document -from frappe.query_builder.custom import ConstantColumn -from frappe.utils import cint, flt - from erpnext import get_default_cost_center from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount from erpnext.accounts.party import get_party_account @@ -19,6 +14,10 @@ from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_s ) from erpnext.accounts.utils import get_account_currency, get_balance_on from erpnext.setup.utils import get_exchange_rate +from frappe import _ +from frappe.model.document import Document +from frappe.query_builder.custom import ConstantColumn +from frappe.utils import cint, flt class BankReconciliationTool(Document): @@ -79,10 +78,17 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None): @frappe.whitelist() -def get_account_balance(bank_account, till_date): +def get_account_balance(bank_account, till_date, company): # returns account balance till the specified date account = frappe.db.get_value("Bank Account", bank_account, "account") - filters = frappe._dict({"account": account, "report_date": till_date, "include_pos_transactions": 1}) + filters = frappe._dict( + { + "account": account, + "report_date": till_date, + "include_pos_transactions": 1, + "company": company, + } + ) data = get_entries(filters) balance_as_per_system = get_balance_on(filters["account"], filters["report_date"]) @@ -94,11 +100,7 @@ def get_account_balance(bank_account, till_date): amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters) - bank_bal = ( - flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system - ) - - return bank_bal + return flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system @frappe.whitelist() diff --git a/erpnext/public/js/bank_reconciliation_tool/data_table_manager.js b/erpnext/public/js/bank_reconciliation_tool/data_table_manager.js index 4aa087e99cf..ad5fd528cda 100644 --- a/erpnext/public/js/bank_reconciliation_tool/data_table_manager.js +++ b/erpnext/public/js/bank_reconciliation_tool/data_table_manager.js @@ -16,7 +16,7 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager { } make_dt() { - var me = this; + const me = this; frappe.call({ method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_bank_transactions", args: { @@ -193,6 +193,7 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager { args: { bank_account: this.bank_account, till_date: this.bank_statement_to_date, + company: this.company, }, callback: (response) => (this.cleared_balance = response.message), }); From 754845a935d735a5e074b7de42f1df40cf8cf2e7 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 6 Jan 2025 21:14:41 +0530 Subject: [PATCH 5/7] fix: Override pre-commit behaviour due to conflicts with CI (cherry picked from commit d7bf73cffa5628c185f4ceabd6020c7e4daf54a6) --- .../bank_reconciliation_tool/bank_reconciliation_tool.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 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 4b677d56f1f..62a4c74a933 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -5,6 +5,11 @@ import json import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.query_builder.custom import ConstantColumn +from frappe.utils import cint, flt + from erpnext import get_default_cost_center from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount from erpnext.accounts.party import get_party_account @@ -14,10 +19,6 @@ from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_s ) from erpnext.accounts.utils import get_account_currency, get_balance_on from erpnext.setup.utils import get_exchange_rate -from frappe import _ -from frappe.model.document import Document -from frappe.query_builder.custom import ConstantColumn -from frappe.utils import cint, flt class BankReconciliationTool(Document): From acd66fa00c087c6d023675679b31a2c96fcde220 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 8 Jan 2025 08:22:37 +0530 Subject: [PATCH 6/7] chore: remove 'Experimental' tag (cherry picked from commit 4620025dcd5833d3a60b5787120f641e463a489b) # Conflicts: # erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json --- .../process_payment_reconciliation.json | 5 ++--- .../process_payment_reconciliation.py | 2 +- .../process_payment_reconciliation_log.json | 5 ++++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.json b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.json index 0511571d754..bfd4e0ad63a 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.json +++ b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.json @@ -1,7 +1,6 @@ { "actions": [], "autoname": "format:ACC-PPR-{#####}", - "beta": 1, "creation": "2023-03-30 21:28:39.793927", "default_view": "List", "doctype": "DocType", @@ -158,7 +157,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2024-08-27 14:48:56.715320", + "modified": "2025-01-08 08:22:14.798085", "modified_by": "Administrator", "module": "Accounts", "name": "Process Payment Reconciliation", @@ -192,4 +191,4 @@ "sort_order": "DESC", "states": [], "title_field": "company" -} +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py index 882a2c4ad1c..35f1e31af34 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py @@ -212,7 +212,7 @@ def trigger_reconciliation_for_queued_docs(): unique_filters = set() queue_size = 5 - fields = ["company", "party_type", "party", "receivable_payable_account"] + fields = ["company", "party_type", "party", "receivable_payable_account", "default_advance_account"] def get_filters_as_tuple(fields, doc): filters = () diff --git a/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json b/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json index b4ac9812cbf..d5e52a72df5 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json +++ b/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json @@ -1,7 +1,6 @@ { "actions": [], "autoname": "format:PPR-LOG-{##}", - "beta": 1, "creation": "2023-03-13 15:00:09.149681", "default_view": "List", "doctype": "DocType", @@ -110,7 +109,11 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], +<<<<<<< HEAD "modified": "2023-11-02 11:32:12.254018", +======= + "modified": "2025-01-08 08:22:19.104975", +>>>>>>> 4620025dcd (chore: remove 'Experimental' tag) "modified_by": "Administrator", "module": "Accounts", "name": "Process Payment Reconciliation Log", From 36dbb867ed23f8e66bcdf839096fcfeaf7d0e896 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 8 Jan 2025 09:19:53 +0530 Subject: [PATCH 7/7] chore: resolve conflict --- .../process_payment_reconciliation_log.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json b/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json index d5e52a72df5..3e3e231fe1d 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json +++ b/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json @@ -109,11 +109,7 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], -<<<<<<< HEAD - "modified": "2023-11-02 11:32:12.254018", -======= "modified": "2025-01-08 08:22:19.104975", ->>>>>>> 4620025dcd (chore: remove 'Experimental' tag) "modified_by": "Administrator", "module": "Accounts", "name": "Process Payment Reconciliation Log",