From e53ccd07450c64e0a0d9d82ee4969673bcffe714 Mon Sep 17 00:00:00 2001 From: Shllokkk Date: Tue, 3 Feb 2026 15:04:39 +0530 Subject: [PATCH 01/63] fix: move company field to first position in sales invoice, purchase invoice, sales order, purchase order and journal entry (cherry picked from commit 8e9365eb3b0a760c507953d8a45e7ba73b39d667) --- .../accounts/doctype/journal_entry/journal_entry.json | 4 ++-- .../accounts/doctype/journal_entry/journal_entry.py | 2 +- .../doctype/purchase_invoice/purchase_invoice.json | 4 ++-- .../accounts/doctype/sales_invoice/sales_invoice.json | 6 +++--- .../buying/doctype/purchase_order/purchase_order.json | 8 ++++---- erpnext/selling/doctype/sales_order/sales_order.json | 10 +++++----- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json index 2465948c5ef..29e6c1fb638 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.json +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json @@ -9,6 +9,7 @@ "engine": "InnoDB", "field_order": [ "entry_type_and_date", + "company", "is_system_generated", "title", "voucher_type", @@ -17,7 +18,6 @@ "reversal_of", "column_break1", "from_template", - "company", "posting_date", "finance_book", "apply_tds", @@ -638,7 +638,7 @@ "table_fieldname": "payment_entries" } ], - "modified": "2025-11-13 17:54:14.542903", + "modified": "2026-02-03 14:40:39.944524", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry", diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 4ea077f5d8c..ca74d060f55 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -74,8 +74,8 @@ class JournalEntry(AccountsController): mode_of_payment: DF.Link | None multi_currency: DF.Check naming_series: DF.Literal["ACC-JV-.YYYY.-"] - party_not_required: DF.Check override_tax_withholding_entries: DF.Check + party_not_required: DF.Check pay_to_recd_from: DF.Data | None payment_order: DF.Link | None periodic_entry_difference_account: DF.Link | None diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 980eee2c48c..02371e778cf 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -8,12 +8,12 @@ "email_append_to": 1, "engine": "InnoDB", "field_order": [ + "company", "title", "naming_series", "supplier", "supplier_name", "tax_id", - "company", "column_break_6", "posting_date", "posting_time", @@ -1668,7 +1668,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2026-01-29 21:21:53.051193", + "modified": "2026-02-03 14:23:47.937128", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index b372da7f74a..93e4dd1598f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -8,12 +8,12 @@ "engine": "InnoDB", "field_order": [ "customer_section", + "company", + "company_tax_id", "naming_series", "customer", "customer_name", "tax_id", - "company", - "company_tax_id", "column_break1", "posting_date", "posting_time", @@ -2306,7 +2306,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2026-01-30 16:45:59.682473", + "modified": "2026-02-03 14:09:44.347133", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 05d03d47676..25a31ea698d 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -9,10 +9,9 @@ "engine": "InnoDB", "field_order": [ "supplier_section", + "company", "title", "naming_series", - "supplier", - "supplier_name", "order_confirmation_no", "order_confirmation_date", "get_items_from_open_material_requests", @@ -21,8 +20,9 @@ "transaction_date", "schedule_date", "column_break1", - "company", + "supplier", "is_subcontracted", + "supplier_name", "has_unit_price_items", "supplier_warehouse", "amended_from", @@ -1310,7 +1310,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2026-01-29 21:22:54.323838", + "modified": "2026-02-03 14:44:55.192192", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index de17b04c450..f8ef775e9e4 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -11,18 +11,18 @@ "field_order": [ "customer_section", "column_break0", + "company", "naming_series", - "customer", - "customer_name", - "tax_id", "order_type", "column_break_7", "transaction_date", "delivery_date", "column_break1", + "customer", + "customer_name", + "tax_id", "po_no", "po_date", - "company", "skip_delivery_note", "has_unit_price_items", "is_subcontracted", @@ -1713,7 +1713,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2026-01-29 21:23:48.362401", + "modified": "2026-02-03 14:45:50.314361", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", From ab59f730648932603464472dd6efcf78c63c4530 Mon Sep 17 00:00:00 2001 From: Diptanil Saha Date: Wed, 4 Feb 2026 10:47:56 +0530 Subject: [PATCH 02/63] fix: remove customer_pos_id reference (#52396) (cherry picked from commit 036f64013d033d78963bcd0abe5fb9c2c0d77c03) --- erpnext/accounts/doctype/pos_profile/test_pos_profile.py | 3 +-- erpnext/public/js/utils/contact_address_quick_entry.js | 6 ------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py index 002c913a7a2..1f02ba7e0a7 100644 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py @@ -99,8 +99,7 @@ def get_customers_list(pos_profile=None): return ( frappe.db.sql( - f""" select name, customer_name, customer_group, - territory, customer_pos_id from tabCustomer where disabled = 0 + f""" select name, customer_name, customer_group, territory from tabCustomer where disabled = 0 and {cond}""", tuple(customer_groups), as_dict=1, diff --git a/erpnext/public/js/utils/contact_address_quick_entry.js b/erpnext/public/js/utils/contact_address_quick_entry.js index 1a1d67b475a..f6ce5d0d28b 100644 --- a/erpnext/public/js/utils/contact_address_quick_entry.js +++ b/erpnext/public/js/utils/contact_address_quick_entry.js @@ -110,12 +110,6 @@ frappe.ui.form.ContactAddressQuickEntryForm = class ContactAddressQuickEntryForm options: "Country", mandatory_depends_on: "eval:doc.city || doc.address_line1", }, - { - label: __("Customer POS Id"), - fieldname: "customer_pos_id", - fieldtype: "Data", - hidden: 1, - }, ]; return variant_fields; From 1f78f45aee164cc37a178f368664b04385ae6e32 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 3 Feb 2026 20:21:51 +0530 Subject: [PATCH 03/63] fix: rate comparison in stock reco (cherry picked from commit f1b4fe12a2d0e6959ef6ac1b614ffe0e87a51518) --- .../stock/doctype/stock_reconciliation/stock_reconciliation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index c7d8461704f..135a0804f12 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -523,6 +523,9 @@ class StockReconciliation(StockController): if abs(difference_amount) > 0: return True + float_precision = frappe.db.get_default("float_precision") or 3 + item_dict["rate"] = flt(item_dict.get("rate"), float_precision) + item.valuation_rate = flt(item.valuation_rate, float_precision) if ( (item.qty is None or item.qty == item_dict.get("qty")) and (item.valuation_rate is None or item.valuation_rate == item_dict.get("rate")) From 64a7956a4a59022242e5f6c6a550a21750566b61 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 4 Feb 2026 12:02:14 +0530 Subject: [PATCH 04/63] fix: return None instead of 0 if valuation rate is falsy (cherry picked from commit e8d1e9d946ff19f608cd47a77734bbc72248fe56) --- .../stock/doctype/stock_reconciliation/stock_reconciliation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 135a0804f12..ac9e94f1e6a 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -525,7 +525,7 @@ class StockReconciliation(StockController): float_precision = frappe.db.get_default("float_precision") or 3 item_dict["rate"] = flt(item_dict.get("rate"), float_precision) - item.valuation_rate = flt(item.valuation_rate, float_precision) + item.valuation_rate = flt(item.valuation_rate, float_precision) if item.valuation_rate else None if ( (item.qty is None or item.qty == item_dict.get("qty")) and (item.valuation_rate is None or item.valuation_rate == item_dict.get("rate")) From 6ff882073220534d990451f2a3587c2961f99514 Mon Sep 17 00:00:00 2001 From: elshafei-developer Date: Mon, 12 Jan 2026 06:56:13 +0000 Subject: [PATCH 05/63] fix(gross profit report): translate column Sales Invoice (cherry picked from commit 3e39d131723d36a4a0d310b246495cf8bef57e63) --- erpnext/accounts/report/gross_profit/gross_profit.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index d2fe570fa3b..a6dc46cabd9 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -176,7 +176,9 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_ column_names = get_column_names() # to display item as Item Code: Item Name - columns[0] = "Sales Invoice:Link/Item:300" + columns[0]["fieldname"] = "sales_invoice" + columns[0]["options"] = "Item" + columns[0]["width"] = 300 # removing Item Code and Item Name columns supplier_master_name = frappe.db.get_single_value("Buying Settings", "supp_master_name") customer_master_name = frappe.db.get_single_value("Selling Settings", "cust_master_name") From e86ab97b7ed6ae2f55dccd90c5ea389b5ae45d82 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 4 Feb 2026 17:26:01 +0530 Subject: [PATCH 06/63] chore: add line in the end so linter check passes --- erpnext/public/js/utils/demo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils/demo.js b/erpnext/public/js/utils/demo.js index e0da8985e9b..db15834ae95 100644 --- a/erpnext/public/js/utils/demo.js +++ b/erpnext/public/js/utils/demo.js @@ -28,4 +28,4 @@ erpnext.demo.clear_demo = function () { }, }); }); -}; \ No newline at end of file +}; From b1b75eca3d5010d94b96f2467e8a81e7f3e86a3f Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Fri, 16 Jan 2026 00:01:34 +0530 Subject: [PATCH 07/63] fix(manufacturing): handle None value for actual_end_date (cherry picked from commit 16f09141da954f16b9ea232c75df1530f0f8644a) --- .../production_analytics.py | 160 ++++++++---------- 1 file changed, 70 insertions(+), 90 deletions(-) diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.py b/erpnext/manufacturing/report/production_analytics/production_analytics.py index 5c84a2dc8d1..f0fe0e87a78 100644 --- a/erpnext/manufacturing/report/production_analytics/production_analytics.py +++ b/erpnext/manufacturing/report/production_analytics/production_analytics.py @@ -8,6 +8,8 @@ from frappe.utils import getdate, today from erpnext.stock.report.stock_analytics.stock_analytics import get_period, get_period_date_ranges +WORK_ORDER_STATUS_LIST = ["Not Started", "Overdue", "Pending", "Completed", "Closed", "Stopped"] + def execute(filters=None): columns = get_columns(filters) @@ -16,119 +18,97 @@ def execute(filters=None): def get_columns(filters): - columns = [{"label": _("Status"), "fieldname": "Status", "fieldtype": "Data", "width": 140}] - + columns = [{"label": _("Status"), "fieldname": "status", "fieldtype": "Data", "width": 140}] ranges = get_period_date_ranges(filters) for _dummy, end_date in ranges: period = get_period(end_date, filters) - columns.append({"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120}) return columns -def get_periodic_data(filters, entry): - periodic_data = { - "Not Started": {}, - "Overdue": {}, - "Pending": {}, - "Completed": {}, - "Closed": {}, - "Stopped": {}, - } +def get_work_orders(filters): + from_date = filters.get("from_date") + to_date = filters.get("to_date") - ranges = get_period_date_ranges(filters) + WorkOrder = frappe.qb.DocType("Work Order") - for from_date, end_date in ranges: - period = get_period(end_date, filters) - for d in entry: - if getdate(from_date) <= getdate(d.creation) <= getdate(end_date) and d.status not in [ - "Draft", - "Submitted", - "Completed", - "Cancelled", - ]: - if d.status in ["Not Started", "Closed", "Stopped"]: - periodic_data = update_periodic_data(periodic_data, d.status, period) - elif getdate(today()) > getdate(d.planned_end_date): - periodic_data = update_periodic_data(periodic_data, "Overdue", period) - elif getdate(today()) < getdate(d.planned_end_date): - periodic_data = update_periodic_data(periodic_data, "Pending", period) - - if ( - getdate(from_date) <= getdate(d.actual_end_date) <= getdate(end_date) - and d.status == "Completed" - ): - periodic_data = update_periodic_data(periodic_data, "Completed", period) - - return periodic_data - - -def update_periodic_data(periodic_data, status, period): - if periodic_data.get(status).get(period): - periodic_data[status][period] += 1 - else: - periodic_data[status][period] = 1 - - return periodic_data + return ( + frappe.qb.from_(WorkOrder) + .select(WorkOrder.creation, WorkOrder.actual_end_date, WorkOrder.planned_end_date, WorkOrder.status) + .where( + (WorkOrder.docstatus == 1) + & (WorkOrder.company == filters.get("company")) + & ( + (WorkOrder.creation.between(from_date, to_date)) + | (WorkOrder.actual_end_date.between(from_date, to_date)) + ) + ) + .run(as_dict=True) + ) def get_data(filters, columns): - data = [] - entry = frappe.get_all( - "Work Order", - fields=[ - "creation", - "actual_end_date", - "planned_end_date", - "status", - ], - filters={"docstatus": 1, "company": filters["company"]}, - ) + ranges = build_ranges(filters) + period_labels = [pd for _fd, _td, pd in ranges] + periodic_data = {status: {pd: 0 for pd in period_labels} for status in WORK_ORDER_STATUS_LIST} + entries = get_work_orders(filters) - periodic_data = get_periodic_data(filters, entry) + for d in entries: + if d.status == "Completed": + if not d.actual_end_date: + continue - labels = ["Not Started", "Overdue", "Pending", "Completed", "Closed", "Stopped"] - chart_data = get_chart_data(periodic_data, columns) - ranges = get_period_date_ranges(filters) + if period := get_period_for_date(getdate(d.actual_end_date), ranges): + periodic_data["Completed"][period] += 1 + continue - for label in labels: - work = {} - work["Status"] = _(label) - for _dummy, end_date in ranges: - period = get_period(end_date, filters) - if periodic_data.get(label).get(period): - work[scrub(period)] = periodic_data.get(label).get(period) + creation_date = getdate(d.creation) + period = get_period_for_date(creation_date, ranges) + if not period: + continue + + if d.status in ("Not Started", "Closed", "Stopped"): + periodic_data[d.status][period] += 1 + else: + if d.planned_end_date and getdate(today()) > getdate(d.planned_end_date): + periodic_data["Overdue"][period] += 1 else: - work[scrub(period)] = 0.0 - data.append(work) + periodic_data["Pending"][period] += 1 - return data, chart_data + data = [] + for status in WORK_ORDER_STATUS_LIST: + row = {"status": _(status)} + for _fd, _td, pd in ranges: + row[scrub(pd)] = periodic_data[status].get(pd, 0) + data.append(row) + + chart = get_chart_data(periodic_data, columns) + return data, chart + + +def get_period_for_date(date, ranges): + for from_date, to_date, period in ranges: + if from_date <= date <= to_date: + return period + return None + + +def build_ranges(filters): + ranges = [] + for from_date, end_date in get_period_date_ranges(filters): + period = get_period(end_date, filters) + ranges.append((getdate(from_date), getdate(end_date), period)) + return ranges def get_chart_data(periodic_data, columns): labels = [d.get("label") for d in columns[1:]] - not_start, overdue, pending, completed, closed, stopped = [], [], [], [], [], [] datasets = [] + for status in WORK_ORDER_STATUS_LIST: + values = [periodic_data.get(status, {}).get(label, 0) for label in labels] + datasets.append({"name": _(status), "values": values}) - for d in labels: - not_start.append(periodic_data.get("Not Started").get(d)) - overdue.append(periodic_data.get("Overdue").get(d)) - pending.append(periodic_data.get("Pending").get(d)) - completed.append(periodic_data.get("Completed").get(d)) - closed.append(periodic_data.get("Closed").get(d)) - stopped.append(periodic_data.get("Stopped").get(d)) - - datasets.append({"name": _("Not Started"), "values": not_start}) - datasets.append({"name": _("Overdue"), "values": overdue}) - datasets.append({"name": _("Pending"), "values": pending}) - datasets.append({"name": _("Completed"), "values": completed}) - datasets.append({"name": _("Closed"), "values": closed}) - datasets.append({"name": _("Stopped"), "values": stopped}) - - chart = {"data": {"labels": labels, "datasets": datasets}} - chart["type"] = "line" - - return chart + return {"data": {"labels": labels, "datasets": datasets}, "type": "line"} From b99ca486d7bc7fcaea771ea79a508b0be14e5bfd Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Wed, 4 Feb 2026 12:18:03 +0530 Subject: [PATCH 08/63] fix(manufacturing): fix chart period keys (cherry picked from commit 27091e516881c1749cbaf3101ff53664fcd9d086) --- .../production_analytics.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.py b/erpnext/manufacturing/report/production_analytics/production_analytics.py index f0fe0e87a78..41fd4dd0e82 100644 --- a/erpnext/manufacturing/report/production_analytics/production_analytics.py +++ b/erpnext/manufacturing/report/production_analytics/production_analytics.py @@ -51,7 +51,7 @@ def get_work_orders(filters): def get_data(filters, columns): ranges = build_ranges(filters) - period_labels = [pd for _fd, _td, pd in ranges] + period_labels = [scrub(pd) for _fd, _td, pd in ranges] periodic_data = {status: {pd: 0 for pd in period_labels} for status in WORK_ORDER_STATUS_LIST} entries = get_work_orders(filters) @@ -60,12 +60,12 @@ def get_data(filters, columns): if not d.actual_end_date: continue - if period := get_period_for_date(getdate(d.actual_end_date), ranges): + if period := scrub(get_period_for_date(getdate(d.actual_end_date), ranges)): periodic_data["Completed"][period] += 1 continue creation_date = getdate(d.creation) - period = get_period_for_date(creation_date, ranges) + period = scrub(get_period_for_date(creation_date, ranges)) if not period: continue @@ -80,8 +80,8 @@ def get_data(filters, columns): data = [] for status in WORK_ORDER_STATUS_LIST: row = {"status": _(status)} - for _fd, _td, pd in ranges: - row[scrub(pd)] = periodic_data[status].get(pd, 0) + for _fd, _td, period in ranges: + row[scrub(period)] = periodic_data[status].get(scrub(period), 0) data.append(row) chart = get_chart_data(periodic_data, columns) @@ -104,11 +104,12 @@ def build_ranges(filters): def get_chart_data(periodic_data, columns): - labels = [d.get("label") for d in columns[1:]] + period_labels = [d.get("label") for d in columns[1:]] + period_fieldnames = [d.get("fieldname") for d in columns[1:]] datasets = [] for status in WORK_ORDER_STATUS_LIST: - values = [periodic_data.get(status, {}).get(label, 0) for label in labels] + values = [periodic_data.get(status, {}).get(fieldname, 0) for fieldname in period_fieldnames] datasets.append({"name": _(status), "values": values}) - return {"data": {"labels": labels, "datasets": datasets}, "type": "line"} + return {"data": {"labels": period_labels, "datasets": datasets}, "type": "line"} From 91043de352138f239493be18432cf720af378aed Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 22 Jan 2026 11:01:55 +0530 Subject: [PATCH 09/63] refactor: scrub http and use https in sales partner (cherry picked from commit 8cf31548f2d1b81cc49c8d7f65adb7b440aefa1e) --- .../setup/doctype/sales_partner/sales_partner.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.py b/erpnext/setup/doctype/sales_partner/sales_partner.py index 36c24c0f37e..6ef5b6dc646 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/sales_partner.py @@ -50,8 +50,17 @@ class SalesPartner(WebsiteGenerator): if not self.route: self.route = "partners/" + self.scrub(self.partner_name) super().validate() - if self.partner_website and not self.partner_website.startswith("http"): - self.partner_website = "http://" + self.partner_website + if self.partner_website: + from urllib.parse import urlsplit, urlunsplit + + # scrub http + parts = urlsplit(self.partner_website) + if not parts.netloc and parts.path: + parts = parts._replace(netloc=parts.path, path="") + if not parts.scheme or parts.scheme == "http": + parts = parts._replace(scheme="https") + + self.partner_website = urlunsplit(parts) def get_context(self, context): address_names = frappe.db.get_all( From c5ff534d58a8a96f51e3a90693c4eb8d0547dd79 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 4 Feb 2026 16:55:36 +0530 Subject: [PATCH 10/63] fix: not able to complete job card (cherry picked from commit 175fe9279c13168c08df8b6d7f5fda44368a1bb0) --- .../doctype/job_card/job_card.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index c9010ff54cc..ba2a36e2ad3 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -1251,10 +1251,26 @@ class JobCard(Document): frappe.db.set_value("Workstation", self.workstation, "status", status) def add_time_logs(self, **kwargs): - row = None kwargs = frappe._dict(kwargs) + if not kwargs.employees and kwargs.to_time: + for row in self.time_logs: + if not row.to_time and row.from_time: + row.to_time = kwargs.to_time + row.time_in_mins = time_diff_in_minutes(row.to_time, row.from_time) + if kwargs.completed_qty: + row.completed_qty = kwargs.completed_qty + row.db_update() + else: + self.add_time_logs_for_employess(kwargs) + + self.validate_time_logs(save=True) + self.save() + + def add_time_logs_for_employess(self, kwargs): + row = None update_status = False + for employee in kwargs.employees: kwargs.employee = employee.get("employee") if kwargs.from_time and not kwargs.to_time: @@ -1290,9 +1306,6 @@ class JobCard(Document): self.set_status(update_status=update_status) - self.validate_time_logs(save=True) - self.save() - def update_workstation_status(self): status_map = { "Open": "Off", From 5298e26a11c3358e64889abae68a784d75f9d8c8 Mon Sep 17 00:00:00 2001 From: archielister Date: Wed, 4 Feb 2026 12:20:43 +0000 Subject: [PATCH 11/63] fix for obtaining bom_no (cherry picked from commit e4df0a393abc884833bd9844fa94b6168efb11d5) --- .../manufacturing/doctype/production_plan/production_plan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 9ae36795fec..ab989185b73 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -497,7 +497,7 @@ class ProductionPlan(Document): item_details = get_item_details(data.item_code, throw=False) if self.combine_items: - bom_no = item_details.bom_no + bom_no = item_details.get("bom_no") if data.get("bom_no"): bom_no = data.get("bom_no") From 96dfecf0d5b3281d81ecd475d53d1cd7053d0556 Mon Sep 17 00:00:00 2001 From: Pandiyan37 Date: Wed, 4 Feb 2026 15:19:56 +0530 Subject: [PATCH 12/63] fix(stock): update target field attribute (cherry picked from commit 7e081542177d47db795b7497b93548761ad2e4fb) --- .../stock/doctype/inventory_dimension/inventory_dimension.py | 2 +- .../doctype/inventory_dimension/test_inventory_dimension.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index 0c50df0c23b..469e4d5e53a 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -139,7 +139,7 @@ class InventoryDimension(Document): self.source_fieldname = scrub(self.dimension_name) if not self.target_fieldname: - self.target_fieldname = scrub(self.reference_document) + self.target_fieldname = scrub(self.dimension_name) def on_update(self): self.add_custom_fields() diff --git a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py index fd9f12ddd46..1d7c475d1ae 100644 --- a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py @@ -117,12 +117,12 @@ class TestInventoryDimension(IntegrationTestCase): inward.load_from_db() sle_data = frappe.db.get_value( - "Stock Ledger Entry", {"voucher_no": inward.name}, ["shelf", "warehouse"], as_dict=1 + "Stock Ledger Entry", {"voucher_no": inward.name}, ["to_shelf", "warehouse"], as_dict=1 ) self.assertEqual(inward.items[0].to_shelf, "Shelf 1") self.assertEqual(sle_data.warehouse, warehouse) - self.assertEqual(sle_data.shelf, "Shelf 1") + self.assertEqual(sle_data.to_shelf, "Shelf 1") outward = make_stock_entry( item_code=item_code, From f8405e4ca4bc1e68d4469d6084d6acaffa83c060 Mon Sep 17 00:00:00 2001 From: Pandiyan37 Date: Wed, 4 Feb 2026 22:10:22 +0530 Subject: [PATCH 13/63] test(stock): testcase for different inventory dimension (cherry picked from commit 21d0ee8db15625799ed8c8dc95d80cff3eef7012) --- .../test_stock_reconciliation.py | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 40f372f2bc7..4b3d9099afc 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -1713,6 +1713,101 @@ class TestStockReconciliation(IntegrationTestCase, StockTestMixin): self.assertEqual(docstatus, 2) + def test_stock_reco_with_opening_stock_with_diff_inventory(self): + from erpnext.stock.doctype.inventory_dimension.test_inventory_dimension import ( + create_inventory_dimension, + ) + + if frappe.db.exists("DocType", "Plant"): + return + + doctype = frappe.get_doc( + { + "doctype": "DocType", + "name": "Plant", + "module": "Stock", + "custom": 1, + "fields": [ + { + "fieldname": "plant_name", + "fieldtype": "Data", + "label": "Plant Name", + "reqd": 1, + } + ], + "autoname": "field:plant_name", + } + ) + doctype.insert(ignore_permissions=True) + create_inventory_dimension(dimension_name="ID-Plant", reference_document="Plant") + + plant_a = frappe.get_doc( + { + "doctype": "Plant", + "plant_name": "Plant A", + } + ).insert(ignore_permissions=True) + + plant_b = frappe.get_doc( + { + "doctype": "Plant", + "plant_name": "Plant B", + } + ).insert(ignore_permissions=True) + + warehouse = "_Test Warehouse - _TC" + + item_code = "Item-Test" + item = self.make_item(item_code, {"is_stock_item": 1}) + + sr = frappe.new_doc("Stock Reconciliation") + sr.purpose = "Opening Stock" + sr.posting_date = nowdate() + sr.posting_time = nowtime() + sr.company = "_Test Company" + + sr.append( + "items", + { + "item_code": item.name, + "warehouse": warehouse, + "qty": 5, + "valuation_rate": 100, + "id_plant": plant_a.name, + }, + ) + + sr.append( + "items", + { + "item_code": item.name, + "warehouse": warehouse, + "qty": 3, + "valuation_rate": 110, + "id_plant": plant_b.name, + }, + ) + + sr.insert() + sr.submit() + + self.assertEqual(len(sr.items), 2) + sle_count = frappe.db.count( + "Stock Ledger Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": sr.name, "is_cancelled": 0}, + ) + self.assertEqual(sle_count, 2) + sle = frappe.get_all( + "Stock Ledger Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": sr.name, "is_cancelled": 0}, + ["item_code", "id_plant", "actual_qty", "valuation_rate"], + ) + for s in sle: + if s.id_plant == plant_a.name: + self.assertEqual(s.actual_qty, 5) + elif s.id_plant == plant_b.name: + self.assertEqual(s.actual_qty, 3) + def create_batch_item_with_batch(item_name, batch_id): batch_item_doc = create_item(item_name, is_stock_item=1) From ce695ebdd05fc85e5372e6f37e2e0472b7fa9882 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 22 Jan 2026 12:04:37 +0530 Subject: [PATCH 14/63] refactor: patch partner_website for old data (cherry picked from commit 8db29b0a81325c2c0fc234b8d218427f1b61618b) # Conflicts: # erpnext/patches.txt --- erpnext/patches.txt | 1 + .../v15_0/replace_http_with_https_in_sales_partner.py | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 erpnext/patches/v15_0/replace_http_with_https_in_sales_partner.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 12058846096..0e5d01b0353 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -462,3 +462,4 @@ erpnext.patches.v15_0.create_accounting_dimensions_in_advance_taxes_and_charges erpnext.patches.v16_0.set_ordered_qty_in_quotation_item erpnext.patches.v16_0.migrate_transaction_deletion_task_flags_to_status # 2 erpnext.patches.v16_0.update_company_custom_field_in_bin +erpnext.patches.v15_0.replace_http_with_https_in_sales_partner diff --git a/erpnext/patches/v15_0/replace_http_with_https_in_sales_partner.py b/erpnext/patches/v15_0/replace_http_with_https_in_sales_partner.py new file mode 100644 index 00000000000..80bc418920a --- /dev/null +++ b/erpnext/patches/v15_0/replace_http_with_https_in_sales_partner.py @@ -0,0 +1,10 @@ +import frappe +from frappe import qb +from pypika.functions import Replace + + +def execute(): + sp = frappe.qb.DocType("Sales Partner") + qb.update(sp).set(sp.partner_website, Replace(sp.partner_website, "http://", "https://")).where( + sp.partner_website.rlike("^http://.*") + ).run() From 9d14c0b60ec59508eb4d97e947a8d1c15efe9e69 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 5 Feb 2026 11:42:52 +0530 Subject: [PATCH 15/63] fix: item code is tuple with operation id (cherry picked from commit 481deee4b27c7fad5e403d33040a5b7b60813ac3) --- erpnext/stock/doctype/stock_entry/stock_entry.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index f5f724efe42..b15bfb745c4 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -971,6 +971,7 @@ class StockEntry(StockController, SubcontractingInwardController): precision = frappe.get_precision("Stock Entry Detail", "qty") for item_code, details in raw_materials.items(): + item_code = item_code[0] if type(item_code) == tuple else item_code if matched_item := self.get_matched_items(item_code): if flt(details.get("qty"), precision) != flt(matched_item.qty, precision): frappe.throw( From 7df18af799fae30a385d2d8a6c5ac04bde22d916 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 3 Feb 2026 15:21:38 +0530 Subject: [PATCH 16/63] fix: correctly calculate running balances for financial report (cherry picked from commit ee2f8d8ebce94dc3588e46413232ce661ffeb3c8) --- .../financial_report_engine.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index 4de556b7e46..ce8ed4adb07 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -636,12 +636,15 @@ class FinancialQueryBuilder: return self._execute_with_permissions(query, "GL Entry") def _calculate_running_balances(self, balances_data: dict, gl_data: list[dict]) -> dict: - for row in gl_data: - account = row["account"] + gl_dict = {row["account"]: row for row in gl_data} + accounts = set(balances_data.keys()) | set(gl_dict.keys()) + + for account in accounts: if account not in balances_data: balances_data[account] = AccountData(account=account, **self._get_account_meta(account)) account_data: AccountData = balances_data[account] + gl_movement = gl_dict.get(account, {}) if account_data.has_periods(): first_period = account_data.get_period(self.periods[0]["key"]) @@ -651,20 +654,13 @@ class FinancialQueryBuilder: for period in self.periods: period_key = period["key"] - movement = row.get(period_key, 0.0) + movement = gl_movement.get(period_key, 0.0) closing_balance = current_balance + movement account_data.add_period(PeriodValue(period_key, current_balance, closing_balance, movement)) current_balance = closing_balance - # Accounts with no movements - for account_data in balances_data.values(): - for period in self.periods: - period_key = period["key"] - if period_key not in account_data.period_values: - account_data.add_period(PeriodValue(period_key, 0.0, 0.0, 0.0)) - def _handle_balance_accumulation(self, balances_data): for account_data in balances_data.values(): account_data: AccountData From 921584c769aea54be6dbc23c41007f8aa4b8b9a3 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 3 Feb 2026 16:03:14 +0530 Subject: [PATCH 17/63] fix: Period Closing Voucher doesn't exist for GL Entry (cherry picked from commit b41c1858a39f98c5576bbaedfdf0354d4588ff48) --- .../financial_report_engine.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index ce8ed4adb07..216a9034be4 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -541,7 +541,7 @@ class FinancialQueryBuilder: .where(acb_table.period_closing_voucher == closing_voucher) ) - query = self._apply_standard_filters(query, acb_table) + query = self._apply_standard_filters(query, acb_table, "Account Closing Balance") results = self._execute_with_permissions(query, "Account Closing Balance") for row in results: @@ -679,12 +679,12 @@ class FinancialQueryBuilder: else: account_data.unaccumulate_values() - def _apply_standard_filters(self, query, table): + def _apply_standard_filters(self, query, table, doctype: str = "GL Entry"): if self.filters.get("ignore_closing_entries"): - if hasattr(table, "is_period_closing_voucher_entry"): - query = query.where(table.is_period_closing_voucher_entry == 0) - else: + if doctype == "GL Entry": query = query.where(table.voucher_type != "Period Closing Voucher") + else: + query = query.where(table.is_period_closing_voucher_entry == 0) if self.filters.get("project"): projects = self.filters.get("project") From 8caf609f8d11baddd29db8ce7cf6b91817cb2c09 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 3 Feb 2026 16:18:27 +0530 Subject: [PATCH 18/63] test: add tests for query builder (cherry picked from commit 61d8308e81cba62774726a13babe31fda84bcbd9) --- .../test_financial_report_engine.py | 277 +++++++++++++++++- 1 file changed, 276 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index 1a3ffc7ab61..f70bf3938f9 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -16,7 +16,8 @@ from erpnext.accounts.doctype.financial_report_template.financial_report_engine from erpnext.accounts.doctype.financial_report_template.test_financial_report_template import ( FinancialReportTemplateTestCase, ) -from erpnext.accounts.utils import get_currency_precision +from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry +from erpnext.accounts.utils import get_currency_precision, get_fiscal_year # On IntegrationTestCase, the doctype test records and all # link-field test record dependencies are recursively loaded @@ -1672,3 +1673,277 @@ class TestFilterExpressionParser(FinancialReportTemplateTestCase): mock_row_invalid = self._create_mock_report_row(invalid_formula) condition = parser.build_condition(mock_row_invalid, account_table) self.assertIsNone(condition) + + +class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): + def test_fetch_balances_with_journal_entries(self): + company = "_Test Company" + cash_account = "_Test Cash - _TC" + bank_account = "_Test Bank - _TC" + + # Create journal entries in different periods + # October: Transfer 1000 from Bank to Cash + jv_oct = make_journal_entry( + account1=cash_account, + account2=bank_account, + amount=1000, + posting_date="2024-10-15", + company=company, + submit=True, + ) + + # November: Transfer 500 from Bank to Cash + jv_nov = make_journal_entry( + account1=cash_account, + account2=bank_account, + amount=500, + posting_date="2024-11-20", + company=company, + submit=True, + ) + + # December: No transactions (test zero movement period) + + try: + # Set up filters and periods for Q4 2024 + filters = { + "company": company, + "from_fiscal_year": "2024", + "to_fiscal_year": "2024", + "period_start_date": "2024-10-01", + "period_end_date": "2024-12-31", + "filter_based_on": "Date Range", + "periodicity": "Monthly", + } + + periods = [ + {"key": "2024_oct", "from_date": "2024-10-01", "to_date": "2024-10-31"}, + {"key": "2024_nov", "from_date": "2024-11-01", "to_date": "2024-11-30"}, + {"key": "2024_dec", "from_date": "2024-12-01", "to_date": "2024-12-31"}, + ] + + query_builder = FinancialQueryBuilder(filters, periods) + + # Create account objects as expected by fetch_account_balances + accounts = [ + frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}), + frappe._dict({"name": bank_account, "account_name": "Bank", "account_number": "1002"}), + ] + + # Fetch balances using the full workflow + balances_data = query_builder.fetch_account_balances(accounts) + + # Verify Cash account balances + cash_data = balances_data.get(cash_account) + self.assertIsNotNone(cash_data, "Cash account should exist in results") + + # October: movement = +1000 (debit) + oct_cash = cash_data.get_period("2024_oct") + self.assertIsNotNone(oct_cash, "October period should exist for cash") + self.assertEqual(oct_cash.movement, 1000.0, "October cash movement should be 1000") + + # November: movement = +500 + nov_cash = cash_data.get_period("2024_nov") + self.assertIsNotNone(nov_cash, "November period should exist for cash") + self.assertEqual(nov_cash.movement, 500.0, "November cash movement should be 500") + self.assertEqual( + nov_cash.opening, oct_cash.closing, "November opening should equal October closing" + ) + + # December: movement = 0 (no transactions) + dec_cash = cash_data.get_period("2024_dec") + self.assertIsNotNone(dec_cash, "December period should exist for cash") + self.assertEqual(dec_cash.movement, 0.0, "December cash movement should be 0") + self.assertEqual( + dec_cash.closing, + nov_cash.closing, + "December closing should equal November closing when no movement", + ) + + # Verify Bank account balances (opposite direction) + bank_data = balances_data.get(bank_account) + self.assertIsNotNone(bank_data, "Bank account should exist in results") + + oct_bank = bank_data.get_period("2024_oct") + self.assertEqual(oct_bank.movement, -1000.0, "October bank movement should be -1000") + + nov_bank = bank_data.get_period("2024_nov") + self.assertEqual(nov_bank.movement, -500.0, "November bank movement should be -500") + + finally: + # Clean up: cancel journal entries + jv_nov.cancel() + jv_oct.cancel() + + def test_opening_balance_from_previous_period_closing(self): + company = "_Test Company" + cash_account = "_Test Cash - _TC" + sales_account = "Sales - _TC" + posting_date_2023 = "2023-06-15" + + # Create journal entry in prior period (2023) + # Cash Dr 5000, Sales Cr 5000 + jv_2023 = make_journal_entry( + account1=cash_account, + account2=sales_account, + amount=5000, + posting_date=posting_date_2023, + company=company, + submit=True, + ) + + pcv = None + jv_2024 = None + + try: + # Create Period Closing Voucher for 2023 + # This will create Account Closing Balance entries + closing_account = frappe.db.get_value( + "Account", + { + "company": company, + "root_type": "Liability", + "is_group": 0, + "account_type": ["not in", ["Payable", "Receivable"]], + }, + "name", + ) + + fy_2023 = get_fiscal_year(posting_date_2023, company=company) + + frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1) + + pcv = frappe.get_doc( + { + "doctype": "Period Closing Voucher", + "transaction_date": "2023-12-31", + "period_start_date": fy_2023[1], + "period_end_date": fy_2023[2], + "company": company, + "fiscal_year": fy_2023[0], + "cost_center": "_Test Cost Center - _TC", + "closing_account_head": closing_account, + "remarks": "Test Period Closing", + } + ) + pcv.insert() + pcv.submit() + pcv.reload() + + # Now create a small transaction in 2024 to ensure the account appears + jv_2024 = make_journal_entry( + account1=cash_account, + account2=sales_account, + amount=100, + posting_date="2024-01-15", + company=company, + submit=True, + ) + + # Set up filters for Q1 2024 (after the period closing) + filters = { + "company": company, + "from_fiscal_year": "2024", + "to_fiscal_year": "2024", + "period_start_date": "2024-01-01", + "period_end_date": "2024-03-31", + "filter_based_on": "Date Range", + "periodicity": "Monthly", + "ignore_closing_entries": True, # Don't include PCV entries in movements + } + + periods = [ + {"key": "2024_jan", "from_date": "2024-01-01", "to_date": "2024-01-31"}, + {"key": "2024_feb", "from_date": "2024-02-01", "to_date": "2024-02-29"}, + {"key": "2024_mar", "from_date": "2024-03-01", "to_date": "2024-03-31"}, + ] + + query_builder = FinancialQueryBuilder(filters, periods) + + accounts = [ + frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}), + ] + + balances_data = query_builder.fetch_account_balances(accounts) + + # Verify Cash account has opening balance from 2023 transactions + cash_data = balances_data.get(cash_account) + self.assertIsNotNone(cash_data, "Cash account should exist in results") + + jan_cash = cash_data.get_period("2024_jan") + self.assertIsNotNone(jan_cash, "January period should exist") + + # Opening balance should be from prior period + # Cash had 5000 debit in 2023, so opening in 2024 should be >= 5000 + # (may be higher if there were other test transactions) + self.assertEqual( + jan_cash.opening, + 5000.0, + "January opening should include balance from 2023 (5000 or more)", + ) + + # Verify running balance logic + # Movement in January is 100 (from jv_2024) + self.assertEqual(jan_cash.movement, 100.0, "January movement should be 100") + self.assertEqual( + jan_cash.closing, jan_cash.opening + jan_cash.movement, "Closing = Opening + Movement" + ) + + # February and March should have no movement but carry the balance + feb_cash = cash_data.get_period("2024_feb") + self.assertEqual(feb_cash.opening, jan_cash.closing, "Feb opening = Jan closing") + self.assertEqual(feb_cash.movement, 0.0, "February should have no movement") + self.assertEqual(feb_cash.closing, feb_cash.opening, "Feb closing = opening when no movement") + + mar_cash = cash_data.get_period("2024_mar") + self.assertEqual(mar_cash.opening, feb_cash.closing, "Mar opening = Feb closing") + self.assertEqual(mar_cash.movement, 0.0, "March should have no movement") + self.assertEqual(mar_cash.closing, mar_cash.opening, "Mar closing = opening when no movement") + + # Set up filters for Q2 2024 + filters_q2 = { + "company": company, + "from_fiscal_year": "2024", + "to_fiscal_year": "2024", + "period_start_date": "2024-04-01", + "period_end_date": "2024-06-30", + "filter_based_on": "Date Range", + "periodicity": "Monthly", + "ignore_closing_entries": True, + } + + periods_q2 = [ + {"key": "2024_apr", "from_date": "2024-04-01", "to_date": "2024-04-30"}, + {"key": "2024_may", "from_date": "2024-05-01", "to_date": "2024-05-31"}, + {"key": "2024_jun", "from_date": "2024-06-01", "to_date": "2024-06-30"}, + ] + + query_builder_q2 = FinancialQueryBuilder(filters_q2, periods_q2) + + balances_data_q2 = query_builder_q2.fetch_account_balances(accounts) + + # Verify Cash account in Q2 + cash_data_q2 = balances_data_q2.get(cash_account) + self.assertIsNotNone(cash_data_q2, "Cash account should exist in Q2 results") + + apr_cash = cash_data_q2.get_period("2024_apr") + self.assertIsNotNone(apr_cash, "April period should exist") + + # Opening balance in April should equal closing in March + self.assertEqual( + apr_cash.opening, + mar_cash.closing, + "April opening should equal March closing balance", + ) + + finally: + # Clean up + if jv_2024: + jv_2024.cancel() + + if pcv: + pcv.reload() + if pcv.docstatus == 1: + pcv.cancel() + + jv_2023.cancel() From 77693b12a4497364ea46c0c5112cdf2031fabe36 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 3 Feb 2026 16:30:05 +0530 Subject: [PATCH 19/63] test: revert original pcv setting (cherry picked from commit f45a5a63a7dd8dc27f3162faba35456743960241) --- .../test_financial_report_engine.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index f70bf3938f9..696da7785c9 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -1794,6 +1794,9 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): pcv = None jv_2024 = None + original_pcv_setting = frappe.db.get_single_value( + "Accounts Settings", "use_legacy_controller_for_pcv" + ) try: # Create Period Closing Voucher for 2023 @@ -1938,6 +1941,10 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): finally: # Clean up + frappe.db.set_single_value( + "Accounts Settings", "use_legacy_controller_for_pcv", original_pcv_setting or 0 + ) + if jv_2024: jv_2024.cancel() From 55eb6311168e2acab5cade91e7e4ae749d595dae Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 3 Feb 2026 16:32:26 +0530 Subject: [PATCH 20/63] test: correct error message (cherry picked from commit a29710dc07c2cc782abbedbc3691ec195e4b1e28) --- .../financial_report_template/test_financial_report_engine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index 696da7785c9..e6915096041 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -1882,7 +1882,7 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): self.assertEqual( jan_cash.opening, 5000.0, - "January opening should include balance from 2023 (5000 or more)", + "January opening should equal to balance from 2023 (5000)", ) # Verify running balance logic From 2994ba1b41e2ccea36c768ae3b99b791eea6df42 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 3 Feb 2026 18:11:34 +0530 Subject: [PATCH 21/63] test: further tests for query builder (cherry picked from commit 12f8bb2937e16c1063559b74e40b73f616f1a450) --- .../test_financial_report_engine.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index e6915096041..dcfe884bdf3 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -1939,6 +1939,8 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): "April opening should equal March closing balance", ) + self.assertEqual(apr_cash.closing, apr_cash.opening, "April closing = opening when no movement") + finally: # Clean up frappe.db.set_single_value( @@ -1954,3 +1956,77 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): pcv.cancel() jv_2023.cancel() + + def test_account_with_gl_entries_but_no_prior_closing_balance(self): + company = "_Test Company" + cash_account = "_Test Cash - _TC" + bank_account = "_Test Bank - _TC" + + # Create journal entries WITHOUT any prior Period Closing Voucher + # This ensures the account exists in gl_dict but NOT in balances_data + jv = make_journal_entry( + account1=cash_account, + account2=bank_account, + amount=2500, + posting_date="2024-07-15", + company=company, + submit=True, + ) + + try: + # Set up filters - use a period with no prior PCV + filters = { + "company": company, + "from_fiscal_year": "2024", + "to_fiscal_year": "2024", + "period_start_date": "2024-07-01", + "period_end_date": "2024-09-30", + "filter_based_on": "Date Range", + "periodicity": "Monthly", + } + + periods = [ + {"key": "2024_jul", "from_date": "2024-07-01", "to_date": "2024-07-31"}, + {"key": "2024_aug", "from_date": "2024-08-01", "to_date": "2024-08-31"}, + {"key": "2024_sep", "from_date": "2024-09-01", "to_date": "2024-09-30"}, + ] + + query_builder = FinancialQueryBuilder(filters, periods) + + # Use accounts that have GL entries but may not have Account Closing Balance + accounts = [ + frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}), + frappe._dict({"name": bank_account, "account_name": "Bank", "account_number": "1002"}), + ] + + balances_data = query_builder.fetch_account_balances(accounts) + + # Verify accounts are present in results even without prior closing balance + cash_data = balances_data.get(cash_account) + self.assertIsNotNone(cash_data, "Cash account should exist in results") + + bank_data = balances_data.get(bank_account) + self.assertIsNotNone(bank_data, "Bank account should exist in results") + + # Verify July has the movement from journal entry + jul_cash = cash_data.get_period("2024_jul") + self.assertIsNotNone(jul_cash, "July period should exist for cash") + self.assertEqual(jul_cash.movement, 2500.0, "July cash movement should be 2500") + + jul_bank = bank_data.get_period("2024_jul") + self.assertIsNotNone(jul_bank, "July period should exist for bank") + self.assertEqual(jul_bank.movement, -2500.0, "July bank movement should be -2500") + + # Verify subsequent periods exist with zero movement + aug_cash = cash_data.get_period("2024_aug") + self.assertIsNotNone(aug_cash, "August period should exist for cash") + self.assertEqual(aug_cash.movement, 0.0, "August cash movement should be 0") + self.assertEqual(aug_cash.opening, jul_cash.closing, "August opening = July closing") + + sep_cash = cash_data.get_period("2024_sep") + self.assertIsNotNone(sep_cash, "September period should exist for cash") + self.assertEqual(sep_cash.movement, 0.0, "September cash movement should be 0") + self.assertEqual(sep_cash.opening, aug_cash.closing, "September opening = August closing") + + finally: + jv.cancel() From 4a7ffce32013849c7936ade59938af019167014d Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 5 Feb 2026 12:42:12 +0530 Subject: [PATCH 22/63] fix: process loss error incorrectly thrown even when semi FG BOM does not have any process loss (cherry picked from commit 99ddc36c26fbdca927b2d1efa9bed1b441299c62) --- erpnext/stock/doctype/stock_entry/stock_entry.py | 4 ++-- erpnext/stock/doctype/stock_entry_type/stock_entry_type.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index b15bfb745c4..4b7a1e6e27d 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -449,12 +449,12 @@ class StockEntry(StockController, SubcontractingInwardController): def set_job_card_data(self): if self.job_card and not self.work_order: data = frappe.db.get_value( - "Job Card", self.job_card, ["for_quantity", "work_order", "bom_no"], as_dict=1 + "Job Card", self.job_card, ["for_quantity", "work_order", "bom_no", "semi_fg_bom"], as_dict=1 ) self.fg_completed_qty = data.for_quantity self.work_order = data.work_order self.from_bom = 1 - self.bom_no = data.bom_no + self.bom_no = data.semi_fg_bom or data.bom_no def validate_job_card_fg_item(self): if not self.job_card: diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index 29c0cd7e05c..75669657558 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -77,7 +77,6 @@ class ManufactureEntry: self.stock_entry.fg_completed_qty = self.for_quantity self.stock_entry.project = self.project self.stock_entry.job_card = self.job_card - self.stock_entry.work_order = self.work_order self.stock_entry.set_stock_entry_type() self.prepare_source_warehouse() From 6a9a28b4ae4c069e8437c3ab7f8265e7a89d1af4 Mon Sep 17 00:00:00 2001 From: Jatin3128 Date: Thu, 5 Feb 2026 05:02:46 +0530 Subject: [PATCH 23/63] fix(balance sheet): removed the extra labels from the chart (cherry picked from commit a64b5f2c5dd59ddb213c68f835cc50d78cae748e) --- erpnext/accounts/report/balance_sheet/balance_sheet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 3606de08ca3..68f4b7800c1 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -232,11 +232,11 @@ def get_report_summary( def get_chart_data(filters, columns, asset, liability, equity, currency): - labels = [d.get("label") for d in columns[2:]] + labels = [d.get("label") for d in columns[4:]] asset_data, liability_data, equity_data = [], [], [] - for p in columns[2:]: + for p in columns[4:]: if asset: asset_data.append(asset[-2].get(p.get("fieldname"))) if liability: From 62616ad9e1685faf09fdada25dfb9da637c774c4 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 5 Feb 2026 14:32:48 +0530 Subject: [PATCH 24/63] fix: stock balance report issue (cherry picked from commit 7e584dd84aef472c80385cc3f7f55f4301e9f98b) --- erpnext/stock/report/stock_balance/stock_balance.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 559e1b31a36..524b8d830d2 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -282,10 +282,8 @@ class StockBalanceReport: for field in self.inventory_dimensions: qty_dict[field] = entry.get(field) - if ( - entry.voucher_type == "Stock Reconciliation" - and frappe.get_cached_value(entry.voucher_type, entry.voucher_no, "purpose") != "Opening Stock" - and (not entry.batch_no or entry.serial_no) + if entry.voucher_type == "Stock Reconciliation" and ( + not entry.batch_no or not entry.serial_no or not entry.serial_and_batch_bundle ): qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) else: From 1d24abf5ddccabce25863d793dd6dd3c67922e70 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 5 Feb 2026 15:02:47 +0530 Subject: [PATCH 25/63] chore: fix issue --- erpnext/stock/report/stock_balance/stock_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 524b8d830d2..ccee40ce25f 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -283,7 +283,7 @@ class StockBalanceReport: qty_dict[field] = entry.get(field) if entry.voucher_type == "Stock Reconciliation" and ( - not entry.batch_no or not entry.serial_no or not entry.serial_and_batch_bundle + not entry.batch_no and not entry.serial_no and not entry.serial_and_batch_bundle ): qty_diff = flt(entry.qty_after_transaction) - flt(qty_dict.bal_qty) else: From d06a46ae8516dddff98e0cbff21766c314a52333 Mon Sep 17 00:00:00 2001 From: Nikhil Kothari Date: Thu, 5 Feb 2026 18:24:26 +0530 Subject: [PATCH 26/63] feat(accounts): expand Journal Entry Template to support dimensions and party (#51621) * feat(accounts): expand Journal Entry Template to support dimensions and party * fix: do not update standard row values (cherry picked from commit ef44528ba5d43e83f167a502734a628453b843f3) --- .../doctype/journal_entry/journal_entry.js | 16 +++++- .../journal_entry_template.js | 26 ++++++++++ .../journal_entry_template.py | 25 +++++++++- .../journal_entry_template_account.json | 49 +++++++++++++++++-- .../journal_entry_template_account.py | 4 ++ erpnext/hooks.py | 1 + erpnext/patches.txt | 1 + ...dimensions_to_journal_template_accounts.py | 11 +++++ 8 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 erpnext/patches/v16_0/add_accounting_dimensions_to_journal_template_accounts.py diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index c115204c28b..640ad3d9ad2 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -277,7 +277,21 @@ frappe.ui.form.on("Journal Entry", { var update_jv_details = function (doc, r) { $.each(r, function (i, d) { var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts"); - frappe.model.set_value(row.doctype, row.name, "account", d.account); + const { + idx, + name, + owner, + parent, + parenttype, + parentfield, + creation, + modified, + modified_by, + doctype, + docstatus, + ...fields + } = d; + frappe.model.set_value(row.doctype, row.name, fields); }); refresh_field("accounts"); }; diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js index cfd6ccfe375..6ef2a80c068 100644 --- a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js +++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js @@ -3,6 +3,7 @@ frappe.ui.form.on("Journal Entry Template", { onload: function (frm) { + erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype); if (frm.is_new()) { frappe.call({ type: "GET", @@ -37,6 +38,31 @@ frappe.ui.form.on("Journal Entry Template", { return { filters: filters }; }); + + frm.set_query("project", "accounts", function (doc, cdt, cdn) { + let row = frappe.get_doc(cdt, cdn); + let filters = { + company: doc.company, + }; + if (row.party_type == "Customer") { + filters.customer = row.party; + } + return { + query: "erpnext.controllers.queries.get_project_name", + filters, + }; + }); + + frm.set_query("party_type", "accounts", function (doc, cdt, cdn) { + const row = locals[cdt][cdn]; + + return { + query: "erpnext.setup.doctype.party_type.party_type.get_party_type", + filters: { + account: row.account, + }, + }; + }); }, voucher_type: function (frm) { var add_accounts = function (doc, r) { diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py index f87efc54e18..f86706774fc 100644 --- a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py +++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py @@ -3,6 +3,7 @@ import frappe +from frappe import _ from frappe.model.document import Document @@ -42,7 +43,29 @@ class JournalEntryTemplate(Document): ] # end: auto-generated types - pass + def validate(self): + self.validate_party() + + def validate_party(self): + """ + Loop over all accounts and see if party and party type is set correctly + """ + for account in self.accounts: + if account.party_type: + account_type = frappe.get_cached_value("Account", account.account, "account_type") + if account_type not in ["Receivable", "Payable"]: + frappe.throw( + _( + "Check row {0} for account {1}: Party Type is only allowed for Receivable or Payable accounts" + ).format(account.idx, account.account) + ) + + if account.party and not account.party_type: + frappe.throw( + _("Check row {0} for account {1}: Party is only allowed if Party Type is set").format( + account.idx, account.account + ) + ) @frappe.whitelist() diff --git a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json index e621fa2557f..0ec8b78884a 100644 --- a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json +++ b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json @@ -5,7 +5,13 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "account" + "account", + "party_type", + "party", + "accounting_dimensions_section", + "cost_center", + "dimension_col_break", + "project" ], "fields": [ { @@ -15,18 +21,55 @@ "label": "Account", "options": "Account", "reqd": 1 + }, + { + "fieldname": "party_type", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Party Type", + "options": "DocType" + }, + { + "fieldname": "party", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Party", + "options": "party_type" + }, + { + "collapsible": 1, + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" + }, + { + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center" + }, + { + "fieldname": "project", + "fieldtype": "Link", + "label": "Project", + "options": "Project" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } ], "istable": 1, "links": [], - "modified": "2024-03-27 13:09:58.986448", + "modified": "2026-01-09 13:16:27.615083", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Template Account", "owner": "Administrator", "permissions": [], + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py index 2426f577a1d..1ab32d34606 100644 --- a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py +++ b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py @@ -16,9 +16,13 @@ class JournalEntryTemplateAccount(Document): from frappe.types import DF account: DF.Link + cost_center: DF.Link | None parent: DF.Data parentfield: DF.Data parenttype: DF.Data + party: DF.DynamicLink | None + party_type: DF.Link | None + project: DF.Link | None # end: auto-generated types pass diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 9440459fef3..bdbe2292139 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -534,6 +534,7 @@ accounting_dimension_doctypes = [ "Purchase Order Item", "Sales Order Item", "Journal Entry Account", + "Journal Entry Template Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0e5d01b0353..838c837321e 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -456,6 +456,7 @@ erpnext.patches.v16_0.update_tax_withholding_field_in_payment_entry erpnext.patches.v16_0.migrate_tax_withholding_data erpnext.patches.v16_0.update_corrected_cancelled_status erpnext.patches.v16_0.fix_barcode_typo +erpnext.patches.v16_0.add_accounting_dimensions_to_journal_template_accounts erpnext.patches.v16_0.set_post_change_gl_entries_on_pos_settings execute:frappe.delete_doc_if_exists("Workspace Sidebar", "Opening & Closing") erpnext.patches.v15_0.create_accounting_dimensions_in_advance_taxes_and_charges diff --git a/erpnext/patches/v16_0/add_accounting_dimensions_to_journal_template_accounts.py b/erpnext/patches/v16_0/add_accounting_dimensions_to_journal_template_accounts.py new file mode 100644 index 00000000000..afdcbaeb706 --- /dev/null +++ b/erpnext/patches/v16_0/add_accounting_dimensions_to_journal_template_accounts.py @@ -0,0 +1,11 @@ +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_dimensions, + make_dimension_in_accounting_doctypes, +) + + +def execute(): + dimensions_and_defaults = get_dimensions() + if dimensions_and_defaults: + for dimension in dimensions_and_defaults[0]: + make_dimension_in_accounting_doctypes(dimension, ["Journal Entry Template Account"]) From 11222653ce0e562e73b3cb7a2c37aa7cd9127882 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 5 Feb 2026 16:40:53 +0530 Subject: [PATCH 27/63] fix: operation status and bom validation (cherry picked from commit 95baf953a81a731fe12ae3e07422e52b0470f727) --- erpnext/manufacturing/doctype/bom/bom.js | 9 ++-- erpnext/manufacturing/doctype/bom/bom.py | 49 +++++++++++++++++++ .../doctype/job_card/job_card.py | 22 +++++++++ .../doctype/work_order/work_order.js | 2 +- .../doctype/work_order/work_order.py | 10 ++++ .../stock/doctype/stock_entry/stock_entry.py | 1 + .../stock_entry_type/stock_entry_type.py | 4 +- 7 files changed, 92 insertions(+), 5 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 7ba01e07851..44cddac46d6 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -580,9 +580,12 @@ frappe.ui.form.on("BOM", { frappe.ui.form.on("BOM Operation", { finished_good(frm, cdt, cdn) { let row = locals[cdt][cdn]; - if (row.finished_good === frm.doc.item) { - frappe.model.set_value(row.doctype, row.name, "is_final_finished_good", 1); - } + frappe.model.set_value( + row.doctype, + row.name, + "is_final_finished_good", + row.finished_good === frm.doc.item + ); }, bom_no(frm, cdt, cdn) { diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index a58a37b92a0..943091487d2 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -296,6 +296,55 @@ class BOM(WebsiteGenerator): self.set_process_loss_qty() self.validate_scrap_items() self.set_default_uom() + self.validate_semi_finished_goods() + self.validate_raw_materials_of_operation() + + def validate_semi_finished_goods(self): + if not self.track_semi_finished_goods or not self.operations: + return + + fg_items = [] + for row in self.operations: + if not row.is_final_finished_good: + continue + + fg_items.append(row.finished_good) + + if not fg_items: + frappe.throw( + _( + "Since you have enabled 'Track Semi Finished Goods', at least one operation must have 'Is Final Finished Good' checked. For that set the FG / Semi FG Item as {0} against an operation." + ).format(bold(self.item)), + ) + + if fg_items and len(fg_items) > 1: + frappe.throw( + _( + "Only one operation can have 'Is Final Finished Good' checked when 'Track Semi Finished Goods' is enabled." + ), + ) + + def validate_raw_materials_of_operation(self): + if not self.track_semi_finished_goods or not self.operations: + return + + operation_idx_with_no_rm = {} + for row in self.operations: + if row.bom_no: + continue + + operation_idx_with_no_rm[row.idx] = row.operation + + for row in self.items: + if row.operation_row_id and row.operation_row_id in operation_idx_with_no_rm: + del operation_idx_with_no_rm[row.operation_row_id] + + for idx, row in operation_idx_with_no_rm.items(): + frappe.throw( + _("For operation {0} at row {1}, please add raw materials or set a BOM against it.").format( + bold(row.operation), idx + ), + ) def set_default_uom(self): if not self.get("items"): diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index ba2a36e2ad3..aa872c13946 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -166,6 +166,25 @@ class JobCard(Document): self.validate_work_order() self.set_employees() + self.validate_semi_finished_goods() + + def validate_semi_finished_goods(self): + if not self.track_semi_finished_goods: + return + + if self.items and not self.transferred_qty and not self.skip_material_transfer: + frappe.throw( + _( + "Materials needs to be transferred to the work in progress warehouse for the job card {0}" + ).format(self.name) + ) + + if self.docstatus == 1 and not self.total_completed_qty: + frappe.throw( + _( + "Total Completed Qty is required for Job Card {0}, please start and complete the job card before submission" + ).format(self.name) + ) def on_update(self): self.validate_job_card_qty() @@ -1354,6 +1373,9 @@ class JobCard(Document): employees=self.employee, sub_operation=kwargs.get("sub_operation"), ) + + if self.docstatus == 1: + self.update_work_order() else: self.add_time_logs(completed_qty=kwargs.qty, employees=self.employee) self.save() diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 78f2ba090cc..a61f95812b1 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -809,7 +809,7 @@ erpnext.work_order = { } } - if (frm.doc.status != "Stopped") { + if (frm.doc.status != "Stopped" && !frm.doc.track_semi_finished_goods) { // If "Material Consumption is check in Manufacturing Settings, allow Material Consumption if (frm.doc.__onload && frm.doc.__onload.material_consumption == 1) { if (flt(doc.material_transferred_for_manufacturing) > 0 || frm.doc.skip_transfer) { diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 80cfc0c2a6e..8f8302b4a21 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -248,6 +248,16 @@ class WorkOrder(Document): if self.is_new() and frappe.db.get_single_value("Stock Settings", "auto_reserve_stock"): self.reserve_stock = 1 + def before_save(self): + self.set_skip_transfer_for_operations() + + def set_skip_transfer_for_operations(self): + if not self.track_semi_finished_goods: + return + + for op in self.operations: + op.skip_material_transfer = self.skip_transfer + def validate_operations_sequence(self): if all([not op.sequence_id for op in self.operations]): for op in self.operations: diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 4b7a1e6e27d..2e2639080cf 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2006,6 +2006,7 @@ class StockEntry(StockController, SubcontractingInwardController): else: job_doc.set_consumed_qty_in_job_card_item(self) job_doc.set_manufactured_qty() + job_doc.update_work_order() if self.work_order: pro_doc = frappe.get_doc("Work Order", self.work_order) diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index 75669657558..30134ad4867 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -110,7 +110,9 @@ class ManufactureEntry: _dict.from_warehouse = self.source_wh.get(item_code) or self.wip_warehouse _dict.to_warehouse = "" - if backflush_based_on != "BOM": + if backflush_based_on != "BOM" and not frappe.db.get_value( + "Job Card", self.job_card, "skip_material_transfer" + ): calculated_qty = flt(_dict.transferred_qty) - flt(_dict.consumed_qty) if calculated_qty < 0: frappe.throw( From 305483e07475361c9228ca166896c2fc48351522 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 5 Feb 2026 21:06:47 +0530 Subject: [PATCH 28/63] fix: stock reservation created against job card (cherry picked from commit dca2cfd0095599488f2571517c9e145e4dd2704a) --- erpnext/manufacturing/doctype/bom/bom.py | 6 +- .../doctype/job_card/job_card.py | 4 +- .../doctype/work_order/work_order.py | 68 ++++++--- .../stock_entry_type/stock_entry_type.py | 133 +++++++++++++++++- 4 files changed, 190 insertions(+), 21 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 943091487d2..ceb2e9d0ffd 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -297,7 +297,9 @@ class BOM(WebsiteGenerator): self.validate_scrap_items() self.set_default_uom() self.validate_semi_finished_goods() - self.validate_raw_materials_of_operation() + + if self.docstatus == 1: + self.validate_raw_materials_of_operation() def validate_semi_finished_goods(self): if not self.track_semi_finished_goods or not self.operations: @@ -333,7 +335,7 @@ class BOM(WebsiteGenerator): if row.bom_no: continue - operation_idx_with_no_rm[row.idx] = row.operation + operation_idx_with_no_rm[row.idx] = row for row in self.items: if row.operation_row_id and row.operation_row_id in operation_idx_with_no_rm: diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index aa872c13946..0bc6807bf2a 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -166,7 +166,9 @@ class JobCard(Document): self.validate_work_order() self.set_employees() - self.validate_semi_finished_goods() + + if self.docstatus == 1: + self.validate_semi_finished_goods() def validate_semi_finished_goods(self): if not self.track_semi_finished_goods: diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 8f8302b4a21..912131e2825 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1609,6 +1609,7 @@ class WorkOrder(Document): "item_code": row.item_code, "voucher_detail_no": row.name, "warehouse": row.source_warehouse, + "status": ("not in", ["Closed", "Cancelled", "Completed"]), }, pluck="name", ): @@ -1817,24 +1818,10 @@ class WorkOrder(Document): elif stock_entry.job_card: # Reserve the final product for the job card. finished_good = frappe.db.get_value("Job Card", stock_entry.job_card, "finished_good") + if finished_good == self.production_item: + return - for row in stock_entry.items: - if row.item_code == finished_good: - item_details = [ - frappe._dict( - { - "item_code": row.item_code, - "stock_qty": row.qty, - "stock_reserved_qty": 0, - "warehouse": row.t_warehouse, - "voucher_no": stock_entry.work_order, - "voucher_type": "Work Order", - "name": row.name, - "delivered_qty": 0, - } - ) - ] - break + item_details = self.get_items_to_reserve_for_job_card(stock_entry, finished_good) else: # Reserve the final product for the sales order. item_details = self.get_so_details() @@ -1888,6 +1875,53 @@ class WorkOrder(Document): return items + def get_items_to_reserve_for_job_card(self, stock_entry, finished_good): + item_details = [] + for row in stock_entry.items: + if row.item_code == finished_good: + name = frappe.db.get_value( + "Work Order Item", + {"item_code": finished_good, "parent": self.name}, + "name", + ) + + sres = frappe.get_all( + "Stock Reservation Entry", + fields=["reserved_qty"], + filters={ + "voucher_no": self.name, + "item_code": finished_good, + "voucher_detail_no": name, + "warehouse": row.t_warehouse, + "docstatus": 1, + "status": "Reserved", + }, + ) + + pending_qty = row.qty + for d in sres: + pending_qty -= d.reserved_qty + + if pending_qty > 0: + item_details = [ + frappe._dict( + { + "item_code": row.item_code, + "stock_qty": pending_qty, + "stock_reserved_qty": 0, + "warehouse": row.t_warehouse, + "voucher_no": stock_entry.work_order, + "voucher_type": "Work Order", + "name": name, + "delivered_qty": 0, + } + ) + ] + + break + + return item_details + def get_wo_details(self): doctype = frappe.qb.DocType("Work Order") child_doctype = frappe.qb.DocType("Work Order Item") diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index 30134ad4867..040b98d84c7 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -2,10 +2,15 @@ # For license information, please see license.txt +from collections import defaultdict + import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import flt +from frappe.utils import cint, flt + +from erpnext.stock.serial_batch_bundle import SerialBatchCreation +from erpnext.stock.utils import get_combine_datetime from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict @@ -106,6 +111,10 @@ class ManufactureEntry: "Manufacturing Settings", "backflush_raw_materials_based_on" ) + available_serial_batches = frappe._dict({}) + if backflush_based_on != "BOM": + available_serial_batches = self.get_transferred_serial_batches() + for item_code, _dict in item_dict.items(): _dict.from_warehouse = self.source_wh.get(item_code) or self.wip_warehouse _dict.to_warehouse = "" @@ -120,9 +129,131 @@ class ManufactureEntry: ) _dict.qty = calculated_qty + self.update_available_serial_batches(_dict, available_serial_batches) self.stock_entry.add_to_stock_entry_detail(item_dict) + def parse_available_serial_batches(self, item_dict, available_serial_batches): + key = (item_dict.item_code, item_dict.from_warehouse) + if key not in available_serial_batches: + return [], {} + + _avl_dict = available_serial_batches[key] + + qty = item_dict.qty + serial_nos = [] + batches = frappe._dict() + + if _avl_dict.serial_nos: + serial_nos = _avl_dict.serial_nos[: cint(qty)] + qty -= len(serial_nos) + for sn in serial_nos: + _avl_dict.serial_nos.remove(sn) + + elif _avl_dict.batches: + batches = frappe._dict() + for batch_no, batch_qty in _avl_dict.batches.items(): + if qty <= 0: + break + if batch_qty <= qty: + batches[batch_no] = batch_qty + qty -= batch_qty + else: + batches[batch_no] = qty + qty = 0 + + for _used_batch_no in batches: + _avl_dict.batches[_used_batch_no] -= batches[_used_batch_no] + if _avl_dict.batches[_used_batch_no] <= 0: + del _avl_dict.batches[_used_batch_no] + + return serial_nos, batches + + def update_available_serial_batches(self, item_dict, available_serial_batches): + serial_nos, batches = self.parse_available_serial_batches(item_dict, available_serial_batches) + if serial_nos or batches: + sabb = SerialBatchCreation( + { + "item_code": item_dict.item_code, + "warehouse": item_dict.from_warehouse, + "posting_datetime": get_combine_datetime( + self.stock_entry.posting_date, self.stock_entry.posting_time + ), + "voucher_type": self.stock_entry.doctype, + "company": self.stock_entry.company, + "type_of_transaction": "Outward", + "qty": item_dict.qty, + "serial_nos": serial_nos, + "batches": batches, + "do_not_submit": True, + } + ).make_serial_and_batch_bundle() + + item_dict.serial_and_batch_bundle = sabb.name + + def get_stock_entry_data(self): + stock_entry = frappe.qb.DocType("Stock Entry") + stock_entry_detail = frappe.qb.DocType("Stock Entry Detail") + + return ( + frappe.qb.from_(stock_entry) + .inner_join(stock_entry_detail) + .on(stock_entry.name == stock_entry_detail.parent) + .select( + stock_entry_detail.item_code, + stock_entry_detail.qty, + stock_entry_detail.serial_and_batch_bundle, + stock_entry_detail.s_warehouse, + stock_entry_detail.t_warehouse, + stock_entry.purpose, + ) + .where( + (stock_entry.job_card == self.job_card) + & (stock_entry_detail.serial_and_batch_bundle.isnotnull()) + & (stock_entry.docstatus == 1) + & (stock_entry.purpose.isin(["Material Transfer for Manufacture", "Manufacture"])) + ) + .orderby(stock_entry.posting_date, stock_entry.posting_time) + ).run(as_dict=True) + + def get_transferred_serial_batches(self): + available_serial_batches = frappe._dict({}) + + stock_entry_data = self.get_stock_entry_data() + + for row in stock_entry_data: + warehouse = ( + row.t_warehouse if row.purpose == "Material Transfer for Manufacture" else row.s_warehouse + ) + key = (row.item_code, warehouse) + if key not in available_serial_batches: + available_serial_batches[key] = frappe._dict( + { + "batches": defaultdict(float), + "serial_nos": [], + } + ) + + _avl_dict = available_serial_batches[key] + + sabb_data = frappe.get_all( + "Serial and Batch Entry", + filters={"parent": row.serial_and_batch_bundle}, + fields=["serial_no", "batch_no", "qty"], + ) + for entry in sabb_data: + if entry.serial_no: + if entry.qty > 0: + _avl_dict.serial_nos.append(entry.serial_no) + else: + _avl_dict.serial_nos.remove(entry.serial_no) + if entry.batch_no: + _avl_dict.batches[entry.batch_no] += flt(entry.qty) * ( + -1 if row.purpose == "Material Transfer for Manufacture" else 1 + ) + + return available_serial_batches + def get_items_from_job_card(self): item_dict = {} items = frappe.get_all( From 8c372faf50908d902b9e1b921ff9e43b63d9f9cf Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 6 Feb 2026 11:29:45 +0530 Subject: [PATCH 29/63] chore: fix linter issue Removed duplicate import of get_bom_items_as_dict from BOM module. --- erpnext/stock/doctype/stock_entry_type/stock_entry_type.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index 040b98d84c7..4a768ee94fd 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -9,11 +9,10 @@ from frappe import _ from frappe.model.document import Document from frappe.utils import cint, flt +from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict from erpnext.stock.serial_batch_bundle import SerialBatchCreation from erpnext.stock.utils import get_combine_datetime -from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict - class StockEntryType(Document): # begin: auto-generated types From c0c6cc58ed7da80558ec48e6d2579904a9ff42d5 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 5 Feb 2026 20:45:46 +0530 Subject: [PATCH 30/63] fix: do not show update stock flag unneccessarily (cherry picked from commit 5fb5b7b30e8bdb5a57f5104ba87d74c17edd968f) # Conflicts: # erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json # erpnext/accounts/doctype/sales_invoice/sales_invoice.json --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 5 +++++ erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 02371e778cf..ade73ac6530 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -606,6 +606,7 @@ }, { "default": "0", + "depends_on": "eval:doc.items.every((item) => !item.pr_detail)", "fieldname": "update_stock", "fieldtype": "Check", "label": "Update Stock", @@ -1668,7 +1669,11 @@ "idx": 204, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2026-02-03 14:23:47.937128", +======= + "modified": "2026-02-05 20:45:16.964500", +>>>>>>> 5fb5b7b30e (fix: do not show update stock flag unneccessarily) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 93e4dd1598f..ec549710654 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -704,6 +704,7 @@ }, { "default": "0", + "depends_on": "eval:doc.items.every((item) => !item.dn_detail)", "fieldname": "update_stock", "fieldtype": "Check", "hide_days": 1, @@ -2306,7 +2307,11 @@ "link_fieldname": "consolidated_invoice" } ], +<<<<<<< HEAD "modified": "2026-02-03 14:09:44.347133", +======= + "modified": "2026-02-05 20:43:44.732805", +>>>>>>> 5fb5b7b30e (fix: do not show update stock flag unneccessarily) "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", From f56c6f93a168178f04602ba88becac73032fdab6 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 6 Feb 2026 12:00:23 +0530 Subject: [PATCH 31/63] chore: resolve conflicts --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index ade73ac6530..21cda420f5a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1669,11 +1669,7 @@ "idx": 204, "is_submittable": 1, "links": [], -<<<<<<< HEAD - "modified": "2026-02-03 14:23:47.937128", -======= "modified": "2026-02-05 20:45:16.964500", ->>>>>>> 5fb5b7b30e (fix: do not show update stock flag unneccessarily) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", From 4847a76cb87d49cd64e0d7b6b50aff2c105ca5e7 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 6 Feb 2026 12:00:47 +0530 Subject: [PATCH 32/63] chore: resolve conflicts --- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index ec549710654..4d0e0c73458 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -2307,11 +2307,7 @@ "link_fieldname": "consolidated_invoice" } ], -<<<<<<< HEAD - "modified": "2026-02-03 14:09:44.347133", -======= "modified": "2026-02-05 20:43:44.732805", ->>>>>>> 5fb5b7b30e (fix: do not show update stock flag unneccessarily) "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", From a1ec68cd1eee257ad148f8773d61818b2d3e469d Mon Sep 17 00:00:00 2001 From: Nishka Gosalia Date: Thu, 22 Jan 2026 20:34:22 +0530 Subject: [PATCH 33/63] fix: Added validation for quality inspection in job card (cherry picked from commit 46b4cf3addd848ebab559a3c09ebbbdd6f96ce94) --- .../doctype/job_card/job_card.py | 65 +++++++++++++++++++ .../doctype/job_card/test_job_card.py | 57 +++++++++++++++- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index aa872c13946..97b4afb7670 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -23,6 +23,10 @@ from frappe.utils import ( time_diff_in_hours, ) +from erpnext.controllers.stock_controller import ( + QualityInspectionNotSubmittedError, + QualityInspectionRejectedError, +) from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, get_bom_items_as_dict from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import ( get_mins_between_operations, @@ -751,6 +755,7 @@ class JobCard(Document): self.set_process_loss() def on_submit(self): + self.validate_inspection() self.validate_transfer_qty() self.validate_job_card() self.update_work_order() @@ -760,6 +765,66 @@ class JobCard(Document): self.update_work_order() self.set_transferred_qty() + def validate_inspection(self): + action_submit, action_reject = frappe.get_single_value( + "Stock Settings", + ["action_if_quality_inspection_is_not_submitted", "action_if_quality_inspection_is_rejected"], + ) + + item = self.finished_good or self.production_item + bom_inspection_required = frappe.db.get_value( + "BOM", self.semi_fg_bom or self.bom_no, "inspection_required" + ) + if bom_inspection_required: + if not self.quality_inspection: + frappe.throw( + _( + "Quality Inspection is required for the item {0} before completing the job card {1}" + ).format(get_link_to_form("Item", item), bold(self.name)) + ) + qa_status, docstatus = frappe.db.get_value( + "Quality Inspection", self.quality_inspection, ["status", "docstatus"] + ) + + if docstatus != 1: + if action_submit == "Stop": + frappe.throw( + _("Quality Inspection {0} is not submitted for the item: {1}").format( + get_link_to_form("Quality Inspection", self.quality_inspection), + get_link_to_form("Item", item), + ), + title=_("Inspection Submission"), + exc=QualityInspectionNotSubmittedError, + ) + else: + frappe.msgprint( + _("Quality Inspection {0} is not submitted for the item: {1}").format( + get_link_to_form("Quality Inspection", self.quality_inspection), + get_link_to_form("Item", item), + ), + alert=True, + indicator="orange", + ) + elif qa_status == "Rejected": + if action_reject == "Stop": + frappe.throw( + _("Quality Inspection {0} is rejected for the item: {1}").format( + get_link_to_form("Quality Inspection", self.quality_inspection), + get_link_to_form("Item", item), + ), + title=_("Inspection Rejected"), + exc=QualityInspectionRejectedError, + ) + else: + frappe.msgprint( + _("Quality Inspection {0} is rejected for the item: {1}").format( + get_link_to_form("Quality Inspection", self.quality_inspection), + get_link_to_form("Item", item), + ), + alert=True, + indicator="orange", + ) + def validate_transfer_qty(self): if ( not self.finished_good diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py index e6eaea39578..028a05d5c9d 100644 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.py +++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py @@ -20,8 +20,9 @@ from erpnext.manufacturing.doctype.job_card.job_card import ( make_stock_entry as make_stock_entry_from_jc, ) from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record -from erpnext.manufacturing.doctype.work_order.work_order import WorkOrder +from erpnext.manufacturing.doctype.work_order.work_order import WorkOrder, make_work_order from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation +from erpnext.stock.doctype.item.test_item import create_item from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.tests.utils import ERPNextTestSuite @@ -73,6 +74,50 @@ class TestJobCard(ERPNextTestSuite): def tearDown(self): frappe.db.rollback() + def test_quality_inspection_mandatory_check(self): + from erpnext.manufacturing.doctype.operation.test_operation import make_operation + + raw = create_item("Fabric-Raw") + cut_fg = create_item("Cut-Fabric-SFG") + stitch_fg = create_item("Stitched-TShirt-SFG") + final = create_item("Finished-TShirt") + + row = {"operation": "Cutting", "workstation": "_Test Workstation 1"} + + cutting = make_operation(row) + stitching = make_operation({"operation": "Stitching", "workstation": "_Test Workstation 1"}) + ironing = make_operation({"operation": "Ironing", "workstation": "_Test Workstation 1"}) + + cut_bom = create_semi_fg_bom(cut_fg.name, raw.name, inspection_required=1) + stitch_bom = create_semi_fg_bom(stitch_fg.name, cut_fg.name, inspection_required=0) + final_bom = frappe.new_doc("BOM") + final_bom.item = final.name + final_bom.quantity = 1 + final_bom.with_operations = 1 + final_bom.track_semi_finished_goods = 1 + final_bom.append("items", {"item_code": raw.name, "qty": 1}) + final_bom.append( + "operations", {"operation": cutting.name, "workstation": "_Test Workstation 1", "bom_no": cut_bom} + ) + final_bom.append( + "operations", + {"operation": stitching.name, "workstation": "_Test Workstation 1", "bom_no": stitch_bom}, + ) + final_bom.append("operations", {"operation": ironing.name, "workstation": "_Test Workstation 1"}) + final_bom.insert() + final_bom.submit() + work_order = make_work_order(final_bom.name, final.name, 1, variant_items=[], use_multi_level_bom=0) + work_order.wip_warehouse = "Work In Progress - WP" + work_order.fg_warehouse = "Finished Goods - WP" + work_order.scrap_warehouse = "All Warehouses - WP" + for operation in work_order.operations: + operation.time_in_mins = 60 + + work_order.submit() + job_card = frappe.get_all("Job Card", filters={"work_order": work_order.name, "operation": "Cutting"}) + job_card_doc = frappe.get_doc("Job Card", job_card[0].name) + self.assertRaises(frappe.ValidationError, job_card_doc.submit) + def test_job_card_operations(self): job_cards = frappe.get_all( "Job Card", filters={"work_order": self.work_order.name}, fields=["operation_id", "name"] @@ -871,3 +916,13 @@ def make_wo_with_transfer_against_jc(): work_order.submit() return work_order + + +def create_semi_fg_bom(semi_fg_item, raw_item, inspection_required): + bom = frappe.new_doc("BOM") + bom.item = semi_fg_item + bom.quantity = 1 + bom.inspection_required = inspection_required + bom.append("items", {"item_code": raw_item, "qty": 1}) + bom.submit() + return bom.name From 7a78e9705ccf4f15a0ba0768d0bc95c4a1826a3e Mon Sep 17 00:00:00 2001 From: Nishka Gosalia Date: Fri, 30 Jan 2026 12:23:38 +0530 Subject: [PATCH 34/63] fix: enabling skip delivery option for order type maintenance (cherry picked from commit 1a22e3cb6168c6e1850b7799ee6200c129a863d0) --- .../doctype/sales_order/sales_order.json | 4 ++-- .../doctype/sales_order/test_sales_order.py | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index f8ef775e9e4..609b093bae3 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -1458,9 +1458,9 @@ }, { "default": "0", + "depends_on": "eval:doc.order_type == 'Maintenance';", "fieldname": "skip_delivery_note", "fieldtype": "Check", - "hidden": 1, "hide_days": 1, "hide_seconds": 1, "label": "Skip Delivery Note", @@ -1713,7 +1713,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2026-02-03 14:45:50.314361", + "modified": "2026-02-06 11:06:16.092658", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index b3cb42906cc..3cb326cbcc3 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -57,6 +57,28 @@ class TestSalesOrder(AccountsTestMixin, IntegrationTestCase): frappe.db.rollback() frappe.set_user("Administrator") + def test_sales_order_skip_delivery_note(self): + so = make_sales_order(do_not_submit=True) + so.order_type = "Maintenance" + so.skip_delivery_note = 1 + so.append( + "items", + { + "item_code": "_Test Item 2", + "qty": 2, + "rate": 100, + }, + ) + so.save() + so.submit() + + so.reload() + si = make_sales_invoice(so.name) + si.insert() + si.submit() + so.reload() + self.assertEqual(so.status, "Completed") + @IntegrationTestCase.change_settings("Selling Settings", {"allow_negative_rates_for_items": 1}) def test_sales_order_with_negative_rate(self): """ From d2387a3af87bc1984bbd7cd66f9a710e9874c64f Mon Sep 17 00:00:00 2001 From: khushi8112 Date: Fri, 6 Feb 2026 12:58:42 +0530 Subject: [PATCH 35/63] fix: apply composite asset logic only in draft (cherry picked from commit ee501e884a9620f4adfed841387f3fb243692586) --- erpnext/assets/doctype/asset/asset.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 1c5c483bac4..1397b23f39b 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -513,12 +513,14 @@ frappe.ui.form.on("Asset", { }, is_composite_asset: function (frm) { - if (frm.doc.is_composite_asset) { - frm.set_value("net_purchase_amount", 0); - } else { - frm.set_df_property("net_purchase_amount", "read_only", 0); + if (frm.doc.docstatus == 0) { + if (frm.doc.is_composite_asset) { + frm.set_value("net_purchase_amount", 0); + } else { + frm.set_df_property("net_purchase_amount", "read_only", 0); + } + frm.trigger("toggle_reference_doc"); } - frm.trigger("toggle_reference_doc"); }, make_sales_invoice: function (frm) { From ece8d0041572fc6ffdbe4acb9f2a6b64b8f4a7b5 Mon Sep 17 00:00:00 2001 From: Nishka Gosalia Date: Fri, 6 Feb 2026 14:34:08 +0530 Subject: [PATCH 36/63] fix: test cases --- erpnext/manufacturing/doctype/bom/bom.py | 2 +- .../doctype/job_card/test_job_card.py | 36 ++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 943091487d2..64688c4621e 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -333,7 +333,7 @@ class BOM(WebsiteGenerator): if row.bom_no: continue - operation_idx_with_no_rm[row.idx] = row.operation + operation_idx_with_no_rm[row.idx] = row for row in self.items: if row.operation_row_id and row.operation_row_id in operation_idx_with_no_rm: diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py index 028a05d5c9d..bcda8913238 100644 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.py +++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py @@ -90,21 +90,39 @@ class TestJobCard(ERPNextTestSuite): cut_bom = create_semi_fg_bom(cut_fg.name, raw.name, inspection_required=1) stitch_bom = create_semi_fg_bom(stitch_fg.name, cut_fg.name, inspection_required=0) - final_bom = frappe.new_doc("BOM") - final_bom.item = final.name - final_bom.quantity = 1 - final_bom.with_operations = 1 - final_bom.track_semi_finished_goods = 1 + final_bom = frappe.new_doc( + "BOM", item=final.name, quantity=1, with_operations=1, track_semi_finished_goods=1 + ) final_bom.append("items", {"item_code": raw.name, "qty": 1}) final_bom.append( - "operations", {"operation": cutting.name, "workstation": "_Test Workstation 1", "bom_no": cut_bom} + "operations", + { + "operation": cutting.name, + "workstation": "_Test Workstation 1", + "bom_no": cut_bom, + "skip_material_transfer": 1, + }, ) final_bom.append( "operations", - {"operation": stitching.name, "workstation": "_Test Workstation 1", "bom_no": stitch_bom}, + { + "operation": stitching.name, + "workstation": "_Test Workstation 1", + "bom_no": stitch_bom, + "skip_material_transfer": 1, + }, ) - final_bom.append("operations", {"operation": ironing.name, "workstation": "_Test Workstation 1"}) - final_bom.insert() + final_bom.append( + "operations", + { + "operation": ironing.name, + "workstation": "_Test Workstation 1", + "is_final_finished_good": 1, + "bom_no": final_bom.name, + "skip_material_transfer": 1, + }, + ) + final_bom.append("items", {"item_code": stitch_fg.name, "qty": 1, "operation_row_id": 3}) final_bom.submit() work_order = make_work_order(final_bom.name, final.name, 1, variant_items=[], use_multi_level_bom=0) work_order.wip_warehouse = "Work In Progress - WP" From 9886b46cb45b371d96da30636dcc454471cf9214 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Fri, 6 Feb 2026 13:12:04 +0530 Subject: [PATCH 37/63] fix(buying): add supplier group link filters in field level (cherry picked from commit cfdc554a19158ede2d1b7b4fff80d2cebdc166f6) # Conflicts: # erpnext/buying/doctype/supplier/supplier.json --- erpnext/buying/doctype/supplier/supplier.js | 8 -------- erpnext/buying/doctype/supplier/supplier.json | 5 +++++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index 4b46ddc3d80..fb4ef867ade 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -135,14 +135,6 @@ frappe.ui.form.on("Supplier", { // indicators erpnext.utils.set_party_dashboard_indicators(frm); } - - frm.set_query("supplier_group", () => { - return { - filters: { - is_group: 0, - }, - }; - }); }, get_supplier_group_details: function (frm) { frappe.call({ diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index a801a2a601d..24b37c20ff5 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -167,6 +167,7 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Supplier Group", + "link_filters": "[[\"Supplier Group\",\"is_group\",\"=\",0]]", "oldfieldname": "supplier_type", "oldfieldtype": "Link", "options": "Supplier Group" @@ -500,7 +501,11 @@ "link_fieldname": "party" } ], +<<<<<<< HEAD "modified": "2026-01-16 15:56:31.139206", +======= + "modified": "2026-02-06 12:58:01.398824", +>>>>>>> cfdc554a19 (fix(buying): add supplier group link filters in field level) "modified_by": "Administrator", "module": "Buying", "name": "Supplier", From 23a26b540bcb675ff97bda627b52a9065ad524d1 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Fri, 6 Feb 2026 13:13:44 +0530 Subject: [PATCH 38/63] fix(stock): add is group filter for warehouse fields (cherry picked from commit a9829f5f7b3f3efef57f4c96f67a09b5a3af7f4a) --- .../material_request/material_request.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 1975343c90b..b730080ea35 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -30,7 +30,10 @@ frappe.ui.form.on("Material Request", { frm.set_query("from_warehouse", "items", function (doc) { return { - filters: { company: doc.company }, + filters: { + company: doc.company, + is_group: 0, + }, }; }); @@ -70,19 +73,28 @@ frappe.ui.form.on("Material Request", { frm.set_query("warehouse", "items", function (doc) { return { - filters: { company: doc.company }, + filters: { + company: doc.company, + is_group: 0, + }, }; }); frm.set_query("set_warehouse", function (doc) { return { - filters: { company: doc.company }, + filters: { + company: doc.company, + is_group: 0, + }, }; }); frm.set_query("set_from_warehouse", function (doc) { return { - filters: { company: doc.company }, + filters: { + company: doc.company, + is_group: 0, + }, }; }); From dd45bb5664439c9607fad088f44ceda897e05762 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Sat, 7 Feb 2026 21:44:42 +0530 Subject: [PATCH 39/63] chore: resolve conflicts --- erpnext/buying/doctype/supplier/supplier.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 24b37c20ff5..78b797d4c2b 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -501,11 +501,7 @@ "link_fieldname": "party" } ], -<<<<<<< HEAD - "modified": "2026-01-16 15:56:31.139206", -======= "modified": "2026-02-06 12:58:01.398824", ->>>>>>> cfdc554a19 (fix(buying): add supplier group link filters in field level) "modified_by": "Administrator", "module": "Buying", "name": "Supplier", From 9766361c07efa00a29278edb84de06cae3c1c296 Mon Sep 17 00:00:00 2001 From: MochaMind Date: Sun, 8 Feb 2026 22:19:45 +0530 Subject: [PATCH 40/63] chore: update POT file (#52530) --- erpnext/locale/main.pot | 1227 ++++++++++++++++++++++++--------------- 1 file changed, 763 insertions(+), 464 deletions(-) diff --git a/erpnext/locale/main.pot b/erpnext/locale/main.pot index 4a738fff71d..eab1b559dde 100644 --- a/erpnext/locale/main.pot +++ b/erpnext/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ERPNext VERSION\n" "Report-Msgid-Bugs-To: hello@frappe.io\n" -"POT-Creation-Date: 2026-02-01 09:43+0000\n" -"PO-Revision-Date: 2026-02-01 09:43+0000\n" +"POT-Creation-Date: 2026-02-08 09:43+0000\n" +"PO-Revision-Date: 2026-02-08 09:43+0000\n" "Last-Translator: hello@frappe.io\n" "Language-Team: hello@frappe.io\n" "MIME-Version: 1.0\n" @@ -16,10 +16,10 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.16.0\n" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1456 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1466 msgid "" "\n" -"\t\t\t\t\tThe Batch {0} of an item {1} has negative stock in the warehouse {2}. Please add a stock quantity of {3} to proceed with this entry." +"\t\t\tThe Batch {0} of an item {1} has negative stock in the warehouse {2}. Please add a stock quantity of {3} to proceed with this entry." msgstr "" #. Label of the column_break_32 (Column Break) field in DocType 'Email Digest' @@ -153,7 +153,7 @@ msgstr "" msgid "% Delivered" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:989 +#: erpnext/manufacturing/doctype/bom/bom.js:992 #, python-format msgid "% Finished Item Quantity" msgstr "" @@ -999,14 +999,10 @@ msgstr "" msgid "A Reconciliation Job {0} is running for the same filters. Cannot reconcile now" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1750 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1754 msgid "A Reverse Journal Entry {0} already exists for this Journal Entry." msgstr "" -#: erpnext/setup/doctype/company/company.py:1097 -msgid "A Transaction Deletion Document: {0} is triggered for {0}" -msgstr "" - #. Description of a DocType #: erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.json msgid "A condition for a Shipping Rule" @@ -1070,6 +1066,10 @@ msgstr "" msgid "ACC-PINV-.YYYY.-" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:88 +msgid "ALL records will be deleted (entire DocType cleared)" +msgstr "" + #: erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py:552 msgid "AMC Expiry (Serial)" msgstr "" @@ -1164,7 +1164,7 @@ msgstr "" #. Label of the qty (Float) field in DocType 'Purchase Receipt Item' #. Label of the qty (Float) field in DocType 'Subcontracting Receipt Item' -#: erpnext/public/js/controllers/transaction.js:2814 +#: erpnext/public/js/controllers/transaction.js:2807 #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json #: erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json msgid "Accepted Quantity" @@ -1197,7 +1197,7 @@ msgstr "" msgid "According to CEFACT/ICG/2010/IC013 or CEFACT/ICG/2010/IC010" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:988 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:989 msgid "According to the BOM {0}, the Item '{1}' is missing in the stock entry." msgstr "" @@ -1659,6 +1659,8 @@ msgstr "" #. Label of the accounting_dimensions_section (Section Break) field in DocType #. 'Journal Entry Account' #. Label of the accounting_dimensions_section (Section Break) field in DocType +#. 'Journal Entry Template Account' +#. Label of the accounting_dimensions_section (Section Break) field in DocType #. 'Loyalty Program' #. Label of the accounting_dimensions_section (Section Break) field in DocType #. 'Opening Invoice Creation Tool' @@ -1744,6 +1746,7 @@ msgstr "" #. 'Subcontracting Receipt Supplied Item' #: erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +#: erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json #: erpnext/accounts/doctype/loyalty_program/loyalty_program.json #: erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json #: erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json @@ -1824,8 +1827,8 @@ msgstr "" msgid "Accounting Entry for Asset" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1959 -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1979 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1960 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1980 msgid "Accounting Entry for LCV in Stock Entry {0}" msgstr "" @@ -1849,8 +1852,8 @@ msgstr "" #: erpnext/controllers/stock_controller.py:686 #: erpnext/controllers/stock_controller.py:703 #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.py:930 -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1904 -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1918 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1905 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1919 #: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:708 msgid "Accounting Entry for Stock" msgstr "" @@ -2550,7 +2553,7 @@ msgid "Add Quote" msgstr "" #. Label of the add_raw_materials (Button) field in DocType 'BOM Operation' -#: erpnext/manufacturing/doctype/bom/bom.js:1017 +#: erpnext/manufacturing/doctype/bom/bom.js:1020 #: erpnext/manufacturing/doctype/bom_operation/bom_operation.json msgid "Add Raw Materials" msgstr "" @@ -2925,7 +2928,7 @@ msgstr "" msgid "Additional Transferred Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:666 +#: erpnext/manufacturing/doctype/work_order/work_order.py:676 msgid "" "Additional Transferred Qty {0}\n" "\t\t\t\t\tcannot be greater than {1}.\n" @@ -3088,7 +3091,7 @@ msgstr "" msgid "Adjust Qty" msgstr "" -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1129 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1130 msgid "Adjustment Against" msgstr "" @@ -3544,7 +3547,7 @@ msgstr "" msgid "All Activities HTML" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:318 +#: erpnext/manufacturing/doctype/bom/bom.py:369 msgid "All BOMs" msgstr "" @@ -3685,15 +3688,15 @@ msgstr "" msgid "All items have already been Invoiced/Returned" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:1208 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:1216 msgid "All items have already been received" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3110 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3112 msgid "All items have already been transferred for this Work Order." msgstr "" -#: erpnext/public/js/controllers/transaction.js:2922 +#: erpnext/public/js/controllers/transaction.js:2915 msgid "All items in this document already have a linked Quality Inspection." msgstr "" @@ -3719,7 +3722,7 @@ msgstr "" msgid "All the required items (raw materials) will be fetched from BOM and populated in this table. Here you can also change the Source Warehouse for any item. And during the production, you can track transferred raw materials from this table." msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:858 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:866 msgid "All these items have already been Invoiced/Returned" msgstr "" @@ -3906,7 +3909,7 @@ msgstr "" msgid "Allow Item To Be Added Multiple Times in a Transaction" msgstr "" -#: erpnext/controllers/selling_controller.py:853 +#: erpnext/controllers/selling_controller.py:847 msgid "Allow Item to Be Added Multiple Times in a Transaction" msgstr "" @@ -4406,7 +4409,7 @@ msgstr "" #: erpnext/accounts/doctype/bank_guarantee/bank_guarantee.json #: erpnext/accounts/doctype/budget_distribution/budget_distribution.json #: erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.json -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:613 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:627 #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json #: erpnext/accounts/doctype/payment_entry/payment_entry.json #: erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json @@ -5728,7 +5731,7 @@ msgstr "" msgid "At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} in the warehouse {4}." msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1350 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1355 msgid "At Row {0}: In Serial and Batch Bundle {1} must have docstatus as 1 and not 0" msgstr "" @@ -5785,7 +5788,7 @@ msgstr "" msgid "At row #{0}: you have selected the Difference Account {1}, which is a Cost of Goods Sold type account. Please select a different account" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1112 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1117 msgid "At row {0}: Batch No is mandatory for Item {1}" msgstr "" @@ -5793,11 +5796,11 @@ msgstr "" msgid "At row {0}: Parent Row No cannot be set for item {1}" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1097 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1102 msgid "At row {0}: Qty is mandatory for the batch {1}" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1104 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1109 msgid "At row {0}: Serial No is mandatory for Item {1}" msgstr "" @@ -6283,7 +6286,7 @@ msgstr "" #: erpnext/stock/report/stock_ageing/stock_ageing.py:170 #: erpnext/stock/report/stock_ageing/stock_ageing.py:204 -#: erpnext/stock/report/stock_balance/stock_balance.py:515 +#: erpnext/stock/report/stock_balance/stock_balance.py:517 msgid "Average Age" msgstr "" @@ -6398,7 +6401,7 @@ msgstr "" #: erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py:109 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json #: erpnext/selling/doctype/sales_order/sales_order.js:1415 -#: erpnext/stock/doctype/material_request/material_request.js:339 +#: erpnext/stock/doctype/material_request/material_request.js:351 #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json #: erpnext/stock/doctype/stock_entry/stock_entry.js:689 #: erpnext/stock/report/bom_search/bom_search.py:38 @@ -6413,7 +6416,7 @@ msgstr "" msgid "BOM 1" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1700 +#: erpnext/manufacturing/doctype/bom/bom.py:1751 msgid "BOM 1 {0} and BOM 2 {1} should not be same" msgstr "" @@ -6639,7 +6642,7 @@ msgstr "" msgid "BOM Website Operation" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2278 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2280 msgid "BOM and Finished Good Quantity is mandatory for Disassembly" msgstr "" @@ -6653,7 +6656,7 @@ msgstr "" msgid "BOM and Production" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:374 +#: erpnext/stock/doctype/material_request/material_request.js:386 #: erpnext/stock/doctype/stock_entry/stock_entry.js:741 msgid "BOM does not contain any stock item" msgstr "" @@ -6662,23 +6665,23 @@ msgstr "" msgid "BOM recursion: {0} cannot be child of {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:700 +#: erpnext/manufacturing/doctype/bom/bom.py:751 msgid "BOM recursion: {1} cannot be parent or child of {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1435 +#: erpnext/manufacturing/doctype/bom/bom.py:1486 msgid "BOM {0} does not belong to Item {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1417 +#: erpnext/manufacturing/doctype/bom/bom.py:1468 msgid "BOM {0} must be active" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1420 +#: erpnext/manufacturing/doctype/bom/bom.py:1471 msgid "BOM {0} must be submitted" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:788 +#: erpnext/manufacturing/doctype/bom/bom.py:839 msgid "BOM {0} not found for the item {1}" msgstr "" @@ -6768,7 +6771,7 @@ msgstr "" #: erpnext/stock/report/available_batch_report/available_batch_report.py:63 #: erpnext/stock/report/available_serial_no/available_serial_no.py:126 #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:84 -#: erpnext/stock/report/stock_balance/stock_balance.py:443 +#: erpnext/stock/report/stock_balance/stock_balance.py:445 #: erpnext/stock/report/stock_ledger/stock_ledger.py:251 msgid "Balance Qty" msgstr "" @@ -6831,7 +6834,7 @@ msgstr "" #: erpnext/stock/report/available_serial_no/available_serial_no.py:174 #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:86 -#: erpnext/stock/report/stock_balance/stock_balance.py:450 +#: erpnext/stock/report/stock_balance/stock_balance.py:452 #: erpnext/stock/report/stock_ledger/stock_ledger.py:308 msgid "Balance Value" msgstr "" @@ -7383,7 +7386,7 @@ msgstr "" #: erpnext/manufacturing/doctype/job_card/job_card.json #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js:89 #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py:115 -#: erpnext/public/js/controllers/transaction.js:2840 +#: erpnext/public/js/controllers/transaction.js:2833 #: erpnext/public/js/utils/barcode_scanner.js:281 #: erpnext/public/js/utils/serial_no_batch_selector.js:438 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -7412,11 +7415,11 @@ msgstr "" msgid "Batch No" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1115 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1120 msgid "Batch No is mandatory" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:3240 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:3256 msgid "Batch No {0} does not exists" msgstr "" @@ -7424,7 +7427,7 @@ msgstr "" msgid "Batch No {0} is linked with Item {1} which has serial no. Please scan serial no instead." msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:436 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:437 msgid "Batch No {0} is not present in the original {1} {2}, hence you can't return it against the {1} {2}" msgstr "" @@ -7439,11 +7442,11 @@ msgstr "" msgid "Batch Nos" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1834 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1850 msgid "Batch Nos are created successfully" msgstr "" -#: erpnext/controllers/sales_and_purchase_return.py:1165 +#: erpnext/controllers/sales_and_purchase_return.py:1187 msgid "Batch Not Available for Return" msgstr "" @@ -7493,7 +7496,7 @@ msgstr "" msgid "Batch and Serial No" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:886 +#: erpnext/manufacturing/doctype/work_order/work_order.py:896 msgid "Batch not created for item {} since it does not have a batch series." msgstr "" @@ -7501,16 +7504,16 @@ msgstr "" msgid "Batch {0} and Warehouse" msgstr "" -#: erpnext/controllers/sales_and_purchase_return.py:1164 +#: erpnext/controllers/sales_and_purchase_return.py:1186 msgid "Batch {0} is not available in warehouse {1}" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3287 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3289 #: erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py:290 msgid "Batch {0} of Item {1} has expired." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3293 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3295 msgid "Batch {0} of Item {1} is disabled." msgstr "" @@ -7574,9 +7577,9 @@ msgstr "" #. Label of a Card Break in the Manufacturing Workspace #. Label of a Link in the Manufacturing Workspace -#: erpnext/manufacturing/doctype/bom/bom.py:1267 +#: erpnext/manufacturing/doctype/bom/bom.py:1318 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json -#: erpnext/stock/doctype/material_request/material_request.js:127 +#: erpnext/stock/doctype/material_request/material_request.js:139 #: erpnext/stock/doctype/stock_entry/stock_entry.js:675 msgid "Bill of Materials" msgstr "" @@ -8680,7 +8683,7 @@ msgstr "" msgid "Can be approved by {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2460 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2504 msgid "Can not close Work Order. Since {0} Job Cards are in Work In Progress state." msgstr "" @@ -8787,6 +8790,10 @@ msgstr "" msgid "Cannot Resubmit Ledger entries for vouchers in Closed fiscal year." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:202 +msgid "Cannot add child table {0} to deletion list. Child tables are automatically deleted with their parent DocTypes." +msgstr "" + #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:226 msgid "Cannot amend {0} {1}, please create a new one instead." msgstr "" @@ -8815,7 +8822,7 @@ msgstr "" msgid "Cannot cancel as processing of cancelled documents is pending." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1071 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1081 msgid "Cannot cancel because submitted Stock Entry {0} exists" msgstr "" @@ -8900,7 +8907,7 @@ msgstr "" msgid "Cannot create return for consolidated invoice {0}." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1124 +#: erpnext/manufacturing/doctype/bom/bom.py:1175 msgid "Cannot deactivate or cancel BOM as it is linked with other BOMs" msgstr "" @@ -8925,11 +8932,20 @@ msgstr "" msgid "Cannot delete an item which has been ordered" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:195 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:778 +msgid "Cannot delete protected core DocType: {0}" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:211 +msgid "Cannot delete virtual DocType: {0}. Virtual DocTypes do not have database tables." +msgstr "" + #: erpnext/setup/doctype/company/company.py:561 msgid "Cannot disable perpetual inventory, as there are existing Stock Ledger Entries for the company {0}. Please cancel the stock transactions first and try again." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:683 +#: erpnext/manufacturing/doctype/work_order/work_order.py:693 msgid "Cannot disassemble more than produced quantity." msgstr "" @@ -8937,10 +8953,6 @@ msgstr "" msgid "Cannot enable Item-wise Inventory Account, as there are existing Stock Ledger Entries for the company {0} with Warehouse-wise Inventory Account. Please cancel the stock transactions first and try again." msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:113 -msgid "Cannot enqueue multi docs for one company. {0} is already queued/running for company: {1}" -msgstr "" - #: erpnext/selling/doctype/sales_order/sales_order.py:782 #: erpnext/selling/doctype/sales_order/sales_order.py:805 msgid "Cannot ensure delivery by Serial No as Item {0} is added with and without Ensure Delivery by Serial No." @@ -8958,23 +8970,19 @@ msgstr "" msgid "Cannot find a default warehouse for item {0}. Please set one in the Item Master or in Stock Settings." msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:519 -msgid "Cannot make any transactions until the deletion job is completed" -msgstr "" - #: erpnext/accounts/party.py:1075 msgid "Cannot merge {0} '{1}' into '{2}' as both have existing accounting entries in different currencies for company '{3}'." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:533 +#: erpnext/manufacturing/doctype/work_order/work_order.py:543 msgid "Cannot produce more Item {0} than Sales Order quantity {1} {2}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1426 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1436 msgid "Cannot produce more item for {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1430 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1440 msgid "Cannot produce more than {0} items for {1}" msgstr "" @@ -9033,6 +9041,10 @@ msgstr "" msgid "Cannot set the field {0} for copying in variants" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:264 +msgid "Cannot start deletion. Another deletion {0} is already queued/running. Please wait for it to complete." +msgstr "" + #: erpnext/accounts/doctype/payment_entry/payment_entry.py:1921 msgid "Cannot {0} from {1} without any negative outstanding invoice" msgstr "" @@ -9068,7 +9080,7 @@ msgstr "" msgid "Capacity Planning" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1057 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1067 msgid "Capacity Planning Error, planned start time can not be same as end time" msgstr "" @@ -9552,6 +9564,14 @@ msgstr "" msgid "Check if material transfer entry is not required" msgstr "" +#: erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py:58 +msgid "Check row {0} for account {1}: Party Type is only allowed for Receivable or Payable accounts" +msgstr "" + +#: erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py:65 +msgid "Check row {0} for account {1}: Party is only allowed if Party Type is set" +msgstr "" + #. Description of the 'Must be Whole Number' (Check) field in DocType 'UOM' #: erpnext/setup/doctype/uom/uom.json msgid "Check this to disallow fractions. (for Nos)" @@ -9619,7 +9639,7 @@ msgstr "" #. Label of the reference_date (Date) field in DocType 'Payment Entry' #: erpnext/accounts/doctype/payment_entry/payment_entry.json -#: erpnext/public/js/controllers/transaction.js:2751 +#: erpnext/public/js/controllers/transaction.js:2744 msgid "Cheque/Reference Date" msgstr "" @@ -9660,6 +9680,12 @@ msgstr "" msgid "Chief Technology Officer" msgstr "" +#. Label of the child_doctypes (Small Text) field in DocType 'Transaction +#. Deletion Record To Delete' +#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json +msgid "Child DocTypes" +msgstr "" + #. Label of the child_docname (Data) field in DocType 'Pricing Rule Detail' #: erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.json msgid "Child Docname" @@ -9667,11 +9693,15 @@ msgstr "" #. Label of the child_row_reference (Data) field in DocType 'Quality #. Inspection' -#: erpnext/public/js/controllers/transaction.js:2846 +#: erpnext/public/js/controllers/transaction.js:2839 #: erpnext/stock/doctype/quality_inspection/quality_inspection.json msgid "Child Row Reference" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:205 +msgid "Child Table Not Allowed" +msgstr "" + #: erpnext/projects/doctype/task/task.py:312 msgid "Child Task exists for this Task. You can not delete this Task." msgstr "" @@ -9680,6 +9710,12 @@ msgstr "" msgid "Child nodes can be only created under 'Group' type nodes" msgstr "" +#. Description of the 'Child DocTypes' (Small Text) field in DocType +#. 'Transaction Deletion Record To Delete' +#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json +msgid "Child tables that will also be deleted" +msgstr "" + #: erpnext/stock/doctype/warehouse/warehouse.py:103 msgid "Child warehouse exists for this warehouse. You can not delete this warehouse." msgstr "" @@ -9714,8 +9750,8 @@ msgstr "" msgid "Clear Demo Data" msgstr "" -#. Label of the clear_notifications (Check) field in DocType 'Transaction -#. Deletion Record' +#. Label of the clear_notifications_status (Select) field in DocType +#. 'Transaction Deletion Record' #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json msgid "Clear Notifications" msgstr "" @@ -9825,7 +9861,7 @@ msgstr "" msgid "Closed Documents" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2383 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2427 msgid "Closed Work Order can not be stopped or Re-opened" msgstr "" @@ -10191,6 +10227,7 @@ msgstr "" #. Label of the company (Link) field in DocType 'Transaction Deletion Record' #. Label of the company (Link) field in DocType 'Vehicle' #. Label of a Link in the Home Workspace +#. Label of the company (Link) field in DocType 'Bin' #. Label of the company (Link) field in DocType 'Delivery Note' #. Label of the company (Link) field in DocType 'Delivery Trip' #. Label of the company (Link) field in DocType 'Item Default' @@ -10448,6 +10485,7 @@ msgstr "" #: erpnext/setup/install.py:165 erpnext/setup/workspace/home/home.json #: erpnext/stock/dashboard_chart_source/stock_value_by_item_group/stock_value_by_item_group.js:8 #: erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.js:8 +#: erpnext/stock/doctype/bin/bin.json #: erpnext/stock/doctype/delivery_note/delivery_note.json #: erpnext/stock/doctype/delivery_trip/delivery_trip.json #: erpnext/stock/doctype/item_default/item_default.json @@ -10494,7 +10532,7 @@ msgstr "" #: erpnext/stock/report/stock_analytics/stock_analytics.js:41 #: erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js:7 #: erpnext/stock/report/stock_balance/stock_balance.js:8 -#: erpnext/stock/report/stock_balance/stock_balance.py:504 +#: erpnext/stock/report/stock_balance/stock_balance.py:506 #: erpnext/stock/report/stock_ledger/stock_ledger.js:8 #: erpnext/stock/report/stock_ledger/stock_ledger.py:358 #: erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js:18 @@ -10642,6 +10680,12 @@ msgstr "" msgid "Company Email" msgstr "" +#. Label of the company_field (Data) field in DocType 'Transaction Deletion +#. Record To Delete' +#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json +msgid "Company Field" +msgstr "" + #. Label of the company_logo (Attach Image) field in DocType 'Company' #: erpnext/public/js/print.js:64 erpnext/setup/doctype/company/company.json msgid "Company Logo" @@ -10673,7 +10717,7 @@ msgstr "" msgid "Company currencies of both the companies should match for Inter Company Transactions." msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:368 +#: erpnext/stock/doctype/material_request/material_request.js:380 #: erpnext/stock/doctype/stock_entry/stock_entry.js:735 msgid "Company field is required" msgstr "" @@ -10690,6 +10734,12 @@ msgstr "" msgid "Company is mandatory for generating an invoice. Please set a default company in Global Defaults." msgstr "" +#. Description of the 'Company Field' (Data) field in DocType 'Transaction +#. Deletion Record To Delete' +#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json +msgid "Company link field name used for filtering (optional - leave empty to delete all records)" +msgstr "" + #: erpnext/setup/doctype/company/company.js:222 msgid "Company name not same" msgstr "" @@ -10811,7 +10861,7 @@ msgstr "" msgid "Completed Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1340 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1350 msgid "Completed Qty cannot be greater than 'Qty to Manufacture'" msgstr "" @@ -11128,7 +11178,7 @@ msgstr "" msgid "Consumed Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1718 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1729 msgid "Consumed Qty cannot be greater than Reserved Qty for item {0}" msgstr "" @@ -11157,7 +11207,7 @@ msgstr "" msgid "Consumed Stock Total Value" msgstr "" -#: erpnext/stock/doctype/stock_entry_type/stock_entry_type.py:118 +#: erpnext/stock/doctype/stock_entry_type/stock_entry_type.py:127 msgid "Consumed quantity of item {0} exceeds transferred quantity." msgstr "" @@ -11587,6 +11637,8 @@ msgstr "" #. Label of the cost_center (Link) field in DocType 'Dunning Type' #. Label of the cost_center (Link) field in DocType 'GL Entry' #. Label of the cost_center (Link) field in DocType 'Journal Entry Account' +#. Label of the cost_center (Link) field in DocType 'Journal Entry Template +#. Account' #. Label of the cost_center (Link) field in DocType 'Loyalty Program' #. Label of the cost_center (Link) field in DocType 'Opening Invoice Creation #. Tool' @@ -11659,6 +11711,7 @@ msgstr "" #: erpnext/accounts/doctype/dunning_type/dunning_type.json #: erpnext/accounts/doctype/gl_entry/gl_entry.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +#: erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json #: erpnext/accounts/doctype/loyalty_program/loyalty_program.json #: erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json #: erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json @@ -11927,7 +11980,7 @@ msgstr "" msgid "Could not auto create Customer due to the following missing mandatory field(s):" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:680 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:688 msgid "Could not create Credit Note automatically, please uncheck 'Issue Credit Note' and submit again" msgstr "" @@ -12019,7 +12072,7 @@ msgstr "" msgid "Create Chart Of Accounts Based On" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:61 +#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:63 msgid "Create Delivery Trip" msgstr "" @@ -12083,7 +12136,7 @@ msgstr "" msgid "Create Ledger Entries for Change Amount" msgstr "" -#: erpnext/buying/doctype/supplier/supplier.js:226 +#: erpnext/buying/doctype/supplier/supplier.js:218 #: erpnext/selling/doctype/customer/customer.js:285 msgid "Create Link" msgstr "" @@ -12184,7 +12237,7 @@ msgid "Create Sales Orders to help you plan your work and deliver on-time" msgstr "" #: erpnext/stock/dashboard/item_dashboard.js:283 -#: erpnext/stock/doctype/material_request/material_request.js:488 +#: erpnext/stock/doctype/material_request/material_request.js:500 msgid "Create Stock Entry" msgstr "" @@ -12383,7 +12436,7 @@ msgstr "" msgid "Credit ({0})" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:627 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:641 msgid "Credit Account" msgstr "" @@ -12461,7 +12514,7 @@ msgstr "" msgid "Credit Limit" msgstr "" -#: erpnext/selling/doctype/customer/customer.py:603 +#: erpnext/selling/doctype/customer/customer.py:606 msgid "Credit Limit Crossed" msgstr "" @@ -12535,7 +12588,7 @@ msgstr "" msgid "Credit Note will update it's own outstanding amount, even if 'Return Against' is specified." msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:677 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:685 msgid "Credit Note {0} has been created automatically" msgstr "" @@ -12552,8 +12605,8 @@ msgstr "" msgid "Credit in Company Currency" msgstr "" -#: erpnext/selling/doctype/customer/customer.py:569 -#: erpnext/selling/doctype/customer/customer.py:624 +#: erpnext/selling/doctype/customer/customer.py:572 +#: erpnext/selling/doctype/customer/customer.py:627 msgid "Credit limit has been crossed for customer {0} ({1}/{2})" msgstr "" @@ -12561,7 +12614,7 @@ msgstr "" msgid "Credit limit is already defined for the Company {0}" msgstr "" -#: erpnext/selling/doctype/customer/customer.py:623 +#: erpnext/selling/doctype/customer/customer.py:626 msgid "Credit limit reached for customer {0}" msgstr "" @@ -12748,7 +12801,7 @@ msgstr "" msgid "Currency of the Closing Account must be {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:634 +#: erpnext/manufacturing/doctype/bom/bom.py:685 msgid "Currency of the price list {0} must be {1} or {2}" msgstr "" @@ -13012,7 +13065,7 @@ msgstr "" #: erpnext/accounts/doctype/pricing_rule/pricing_rule.json #: erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json #: erpnext/accounts/doctype/promotional_scheme/promotional_scheme.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:308 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:309 #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/accounts/doctype/sales_invoice_reference/sales_invoice_reference.json #: erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -13029,7 +13082,7 @@ msgstr "" #: erpnext/accounts/report/sales_register/sales_register.py:187 #: erpnext/assets/doctype/asset/asset.json #: erpnext/buying/doctype/purchase_order/purchase_order.json -#: erpnext/buying/doctype/supplier/supplier.js:194 +#: erpnext/buying/doctype/supplier/supplier.js:186 #: erpnext/crm/doctype/contract/contract.json #: erpnext/crm/doctype/lead/lead.js:32 #: erpnext/crm/doctype/opportunity/opportunity.js:99 @@ -13561,7 +13614,7 @@ msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1142 #: erpnext/selling/doctype/sales_order/sales_order.py:432 -#: erpnext/stock/doctype/delivery_note/delivery_note.py:424 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:432 msgid "Customer {0} does not belong to project {1}" msgstr "" @@ -13671,7 +13724,7 @@ msgstr "" msgid "DFS" msgstr "" -#: erpnext/projects/doctype/project/project.py:673 +#: erpnext/projects/doctype/project/project.py:675 msgid "Daily Project Summary for {0}" msgstr "" @@ -13930,7 +13983,7 @@ msgstr "" msgid "Debit / Credit Note Posting Date" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:617 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:631 msgid "Debit Account" msgstr "" @@ -14170,7 +14223,7 @@ msgstr "" msgid "Default BOM ({0}) must be active for this item or its template" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2185 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2229 msgid "Default BOM for {0} not found" msgstr "" @@ -14178,7 +14231,7 @@ msgstr "" msgid "Default BOM not found for FG Item {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2182 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2226 msgid "Default BOM not found for Item {0} and Project {1}" msgstr "" @@ -14710,8 +14763,8 @@ msgstr "" msgid "Delete Accounting and Stock Ledger Entries on deletion of Transaction" msgstr "" -#. Label of the delete_bin_data (Check) field in DocType 'Transaction Deletion -#. Record' +#. Label of the delete_bin_data_status (Select) field in DocType 'Transaction +#. Deletion Record' #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json msgid "Delete Bins" msgstr "" @@ -14726,14 +14779,14 @@ msgstr "" msgid "Delete Dimension" msgstr "" -#. Label of the delete_leads_and_addresses (Check) field in DocType +#. Label of the delete_leads_and_addresses_status (Select) field in DocType #. 'Transaction Deletion Record' #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json msgid "Delete Leads and Addresses" msgstr "" -#. Label of the delete_transactions (Check) field in DocType 'Transaction -#. Deletion Record' +#. Label of the delete_transactions_status (Select) field in DocType +#. 'Transaction Deletion Record' #: erpnext/setup/doctype/company/company.js:168 #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json msgid "Delete Transactions" @@ -14752,7 +14805,8 @@ msgstr "" msgid "Deleting {0} and all associated Common Code documents..." msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:506 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1095 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1114 msgid "Deletion in Progress!" msgstr "" @@ -14760,6 +14814,14 @@ msgstr "" msgid "Deletion is not permitted for country {0}" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:216 +msgid "Deletion process restarted" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:97 +msgid "Deletion will start automatically after submission." +msgstr "" + #. Label of the delimiter_options (Data) field in DocType 'Bank Statement #. Import' #: erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json @@ -14918,8 +14980,8 @@ msgstr "" #. Label of the delivery_note (Link) field in DocType 'Shipment Delivery Note' #. Label of a Link in the Stock Workspace #: erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:128 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:331 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:129 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:332 #: erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js:36 #: erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json #: erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.js:22 @@ -15258,7 +15320,7 @@ msgstr "" msgid "Depreciation Posting Date" msgstr "" -#: erpnext/assets/doctype/asset/asset.js:832 +#: erpnext/assets/doctype/asset/asset.js:834 msgid "Depreciation Posting Date cannot be before Available-for-use Date" msgstr "" @@ -15381,7 +15443,7 @@ msgstr "" msgid "Difference Account must be a Asset/Liability type account (Temporary Opening), since this Stock Entry is an Opening Entry" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:983 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:986 msgid "Difference Account must be a Asset/Liability type account, since this Stock Reconciliation is an Opening Entry" msgstr "" @@ -16168,7 +16230,7 @@ msgstr "" msgid "Do not update variants on save" msgstr "" -#: erpnext/assets/doctype/asset/asset.js:870 +#: erpnext/assets/doctype/asset/asset.js:872 msgid "Do you really want to restore this scrapped asset?" msgstr "" @@ -16196,14 +16258,45 @@ msgstr "" msgid "Do you want to submit the stock entry?" msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:81 -msgid "DocTypes should not be added manually to the 'Excluded DocTypes' table. You are only allowed to remove entries from it." +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:180 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:441 +msgid "DocType {0} does not exist" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:295 +msgid "DocType {0} with company field '{1}' is already in the list" +msgstr "" + +#. Label of the doctypes_to_delete (Table) field in DocType 'Transaction +#. Deletion Record' +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json +msgid "DocTypes To Delete" +msgstr "" + +#. Description of the 'Excluded DocTypes' (Table) field in DocType 'Transaction +#. Deletion Record' +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json +msgid "DocTypes that will NOT be deleted." +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:84 +msgid "DocTypes with a company field:" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:88 +msgid "DocTypes without a company field:" msgstr "" #: erpnext/templates/pages/search_help.py:22 msgid "Docs Search" msgstr "" +#. Label of the document_count (Int) field in DocType 'Transaction Deletion +#. Record To Delete' +#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json +msgid "Document Count" +msgstr "" + #. Label of the document_type (Link) field in DocType 'Subscription Invoice' #: erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json msgid "Document Type " @@ -16406,7 +16499,7 @@ msgstr "" #. Name of a DocType #: erpnext/accounts/doctype/dunning/dunning.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:155 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:156 msgid "Dunning" msgstr "" @@ -16455,6 +16548,10 @@ msgstr "" msgid "Duplicate Customer Group" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:188 +msgid "Duplicate DocType" +msgstr "" + #: erpnext/setup/doctype/authorization_rule/authorization_rule.py:71 msgid "Duplicate Entry. Please check Authorization Rule {0}" msgstr "" @@ -16509,6 +16606,10 @@ msgstr "" msgid "Duplicate entry against the item code {0} and manufacturer {1}" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:187 +msgid "Duplicate entry: {0}{1}" +msgstr "" + #: erpnext/accounts/doctype/pos_profile/pos_profile.py:164 msgid "Duplicate item group found in the item group table" msgstr "" @@ -16551,12 +16652,12 @@ msgstr "" msgid "Dyne" msgstr "" -#: erpnext/regional/italy/utils.py:221 erpnext/regional/italy/utils.py:241 -#: erpnext/regional/italy/utils.py:251 erpnext/regional/italy/utils.py:259 -#: erpnext/regional/italy/utils.py:266 erpnext/regional/italy/utils.py:270 -#: erpnext/regional/italy/utils.py:277 erpnext/regional/italy/utils.py:286 -#: erpnext/regional/italy/utils.py:311 erpnext/regional/italy/utils.py:318 -#: erpnext/regional/italy/utils.py:423 +#: erpnext/regional/italy/utils.py:228 erpnext/regional/italy/utils.py:248 +#: erpnext/regional/italy/utils.py:258 erpnext/regional/italy/utils.py:266 +#: erpnext/regional/italy/utils.py:273 erpnext/regional/italy/utils.py:277 +#: erpnext/regional/italy/utils.py:284 erpnext/regional/italy/utils.py:293 +#: erpnext/regional/italy/utils.py:318 erpnext/regional/italy/utils.py:325 +#: erpnext/regional/italy/utils.py:430 msgid "E-Invoicing Information Missing" msgstr "" @@ -16608,7 +16709,7 @@ msgstr "" msgid "Earliest" msgstr "" -#: erpnext/stock/report/stock_balance/stock_balance.py:516 +#: erpnext/stock/report/stock_balance/stock_balance.py:518 msgid "Earliest Age" msgstr "" @@ -17005,7 +17106,7 @@ msgstr "" msgid "Employee {0} does not belong to the company {1}" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:334 +#: erpnext/manufacturing/doctype/job_card/job_card.py:359 msgid "Employee {0} is currently working on another workstation. Please assign another employee." msgstr "" @@ -17017,6 +17118,10 @@ msgstr "" msgid "Empty" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:750 +msgid "Empty To Delete List" +msgstr "" + #. Name of a UOM #: erpnext/setup/setup_wizard/data/uom_data.json msgid "Ems(Pica)" @@ -17310,7 +17415,7 @@ msgstr "" msgid "Enter Serial Nos" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:425 +#: erpnext/stock/doctype/material_request/material_request.js:437 msgid "Enter Supplier" msgstr "" @@ -17352,7 +17457,7 @@ msgstr "" msgid "Enter customer's phone number" msgstr "" -#: erpnext/assets/doctype/asset/asset.js:841 +#: erpnext/assets/doctype/asset/asset.js:843 msgid "Enter date to scrap asset" msgstr "" @@ -17391,7 +17496,7 @@ msgstr "" msgid "Enter the opening stock units." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:962 +#: erpnext/manufacturing/doctype/bom/bom.js:965 msgid "Enter the quantity of the Item that will be manufactured from this Bill of Materials." msgstr "" @@ -17468,6 +17573,10 @@ msgstr "" msgid "Error evaluating the criteria formula" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:267 +msgid "Error getting details for {0}: {1}" +msgstr "" + #: erpnext/accounts/doctype/bank_transaction/bank_transaction.py:310 msgid "Error in party matching for Bank Transaction {0}" msgstr "" @@ -17567,7 +17676,7 @@ msgstr "" msgid "Excess Materials Consumed" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1031 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1117 msgid "Excess Transfer" msgstr "" @@ -18067,7 +18176,7 @@ msgstr "" msgid "Extra Consumed Qty" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:231 +#: erpnext/manufacturing/doctype/job_card/job_card.py:256 msgid "Extra Job Card Quantity" msgstr "" @@ -18245,7 +18354,7 @@ msgstr "" msgid "Fetch Subscription Updates" msgstr "" -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1068 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1069 msgid "Fetch Timesheet" msgstr "" @@ -18267,7 +18376,7 @@ msgstr "" msgid "Fetch Value From" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:360 +#: erpnext/stock/doctype/material_request/material_request.js:372 #: erpnext/stock/doctype/stock_entry/stock_entry.js:712 msgid "Fetch exploded BOM (including sub-assemblies)" msgstr "" @@ -18295,7 +18404,7 @@ msgid "Fetching Sales Orders..." msgstr "" #: erpnext/accounts/doctype/dunning/dunning.js:135 -#: erpnext/public/js/controllers/transaction.js:1496 +#: erpnext/public/js/controllers/transaction.js:1489 msgid "Fetching exchange rates ..." msgstr "" @@ -18303,6 +18412,10 @@ msgstr "" msgid "Fetching..." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:222 +msgid "Field '{0}' is not a valid Company link field for DocType {1}" +msgstr "" + #. Label of the field_mapping_section (Section Break) field in DocType #. 'Inventory Dimension' #: erpnext/stock/doctype/inventory_dimension/inventory_dimension.json @@ -18321,6 +18434,18 @@ msgstr "" msgid "Fields will be copied over only at time of creation." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1062 +msgid "File does not belong to this Transaction Deletion Record" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1056 +msgid "File not found" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1070 +msgid "File not found on server" +msgstr "" + #. Label of the file_to_rename (Attach) field in DocType 'Rename Tool' #: erpnext/utilities/doctype/rename_tool/rename_tool.json msgid "File to Rename" @@ -18661,7 +18786,7 @@ msgstr "" msgid "Finished Goods based Operating Cost" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1670 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1671 msgid "Finished Item {0} does not match with Work Order {1}" msgstr "" @@ -18715,7 +18840,7 @@ msgstr "" msgid "First Response Time for Opportunity" msgstr "" -#: erpnext/regional/italy/utils.py:229 +#: erpnext/regional/italy/utils.py:236 msgid "Fiscal Regime is mandatory, kindly set the fiscal regime in the company {0}" msgstr "" @@ -18825,7 +18950,7 @@ msgstr "" msgid "Fixed Asset Turnover Ratio" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:691 +#: erpnext/manufacturing/doctype/bom/bom.py:742 msgid "Fixed Asset item {0} cannot be used in BOMs." msgstr "" @@ -18903,7 +19028,7 @@ msgstr "" msgid "Following Material Requests have been raised automatically based on Item's re-order level" msgstr "" -#: erpnext/selling/doctype/customer/customer.py:794 +#: erpnext/selling/doctype/customer/customer.py:797 msgid "Following fields are mandatory to create address:" msgstr "" @@ -18955,7 +19080,7 @@ msgstr "" msgid "For Company" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:403 +#: erpnext/stock/doctype/material_request/material_request.js:415 msgid "For Default Supplier (Optional)" msgstr "" @@ -19024,7 +19149,7 @@ msgstr "" #: erpnext/manufacturing/doctype/production_plan/production_plan.js:471 #: erpnext/manufacturing/doctype/production_plan/production_plan.json #: erpnext/selling/doctype/sales_order/sales_order.js:1407 -#: erpnext/stock/doctype/material_request/material_request.js:349 +#: erpnext/stock/doctype/material_request/material_request.js:361 #: erpnext/templates/form_grid/material_request_grid.html:36 msgid "For Warehouse" msgstr "" @@ -19033,11 +19158,11 @@ msgstr "" msgid "For Work Order" msgstr "" -#: erpnext/controllers/status_updater.py:281 +#: erpnext/controllers/status_updater.py:282 msgid "For an item {0}, quantity must be negative number" msgstr "" -#: erpnext/controllers/status_updater.py:278 +#: erpnext/controllers/status_updater.py:279 msgid "For an item {0}, quantity must be positive number" msgstr "" @@ -19067,11 +19192,15 @@ msgstr "" msgid "For item {0}, only {1} asset have been created or linked to {2}. Please create or link {3} more asset with the respective document." msgstr "" -#: erpnext/controllers/status_updater.py:286 +#: erpnext/controllers/status_updater.py:287 msgid "For item {0}, rate must be a positive number. To Allow negative rates, enable {1} in {2}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2530 +#: erpnext/manufacturing/doctype/bom/bom.py:346 +msgid "For operation {0} at row {1}, please add raw materials or set a BOM against it." +msgstr "" + +#: erpnext/manufacturing/doctype/work_order/work_order.py:2574 msgid "For operation {0}: Quantity ({1}) can not be greater than pending quantity({2})" msgstr "" @@ -19088,7 +19217,7 @@ msgstr "" msgid "For projected and forecast quantities, the system will consider all child warehouses under the selected parent warehouse." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1702 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1703 msgid "For quantity {0} should not be greater than allowed quantity {1}" msgstr "" @@ -19121,11 +19250,11 @@ msgstr "" msgid "For the convenience of customers, these codes can be used in print formats like Invoices and Delivery Notes" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:977 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:978 msgid "For the item {0}, the consumed quantity should be {1} according to the BOM {2}." msgstr "" -#: erpnext/public/js/controllers/transaction.js:1306 +#: erpnext/public/js/controllers/transaction.js:1299 msgctxt "Clear payment terms template and/or payment schedule when due date is changed" msgid "For the new {0} to take effect, would you like to clear the current {1}?" msgstr "" @@ -19134,7 +19263,7 @@ msgstr "" msgid "For the {0}, no stock is available for the return in the warehouse {1}." msgstr "" -#: erpnext/controllers/sales_and_purchase_return.py:1216 +#: erpnext/controllers/sales_and_purchase_return.py:1238 msgid "For the {0}, the quantity is required to make the return entry" msgstr "" @@ -19911,6 +20040,14 @@ msgstr "" msgid "Generate Stock Closing Entry" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:112 +msgid "Generate To Delete List" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:468 +msgid "Generate To Delete list first" +msgstr "" + #. Description of a DocType #: erpnext/stock/doctype/packing_slip/packing_slip.json msgid "Generate packing slips for packages to be delivered. Used to notify package number, package contents and its weight." @@ -20008,10 +20145,10 @@ msgstr "" #. Label of the get_items_from (Select) field in DocType 'Production Plan' #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:166 #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:191 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:292 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:324 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:358 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1124 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:293 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:325 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:359 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1125 #: erpnext/buying/doctype/purchase_order/purchase_order.js:561 #: erpnext/buying/doctype/purchase_order/purchase_order.js:584 #: erpnext/buying/doctype/request_for_quotation/request_for_quotation.js:376 @@ -20030,8 +20167,8 @@ msgstr "" #: erpnext/selling/doctype/sales_order/sales_order.js:1200 #: erpnext/stock/doctype/delivery_note/delivery_note.js:187 #: erpnext/stock/doctype/delivery_note/delivery_note.js:239 -#: erpnext/stock/doctype/material_request/material_request.js:129 -#: erpnext/stock/doctype/material_request/material_request.js:226 +#: erpnext/stock/doctype/material_request/material_request.js:141 +#: erpnext/stock/doctype/material_request/material_request.js:238 #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.js:144 #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.js:244 #: erpnext/stock/doctype/stock_entry/stock_entry.js:351 @@ -20053,7 +20190,7 @@ msgstr "" msgid "Get Items for Purchase Only" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:334 +#: erpnext/stock/doctype/material_request/material_request.js:346 #: erpnext/stock/doctype/stock_entry/stock_entry.js:715 #: erpnext/stock/doctype/stock_entry/stock_entry.js:728 msgid "Get Items from BOM" @@ -20168,7 +20305,7 @@ msgstr "" msgid "Get Suppliers By" msgstr "" -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1120 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1121 msgid "Get Timesheets" msgstr "" @@ -20238,7 +20375,7 @@ msgstr "" msgid "Goods Transferred" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2219 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2221 msgid "Goods are already received against the outward entry {0}" msgstr "" @@ -21089,6 +21226,10 @@ msgstr "" msgid "IBAN" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:93 +msgid "IMPORTANT: Create a backup before proceeding!" +msgstr "" + #. Name of a report #: erpnext/regional/report/irs_1099/irs_1099.json msgid "IRS 1099" @@ -21748,6 +21889,10 @@ msgstr "" msgid "Import Successful" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:560 +msgid "Import Summary" +msgstr "" + #. Label of a Link in the Buying Workspace #. Name of a DocType #: erpnext/buying/workspace/buying/buying.json @@ -21768,6 +21913,10 @@ msgstr "" msgid "Import in Bulk" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:192 +msgid "Imported {0} DocTypes" +msgstr "" + #: erpnext/edi/doctype/common_code/common_code.py:109 msgid "Importing Common Codes" msgstr "" @@ -21820,7 +21969,7 @@ msgstr "" #: erpnext/stock/report/available_serial_no/available_serial_no.py:112 #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:82 -#: erpnext/stock/report/stock_balance/stock_balance.py:471 +#: erpnext/stock/report/stock_balance/stock_balance.py:473 #: erpnext/stock/report/stock_ledger/stock_ledger.py:237 msgid "In Qty" msgstr "" @@ -21844,15 +21993,15 @@ msgstr "" msgid "In Transit" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:487 +#: erpnext/stock/doctype/material_request/material_request.js:499 msgid "In Transit Transfer" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:456 +#: erpnext/stock/doctype/material_request/material_request.js:468 msgid "In Transit Warehouse" msgstr "" -#: erpnext/stock/report/stock_balance/stock_balance.py:477 +#: erpnext/stock/report/stock_balance/stock_balance.py:479 msgid "In Value" msgstr "" @@ -22271,7 +22420,7 @@ msgstr "" msgid "Incorrect Balance Qty After Transaction" msgstr "" -#: erpnext/controllers/subcontracting_controller.py:1063 +#: erpnext/controllers/subcontracting_controller.py:1071 msgid "Incorrect Batch Consumed" msgstr "" @@ -22279,7 +22428,7 @@ msgstr "" msgid "Incorrect Check in (group) Warehouse for Reorder" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:984 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:985 msgid "Incorrect Component Quantity" msgstr "" @@ -22305,7 +22454,7 @@ msgstr "" msgid "Incorrect Serial No Valuation" msgstr "" -#: erpnext/controllers/subcontracting_controller.py:1076 +#: erpnext/controllers/subcontracting_controller.py:1084 msgid "Incorrect Serial Number Consumed" msgstr "" @@ -22456,8 +22605,8 @@ msgstr "" msgid "Initial Email Notification Sent" msgstr "" -#. Label of the initialize_doctypes_table (Check) field in DocType 'Transaction -#. Deletion Record' +#. Label of the initialize_doctypes_table_status (Select) field in DocType +#. 'Transaction Deletion Record' #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json msgid "Initialize Summary Table" msgstr "" @@ -22481,6 +22630,7 @@ msgid "Inspected By" msgstr "" #: erpnext/controllers/stock_controller.py:1453 +#: erpnext/manufacturing/doctype/job_card/job_card.py:817 msgid "Inspection Rejected" msgstr "" @@ -22504,6 +22654,7 @@ msgid "Inspection Required before Purchase" msgstr "" #: erpnext/controllers/stock_controller.py:1438 +#: erpnext/manufacturing/doctype/job_card/job_card.py:798 msgid "Inspection Submission" msgstr "" @@ -22533,7 +22684,7 @@ msgstr "" msgid "Installation Note Item" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:631 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:639 msgid "Installation Note {0} has already been submitted" msgstr "" @@ -22854,14 +23005,22 @@ msgstr "" msgid "Invalid Barcode. There is no Item attached to this barcode." msgstr "" -#: erpnext/public/js/controllers/transaction.js:3106 +#: erpnext/public/js/controllers/transaction.js:3099 msgid "Invalid Blanket Order for the selected Customer and Item" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:494 +msgid "Invalid CSV format. Expected column: doctype_name" +msgstr "" + #: erpnext/quality_management/doctype/quality_procedure/quality_procedure.py:72 msgid "Invalid Child Procedure" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:225 +msgid "Invalid Company Field" +msgstr "" + #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:2307 msgid "Invalid Company for Inter Company Transaction." msgstr "" @@ -22954,7 +23113,7 @@ msgstr "" msgid "Invalid Priority" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1173 +#: erpnext/manufacturing/doctype/bom/bom.py:1224 msgid "Invalid Process Loss Configuration" msgstr "" @@ -22987,16 +23146,16 @@ msgstr "" msgid "Invalid Schedule" msgstr "" -#: erpnext/controllers/selling_controller.py:309 +#: erpnext/controllers/selling_controller.py:310 msgid "Invalid Selling Price" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1745 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1746 msgid "Invalid Serial and Batch Bundle" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1018 -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1040 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1019 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1041 msgid "Invalid Source and Target Warehouse" msgstr "" @@ -23017,6 +23176,10 @@ msgstr "" msgid "Invalid condition expression" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1051 +msgid "Invalid file URL" +msgstr "" + #: erpnext/accounts/doctype/financial_report_template/financial_report_template.js:93 msgid "Invalid filter formula. Please check the syntax." msgstr "" @@ -23145,7 +23308,7 @@ msgstr "" #. Account' #: erpnext/accounts/doctype/invoice_discounting/invoice_discounting.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:145 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:146 msgid "Invoice Discounting" msgstr "" @@ -23873,7 +24036,7 @@ msgstr "" msgid "Issue Date" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:168 +#: erpnext/stock/doctype/material_request/material_request.js:180 msgid "Issue Material" msgstr "" @@ -23947,7 +24110,7 @@ msgstr "" msgid "It can take upto few hours for accurate stock values to be visible after merging items." msgstr "" -#: erpnext/public/js/controllers/transaction.js:2508 +#: erpnext/public/js/controllers/transaction.js:2501 msgid "It is needed to fetch Item Details." msgstr "" @@ -24007,7 +24170,7 @@ msgstr "" #: erpnext/buying/workspace/buying/buying.json #: erpnext/controllers/taxes_and_totals.py:1207 #: erpnext/manufacturing/doctype/blanket_order/blanket_order.json -#: erpnext/manufacturing/doctype/bom/bom.js:1055 +#: erpnext/manufacturing/doctype/bom/bom.js:1058 #: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/plant_floor/plant_floor.js:109 #: erpnext/manufacturing/doctype/workstation/workstation_job_card.html:25 @@ -24063,7 +24226,7 @@ msgstr "" #: erpnext/stock/report/stock_ageing/stock_ageing.js:46 #: erpnext/stock/report/stock_analytics/stock_analytics.js:15 #: erpnext/stock/report/stock_analytics/stock_analytics.py:28 -#: erpnext/stock/report/stock_balance/stock_balance.py:398 +#: erpnext/stock/report/stock_balance/stock_balance.py:400 #: erpnext/stock/report/stock_ledger/stock_ledger.py:207 #: erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.js:27 #: erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py:51 @@ -24246,7 +24409,7 @@ msgstr "" #: erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.json #: erpnext/accounts/doctype/promotional_scheme/promotional_scheme.json #: erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1077 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1078 #: erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py:68 #: erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py:37 #: erpnext/accounts/report/gross_profit/gross_profit.py:301 @@ -24301,7 +24464,7 @@ msgstr "" #: erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py:86 #: erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py:119 #: erpnext/projects/doctype/timesheet/timesheet.js:214 -#: erpnext/public/js/controllers/transaction.js:2802 +#: erpnext/public/js/controllers/transaction.js:2795 #: erpnext/public/js/stock_reservation.js:112 #: erpnext/public/js/stock_reservation.js:318 erpnext/public/js/utils.js:488 #: erpnext/public/js/utils.js:645 @@ -24562,7 +24725,7 @@ msgstr "" #: erpnext/stock/report/stock_analytics/stock_analytics.js:8 #: erpnext/stock/report/stock_analytics/stock_analytics.py:37 #: erpnext/stock/report/stock_balance/stock_balance.js:32 -#: erpnext/stock/report/stock_balance/stock_balance.py:406 +#: erpnext/stock/report/stock_balance/stock_balance.py:408 #: erpnext/stock/report/stock_ledger/stock_ledger.js:71 #: erpnext/stock/report/stock_ledger/stock_ledger.py:265 #: erpnext/stock/report/stock_projected_qty/stock_projected_qty.js:39 @@ -24777,7 +24940,7 @@ msgstr "" #: erpnext/manufacturing/report/production_planning_report/production_planning_report.py:371 #: erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py:92 #: erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py:138 -#: erpnext/public/js/controllers/transaction.js:2808 +#: erpnext/public/js/controllers/transaction.js:2801 #: erpnext/public/js/utils.js:736 #: erpnext/selling/doctype/quotation_item/quotation_item.json #: erpnext/selling/doctype/sales_order/sales_order.js:1252 @@ -24818,7 +24981,7 @@ msgstr "" #: erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py:440 #: erpnext/stock/report/stock_ageing/stock_ageing.py:138 #: erpnext/stock/report/stock_analytics/stock_analytics.py:30 -#: erpnext/stock/report/stock_balance/stock_balance.py:404 +#: erpnext/stock/report/stock_balance/stock_balance.py:406 #: erpnext/stock/report/stock_ledger/stock_ledger.py:213 #: erpnext/stock/report/stock_projected_qty/stock_projected_qty.py:110 #: erpnext/stock/report/stock_qty_vs_batch_qty/stock_qty_vs_batch_qty.py:31 @@ -25155,7 +25318,7 @@ msgstr "" msgid "Item and Warranty Details" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3266 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3268 msgid "Item for row {0} does not match Material Request" msgstr "" @@ -25189,7 +25352,7 @@ msgstr "" msgid "Item qty can not be updated as raw materials are already processed." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1148 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1149 msgid "Item rate has been updated to zero as Allow Zero Valuation Rate is checked for item {0}" msgstr "" @@ -25232,7 +25395,7 @@ msgstr "" msgid "Item {0} does not exist" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:619 +#: erpnext/manufacturing/doctype/bom/bom.py:670 msgid "Item {0} does not exist in the system or has expired" msgstr "" @@ -25240,7 +25403,7 @@ msgstr "" msgid "Item {0} does not exist." msgstr "" -#: erpnext/controllers/selling_controller.py:850 +#: erpnext/controllers/selling_controller.py:844 msgid "Item {0} entered multiple times." msgstr "" @@ -25288,7 +25451,7 @@ msgstr "" msgid "Item {0} is not a subcontracted item" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2131 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2133 msgid "Item {0} is not active or end of life has been reached" msgstr "" @@ -25308,7 +25471,7 @@ msgstr "" msgid "Item {0} must be a non-stock item" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1481 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1482 msgid "Item {0} not found in 'Raw Materials Supplied' table in {1} {2}" msgstr "" @@ -25361,7 +25524,7 @@ msgstr "" msgid "Item/Item Code required to get Item Tax Template." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:361 +#: erpnext/manufacturing/doctype/bom/bom.py:412 msgid "Item: {0} does not exist in the system" msgstr "" @@ -25412,7 +25575,7 @@ msgstr "" msgid "Items not found." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1144 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1145 msgid "Items rate has been updated to zero as Allow Zero Valuation Rate is checked for the following items: {0}" msgstr "" @@ -25484,7 +25647,7 @@ msgstr "" #: erpnext/buying/doctype/purchase_order_item/purchase_order_item.json #: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/job_card/job_card.json -#: erpnext/manufacturing/doctype/job_card/job_card.py:896 +#: erpnext/manufacturing/doctype/job_card/job_card.py:982 #: erpnext/manufacturing/doctype/operation/operation.json #: erpnext/manufacturing/doctype/work_order/work_order.js:396 #: erpnext/manufacturing/doctype/work_order/work_order.json @@ -25545,7 +25708,7 @@ msgstr "" msgid "Job Card and Capacity Planning" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1356 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1458 msgid "Job Card {0} has been completed" msgstr "" @@ -25621,7 +25784,7 @@ msgstr "" msgid "Job Worker Warehouse" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2583 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2627 msgid "Job card {0} created" msgstr "" @@ -25832,7 +25995,7 @@ msgstr "" msgid "Kilowatt-Hour" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:898 +#: erpnext/manufacturing/doctype/job_card/job_card.py:984 msgid "Kindly cancel the Manufacturing Entries first against the work order {0}." msgstr "" @@ -26036,7 +26199,7 @@ msgstr "" msgid "Latest" msgstr "" -#: erpnext/stock/report/stock_balance/stock_balance.py:517 +#: erpnext/stock/report/stock_balance/stock_balance.py:519 msgid "Latest Age" msgstr "" @@ -26330,7 +26493,7 @@ msgstr "" msgid "License Plate" msgstr "" -#: erpnext/controllers/status_updater.py:470 +#: erpnext/controllers/status_updater.py:471 msgid "Limit Crossed" msgstr "" @@ -26416,12 +26579,12 @@ msgstr "" msgid "Linked with submitted documents" msgstr "" -#: erpnext/buying/doctype/supplier/supplier.js:220 +#: erpnext/buying/doctype/supplier/supplier.js:212 #: erpnext/selling/doctype/customer/customer.js:279 msgid "Linking Failed" msgstr "" -#: erpnext/buying/doctype/supplier/supplier.js:219 +#: erpnext/buying/doctype/supplier/supplier.js:211 msgid "Linking to Customer Failed. Please try again." msgstr "" @@ -26690,7 +26853,7 @@ msgstr "" #: erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json #: erpnext/accounts/doctype/loyalty_program/loyalty_program.json #: erpnext/accounts/doctype/pos_invoice/pos_invoice.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1175 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1176 #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/selling/doctype/customer/customer.json #: erpnext/selling/page/point_of_sale/pos_item_cart.js:952 @@ -26878,7 +27041,7 @@ msgstr "" #. Label of the maintenance_schedule (Link) field in DocType 'Maintenance #. Visit' #. Label of a Link in the Support Workspace -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:161 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:162 #: erpnext/crm/workspace/crm/crm.json #: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json #: erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js:81 @@ -27237,8 +27400,8 @@ msgstr "" #: erpnext/stock/doctype/material_request_item/material_request_item.json #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json #: erpnext/stock/doctype/stock_entry/stock_entry.json -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1225 -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1241 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1226 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1242 #: erpnext/stock/doctype/stock_entry_type/stock_entry_type.json #: erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json #: erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json @@ -27382,7 +27545,7 @@ msgstr "" msgid "Manufacturing Manager" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2384 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2386 msgid "Manufacturing Quantity is mandatory" msgstr "" @@ -27604,7 +27767,7 @@ msgstr "" #. Option for the 'Purpose' (Select) field in DocType 'Stock Entry Type' #: erpnext/setup/setup_wizard/operations/install_fixtures.py:114 #: erpnext/stock/doctype/stock_entry/stock_entry.json -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1226 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1227 #: erpnext/stock/doctype/stock_entry_type/stock_entry_type.json msgid "Material Consumption for Manufacture" msgstr "" @@ -27634,7 +27797,7 @@ msgstr "" #. Option for the 'Purpose' (Select) field in DocType 'Stock Entry' #. Option for the 'Purpose' (Select) field in DocType 'Stock Entry Type' #: erpnext/setup/setup_wizard/operations/install_fixtures.py:77 -#: erpnext/stock/doctype/material_request/material_request.js:176 +#: erpnext/stock/doctype/material_request/material_request.js:188 #: erpnext/stock/doctype/stock_entry/stock_entry.json #: erpnext/stock/doctype/stock_entry_type/stock_entry_type.json msgid "Material Receipt" @@ -27788,7 +27951,7 @@ msgstr "" msgid "Material Request used to make this Stock Entry" msgstr "" -#: erpnext/controllers/subcontracting_controller.py:1329 +#: erpnext/controllers/subcontracting_controller.py:1337 msgid "Material Request {0} is cancelled or stopped" msgstr "" @@ -27846,7 +28009,7 @@ msgstr "" #: erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json #: erpnext/setup/setup_wizard/operations/install_fixtures.py:83 #: erpnext/stock/doctype/item/item.json -#: erpnext/stock/doctype/material_request/material_request.js:154 +#: erpnext/stock/doctype/material_request/material_request.js:166 #: erpnext/stock/doctype/material_request/material_request.json #: erpnext/stock/doctype/pick_list/pick_list.json #: erpnext/stock/doctype/stock_entry/stock_entry.json @@ -27854,7 +28017,7 @@ msgstr "" msgid "Material Transfer" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:160 +#: erpnext/stock/doctype/material_request/material_request.js:172 msgid "Material Transfer (In Transit)" msgstr "" @@ -27902,11 +28065,12 @@ msgstr "" msgid "Material to Supplier" msgstr "" -#: erpnext/controllers/subcontracting_controller.py:1562 +#: erpnext/controllers/subcontracting_controller.py:1570 msgid "Materials are already received against the {0} {1}" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:752 +#: erpnext/manufacturing/doctype/job_card/job_card.py:183 +#: erpnext/manufacturing/doctype/job_card/job_card.py:838 msgid "Materials needs to be transferred to the work in progress warehouse for the job card {0}" msgstr "" @@ -27997,11 +28161,11 @@ msgstr "" msgid "Maximum Payment Amount" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3869 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3871 msgid "Maximum Samples - {0} can be retained for Batch {1} and Item {2}." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3860 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3862 msgid "Maximum Samples - {0} have already been retained for Batch {1} and Item {2} in Batch {3}." msgstr "" @@ -28456,7 +28620,7 @@ msgstr "" msgid "Missing Finance Book" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1680 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1681 msgid "Missing Finished Good" msgstr "" @@ -28464,7 +28628,7 @@ msgstr "" msgid "Missing Formula" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:991 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:992 msgid "Missing Item" msgstr "" @@ -28484,8 +28648,8 @@ msgstr "" msgid "Missing required filter: {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1132 -#: erpnext/manufacturing/doctype/work_order/work_order.py:1452 +#: erpnext/manufacturing/doctype/bom/bom.py:1183 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1462 msgid "Missing value" msgstr "" @@ -28751,11 +28915,15 @@ msgstr "" msgid "Multiple Warehouse Accounts" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:244 +msgid "Multiple company fields available: {0}. Please select manually." +msgstr "" + #: erpnext/controllers/accounts_controller.py:1302 msgid "Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1687 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1688 msgid "Multiple items cannot be marked as finished item" msgstr "" @@ -28764,7 +28932,7 @@ msgid "Music" msgstr "" #. Label of the must_be_whole_number (Check) field in DocType 'UOM' -#: erpnext/manufacturing/doctype/work_order/work_order.py:1399 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1409 #: erpnext/setup/doctype/uom/uom.json #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:267 #: erpnext/utilities/transaction_base.py:566 @@ -28840,10 +29008,14 @@ msgstr "" msgid "Naming Series and Price Defaults" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:94 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:95 msgid "Naming Series is mandatory" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:932 +msgid "Naming series '{0}' for DocType '{1}' does not contain standard '.' or '{{' separator. Using fallback extraction." +msgstr "" + #. Name of a UOM #: erpnext/setup/setup_wizard/data/uom_data.json msgid "Nanocoulomb" @@ -28879,16 +29051,16 @@ msgstr "" msgid "Needs Analysis" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:620 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:623 msgid "Negative Quantity is not allowed" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1465 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1475 #: erpnext/stock/serial_batch_bundle.py:1520 msgid "Negative Stock Error" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:625 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:628 msgid "Negative Valuation Rate is not allowed" msgstr "" @@ -29447,6 +29619,10 @@ msgstr "" msgid "No Delivery Note selected for Customer {}" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:749 +msgid "No DocTypes in To Delete list. Please generate or import the list before submitting." +msgstr "" + #: erpnext/public/js/utils/ledger_preview.js:64 msgid "No Impact on Accounting Ledger" msgstr "" @@ -29459,7 +29635,7 @@ msgstr "" msgid "No Item with Serial No {0}" msgstr "" -#: erpnext/controllers/subcontracting_controller.py:1476 +#: erpnext/controllers/subcontracting_controller.py:1484 msgid "No Items selected for transfer." msgstr "" @@ -29512,7 +29688,7 @@ msgstr "" msgid "No Selection" msgstr "" -#: erpnext/controllers/sales_and_purchase_return.py:951 +#: erpnext/controllers/sales_and_purchase_return.py:973 msgid "No Serial / Batches are available for return" msgstr "" @@ -29598,7 +29774,7 @@ msgstr "" msgid "No employee was scheduled for call popup" msgstr "" -#: erpnext/controllers/subcontracting_controller.py:1371 +#: erpnext/controllers/subcontracting_controller.py:1379 msgid "No item available for transfer." msgstr "" @@ -29771,7 +29947,11 @@ msgstr "" msgid "No reserved stock to unreserve." msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:802 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:152 +msgid "No rows with zero document count found" +msgstr "" + +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:805 msgid "No stock ledger entries were created. Please set the quantity or valuation rate for the items properly and try again." msgstr "" @@ -29825,7 +30005,7 @@ msgstr "" msgid "Non Profit" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1533 +#: erpnext/manufacturing/doctype/bom/bom.py:1584 msgid "Non stock items" msgstr "" @@ -29838,7 +30018,7 @@ msgstr "" msgid "Non-Zeros" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:554 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:557 msgid "None of the items have any change in quantity or value." msgstr "" @@ -29899,7 +30079,6 @@ msgstr "" #: erpnext/manufacturing/doctype/production_plan/production_plan_list.js:7 #: erpnext/manufacturing/doctype/work_order/work_order.json #: erpnext/manufacturing/doctype/work_order/work_order_list.js:15 -#: erpnext/manufacturing/report/production_analytics/production_analytics.py:124 #: erpnext/stock/doctype/material_request/material_request.json #: erpnext/stock/doctype/material_request/material_request_list.js:9 msgid "Not Started" @@ -29955,7 +30134,7 @@ msgstr "" msgid "Note: Email will not be sent to disabled users" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:703 +#: erpnext/manufacturing/doctype/bom/bom.py:754 msgid "Note: If you want to use the finished good {0} as a raw material, then enable the 'Do Not Explode' checkbox in the Items table against the same raw material." msgstr "" @@ -30372,6 +30551,10 @@ msgstr "" msgid "Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1065 +msgid "Only CSV files are allowed" +msgstr "" + #. Label of the tax_on_excess_amount (Check) field in DocType 'Tax Withholding #. Category' #: erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json @@ -30420,7 +30603,11 @@ msgstr "" msgid "Only one of Deposit or Withdrawal should be non-zero when applying an Excluded Fee." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1240 +#: erpnext/manufacturing/doctype/bom/bom.py:324 +msgid "Only one operation can have 'Is Final Finished Good' checked when 'Track Semi Finished Goods' is enabled." +msgstr "" + +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1241 msgid "Only one {0} entry can be created against the Work Order {1}" msgstr "" @@ -30705,7 +30892,7 @@ msgid "Opening Purchase Invoices have been created." msgstr "" #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:81 -#: erpnext/stock/report/stock_balance/stock_balance.py:457 +#: erpnext/stock/report/stock_balance/stock_balance.py:459 msgid "Opening Qty" msgstr "" @@ -30725,7 +30912,7 @@ msgstr "" msgid "Opening Time" msgstr "" -#: erpnext/stock/report/stock_balance/stock_balance.py:464 +#: erpnext/stock/report/stock_balance/stock_balance.py:466 msgid "Opening Value" msgstr "" @@ -30767,7 +30954,7 @@ msgstr "" msgid "Operating Cost Per BOM Quantity" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1620 +#: erpnext/manufacturing/doctype/bom/bom.py:1671 msgid "Operating Cost as per Work Order / BOM" msgstr "" @@ -30843,7 +31030,7 @@ msgstr "" msgid "Operation Time" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1458 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1468 msgid "Operation Time must be greater than 0 for Operation {0}" msgstr "" @@ -30862,7 +31049,7 @@ msgstr "" msgid "Operation {0} added multiple times in the work order {1}" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1145 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1231 msgid "Operation {0} does not belong to the work order {1}" msgstr "" @@ -30892,7 +31079,7 @@ msgstr "" msgid "Operations Routing" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1141 +#: erpnext/manufacturing/doctype/bom/bom.py:1192 msgid "Operations cannot be left blank" msgstr "" @@ -31301,12 +31488,12 @@ msgstr "" #: erpnext/stock/report/available_serial_no/available_serial_no.py:119 #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:83 -#: erpnext/stock/report/stock_balance/stock_balance.py:479 +#: erpnext/stock/report/stock_balance/stock_balance.py:481 #: erpnext/stock/report/stock_ledger/stock_ledger.py:244 msgid "Out Qty" msgstr "" -#: erpnext/stock/report/stock_balance/stock_balance.py:485 +#: erpnext/stock/report/stock_balance/stock_balance.py:487 msgid "Out Value" msgstr "" @@ -31463,7 +31650,7 @@ msgstr "" msgid "Over Receipt" msgstr "" -#: erpnext/controllers/status_updater.py:475 +#: erpnext/controllers/status_updater.py:476 msgid "Over Receipt/Delivery of {0} {1} ignored for item {2} because you have {3} role." msgstr "" @@ -31483,7 +31670,7 @@ msgstr "" msgid "Over Withheld" msgstr "" -#: erpnext/controllers/status_updater.py:477 +#: erpnext/controllers/status_updater.py:478 msgid "Overbilling of {0} {1} ignored for item {2} because you have {3} role." msgstr "" @@ -31506,7 +31693,6 @@ msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:281 #: erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json #: erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.json -#: erpnext/manufacturing/report/production_analytics/production_analytics.py:125 #: erpnext/projects/doctype/task/task.json #: erpnext/projects/report/project_summary/project_summary.py:100 #: erpnext/projects/web_form/tasks/tasks.json @@ -31910,7 +32096,7 @@ msgstr "" msgid "Package Weight Details" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:71 +#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:73 msgid "Packaging Slip From Delivery Note" msgstr "" @@ -31967,7 +32153,7 @@ msgstr "" msgid "Packing Slip Item" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:647 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:655 msgid "Packing Slip(s) cancelled" msgstr "" @@ -32286,8 +32472,11 @@ msgid "Partial stock can be reserved. For example, If you have a Sales Order of msgstr "" #. Option for the 'Status' (Select) field in DocType 'Timesheet' +#. Option for the 'Status' (Select) field in DocType 'Delivery Note' #: erpnext/projects/doctype/timesheet/timesheet.json #: erpnext/projects/doctype/timesheet/timesheet_list.js:5 +#: erpnext/stock/doctype/delivery_note/delivery_note.json +#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:24 msgid "Partially Billed" msgstr "" @@ -32433,6 +32622,8 @@ msgstr "" #. Revaluation Account' #. Label of the party (Dynamic Link) field in DocType 'GL Entry' #. Label of the party (Dynamic Link) field in DocType 'Journal Entry Account' +#. Label of the party (Dynamic Link) field in DocType 'Journal Entry Template +#. Account' #. Label of the party (Dynamic Link) field in DocType 'Opening Invoice Creation #. Tool Item' #. Label of the party (Dynamic Link) field in DocType 'Payment Entry' @@ -32452,6 +32643,7 @@ msgstr "" #: erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json #: erpnext/accounts/doctype/gl_entry/gl_entry.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +#: erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json #: erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json #: erpnext/accounts/doctype/payment_entry/payment_entry.json #: erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json @@ -32608,6 +32800,8 @@ msgstr "" #. Account' #. Label of the party_type (Link) field in DocType 'GL Entry' #. Label of the party_type (Link) field in DocType 'Journal Entry Account' +#. Label of the party_type (Link) field in DocType 'Journal Entry Template +#. Account' #. Label of the party_type (Link) field in DocType 'Opening Invoice Creation #. Tool Item' #. Label of the party_type (Link) field in DocType 'Payment Entry' @@ -32629,6 +32823,7 @@ msgstr "" #: erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json #: erpnext/accounts/doctype/gl_entry/gl_entry.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +#: erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json #: erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json #: erpnext/accounts/doctype/payment_entry/payment_entry.json #: erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json @@ -32811,7 +33006,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:119 #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py:20 #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice_list.js:55 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:97 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:98 #: erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py:25 #: erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js:42 #: erpnext/buying/doctype/purchase_order/purchase_order.js:421 @@ -33140,7 +33335,7 @@ msgstr "" #: erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json #: erpnext/accounts/doctype/payment_request/payment_request.json #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:135 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:138 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:139 #: erpnext/buying/doctype/purchase_order/purchase_order.js:429 #: erpnext/selling/doctype/sales_order/sales_order.js:1152 msgid "Payment Request" @@ -33813,7 +34008,7 @@ msgstr "" #. Label of a Link in the Stock Workspace #: erpnext/selling/doctype/sales_order/sales_order.js:1022 #: erpnext/stock/doctype/delivery_note/delivery_note.js:199 -#: erpnext/stock/doctype/material_request/material_request.js:144 +#: erpnext/stock/doctype/material_request/material_request.js:156 #: erpnext/stock/doctype/pick_list/pick_list.json #: erpnext/stock/doctype/stock_entry/stock_entry.json #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json @@ -34278,7 +34473,7 @@ msgstr "" msgid "Please click on 'Generate Schedule' to get schedule" msgstr "" -#: erpnext/selling/doctype/customer/customer.py:595 +#: erpnext/selling/doctype/customer/customer.py:598 msgid "Please contact any of the following users to extend the credit limits for {0}: {1}" msgstr "" @@ -34286,7 +34481,7 @@ msgstr "" msgid "Please contact any of the following users to {} this transaction." msgstr "" -#: erpnext/selling/doctype/customer/customer.py:588 +#: erpnext/selling/doctype/customer/customer.py:591 msgid "Please contact your administrator to extend the credit limits for {0}." msgstr "" @@ -34350,7 +34545,7 @@ msgstr "" msgid "Please enable {0} in the {1}." msgstr "" -#: erpnext/controllers/selling_controller.py:852 +#: erpnext/controllers/selling_controller.py:846 msgid "Please enable {} in {} to allow same item in multiple rows" msgstr "" @@ -34383,11 +34578,11 @@ msgstr "" msgid "Please enter Approving Role or Approving User" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:675 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:678 msgid "Please enter Batch No" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:968 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:971 msgid "Please enter Cost Center" msgstr "" @@ -34399,7 +34594,7 @@ msgstr "" msgid "Please enter Employee Id of this sales person" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:977 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:980 msgid "Please enter Expense Account" msgstr "" @@ -34408,7 +34603,7 @@ msgstr "" msgid "Please enter Item Code to get Batch Number" msgstr "" -#: erpnext/public/js/controllers/transaction.js:2963 +#: erpnext/public/js/controllers/transaction.js:2956 msgid "Please enter Item Code to get batch no" msgstr "" @@ -34448,7 +34643,7 @@ msgstr "" msgid "Please enter Root Type for account- {0}" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:677 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:680 msgid "Please enter Serial No" msgstr "" @@ -34561,6 +34756,14 @@ msgstr "" msgid "Please fix overlapping time slots for {0}." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:270 +msgid "Please generate To Delete list before submitting" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:70 +msgid "Please generate the To Delete list before submitting" +msgstr "" + #: erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py:67 msgid "Please import accounts against parent company or enable {} in company master." msgstr "" @@ -34654,7 +34857,7 @@ msgstr "" msgid "Please select Charge Type first" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:480 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:494 msgid "Please select Company" msgstr "" @@ -34663,7 +34866,7 @@ msgstr "" msgid "Please select Company and Posting Date to getting entries" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:722 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:736 #: erpnext/manufacturing/doctype/plant_floor/plant_floor.js:28 msgid "Please select Company first" msgstr "" @@ -34683,12 +34886,12 @@ msgid "Please select Existing Company for creating Chart of Accounts" msgstr "" #: erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.py:210 -#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:322 +#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:299 msgid "Please select Finished Good Item for Service Item {0}" msgstr "" -#: erpnext/assets/doctype/asset/asset.js:667 -#: erpnext/assets/doctype/asset/asset.js:682 +#: erpnext/assets/doctype/asset/asset.js:669 +#: erpnext/assets/doctype/asset/asset.js:684 msgid "Please select Item Code first" msgstr "" @@ -34712,11 +34915,11 @@ msgstr "" msgid "Please select Posting Date before selecting Party" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:723 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:737 msgid "Please select Posting Date first" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1186 +#: erpnext/manufacturing/doctype/bom/bom.py:1237 msgid "Please select Price List" msgstr "" @@ -34740,7 +34943,7 @@ msgstr "" msgid "Please select Stock Asset Account" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1604 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1605 msgid "Please select Subcontracting Order instead of Purchase Order {0}" msgstr "" @@ -34748,7 +34951,7 @@ msgstr "" msgid "Please select Unrealized Profit / Loss account or add default Unrealized Profit / Loss account account for company {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1441 +#: erpnext/manufacturing/doctype/bom/bom.py:1492 msgid "Please select a BOM" msgstr "" @@ -34758,10 +34961,10 @@ msgid "Please select a Company" msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.js:268 -#: erpnext/manufacturing/doctype/bom/bom.js:677 +#: erpnext/manufacturing/doctype/bom/bom.js:680 #: erpnext/manufacturing/doctype/bom/bom.py:276 #: erpnext/public/js/controllers/accounts.js:277 -#: erpnext/public/js/controllers/transaction.js:3262 +#: erpnext/public/js/controllers/transaction.js:3255 msgid "Please select a Company first." msgstr "" @@ -34785,7 +34988,7 @@ msgstr "" msgid "Please select a Warehouse" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1470 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1572 msgid "Please select a Work Order first." msgstr "" @@ -34862,7 +35065,7 @@ msgstr "" msgid "Please select atleast one operation to create Job Card" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1699 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1703 msgid "Please select correct account" msgstr "" @@ -34982,7 +35185,7 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:58 #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:68 #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:78 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:788 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:789 msgid "Please set Company" msgstr "" @@ -34998,12 +35201,12 @@ msgstr "" msgid "Please set Email/Phone for the contact" msgstr "" -#: erpnext/regional/italy/utils.py:250 +#: erpnext/regional/italy/utils.py:257 #, python-format msgid "Please set Fiscal Code for the customer '%s'" msgstr "" -#: erpnext/regional/italy/utils.py:258 +#: erpnext/regional/italy/utils.py:265 #, python-format msgid "Please set Fiscal Code for the public administration '%s'" msgstr "" @@ -35029,7 +35232,7 @@ msgstr "" msgid "Please set Root Type" msgstr "" -#: erpnext/regional/italy/utils.py:265 +#: erpnext/regional/italy/utils.py:272 #, python-format msgid "Please set Tax ID for the customer '%s'" msgstr "" @@ -35054,7 +35257,7 @@ msgstr "" msgid "Please set a Cost Center for the Asset or set an Asset Depreciation Cost Center for the Company {}" msgstr "" -#: erpnext/projects/doctype/project/project.py:729 +#: erpnext/projects/doctype/project/project.py:731 msgid "Please set a default Holiday List for Company {0}" msgstr "" @@ -35070,7 +35273,7 @@ msgstr "" msgid "Please set actual demand or sales forecast to generate Material Requirements Planning Report." msgstr "" -#: erpnext/regional/italy/utils.py:220 +#: erpnext/regional/italy/utils.py:227 #, python-format msgid "Please set an Address on the Company '%s'" msgstr "" @@ -35083,11 +35286,11 @@ msgstr "" msgid "Please set an email id for the Lead {0}" msgstr "" -#: erpnext/regional/italy/utils.py:276 +#: erpnext/regional/italy/utils.py:283 msgid "Please set at least one row in the Taxes and Charges Table" msgstr "" -#: erpnext/regional/italy/utils.py:240 +#: erpnext/regional/italy/utils.py:247 msgid "Please set both the Tax ID and Fiscal Code on Company {0}" msgstr "" @@ -35144,11 +35347,11 @@ msgstr "" msgid "Please set opening number of booked depreciations" msgstr "" -#: erpnext/public/js/controllers/transaction.js:2651 +#: erpnext/public/js/controllers/transaction.js:2644 msgid "Please set recurring after saving" msgstr "" -#: erpnext/regional/italy/utils.py:270 +#: erpnext/regional/italy/utils.py:277 msgid "Please set the Customer Address" msgstr "" @@ -35160,11 +35363,11 @@ msgstr "" msgid "Please set the Item Code first" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1533 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1635 msgid "Please set the Target Warehouse in the Job Card" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1537 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1639 msgid "Please set the WIP Warehouse in the Job Card" msgstr "" @@ -35191,7 +35394,7 @@ msgstr "" msgid "Please set {0} for Batched Item {1}, which is used to set {2} on Submit." msgstr "" -#: erpnext/regional/italy/utils.py:422 +#: erpnext/regional/italy/utils.py:429 msgid "Please set {0} for address {1}" msgstr "" @@ -35221,7 +35424,7 @@ msgstr "" #: erpnext/accounts/doctype/pos_invoice/pos_invoice.js:120 #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:419 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:525 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:526 msgid "Please specify Company to proceed" msgstr "" @@ -35238,7 +35441,7 @@ msgstr "" msgid "Please specify at least one attribute in the Attributes table" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:615 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:618 msgid "Please specify either Quantity or Valuation Rate or both" msgstr "" @@ -35471,7 +35674,7 @@ msgstr "" msgid "Posting Date cannot be future date" msgstr "" -#: erpnext/public/js/controllers/transaction.js:1012 +#: erpnext/public/js/controllers/transaction.js:1005 msgid "Posting Date will change to today's date as Edit Posting Date and Time is unchecked. Are you sure want to proceed?" msgstr "" @@ -35533,7 +35736,7 @@ msgstr "" msgid "Posting Time" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2332 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2334 msgid "Posting date and posting time is mandatory" msgstr "" @@ -35928,7 +36131,7 @@ msgstr "" msgid "Price is not set for the item." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:515 +#: erpnext/manufacturing/doctype/bom/bom.py:566 msgid "Price not found for item {0} in price list {1}" msgstr "" @@ -36301,7 +36504,7 @@ msgstr "" msgid "Process Loss" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1169 +#: erpnext/manufacturing/doctype/bom/bom.py:1220 msgid "Process Loss Percentage cannot be greater than 100" msgstr "" @@ -36420,6 +36623,10 @@ msgstr "" msgid "Processing XML Files" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:188 +msgid "Processing import..." +msgstr "" + #: erpnext/buying/doctype/supplier/supplier_dashboard.py:10 msgid "Procurement" msgstr "" @@ -36748,7 +36955,7 @@ msgstr "" msgid "Progress (%)" msgstr "" -#: erpnext/projects/doctype/project/project.py:368 +#: erpnext/projects/doctype/project/project.py:370 msgid "Project Collaboration Invitation" msgstr "" @@ -36790,7 +36997,7 @@ msgstr "" msgid "Project Summary" msgstr "" -#: erpnext/projects/doctype/project/project.py:667 +#: erpnext/projects/doctype/project/project.py:669 msgid "Project Summary for {0}" msgstr "" @@ -36910,7 +37117,7 @@ msgstr "" #. Name of a Workspace #. Label of a Card Break in the Projects Workspace -#: erpnext/config/projects.py:7 erpnext/projects/doctype/project/project.py:445 +#: erpnext/config/projects.py:7 erpnext/projects/doctype/project/project.py:447 #: erpnext/projects/workspace/projects/projects.json #: erpnext/selling/doctype/customer/customer_dashboard.py:26 #: erpnext/selling/doctype/sales_order/sales_order_dashboard.py:28 @@ -37040,6 +37247,11 @@ msgstr "" msgid "Prospects Engaged But Not Converted" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:196 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:779 +msgid "Protected DocType" +msgstr "" + #. Description of the 'Company Email' (Data) field in DocType 'Employee' #: erpnext/setup/doctype/employee/employee.json msgid "Provide Email Address registered in company" @@ -37316,7 +37528,7 @@ msgstr "" #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/setup/doctype/authorization_rule/authorization_rule.json #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json -#: erpnext/stock/doctype/material_request/material_request.js:184 +#: erpnext/stock/doctype/material_request/material_request.js:196 #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.js:217 #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json #: erpnext/stock/doctype/stock_entry/stock_entry.json @@ -37745,7 +37957,7 @@ msgstr "" #: erpnext/controllers/trends.py:268 erpnext/controllers/trends.py:280 #: erpnext/controllers/trends.py:285 #: erpnext/crm/doctype/opportunity_item/opportunity_item.json -#: erpnext/manufacturing/doctype/bom/bom.js:1075 +#: erpnext/manufacturing/doctype/bom/bom.js:1078 #: erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json #: erpnext/manufacturing/doctype/bom_item/bom_item.json #: erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json @@ -37871,11 +38083,11 @@ msgstr "" msgid "Qty To Manufacture" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1395 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1405 msgid "Qty To Manufacture ({0}) cannot be a fraction for the UOM {2}. To allow this, disable '{1}' in the UOM {2}." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:228 +#: erpnext/manufacturing/doctype/job_card/job_card.py:253 msgid "Qty To Manufacture in the job card cannot be greater than Qty To Manufacture in the work order for the operation {0}.

Solution: Either you can reduce the Qty To Manufacture in the job card or set the 'Overproduction Percentage For Work Order' in the {1}." msgstr "" @@ -37978,7 +38190,7 @@ msgid "Qty to Fetch" msgstr "" #: erpnext/manufacturing/doctype/job_card/job_card.js:304 -#: erpnext/manufacturing/doctype/job_card/job_card.py:788 +#: erpnext/manufacturing/doctype/job_card/job_card.py:874 msgid "Qty to Manufacture" msgstr "" @@ -38192,6 +38404,20 @@ msgstr "" msgid "Quality Inspection Template Name" msgstr "" +#: erpnext/manufacturing/doctype/job_card/job_card.py:783 +msgid "Quality Inspection is required for the item {0} before completing the job card {1}" +msgstr "" + +#: erpnext/manufacturing/doctype/job_card/job_card.py:794 +#: erpnext/manufacturing/doctype/job_card/job_card.py:803 +msgid "Quality Inspection {0} is not submitted for the item: {1}" +msgstr "" + +#: erpnext/manufacturing/doctype/job_card/job_card.py:813 +#: erpnext/manufacturing/doctype/job_card/job_card.py:822 +msgid "Quality Inspection {0} is rejected for the item: {1}" +msgstr "" + #: erpnext/public/js/controllers/transaction.js:384 #: erpnext/stock/doctype/stock_entry/stock_entry.js:197 msgid "Quality Inspection(s)" @@ -38336,7 +38562,7 @@ msgstr "" #: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:67 #: erpnext/stock/dashboard/item_dashboard.js:248 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json -#: erpnext/stock/doctype/material_request/material_request.js:356 +#: erpnext/stock/doctype/material_request/material_request.js:368 #: erpnext/stock/doctype/material_request_item/material_request_item.json #: erpnext/stock/doctype/packing_slip_item/packing_slip_item.json #: erpnext/stock/doctype/pick_list_item/pick_list_item.json @@ -38464,11 +38690,11 @@ msgstr "" msgid "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:683 +#: erpnext/manufacturing/doctype/bom/bom.py:734 msgid "Quantity required for Item {0} in row {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:627 +#: erpnext/manufacturing/doctype/bom/bom.py:678 #: erpnext/manufacturing/doctype/job_card/job_card.js:385 #: erpnext/manufacturing/doctype/job_card/job_card.js:455 #: erpnext/manufacturing/doctype/workstation/workstation.js:303 @@ -38483,11 +38709,11 @@ msgstr "" msgid "Quantity to Manufacture" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2523 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2567 msgid "Quantity to Manufacture can not be zero for the operation {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1387 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1397 msgid "Quantity to Manufacture must be greater than 0." msgstr "" @@ -38532,7 +38758,7 @@ msgstr "" msgid "Queue Size should be between 5 and 100" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:611 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:625 msgid "Quick Journal Entry" msgstr "" @@ -38571,7 +38797,7 @@ msgstr "" #. Label of the prevdoc_docname (Link) field in DocType 'Sales Order Item' #. Label of a Link in the Selling Workspace #. Option for the 'Transaction' (Select) field in DocType 'Authorization Rule' -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:299 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:300 #: erpnext/buying/doctype/supplier_quotation/supplier_quotation.js:51 #: erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.html:20 #: erpnext/crm/doctype/contract/contract.json @@ -39083,7 +39309,7 @@ msgstr "" #. Label of the section_break_8 (Section Break) field in DocType 'Job Card' #. Label of the mr_items (Table) field in DocType 'Production Plan' #: erpnext/manufacturing/doctype/bom/bom.js:406 -#: erpnext/manufacturing/doctype/bom/bom.js:1048 +#: erpnext/manufacturing/doctype/bom/bom.js:1051 #: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/job_card/job_card.json #: erpnext/manufacturing/doctype/production_plan/production_plan.json @@ -39147,7 +39373,7 @@ msgstr "" msgid "Raw Materials Supplied Cost" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:675 +#: erpnext/manufacturing/doctype/bom/bom.py:726 msgid "Raw Materials cannot be blank." msgstr "" @@ -39172,7 +39398,7 @@ msgstr "" #: erpnext/manufacturing/doctype/work_order/work_order.js:733 #: erpnext/selling/doctype/sales_order/sales_order.js:968 #: erpnext/selling/doctype/sales_order/sales_order_list.js:70 -#: erpnext/stock/doctype/material_request/material_request.js:231 +#: erpnext/stock/doctype/material_request/material_request.js:243 #: erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.js:116 #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:164 msgid "Re-open" @@ -39712,7 +39938,7 @@ msgstr "" msgid "Reference #{0} dated {1}" msgstr "" -#: erpnext/public/js/controllers/transaction.js:2764 +#: erpnext/public/js/controllers/transaction.js:2757 msgid "Reference Date for Early Payment Discount" msgstr "" @@ -39846,11 +40072,11 @@ msgstr "" msgid "References" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:391 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:399 msgid "References to Sales Invoices are Incomplete" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:386 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:394 msgid "References to Sales Orders are Incomplete" msgstr "" @@ -40088,14 +40314,22 @@ msgstr "" msgid "Remove Parent Row No in Items Table" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:140 +msgid "Remove Zero Counts" +msgstr "" + #: erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js:9 msgid "Remove item if charges is not applicable to that item" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:561 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:564 msgid "Removed items with no change in quantity or value." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:161 +msgid "Removed {0} rows with zero document count. Please save to persist changes." +msgstr "" + #: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py:87 msgid "Removing rows without exchange gain or loss" msgstr "" @@ -40474,7 +40708,7 @@ msgstr "" #: erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js:70 #: erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py:272 #: erpnext/buying/workspace/buying/buying.json -#: erpnext/stock/doctype/material_request/material_request.js:190 +#: erpnext/stock/doctype/material_request/material_request.js:202 msgid "Request for Quotation" msgstr "" @@ -40815,7 +41049,7 @@ msgstr "" #: erpnext/stock/doctype/bin/bin.json #: erpnext/stock/doctype/pick_list/pick_list.js:168 #: erpnext/stock/report/reserved_stock/reserved_stock.json -#: erpnext/stock/report/stock_balance/stock_balance.py:497 +#: erpnext/stock/report/stock_balance/stock_balance.py:499 #: erpnext/stock/stock_ledger.py:2269 #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:205 #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:333 @@ -40873,7 +41107,7 @@ msgstr "" msgid "Reserving Stock..." msgstr "" -#. Label of the reset_company_default_values (Check) field in DocType +#. Label of the reset_company_default_values_status (Select) field in DocType #. 'Transaction Deletion Record' #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json msgid "Reset Company Default Values" @@ -41149,7 +41383,7 @@ msgstr "" msgid "Return" msgstr "" -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:110 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:111 msgid "Return / Credit Note" msgstr "" @@ -41715,7 +41949,7 @@ msgstr "" msgid "Row # {0}: Returned Item {1} does not exist in {2} {3}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:260 +#: erpnext/manufacturing/doctype/work_order/work_order.py:270 msgid "Row #1: Sequence ID must be 1 for Operation {0}." msgstr "" @@ -41839,7 +42073,7 @@ msgstr "" msgid "Row #{0}: Cannot set Rate if the billed amount is greater than the amount for Item {1}." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1026 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1112 msgid "Row #{0}: Cannot transfer more than Required Qty {1} for Item {2} against Job Card {3}" msgstr "" @@ -41889,11 +42123,11 @@ msgstr "" msgid "Row #{0}: Customer Provided Item {1} cannot be added multiple times in the Subcontracting Inward process." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:337 +#: erpnext/manufacturing/doctype/work_order/work_order.py:347 msgid "Row #{0}: Customer Provided Item {1} cannot be added multiple times." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:362 +#: erpnext/manufacturing/doctype/work_order/work_order.py:372 msgid "Row #{0}: Customer Provided Item {1} does not exist in the Required Items table linked to the Subcontracting Inward Order." msgstr "" @@ -41901,7 +42135,7 @@ msgstr "" msgid "Row #{0}: Customer Provided Item {1} exceeds quantity available through Subcontracting Inward Order" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:350 +#: erpnext/manufacturing/doctype/work_order/work_order.py:360 msgid "Row #{0}: Customer Provided Item {1} has insufficient quantity in the Subcontracting Inward Order. Available quantity is {2}." msgstr "" @@ -41986,7 +42220,7 @@ msgstr "" msgid "Row #{0}: From Date cannot be before To Date" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:778 +#: erpnext/manufacturing/doctype/job_card/job_card.py:864 msgid "Row #{0}: From Time and To Time fields are required" msgstr "" @@ -41994,7 +42228,7 @@ msgstr "" msgid "Row #{0}: Item added" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1535 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1536 msgid "Row #{0}: Item {1} cannot be transferred more than {2} against {3} {4}" msgstr "" @@ -42022,7 +42256,7 @@ msgstr "" msgid "Row #{0}: Item {1} is not a Customer Provided Item." msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:758 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:761 msgid "Row #{0}: Item {1} is not a Serialized/Batched Item. It cannot have a Serial No/Batch No against it." msgstr "" @@ -42193,11 +42427,11 @@ msgstr "" msgid "" "Row #{0}: Selling rate for item {1} is lower than its {2}.\n" "\t\t\t\t\tSelling {3} should be atleast {4}.

Alternatively,\n" -"\t\t\t\t\tyou can disable selling price validation in {5} to bypass\n" +"\t\t\t\t\tyou can disable '{5}' in {6} to bypass\n" "\t\t\t\t\tthis validation." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:266 +#: erpnext/manufacturing/doctype/work_order/work_order.py:276 msgid "Row #{0}: Sequence ID must be {1} or {2} for Operation {3}." msgstr "" @@ -42241,19 +42475,19 @@ msgstr "" msgid "Row #{0}: Source Warehouse must be same as Customer Warehouse {1} from the linked Subcontracting Inward Order" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:371 +#: erpnext/manufacturing/doctype/work_order/work_order.py:381 msgid "Row #{0}: Source Warehouse {1} for item {2} cannot be a customer warehouse." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:326 +#: erpnext/manufacturing/doctype/work_order/work_order.py:336 msgid "Row #{0}: Source Warehouse {1} for item {2} must be same as Source Warehouse {3} in the Work Order." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1015 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1016 msgid "Row #{0}: Source and Target Warehouse cannot be the same for Material Transfer" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1037 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1038 msgid "Row #{0}: Source, Target Warehouse and Inventory Dimensions cannot be the exact same for Material Transfer" msgstr "" @@ -42289,7 +42523,7 @@ msgstr "" msgid "Row #{0}: Stock is already reserved for the Item {1}." msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:545 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:553 msgid "Row #{0}: Stock is reserved for item {1} in warehouse {2}." msgstr "" @@ -42459,7 +42693,7 @@ msgstr "" msgid "Row No {0}: Warehouse is required. Please set a Default Warehouse for Item {1} and Company {2}" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:706 +#: erpnext/manufacturing/doctype/job_card/job_card.py:731 msgid "Row {0} : Operation is required against the raw material item {1}" msgstr "" @@ -42467,7 +42701,7 @@ msgstr "" msgid "Row {0} picked quantity is less than the required quantity, additional {1} {2} required." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1559 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1560 msgid "Row {0}# Item {1} not found in 'Raw Materials Supplied' table in {2} {3}" msgstr "" @@ -42499,7 +42733,7 @@ msgstr "" msgid "Row {0}: Allocated amount {1} must be less than or equal to remaining payment amount {2}" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1220 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1221 msgid "Row {0}: As {1} is enabled, raw materials cannot be added to {2} entry. Use {3} entry to consume raw materials." msgstr "" @@ -42533,7 +42767,7 @@ msgstr "" msgid "Row {0}: Credit entry can not be linked with a {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:487 +#: erpnext/manufacturing/doctype/bom/bom.py:538 msgid "Row {0}: Currency of the BOM #{1} should be equal to the selected currency {2}" msgstr "" @@ -42541,7 +42775,7 @@ msgstr "" msgid "Row {0}: Debit entry can not be linked with a {1}" msgstr "" -#: erpnext/controllers/selling_controller.py:874 +#: erpnext/controllers/selling_controller.py:868 msgid "Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same" msgstr "" @@ -42590,7 +42824,7 @@ msgstr "" msgid "Row {0}: From Time and To Time is mandatory." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:283 +#: erpnext/manufacturing/doctype/job_card/job_card.py:308 #: erpnext/projects/doctype/timesheet/timesheet.py:225 msgid "Row {0}: From Time and To Time of {1} is overlapping with {2}" msgstr "" @@ -42599,7 +42833,7 @@ msgstr "" msgid "Row {0}: From Warehouse is mandatory for internal transfers" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:274 +#: erpnext/manufacturing/doctype/job_card/job_card.py:299 msgid "Row {0}: From time must be less than to time" msgstr "" @@ -42615,7 +42849,7 @@ msgstr "" msgid "Row {0}: Item Tax template updated as per validity and rate applied" msgstr "" -#: erpnext/controllers/selling_controller.py:639 +#: erpnext/controllers/selling_controller.py:633 msgid "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer" msgstr "" @@ -42635,7 +42869,7 @@ msgstr "" msgid "Row {0}: Item {1}'s quantity cannot be higher than the available quantity." msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:602 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:610 msgid "Row {0}: Packed Qty must be equal to {1} Qty." msgstr "" @@ -42679,15 +42913,15 @@ msgstr "" msgid "Row {0}: Please select an valid BOM for Item {1}." msgstr "" -#: erpnext/regional/italy/utils.py:283 +#: erpnext/regional/italy/utils.py:290 msgid "Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges" msgstr "" -#: erpnext/regional/italy/utils.py:310 +#: erpnext/regional/italy/utils.py:317 msgid "Row {0}: Please set the Mode of Payment in Payment Schedule" msgstr "" -#: erpnext/regional/italy/utils.py:315 +#: erpnext/regional/italy/utils.py:322 msgid "Row {0}: Please set the correct code on Mode of Payment {1}" msgstr "" @@ -42727,7 +42961,7 @@ msgstr "" msgid "Row {0}: Shift cannot be changed since the depreciation has already been processed" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1572 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1573 msgid "Row {0}: Subcontracted Item is mandatory for the raw material {1}" msgstr "" @@ -42755,7 +42989,7 @@ msgstr "" msgid "Row {0}: To set {1} periodicity, difference between from and to date must be greater than or equal to {2}" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3361 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3363 msgid "Row {0}: Transferred quantity cannot be greater than the requested quantity." msgstr "" @@ -42763,8 +42997,8 @@ msgstr "" msgid "Row {0}: UOM Conversion Factor is mandatory" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1152 -#: erpnext/manufacturing/doctype/work_order/work_order.py:400 +#: erpnext/manufacturing/doctype/bom/bom.py:1203 +#: erpnext/manufacturing/doctype/work_order/work_order.py:410 msgid "Row {0}: Workstation or Workstation Type is mandatory for an operation {1}" msgstr "" @@ -43108,7 +43342,7 @@ msgstr "" #: erpnext/setup/doctype/authorization_rule/authorization_rule.json #: erpnext/setup/workspace/home/home.json #: erpnext/stock/doctype/delivery_note/delivery_note.js:347 -#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:65 +#: erpnext/stock/doctype/delivery_note/delivery_note_list.js:67 #: erpnext/stock/doctype/quality_inspection/quality_inspection.json msgid "Sales Invoice" msgstr "" @@ -43189,7 +43423,7 @@ msgstr "" msgid "Sales Invoice mode is activated in POS. Please create Sales Invoice instead." msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:622 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:630 msgid "Sales Invoice {0} has already been submitted" msgstr "" @@ -43242,13 +43476,13 @@ msgstr "" #. Label of a Link in the Subcontracting Workspace #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json #: erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:277 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:278 #: erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json #: erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py:276 #: erpnext/accounts/report/sales_register/sales_register.py:238 #: erpnext/buying/doctype/purchase_order_item/purchase_order_item.json #: erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json -#: erpnext/controllers/selling_controller.py:526 +#: erpnext/controllers/selling_controller.py:494 #: erpnext/crm/doctype/contract/contract.json #: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js:65 #: erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json @@ -43276,7 +43510,7 @@ msgstr "" #: erpnext/setup/doctype/authorization_rule/authorization_rule.json #: erpnext/stock/doctype/delivery_note/delivery_note.js:157 #: erpnext/stock/doctype/delivery_note/delivery_note.js:223 -#: erpnext/stock/doctype/material_request/material_request.js:224 +#: erpnext/stock/doctype/material_request/material_request.js:236 #: erpnext/stock/doctype/material_request_item/material_request_item.json #: erpnext/stock/doctype/pick_list_item/pick_list_item.json #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -43374,7 +43608,7 @@ msgstr "" msgid "Sales Order Trends" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:274 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:282 msgid "Sales Order required for Item {0}" msgstr "" @@ -43386,12 +43620,12 @@ msgstr "" msgid "Sales Order {0} is not submitted" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:451 +#: erpnext/manufacturing/doctype/work_order/work_order.py:461 msgid "Sales Order {0} is not valid" msgstr "" -#: erpnext/controllers/selling_controller.py:507 -#: erpnext/manufacturing/doctype/work_order/work_order.py:456 +#: erpnext/controllers/selling_controller.py:475 +#: erpnext/manufacturing/doctype/work_order/work_order.py:466 msgid "Sales Order {0} is {1}" msgstr "" @@ -43762,7 +43996,7 @@ msgstr "" msgid "Same Item" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:597 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:600 msgid "Same item and warehouse combination already entered." msgstr "" @@ -43794,12 +44028,12 @@ msgstr "" #. Label of the sample_size (Float) field in DocType 'Quality Inspection' #: erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py:93 -#: erpnext/public/js/controllers/transaction.js:2821 +#: erpnext/public/js/controllers/transaction.js:2814 #: erpnext/stock/doctype/quality_inspection/quality_inspection.json msgid "Sample Size" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3851 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3853 msgid "Sample quantity {0} cannot be more than received quantity {1}" msgstr "" @@ -44269,7 +44503,7 @@ msgstr "" msgid "Select Items based on Delivery Date" msgstr "" -#: erpnext/public/js/controllers/transaction.js:2860 +#: erpnext/public/js/controllers/transaction.js:2853 msgid "Select Items for Quality Inspection" msgstr "" @@ -44294,7 +44528,7 @@ msgstr "" msgid "Select Job Worker Address" msgstr "" -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1172 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1173 #: erpnext/selling/page/point_of_sale/pos_item_cart.js:955 msgid "Select Loyalty Program" msgstr "" @@ -44366,7 +44600,7 @@ msgstr "" msgid "Select a Company this Employee belongs to." msgstr "" -#: erpnext/buying/doctype/supplier/supplier.js:190 +#: erpnext/buying/doctype/supplier/supplier.js:182 msgid "Select a Customer" msgstr "" @@ -44382,7 +44616,7 @@ msgstr "" msgid "Select a Supplier" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:407 +#: erpnext/stock/doctype/material_request/material_request.js:419 msgid "Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only." msgstr "" @@ -44445,7 +44679,7 @@ msgstr "" msgid "Select the Item to be manufactured." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:955 +#: erpnext/manufacturing/doctype/bom/bom.js:958 msgid "Select the Item to be manufactured. The Item name, UoM, Company, and Currency will be fetched automatically." msgstr "" @@ -44458,7 +44692,7 @@ msgstr "" msgid "Select the customer or supplier." msgstr "" -#: erpnext/assets/doctype/asset/asset.js:844 +#: erpnext/assets/doctype/asset/asset.js:846 msgid "Select the date" msgstr "" @@ -44466,7 +44700,7 @@ msgstr "" msgid "Select the date and your timezone" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:974 +#: erpnext/manufacturing/doctype/bom/bom.js:977 msgid "Select the raw materials (Items) required to manufacture the Item" msgstr "" @@ -44760,14 +44994,14 @@ msgstr "" #: erpnext/manufacturing/doctype/job_card/job_card.json #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js:74 #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py:114 -#: erpnext/public/js/controllers/transaction.js:2834 +#: erpnext/public/js/controllers/transaction.js:2827 #: erpnext/public/js/utils/serial_no_batch_selector.js:421 #: erpnext/selling/doctype/installation_note_item/installation_note_item.json #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json #: erpnext/stock/doctype/packed_item/packed_item.json #: erpnext/stock/doctype/pick_list_item/pick_list_item.json #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:158 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:159 #: erpnext/stock/doctype/serial_and_batch_entry/serial_and_batch_entry.json #: erpnext/stock/doctype/serial_no/serial_no.json #: erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -44818,7 +45052,7 @@ msgstr "" msgid "Serial No Range" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2497 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2513 msgid "Serial No Reserved" msgstr "" @@ -44869,7 +45103,7 @@ msgstr "" msgid "Serial No and Batch Traceability" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1107 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1112 msgid "Serial No is mandatory" msgstr "" @@ -44898,11 +45132,11 @@ msgstr "" msgid "Serial No {0} does not exist" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:3234 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:3250 msgid "Serial No {0} does not exists" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:357 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:358 msgid "Serial No {0} is already Delivered. You cannot use them again in Manufacture / Repack entry." msgstr "" @@ -44914,7 +45148,7 @@ msgstr "" msgid "Serial No {0} is already assigned to customer {1}. Can only be returned against the customer {1}" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:429 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:430 msgid "Serial No {0} is not present in the {1} {2}, hence you can't return it against the {1} {2}" msgstr "" @@ -44938,7 +45172,7 @@ msgstr "" #: erpnext/public/js/utils/serial_no_batch_selector.js:16 #: erpnext/public/js/utils/serial_no_batch_selector.js:190 #: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js:50 -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:158 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:159 msgid "Serial Nos" msgstr "" @@ -44952,7 +45186,7 @@ msgstr "" msgid "Serial Nos and Batches" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1783 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1799 msgid "Serial Nos are created successfully" msgstr "" @@ -44960,7 +45194,7 @@ msgstr "" msgid "Serial Nos are reserved in Stock Reservation Entries, you need to unreserve them before proceeding." msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:363 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:364 msgid "Serial Nos {0} are already Delivered. You cannot use them again in Manufacture / Repack entry." msgstr "" @@ -45034,11 +45268,11 @@ msgstr "" msgid "Serial and Batch Bundle" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2005 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2021 msgid "Serial and Batch Bundle created" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2077 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2093 msgid "Serial and Batch Bundle updated" msgstr "" @@ -45160,7 +45394,7 @@ msgstr "" #: erpnext/accounts/doctype/budget/budget.json #: erpnext/accounts/doctype/cashier_closing/cashier_closing.json #: erpnext/accounts/doctype/dunning/dunning.json -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:645 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:659 #: erpnext/accounts/doctype/journal_entry/journal_entry.json #: erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json #: erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -45403,12 +45637,12 @@ msgid "Service Stop Date" msgstr "" #: erpnext/accounts/deferred_revenue.py:45 -#: erpnext/public/js/controllers/transaction.js:1678 +#: erpnext/public/js/controllers/transaction.js:1671 msgid "Service Stop Date cannot be after Service End Date" msgstr "" #: erpnext/accounts/deferred_revenue.py:42 -#: erpnext/public/js/controllers/transaction.js:1675 +#: erpnext/public/js/controllers/transaction.js:1668 msgid "Service Stop Date cannot be before Service Start Date" msgstr "" @@ -45485,7 +45719,7 @@ msgstr "" msgid "Set Landed Cost Based on Purchase Invoice Rate" msgstr "" -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1184 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1185 msgid "Set Loyalty Program" msgstr "" @@ -45514,7 +45748,7 @@ msgstr "" msgid "Set Posting Date" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:1001 +#: erpnext/manufacturing/doctype/bom/bom.js:1004 msgid "Set Process Loss Item Quantity" msgstr "" @@ -45637,7 +45871,7 @@ msgstr "" msgid "Set fieldname from which you want to fetch the data from the parent form." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:991 +#: erpnext/manufacturing/doctype/bom/bom.js:994 msgid "Set quantity of process loss item:" msgstr "" @@ -45742,8 +45976,8 @@ msgstr "" msgid "Setting up company" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1131 -#: erpnext/manufacturing/doctype/work_order/work_order.py:1451 +#: erpnext/manufacturing/doctype/bom/bom.py:1182 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1461 msgid "Setting {0} is required" msgstr "" @@ -45905,7 +46139,7 @@ msgstr "" msgid "Shipment details" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:793 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:801 msgid "Shipments" msgstr "" @@ -46406,6 +46640,10 @@ msgstr "" msgid "Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table." msgstr "" +#: erpnext/manufacturing/doctype/bom/bom.py:317 +msgid "Since you have enabled 'Track Semi Finished Goods', at least one operation must have 'Is Final Finished Good' checked. For that set the FG / Semi FG Item as {0} against an operation." +msgstr "" + #: erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py:111 msgid "Since {0} are Serial No/Batch No items, you cannot enable 'Recreate Stock Ledgers' in Repost Item Valuation." msgstr "" @@ -46448,6 +46686,10 @@ msgstr "" msgid "Skip Material Transfer to WIP Warehouse" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:559 +msgid "Skipped {0} DocType(s):
{1}" +msgstr "" + #. Label of the customer_skype (Data) field in DocType 'Appointment' #: erpnext/crm/doctype/appointment/appointment.json msgid "Skype ID" @@ -46611,7 +46853,7 @@ msgstr "" msgid "Source Warehouse is mandatory for the Item {0}." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:285 +#: erpnext/manufacturing/doctype/work_order/work_order.py:295 msgid "Source Warehouse {0} must be same as Customer Warehouse {1} in the Subcontracting Inward Order." msgstr "" @@ -46672,7 +46914,7 @@ msgstr "" msgid "Spending for Account {0} ({1}) between {2} and {3} has already exceeded the new allocated budget. Spent: {4}, Budget: {5}" msgstr "" -#: erpnext/assets/doctype/asset/asset.js:605 +#: erpnext/assets/doctype/asset/asset.js:607 #: erpnext/stock/doctype/batch/batch.js:91 #: erpnext/stock/doctype/batch/batch.js:183 #: erpnext/support/doctype/issue/issue.js:114 @@ -46680,7 +46922,7 @@ msgid "Split" msgstr "" #: erpnext/assets/doctype/asset/asset.js:120 -#: erpnext/assets/doctype/asset/asset.js:589 +#: erpnext/assets/doctype/asset/asset.js:591 msgid "Split Asset" msgstr "" @@ -46703,7 +46945,7 @@ msgstr "" msgid "Split Issue" msgstr "" -#: erpnext/assets/doctype/asset/asset.js:595 +#: erpnext/assets/doctype/asset/asset.js:597 msgid "Split Qty" msgstr "" @@ -46844,10 +47086,6 @@ msgstr "" msgid "Start Date should be lower than End Date" msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:21 -msgid "Start Deletion" -msgstr "" - #: erpnext/manufacturing/doctype/job_card/job_card.js:215 #: erpnext/manufacturing/doctype/workstation/workstation.js:124 msgid "Start Job" @@ -46942,7 +47180,7 @@ msgstr "" msgid "Status Illustration" msgstr "" -#: erpnext/projects/doctype/project/project.py:710 +#: erpnext/projects/doctype/project/project.py:712 msgid "Status must be Cancelled or Completed" msgstr "" @@ -47143,7 +47381,7 @@ msgstr "" msgid "Stock Entry {0} created" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1396 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1498 msgid "Stock Entry {0} has created" msgstr "" @@ -47380,7 +47618,7 @@ msgstr "" #: erpnext/stock/doctype/pick_list/pick_list.js:165 #: erpnext/stock/doctype/pick_list/pick_list.js:170 #: erpnext/stock/doctype/stock_entry/stock_entry_dashboard.py:12 -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:735 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:738 #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:674 #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1237 #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1644 @@ -47407,12 +47645,12 @@ msgstr "" #: erpnext/controllers/subcontracting_inward_controller.py:1003 #: erpnext/manufacturing/doctype/production_plan/production_plan.py:2234 -#: erpnext/manufacturing/doctype/work_order/work_order.py:2065 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2109 #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1777 msgid "Stock Reservation Entries Created" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:453 +#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:430 msgid "Stock Reservation Entries created" msgstr "" @@ -47435,7 +47673,7 @@ msgstr "" msgid "Stock Reservation Entry created against a Pick List cannot be updated. If you need to make changes, we recommend canceling the existing entry and creating a new one." msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:555 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:563 msgid "Stock Reservation Warehouse Mismatch" msgstr "" @@ -47580,7 +47818,7 @@ msgstr "" #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json #: erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py:35 #: erpnext/stock/report/reserved_stock/reserved_stock.py:110 -#: erpnext/stock/report/stock_balance/stock_balance.py:436 +#: erpnext/stock/report/stock_balance/stock_balance.py:438 #: erpnext/stock/report/stock_ledger/stock_ledger.py:215 #: erpnext/subcontracting/doctype/subcontracting_inward_order_item/subcontracting_inward_order_item.json #: erpnext/subcontracting/doctype/subcontracting_inward_order_received_item/subcontracting_inward_order_received_item.json @@ -47761,7 +47999,7 @@ msgstr "" msgid "Stop Reason" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1061 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1071 msgid "Stopped Work Order cannot be cancelled, Unstop it first to cancel" msgstr "" @@ -47915,7 +48153,7 @@ msgstr "" msgid "Subcontracted Item To Be Received" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:212 +#: erpnext/stock/doctype/material_request/material_request.js:224 msgid "Subcontracted Purchase Order" msgstr "" @@ -48053,7 +48291,7 @@ msgstr "" #. Label of the subcontracting_order (Link) field in DocType 'Subcontracting #. Receipt Supplied Item' #: erpnext/buying/doctype/purchase_order/purchase_order.js:399 -#: erpnext/controllers/subcontracting_controller.py:1159 +#: erpnext/controllers/subcontracting_controller.py:1167 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json #: erpnext/stock/doctype/stock_entry/stock_entry.json #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json @@ -48369,7 +48607,7 @@ msgstr "" msgid "Successfully imported {0} records." msgstr "" -#: erpnext/buying/doctype/supplier/supplier.js:212 +#: erpnext/buying/doctype/supplier/supplier.js:204 msgid "Successfully linked to Customer" msgstr "" @@ -48809,7 +49047,7 @@ msgstr "" #: erpnext/buying/workspace/buying/buying.json #: erpnext/crm/doctype/opportunity/opportunity.js:81 #: erpnext/selling/doctype/quotation/quotation.json -#: erpnext/stock/doctype/material_request/material_request.js:196 +#: erpnext/stock/doctype/material_request/material_request.js:208 msgid "Supplier Quotation" msgstr "" @@ -49279,15 +49517,15 @@ msgstr "" msgid "Target Warehouse for Finished Good must be same as Finished Good Warehouse {1} in Work Order {2} linked to the Subcontracting Inward Order." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:743 +#: erpnext/manufacturing/doctype/work_order/work_order.py:753 msgid "Target Warehouse is required before Submit" msgstr "" -#: erpnext/controllers/selling_controller.py:880 +#: erpnext/controllers/selling_controller.py:874 msgid "Target Warehouse is set for some items but the customer is not an internal customer." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:301 +#: erpnext/manufacturing/doctype/work_order/work_order.py:311 msgid "Target Warehouse {0} must be same as Delivery Warehouse {1} in the Subcontracting Inward Order Item." msgstr "" @@ -50319,7 +50557,7 @@ msgstr "" msgid "The Pick List having Stock Reservation Entries cannot be updated. If you need to make changes, we recommend canceling the existing Stock Reservation Entries before updating the Pick List." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2608 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2610 msgid "The Process Loss Qty has reset as per job cards Process Loss Qty" msgstr "" @@ -50331,11 +50569,11 @@ msgstr "" msgid "The Serial No at Row #{0}: {1} is not available in warehouse {2}." msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2494 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:2510 msgid "The Serial No {0} is reserved against the {1} {2} and cannot be used for any other transaction." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1742 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1743 msgid "The Serial and Batch Bundle {0} is not valid for this transaction. The 'Type of Transaction' should be 'Outward' instead of 'Inward' in Serial and Batch Bundle {0}" msgstr "" @@ -50361,7 +50599,7 @@ msgstr "" msgid "The batch {0} is already reserved in {1} {2}. So, cannot proceed with the {3} {4}, which is created against the {5} {6}." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1218 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1304 msgid "The completed quantity {0} of an operation {1} cannot be greater than the completed quantity {2} of a previous operation {3}." msgstr "" @@ -50398,7 +50636,7 @@ msgstr "" msgid "The field To Shareholder cannot be blank" msgstr "" -#: erpnext/stock/doctype/delivery_note/delivery_note.py:405 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:413 msgid "The field {0} in row {1} is not set" msgstr "" @@ -50577,8 +50815,8 @@ msgstr "" msgid "The seller and the buyer cannot be the same" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:175 -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:187 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:176 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:188 msgid "The serial and batch bundle {0} not linked to {1} {2}" msgstr "" @@ -50602,7 +50840,7 @@ msgstr "" msgid "The stock for the item {0} in the {1} warehouse was negative on the {2}. You should create a positive entry {3} before the date {4} and time {5} to post the correct valuation rate. For more details, please read the documentation." msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:729 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:732 msgid "The stock has been reserved for the following Items and Warehouses, un-reserve the same to {0} the Stock Reconciliation:

{1}" msgstr "" @@ -50616,11 +50854,11 @@ msgstr "" msgid "The system will create a Sales Invoice or a POS Invoice from the POS interface based on this setting. For high-volume transactions, it is recommended to use POS Invoice." msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1024 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1027 msgid "The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Reconciliation and revert to the Draft stage" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1035 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1038 msgid "The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Reconciliation and revert to the Submitted stage" msgstr "" @@ -50676,11 +50914,11 @@ msgstr "" msgid "The warehouse where your Items will be transferred when you begin production. Group Warehouse can also be selected as a Work in Progress warehouse." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:791 +#: erpnext/manufacturing/doctype/job_card/job_card.py:877 msgid "The {0} ({1}) must be equal to {2} ({3})" msgstr "" -#: erpnext/public/js/controllers/transaction.js:3301 +#: erpnext/public/js/controllers/transaction.js:3294 msgid "The {0} contains Unit Price Items." msgstr "" @@ -50696,7 +50934,7 @@ msgstr "" msgid "The {0} {1} does not match with the {0} {2} in the {3} {4}" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:894 +#: erpnext/manufacturing/doctype/job_card/job_card.py:980 msgid "The {0} {1} is used to calculate the valuation cost for the finished good {2}." msgstr "" @@ -50760,7 +50998,7 @@ msgstr "" msgid "There is no batch found against the {0}: {1}" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:1679 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:1680 msgid "There must be atleast 1 Finished Good in this Stock Entry" msgstr "" @@ -50831,7 +51069,7 @@ msgstr "" msgid "This covers all scorecards tied to this Setup" msgstr "" -#: erpnext/controllers/status_updater.py:459 +#: erpnext/controllers/status_updater.py:460 msgid "This document is over limit by {0} {1} for item {4}. Are you making another {3} against the same {2}?" msgstr "" @@ -51032,7 +51270,7 @@ msgstr "" msgid "This will restrict user access to other employee records" msgstr "" -#: erpnext/controllers/selling_controller.py:881 +#: erpnext/controllers/selling_controller.py:875 msgid "This {} will be treated as material transfer." msgstr "" @@ -51143,7 +51381,7 @@ msgstr "" msgid "Time in mins." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:770 +#: erpnext/manufacturing/doctype/job_card/job_card.py:856 msgid "Time logs are required for {0} {1}" msgstr "" @@ -51166,7 +51404,7 @@ msgstr "" #. Name of a DocType #. Label of a Link in the Projects Workspace -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1065 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:1066 #: erpnext/projects/doctype/timesheet/timesheet.json #: erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py:26 #: erpnext/projects/report/timesheet_billing_summary/timesheet_billing_summary.py:59 @@ -51274,6 +51512,10 @@ msgstr "" msgid "To Datetime" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:118 +msgid "To Delete list generated with {0} DocTypes" +msgstr "" + #. Option for the 'Sales Order Status' (Select) field in DocType 'Production #. Plan' #. Option for the 'Status' (Select) field in DocType 'Sales Order' @@ -51456,7 +51698,7 @@ msgstr "" msgid "To Warehouse (Optional)" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:969 +#: erpnext/manufacturing/doctype/bom/bom.js:972 msgid "To add Operations tick the 'With Operations' checkbox." msgstr "" @@ -51464,11 +51706,11 @@ msgstr "" msgid "To add subcontracted Item's raw materials if include exploded items is disabled." msgstr "" -#: erpnext/controllers/status_updater.py:452 +#: erpnext/controllers/status_updater.py:453 msgid "To allow over billing, update \"Over Billing Allowance\" in Accounts Settings or the Item." msgstr "" -#: erpnext/controllers/status_updater.py:448 +#: erpnext/controllers/status_updater.py:449 msgid "To allow over receipt / delivery, update \"Over Receipt/Delivery Allowance\" in Stock Settings or the Item." msgstr "" @@ -51815,11 +52057,15 @@ msgstr "" #. Label of the total_completed_qty (Float) field in DocType 'Job Card' #: erpnext/manufacturing/doctype/job_card/job_card.json -#: erpnext/manufacturing/doctype/job_card/job_card.py:787 +#: erpnext/manufacturing/doctype/job_card/job_card.py:873 #: erpnext/manufacturing/report/job_card_summary/job_card_summary.py:174 msgid "Total Completed Qty" msgstr "" +#: erpnext/manufacturing/doctype/job_card/job_card.py:190 +msgid "Total Completed Qty is required for Job Card {0}, please start and complete the job card before submission" +msgstr "" + #. Label of the total_consumed_material_cost (Currency) field in DocType #. 'Project' #: erpnext/projects/doctype/project/project.json @@ -52514,8 +52760,8 @@ msgstr "" msgid "Transaction Date" msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:507 -msgid "Transaction Deletion Document: {0} is running for this Company. {1}" +#: erpnext/setup/doctype/company/company.py:1104 +msgid "Transaction Deletion Document {0} has been triggered for company {1}" msgstr "" #. Name of a DocType @@ -52533,6 +52779,19 @@ msgstr "" msgid "Transaction Deletion Record Item" msgstr "" +#. Name of a DocType +#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json +msgid "Transaction Deletion Record To Delete" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1096 +msgid "Transaction Deletion Record {0} is already running. {1}" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1115 +msgid "Transaction Deletion Record {0} is currently deleting {1}. Cannot save documents until deletion completes." +msgstr "" + #. Label of the transaction_details_section (Section Break) field in DocType #. 'GL Entry' #. Label of the transaction_details (Section Break) field in DocType 'Payment @@ -52607,7 +52866,7 @@ msgstr "" msgid "Transaction from which tax is withheld" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:763 +#: erpnext/manufacturing/doctype/job_card/job_card.py:849 msgid "Transaction not allowed against stopped Work Order {0}" msgstr "" @@ -53106,7 +53365,7 @@ msgstr "" msgid "UOM Name" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3773 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3775 msgid "UOM conversion factor required for UOM: {0} in Item: {1}" msgstr "" @@ -53148,6 +53407,10 @@ msgstr "" msgid "UnReconcile Allocations" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:462 +msgid "Unable to fetch DocType details. Please contact system administrator." +msgstr "" + #: erpnext/setup/utils.py:182 msgid "Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually" msgstr "" @@ -53161,7 +53424,7 @@ msgstr "" msgid "Unable to find score starting at {0}. You need to have standing scores covering 0 to 100" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1019 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1029 msgid "Unable to find the time slot in the next {0} days for the operation {1}. Please increase the 'Capacity Planning For (Days)' in the {2}." msgstr "" @@ -53233,6 +53496,10 @@ msgstr "" msgid "Under Working Hours table, you can add start and end times for a Workstation. For example, a Workstation may be active from 9 am to 1 pm, then 2 pm to 5 pm. You can also specify the working hours based on shifts. While scheduling a Work Order, the system will check for the availability of the Workstation based on the working hours specified." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:931 +msgid "Unexpected Naming Series Pattern" +msgstr "" + #. Option for the 'Fulfilment Status' (Select) field in DocType 'Contract' #: erpnext/crm/doctype/contract/contract.json msgid "Unfulfilled" @@ -53890,7 +54157,7 @@ msgstr "" msgid "Use Transaction Date Exchange Rate" msgstr "" -#: erpnext/projects/doctype/project/project.py:561 +#: erpnext/projects/doctype/project/project.py:563 msgid "Use a name that is different from previous project name" msgstr "" @@ -53926,7 +54193,7 @@ msgstr "" #. Label of the user_remark (Small Text) field in DocType 'Journal Entry' #. Label of the user_remark (Small Text) field in DocType 'Journal Entry #. Account' -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:641 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:655 #: erpnext/accounts/doctype/journal_entry/journal_entry.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json msgid "User Remark" @@ -54241,7 +54508,7 @@ msgstr "" #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:85 #: erpnext/stock/report/item_prices/item_prices.py:57 #: erpnext/stock/report/serial_no_ledger/serial_no_ledger.py:67 -#: erpnext/stock/report/stock_balance/stock_balance.py:487 +#: erpnext/stock/report/stock_balance/stock_balance.py:489 #: erpnext/stock/report/stock_ledger/stock_ledger.py:298 msgid "Valuation Rate" msgstr "" @@ -54262,7 +54529,7 @@ msgstr "" msgid "Valuation Rate is mandatory if Opening Stock entered" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:781 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:784 msgid "Valuation Rate required for Item {0} at row {1}" msgstr "" @@ -54272,7 +54539,7 @@ msgstr "" msgid "Valuation and Total" msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1001 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1004 msgid "Valuation rate for customer provided items has been set to zero." msgstr "" @@ -54642,6 +54909,10 @@ msgstr "" msgid "Vimeo" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:214 +msgid "Virtual DocType" +msgstr "" + #: erpnext/templates/pages/help.html:46 msgid "Visit the forums" msgstr "" @@ -54770,7 +55041,7 @@ msgstr "" msgid "Voucher No" msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1333 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1338 msgid "Voucher No is mandatory" msgstr "" @@ -55013,7 +55284,7 @@ msgid "Warehouse not found against the account {0}" msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1215 -#: erpnext/stock/doctype/delivery_note/delivery_note.py:432 +#: erpnext/stock/doctype/delivery_note/delivery_note.py:440 msgid "Warehouse required for stock Item {0}" msgstr "" @@ -55159,11 +55430,11 @@ msgstr "" msgid "Warning: Another {0} # {1} exists against stock entry {2}" msgstr "" -#: erpnext/stock/doctype/material_request/material_request.js:544 +#: erpnext/stock/doctype/material_request/material_request.js:556 msgid "Warning: Material Requested Qty is less than Minimum Order Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1436 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1446 msgid "Warning: Quantity exceeds maximum producible quantity based on quantity of raw materials received through the Subcontracting Inward Order {0}." msgstr "" @@ -55171,6 +55442,10 @@ msgstr "" msgid "Warning: Sales Order {0} already exists against Customer's Purchase Order {1}" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:75 +msgid "Warning: This action cannot be undone!" +msgstr "" + #: erpnext/accounts/doctype/financial_report_template/financial_report_validation.py:77 msgid "Warnings" msgstr "" @@ -55387,6 +55662,10 @@ msgstr "" msgid "What do you need help with?" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:82 +msgid "What will be deleted:" +msgstr "" + #. Label of the whatsapp_no (Data) field in DocType 'Lead' #. Label of the whatsapp (Data) field in DocType 'Opportunity' #: erpnext/crm/doctype/lead/lead.json @@ -55579,7 +55858,7 @@ msgstr "" #: erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py:104 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json #: erpnext/selling/doctype/sales_order/sales_order.js:1050 -#: erpnext/stock/doctype/material_request/material_request.js:204 +#: erpnext/stock/doctype/material_request/material_request.js:216 #: erpnext/stock/doctype/material_request/material_request.json #: erpnext/stock/doctype/material_request/material_request.py:899 #: erpnext/stock/doctype/pick_list/pick_list.json @@ -55645,12 +55924,12 @@ msgstr "" msgid "Work Order cannot be created for following reason:
{0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1380 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1390 msgid "Work Order cannot be raised against a Item Template" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2387 -#: erpnext/manufacturing/doctype/work_order/work_order.py:2467 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2431 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2511 msgid "Work Order has been {0}" msgstr "" @@ -55692,7 +55971,7 @@ msgstr "" msgid "Work-in-Progress Warehouse" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:741 +#: erpnext/manufacturing/doctype/work_order/work_order.py:751 msgid "Work-in-Progress Warehouse is required before Submit" msgstr "" @@ -56026,7 +56305,7 @@ msgid "You can only have Plans with the same billing cycle in a Subscription" msgstr "" #: erpnext/accounts/doctype/pos_invoice/pos_invoice.js:423 -#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:927 +#: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:928 msgid "You can only redeem max {0} points in this order." msgstr "" @@ -56046,11 +56325,11 @@ msgstr "" msgid "You can use {0} to reconcile against {1} later." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1230 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1316 msgid "You can't make any changes to Job Card since Work Order is closed." msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:218 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:219 msgid "You can't process the serial number {0} as it has already been used in the SABB {1}. {2} if you want to inward same serial number multiple times then enabled 'Allow existing Serial No to be Manufactured/Received again' in the {3}" msgstr "" @@ -56058,7 +56337,7 @@ msgstr "" msgid "You can't redeem Loyalty Points having more value than the Total Amount." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:725 +#: erpnext/manufacturing/doctype/bom/bom.js:728 msgid "You cannot change the rate if BOM is mentioned against any Item." msgstr "" @@ -56090,7 +56369,7 @@ msgstr "" msgid "You cannot enable both the settings '{0}' and '{1}'." msgstr "" -#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:156 +#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:157 msgid "You cannot outward following {0} as either they are Delivered, Inactive or located in a different warehouse." msgstr "" @@ -56138,7 +56417,7 @@ msgstr "" msgid "You have already selected items from {0} {1}" msgstr "" -#: erpnext/projects/doctype/project/project.py:361 +#: erpnext/projects/doctype/project/project.py:363 msgid "You have been invited to collaborate on the project {0}." msgstr "" @@ -56234,7 +56513,7 @@ msgstr "" msgid "[Important] [ERPNext] Auto Reorder Errors" msgstr "" -#: erpnext/controllers/status_updater.py:290 +#: erpnext/controllers/status_updater.py:291 msgid "`Allow Negative rates for Items`" msgstr "" @@ -56254,7 +56533,7 @@ msgstr "" msgid "as Title" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.js:993 +#: erpnext/manufacturing/doctype/bom/bom.js:996 msgid "as a percentage of finished item quantity" msgstr "" @@ -56496,8 +56775,8 @@ msgstr "" msgid "subscription is already cancelled." msgstr "" -#: erpnext/controllers/status_updater.py:462 -#: erpnext/controllers/status_updater.py:481 +#: erpnext/controllers/status_updater.py:463 +#: erpnext/controllers/status_updater.py:482 msgid "target_ref_field" msgstr "" @@ -56550,7 +56829,7 @@ msgstr "" msgid "{0} '{1}' not in Fiscal Year {2}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:633 +#: erpnext/manufacturing/doctype/work_order/work_order.py:643 msgid "{0} ({1}) cannot be greater than planned quantity ({2}) in Work Order {3}" msgstr "" @@ -56586,7 +56865,7 @@ msgstr "" msgid "{0} Number {1} is already used in {2} {3}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1578 +#: erpnext/manufacturing/doctype/bom/bom.py:1629 msgid "{0} Operating Cost for operation {1}" msgstr "" @@ -56728,6 +57007,10 @@ msgstr "" msgid "{0} in row {1}" msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:448 +msgid "{0} is a child table and will be deleted automatically with its parent" +msgstr "" + #: erpnext/accounts/doctype/pos_profile/pos_profile.py:94 msgid "{0} is a mandatory Accounting Dimension.
Please set a value for {0} in Accounting Dimensions section." msgstr "" @@ -56738,7 +57021,7 @@ msgstr "" msgid "{0} is added multiple times on rows: {1}" msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:201 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:624 msgid "{0} is already running for {1}" msgstr "" @@ -56791,7 +57074,7 @@ msgstr "" msgid "{0} is not enabled in {1}" msgstr "" -#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:209 +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:632 msgid "{0} is not running. Cannot trigger events for this Document" msgstr "" @@ -56827,7 +57110,7 @@ msgstr "" msgid "{0} not allowed to transact with {1}. Please change the Company or add the Company in the 'Allowed To Transact With'-Section in the Customer record." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:522 +#: erpnext/manufacturing/doctype/bom/bom.py:573 msgid "{0} not found for item {1}" msgstr "" @@ -56843,7 +57126,7 @@ msgstr "" msgid "{0} qty of Item {1} is being received into Warehouse {2} with capacity {3}." msgstr "" -#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:719 +#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:722 msgid "{0} units are reserved for Item {1} in Warehouse {2}, please un-reserve the same to {3} the Stock Reconciliation." msgstr "" @@ -56896,7 +57179,7 @@ msgstr "" msgid "{0} will be set as the {1} in subsequently scanned items" msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:903 +#: erpnext/manufacturing/doctype/job_card/job_card.py:989 msgid "{0} {1}" msgstr "" @@ -56956,8 +57239,8 @@ msgstr "" msgid "{0} {1} is associated with {2}, but Party Account is {3}" msgstr "" -#: erpnext/controllers/selling_controller.py:526 -#: erpnext/controllers/subcontracting_controller.py:1159 +#: erpnext/controllers/selling_controller.py:494 +#: erpnext/controllers/subcontracting_controller.py:1167 msgid "{0} {1} is cancelled or closed" msgstr "" @@ -57094,11 +57377,27 @@ msgstr "" msgid "{0}'s {1} cannot be after {2}'s Expected End Date." msgstr "" -#: erpnext/manufacturing/doctype/job_card/job_card.py:1202 -#: erpnext/manufacturing/doctype/job_card/job_card.py:1210 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1288 +#: erpnext/manufacturing/doctype/job_card/job_card.py:1296 msgid "{0}, complete the operation {1} before the operation {2}." msgstr "" +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:519 +msgid "{0}: Child table (auto-deleted with parent)" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:514 +msgid "{0}: Not found" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:510 +msgid "{0}: Protected DocType" +msgstr "" + +#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:524 +msgid "{0}: Virtual DocType (no database table)" +msgstr "" + #: erpnext/controllers/accounts_controller.py:539 msgid "{0}: {1} does not belong to the Company: {2}" msgstr "" From abef9109b0caf67554d8cf999dc072cf9942101e Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Mon, 9 Feb 2026 10:11:48 +0530 Subject: [PATCH 41/63] revert: "fix: allow sales invoice to be renamed" This reverts commit 95fdbe55f9ecf1c894bf2f4d9121be34b2de8013. (cherry picked from commit 2660907ac8a16eba50489431da9455729b578ab7) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 4d0e0c73458..b668e13e36c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -1,7 +1,6 @@ { "actions": [], "allow_import": 1, - "allow_rename": 1, "autoname": "naming_series:", "creation": "2022-01-25 10:29:57.771398", "doctype": "DocType", @@ -2307,7 +2306,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2026-02-05 20:43:44.732805", + "modified": "2026-02-06 20:43:44.732805", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", From e2c12043aec418a4d629e955b4bfd03642fe3104 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Sat, 7 Feb 2026 11:16:35 +0530 Subject: [PATCH 42/63] fix(stock): ignore pos reserved batches for stock levels (cherry picked from commit 277ba9cb794b1a979a9b3a59208f56679c20faf3) --- .../serial_and_batch_bundle/serial_and_batch_bundle.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 7ac65775b23..a0c0755c7ca 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 @@ -2690,7 +2690,10 @@ def get_auto_batch_nos(kwargs): available_batches = get_available_batches(kwargs) stock_ledgers_batches = get_stock_ledgers_batches(kwargs) - pos_invoice_batches = get_reserved_batches_for_pos(kwargs) + + pos_invoice_batches = frappe._dict() + if not kwargs.for_stock_levels: + pos_invoice_batches = get_reserved_batches_for_pos(kwargs) sre_reserved_batches = frappe._dict() if not kwargs.ignore_reserved_stock: From 59f6012c57e75781e5cf93b1c90e14565800ae98 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Sat, 7 Feb 2026 11:18:06 +0530 Subject: [PATCH 43/63] test(stock): add test to ignore pos reserved batches for stock levels (cherry picked from commit 47ac67f7a23fdc0e2bc29409e4d49080cf2c3c32) --- erpnext/stock/doctype/batch/test_batch.py | 78 +++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index 6154a982c98..31d6cc1f241 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -123,6 +123,80 @@ class TestBatch(IntegrationTestCase): for d in batches: self.assertEqual(d.qty, batchwise_qty[(d.batch_no, d.warehouse)]) + def test_batch_qty_on_pos_creation(self): + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import ( + init_user_and_profile, + ) + from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice + from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry + from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( + get_auto_batch_nos, + ) + from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_batch_item_with_batch, + ) + + invoice_type = frappe.db.get_single_value("POS Settings", "invoice_type") + session_user = frappe.session.user + + try: + # Set invoice type to POS Invoice + frappe.db.set_single_value("POS Settings", "invoice_type", "POS Invoice") + + # Create batch item + create_batch_item_with_batch("_Test BATCH ITEM", "TestBatch-RS 02") + + # Create stock entry + se = make_stock_entry( + target="_Test Warehouse - _TC", + item_code="_Test BATCH ITEM", + qty=30, + basic_rate=100, + ) + + se.reload() + + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + # Create opening entry + session_user = frappe.session.user + test_user, pos_profile = init_user_and_profile() + create_opening_entry(pos_profile, test_user.name) + + # POS Invoice 1, for the batch without bundle + pos_inv1 = create_pos_invoice(item="_Test BATCH ITEM", rate=300, qty=15, do_not_save=1) + pos_inv1.append( + "payments", + {"mode_of_payment": "Cash", "amount": 4500}, + ) + pos_inv1.items[0].batch_no = batch_no + pos_inv1.save() + pos_inv1.submit() + pos_inv1.reload() + + # Get auto batch nos after pos invoice + batches = get_auto_batch_nos( + frappe._dict( + { + "item_code": "_Test BATCH ITEM", + "warehouse": "_Test Warehouse - _TC", + "for_stock_levels": True, + "ignore_reserved_stock": True, + } + ) + ) + + # Check batch qty after pos invoice + row = _find_batch_row(batches, batch_no, "_Test Warehouse - _TC") + self.assertIsNotNone(row) + self.assertEqual(row.qty, 30) + + finally: + # Set invoice type to Sales Invoice + frappe.db.set_single_value("POS Settings", "invoice_type", invoice_type) + # Set user to session user + frappe.set_user(session_user) + def test_stock_entry_incoming(self): """Test batch creation via Stock Entry (Work Order)""" @@ -610,6 +684,10 @@ def create_price_list_for_batch(item_code, batch, rate): ).insert() +def _find_batch_row(batches, batch_no, warehouse): + return next((b for b in batches if b.batch_no == batch_no and b.warehouse == warehouse), None) + + def make_new_batch(**args): args = frappe._dict(args) From cf7c127dc66d0d3ccab5038a7f7680a20e394d62 Mon Sep 17 00:00:00 2001 From: ravibharathi656 Date: Fri, 6 Feb 2026 15:48:46 +0530 Subject: [PATCH 44/63] fix(quotation): ignore zero ordered_qty (cherry picked from commit 32ea37035e36e0862fda165ebceb3b9331b9e861) --- erpnext/selling/doctype/quotation/quotation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index fd6f6ec812a..3db03a18513 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -621,6 +621,9 @@ def handle_mandatory_error(e, customer, lead_name): def get_ordered_items(quotation: str): return frappe._dict( frappe.get_all( - "Quotation Item", {"docstatus": 1, "parent": quotation}, ["name", "ordered_qty"], as_list=True + "Quotation Item", + {"docstatus": 1, "parent": quotation, "ordered_qty": (">", 0)}, + ["name", "ordered_qty"], + as_list=True, ) ) From b6afe7f4da2fe24ccd5c6178be9026cd756b70b5 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 9 Feb 2026 15:04:19 +0530 Subject: [PATCH 45/63] feat: allow negative stock for the batch item (cherry picked from commit 376ab0e34649d8d93fc9001dfb4f1f702b42476d) --- .../serial_and_batch_bundle/serial_and_batch_bundle.py | 3 +++ .../stock/doctype/stock_settings/stock_settings.json | 10 +++++++++- erpnext/stock/doctype/stock_settings/stock_settings.py | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) 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 7ac65775b23..2ce71333bd5 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 @@ -1462,6 +1462,9 @@ class SerialandBatchBundle(Document): def throw_negative_batch(self, batch_no, available_qty, precision): from erpnext.stock.stock_ledger import NegativeStockError + if frappe.db.get_single_value("Stock Settings", "allow_negative_stock_for_batch"): + return + frappe.throw( _( """ diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json index bc53daa2ec4..e3851b5b41f 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.json +++ b/erpnext/stock/doctype/stock_settings/stock_settings.json @@ -47,6 +47,7 @@ "disable_serial_no_and_batch_selector", "use_serial_batch_fields", "do_not_update_serial_batch_on_creation_of_auto_bundle", + "allow_negative_stock_for_batch", "serial_and_batch_bundle_section", "set_serial_and_batch_bundle_naming_based_on_naming_series", "section_break_gnhq", @@ -546,6 +547,13 @@ "fieldname": "validate_material_transfer_warehouses", "fieldtype": "Check", "label": "Validate Material Transfer Warehouses" + }, + { + "default": "0", + "description": "If enabled, the system will allow negative stock entries for the batch, but this could calculate the valuation rate incorrectly, so avoid using this option.", + "fieldname": "allow_negative_stock_for_batch", + "fieldtype": "Check", + "label": "Allow Negative Stock for Batch" } ], "hide_toolbar": 1, @@ -554,7 +562,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2026-01-02 18:19:59.034785", + "modified": "2026-02-09 15:01:12.466175", "modified_by": "Administrator", "module": "Stock", "name": "Stock Settings", diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py index a112cd089e2..2ab8c93bcb7 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/stock_settings.py @@ -30,6 +30,7 @@ class StockSettings(Document): allow_from_pr: DF.Check allow_internal_transfer_at_arms_length_price: DF.Check allow_negative_stock: DF.Check + allow_negative_stock_for_batch: DF.Check allow_partial_reservation: DF.Check allow_to_edit_stock_uom_qty_for_purchase: DF.Check allow_to_edit_stock_uom_qty_for_sales: DF.Check From 898d2e3c9a6e5502f11fff838257e90a5da1d227 Mon Sep 17 00:00:00 2001 From: Poojashree T R <159940572+22-poojashree@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:20:42 +0530 Subject: [PATCH 46/63] fix: validate asset movement transaction date (#52340) * fix: validate asset transaction date * fix: validate asset transaction date * fix: add translation in validate_transaction_date * test: test_movement_transaction_date * fix: to ensure test reliability (cherry picked from commit e98b68c38f303dda754b3139f247e3865a423a40) --- .../doctype/asset_movement/asset_movement.py | 15 +++++++- .../asset_movement/test_asset_movement.py | 38 ++++++++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index 25a06e463bb..c3248563440 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -5,7 +5,7 @@ import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import cstr, get_link_to_form +from frappe.utils import cstr, get_datetime, get_link_to_form from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity @@ -34,6 +34,7 @@ class AssetMovement(Document): for d in self.assets: self.validate_asset(d) self.validate_movement(d) + self.validate_transaction_date(d) def validate_asset(self, d): status, company = frappe.db.get_value("Asset", d.asset, ["status", "company"]) @@ -51,6 +52,18 @@ class AssetMovement(Document): else: self.validate_employee(d) + def validate_transaction_date(self, d): + previous_movement_date = frappe.db.get_value( + "Asset Movement", + [["Asset Movement Item", "asset", "=", d.asset], ["docstatus", "=", 1]], + "transaction_date", + order_by="transaction_date desc", + ) + if previous_movement_date and get_datetime(previous_movement_date) > get_datetime( + self.transaction_date + ): + frappe.throw(_("Transaction date can't be earlier than previous movement date")) + def validate_location_and_employee(self, d): self.validate_location(d) self.validate_employee(d) diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.py b/erpnext/assets/doctype/asset_movement/test_asset_movement.py index 620ea434e24..0cceb011a25 100644 --- a/erpnext/assets/doctype/asset_movement/test_asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.py @@ -4,9 +4,9 @@ import unittest import frappe from frappe.tests import IntegrationTestCase -from frappe.utils import now +from frappe.utils import add_days, now -from erpnext.assets.doctype.asset.test_asset import create_asset_data +from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data from erpnext.setup.doctype.employee.test_employee import make_employee from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt @@ -147,6 +147,33 @@ class TestAssetMovement(IntegrationTestCase): movement1.cancel() self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location") + def test_movement_transaction_date(self): + asset = create_asset(item_code="Macbook Pro", do_not_save=1) + asset.save().submit() + + if not frappe.db.exists("Location", "Test Location 2"): + frappe.get_doc({"doctype": "Location", "location_name": "Test Location 2"}).insert() + + asset_creation_date = frappe.db.get_value( + "Asset Movement", + [["Asset Movement Item", "asset", "=", asset.name], ["docstatus", "=", 1]], + "transaction_date", + ) + asset_movement = create_asset_movement( + purpose="Transfer", + company=asset.company, + assets=[ + { + "asset": asset.name, + "source_location": "Test Location", + "target_location": "Test Location 2", + } + ], + transaction_date=add_days(asset_creation_date, -1), + do_not_save=True, + ) + self.assertRaises(frappe.ValidationError, asset_movement.save) + def create_asset_movement(**args): args = frappe._dict(args) @@ -165,9 +192,10 @@ def create_asset_movement(**args): "reference_name": args.reference_name, } ) - - movement.insert() - movement.submit() + if not args.do_not_save: + movement.insert(ignore_if_duplicate=True) + if not args.do_not_submit: + movement.submit() return movement From 29d33b31394d4633205d80db4e1c4728cec64de1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 8 Jan 2026 15:23:40 +0530 Subject: [PATCH 47/63] fix: Workspace sidebar links for Debit/Credit Notes (cherry picked from commit 8acf373e68780476c172cf4943f329def36f4ef4) # Conflicts: # erpnext/workspace_sidebar/invoicing.json --- erpnext/workspace_sidebar/invoicing.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/workspace_sidebar/invoicing.json b/erpnext/workspace_sidebar/invoicing.json index 99a6b367953..0dd072deee4 100644 --- a/erpnext/workspace_sidebar/invoicing.json +++ b/erpnext/workspace_sidebar/invoicing.json @@ -314,7 +314,11 @@ "type": "Link" } ], +<<<<<<< HEAD:erpnext/workspace_sidebar/invoicing.json "modified": "2026-01-26 21:23:15.665712", +======= + "modified": "2026-01-08 15:04:31.767795", +>>>>>>> 8acf373e68 (fix: Workspace sidebar links for Debit/Credit Notes):erpnext/workspace_sidebar/accounting.json "modified_by": "Administrator", "module": "Accounts", "name": "Invoicing", From e9212c6a3255ae88686b6ebc384cfec1bd90bd4e Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Mon, 9 Feb 2026 21:03:37 +0530 Subject: [PATCH 48/63] chore: resolve conflicts --- erpnext/workspace_sidebar/invoicing.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/workspace_sidebar/invoicing.json b/erpnext/workspace_sidebar/invoicing.json index 0dd072deee4..9a80f8237a6 100644 --- a/erpnext/workspace_sidebar/invoicing.json +++ b/erpnext/workspace_sidebar/invoicing.json @@ -314,11 +314,7 @@ "type": "Link" } ], -<<<<<<< HEAD:erpnext/workspace_sidebar/invoicing.json - "modified": "2026-01-26 21:23:15.665712", -======= - "modified": "2026-01-08 15:04:31.767795", ->>>>>>> 8acf373e68 (fix: Workspace sidebar links for Debit/Credit Notes):erpnext/workspace_sidebar/accounting.json + "modified": "2026-01-27 21:23:15.665712", "modified_by": "Administrator", "module": "Accounts", "name": "Invoicing", From 53e512ceaf6fb81e0b9222f7d700070fea95917f Mon Sep 17 00:00:00 2001 From: Pandiyan37 Date: Sun, 8 Feb 2026 10:39:29 +0530 Subject: [PATCH 49/63] fix(stock): set source warehouse for issue type (cherry picked from commit a34e8c99cd053d5f469d99557bd5f5b9fc5358bf) --- erpnext/stock/doctype/material_request/material_request.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index b98870788a5..1868730ffd3 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -777,6 +777,9 @@ def make_stock_entry(source_name, target_doc=None): target.purpose = source.material_request_type target.from_warehouse = source.set_from_warehouse target.to_warehouse = source.set_warehouse + if source.material_request_type == "Material Issue": + target.from_warehouse = source.set_warehouse + target.to_warehouse = None if source.job_card: target.purpose = "Material Transfer for Manufacture" From 8c4a9040b729b2c5c3d121e10cd08b2b746d3ea0 Mon Sep 17 00:00:00 2001 From: Pandiyan37 Date: Mon, 9 Feb 2026 13:06:27 +0530 Subject: [PATCH 50/63] test(stock): add test to check from warehouse for issue type (cherry picked from commit da0322e994b069879b5e86c5601d06d73606ac11) --- .../material_request/test_material_request.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 24a30581188..d7a32b25b0d 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -1104,6 +1104,19 @@ class TestMaterialRequest(IntegrationTestCase): self.assertRaises(frappe.ValidationError, end_transit_2.submit) + def test_make_stock_entry_material_issue_warehouse_mapping(self): + """Test to ensure while making stock entry from material request of type Material Issue, warehouse is mapped correctly""" + mr = make_material_request(material_request_type="Material Issue", do_not_submit=True) + mr.set_warehouse = "_Test Warehouse - _TC" + mr.save() + mr.submit() + + se = make_stock_entry(mr.name) + self.assertEqual(se.from_warehouse, "_Test Warehouse - _TC") + self.assertIsNone(se.to_warehouse) + se.save() + se.submit() + def get_in_transit_warehouse(company): if not frappe.db.exists("Warehouse Type", "Transit"): From 801a26ae67f98d8ebc74d9dcf4019a555e7f5c45 Mon Sep 17 00:00:00 2001 From: Pandiyan37 Date: Mon, 9 Feb 2026 16:51:32 +0530 Subject: [PATCH 51/63] fix(stock): inward stock for pick list test record (cherry picked from commit f22b9e297b3ab1913cdf11d8ba9fd4bf18a3cc56) --- .../material_request/test_material_request.py | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index d7a32b25b0d..da5bfd270df 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -1017,15 +1017,27 @@ class TestMaterialRequest(IntegrationTestCase): import json from erpnext.stock.doctype.pick_list.pick_list import create_stock_entry + from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry - mr = make_material_request(material_request_type="Material Transfer") + new_item = create_item("_Test Pick List Item", is_stock_item=1) + item_code = new_item.name + + make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=10, + do_not_save=False, + do_not_submit=False, + ) + + mr = make_material_request(item_code=item_code, material_request_type="Material Transfer") pl = create_pick_list(mr.name) pl.save() pl.locations[0].qty = 5 pl.locations[0].stock_qty = 5 pl.submit() - to_warehouse = create_warehouse("Test To Warehouse") + to_warehouse = create_warehouse("_Test Warehouse - _TC") se_data = create_stock_entry(json.dumps(pl.as_dict())) se = frappe.get_doc(se_data) @@ -1044,6 +1056,15 @@ class TestMaterialRequest(IntegrationTestCase): def test_mr_pick_list_qty_validation(self): """Test for checking pick list qty validation from Material Request""" + from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + + make_stock_entry( + item_code="_Test Item", + target="_Test Warehouse - _TC", + qty=10, + do_not_save=False, + do_not_submit=False, + ) mr = make_material_request(material_request_type="Material Transfer") pl = create_pick_list(mr.name) From e753df8ff05c12f94017db4bb23b1bdd30369817 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:45:02 +0530 Subject: [PATCH 52/63] fix: email campaign timeout issue (backport #51994) (#52556) fix: email campaign timeout issue (#51994) * fix: email campaign timeout issue * refactor: email campaign backend logic * refactor: use sendmail instead of manually batching (cherry picked from commit 22123dd95521915ccb3cd95537498ea4115677ff) Co-authored-by: Pratik Badhe --- .../doctype/email_campaign/email_campaign.py | 167 +++++++++++++----- 1 file changed, 121 insertions(+), 46 deletions(-) diff --git a/erpnext/crm/doctype/email_campaign/email_campaign.py b/erpnext/crm/doctype/email_campaign/email_campaign.py index a5a2132dc0c..9e24a26caa8 100644 --- a/erpnext/crm/doctype/email_campaign/email_campaign.py +++ b/erpnext/crm/doctype/email_campaign/email_campaign.py @@ -38,18 +38,18 @@ class EmailCampaign(Document): def set_date(self): if getdate(self.start_date) < getdate(today()): frappe.throw(_("Start Date cannot be before the current date")) + # set the end date as start date + max(send after days) in campaign schedule - send_after_days = [] - campaign = frappe.get_doc("Campaign", self.campaign_name) - for entry in campaign.get("campaign_schedules"): - send_after_days.append(entry.send_after_days) - try: - self.end_date = add_days(getdate(self.start_date), max(send_after_days)) - except ValueError: + campaign = frappe.get_cached_doc("Campaign", self.campaign_name) + send_after_days = [entry.send_after_days for entry in campaign.get("campaign_schedules")] + + if not send_after_days: frappe.throw( _("Please set up the Campaign Schedule in the Campaign {0}").format(self.campaign_name) ) + self.end_date = add_days(getdate(self.start_date), max(send_after_days)) + def validate_lead(self): lead_email_id = frappe.db.get_value("Lead", self.recipient, "email_id") if not lead_email_id: @@ -77,58 +77,128 @@ class EmailCampaign(Document): start_date = getdate(self.start_date) end_date = getdate(self.end_date) today_date = getdate(today()) + if start_date > today_date: - self.db_set("status", "Scheduled", update_modified=False) + new_status = "Scheduled" elif end_date >= today_date: - self.db_set("status", "In Progress", update_modified=False) - elif end_date < today_date: - self.db_set("status", "Completed", update_modified=False) + new_status = "In Progress" + else: + new_status = "Completed" + + if self.status != new_status: + self.db_set("status", new_status, update_modified=False) # called through hooks to send campaign mails to leads def send_email_to_leads_or_contacts(): + today_date = getdate(today()) + + # Get all active email campaigns in a single query email_campaigns = frappe.get_all( - "Email Campaign", filters={"status": ("not in", ["Unsubscribed", "Completed", "Scheduled"])} + "Email Campaign", + filters={"status": "In Progress"}, + fields=["name", "campaign_name", "email_campaign_for", "recipient", "start_date", "sender"], ) - for camp in email_campaigns: - email_campaign = frappe.get_doc("Email Campaign", camp.name) - campaign = frappe.get_cached_doc("Campaign", email_campaign.campaign_name) + + if not email_campaigns: + return + + # Process each email campaign + for email_campaign in email_campaigns: + try: + campaign = frappe.get_cached_doc("Campaign", email_campaign.campaign_name) + except frappe.DoesNotExistError: + frappe.log_error( + title=_("Email Campaign Error"), + message=_("Campaign {0} not found").format(email_campaign.campaign_name), + ) + continue + + # Find schedules that match today for entry in campaign.get("campaign_schedules"): - scheduled_date = add_days(email_campaign.get("start_date"), entry.get("send_after_days")) - if scheduled_date == getdate(today()): - send_mail(entry, email_campaign) + try: + scheduled_date = add_days(getdate(email_campaign.start_date), entry.get("send_after_days")) + if scheduled_date == today_date: + send_mail(entry, email_campaign) + except Exception: + frappe.log_error( + title=_("Email Campaign Send Error"), + message=_("Failed to send email for campaign {0} to {1}").format( + email_campaign.name, email_campaign.recipient + ), + ) def send_mail(entry, email_campaign): - recipient_list = [] - if email_campaign.email_campaign_for == "Email Group": - for member in frappe.db.get_list( - "Email Group Member", filters={"email_group": email_campaign.get("recipient")}, fields=["email"] - ): - recipient_list.append(member["email"]) + campaign_for = email_campaign.get("email_campaign_for") + recipient = email_campaign.get("recipient") + sender_user = email_campaign.get("sender") + campaign_name = email_campaign.get("name") + + # Get recipient emails + if campaign_for == "Email Group": + recipient_list = frappe.get_all( + "Email Group Member", + filters={"email_group": recipient, "unsubscribed": 0}, + pluck="email", + ) else: - recipient_list.append( - frappe.db.get_value( - email_campaign.email_campaign_for, email_campaign.get("recipient"), "email_id" + email_id = frappe.db.get_value(campaign_for, recipient, "email_id") + if not email_id: + frappe.log_error( + title=_("Email Campaign Error"), + message=_("No email found for {0} {1}").format(campaign_for, recipient), ) + return + recipient_list = [email_id] + + if not recipient_list: + frappe.log_error( + title=_("Email Campaign Error"), + message=_("No recipients found for campaign {0}").format(campaign_name), + ) + return + + # Get email template and sender + email_template = frappe.get_cached_doc("Email Template", entry.get("email_template")) + sender = frappe.db.get_value("User", sender_user, "email") if sender_user else None + + # Build context for template rendering + if campaign_for != "Email Group": + context = {"doc": frappe.get_doc(campaign_for, recipient)} + else: + # For email groups, use the email group document as context + context = {"doc": frappe.get_doc("Email Group", recipient)} + + # Render template + subject = frappe.render_template(email_template.get("subject"), context) + content = frappe.render_template(email_template.response_, context) + + try: + comm = make( + doctype="Email Campaign", + name=campaign_name, + subject=subject, + content=content, + sender=sender, + recipients=recipient_list, + communication_medium="Email", + sent_or_received="Sent", + send_email=False, + email_template=email_template.name, ) - email_template = frappe.get_doc("Email Template", entry.get("email_template")) - sender = frappe.db.get_value("User", email_campaign.get("sender"), "email") - context = {"doc": frappe.get_doc(email_campaign.email_campaign_for, email_campaign.recipient)} - # send mail and link communication to document - comm = make( - doctype="Email Campaign", - name=email_campaign.name, - subject=frappe.render_template(email_template.get("subject"), context), - content=frappe.render_template(email_template.response_, context), - sender=sender, - bcc=recipient_list, - communication_medium="Email", - sent_or_received="Sent", - send_email=True, - email_template=email_template.name, - ) + frappe.sendmail( + recipients=recipient_list, + subject=subject, + content=content, + sender=sender, + communication=comm["name"], + queue_separately=True, + ) + except Exception: + frappe.log_error(title="Email Campaign Failed.") + return comm @@ -140,7 +210,12 @@ def unsubscribe_recipient(unsubscribe, method): # called through hooks to update email campaign status daily def set_email_campaign_status(): - email_campaigns = frappe.get_all("Email Campaign", filters={"status": ("!=", "Unsubscribed")}) - for entry in email_campaigns: - email_campaign = frappe.get_doc("Email Campaign", entry.name) + email_campaigns = frappe.get_all( + "Email Campaign", + filters={"status": ("!=", "Unsubscribed")}, + pluck="name", + ) + + for name in email_campaigns: + email_campaign = frappe.get_doc("Email Campaign", name) email_campaign.update_status() From dffb6ac4cf83d2d36b20f2ea6397da362940942b Mon Sep 17 00:00:00 2001 From: Trusted Computer <75872475+trustedcomputer@users.noreply.github.com> Date: Mon, 9 Feb 2026 10:26:57 -0800 Subject: [PATCH 53/63] fix: remove incorrect validation from email digest throwing spurious error (backport #51827) (#52579) --- erpnext/setup/doctype/email_digest/email_digest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 3777e330e75..7f087768fe7 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -162,8 +162,6 @@ class EmailDigest(Document): context.purchase_order_list, context.purchase_orders_items_overdue_list, ) = self.get_purchase_orders_items_overdue_list() - if not context.purchase_order_list: - frappe.throw(_("No items to be received are overdue")) if not context: return None From b8256e5f318ca8e30de71f97a959b78e7c4be990 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:26:00 +0530 Subject: [PATCH 54/63] fix(map_current_doc): prevent mutation of query args in get_query (backport #52202) (#52584) fix(map_current_doc): prevent mutation of query args in get_query (#52202) (cherry picked from commit 23a73c9cdba6e070278e4d73be047024aa806a4c) Co-authored-by: V Shankar --- erpnext/public/js/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 355dadbc534..08b745d2c32 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -989,7 +989,7 @@ erpnext.utils.map_current_doc = function (opts) { } if (query_args.filters || query_args.query) { - opts.get_query = () => query_args; + opts.get_query = () => JSON.parse(JSON.stringify(query_args)); } if (opts.source_doctype) { From ffd9b248f6644d8be983f90249b0e5386e9d06a5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:47:17 +0530 Subject: [PATCH 55/63] refactor: drop usages of db_query (backport #52559) (#52565) refactor: drop usages of db_query (cherry picked from commit 1e45195ef9de6534e02977cf14dc020000b32431) Signed-off-by: Akhil Narang Co-authored-by: Akhil Narang --- erpnext/stock/dashboard/item_dashboard.py | 4 ++-- erpnext/stock/dashboard/warehouse_capacity_dashboard.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py index 3d7c21639e0..d77ed7a6212 100644 --- a/erpnext/stock/dashboard/item_dashboard.py +++ b/erpnext/stock/dashboard/item_dashboard.py @@ -1,5 +1,5 @@ import frappe -from frappe.model.db_query import DatabaseQuery +from frappe.desk.reportview import build_match_conditions from frappe.utils import cint, flt from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( @@ -30,7 +30,7 @@ def get_data( filters.append(["item_code", "in", items]) try: # check if user has any restrictions based on user permissions on warehouse - if DatabaseQuery("Warehouse", user=frappe.session.user).build_match_conditions(): + if build_match_conditions("Warehouse", user=frappe.session.user): filters.append(["warehouse", "in", [w.name for w in frappe.get_list("Warehouse")]]) except frappe.PermissionError: # user does not have access on warehouse diff --git a/erpnext/stock/dashboard/warehouse_capacity_dashboard.py b/erpnext/stock/dashboard/warehouse_capacity_dashboard.py index 24e0ef11ffa..75b2951e30b 100644 --- a/erpnext/stock/dashboard/warehouse_capacity_dashboard.py +++ b/erpnext/stock/dashboard/warehouse_capacity_dashboard.py @@ -1,5 +1,5 @@ import frappe -from frappe.model.db_query import DatabaseQuery +from frappe.desk.reportview import build_match_conditions from frappe.utils import flt, nowdate from erpnext.stock.utils import get_stock_balance @@ -54,7 +54,7 @@ def get_filters(item_code=None, warehouse=None, parent_warehouse=None, company=N def get_warehouse_filter_based_on_permissions(filters): try: # check if user has any restrictions based on user permissions on warehouse - if DatabaseQuery("Warehouse", user=frappe.session.user).build_match_conditions(): + if build_match_conditions("Warehouse", user=frappe.session.user): filters.append(["warehouse", "in", [w.name for w in frappe.get_list("Warehouse")]]) return False, filters except frappe.PermissionError: From 1c3fe000ba534a910851151667379ee8ccf5c365 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 21:01:04 +0000 Subject: [PATCH 56/63] fix: Added a missing option to the currency field (backport #52528) (#52587) fix: Added a missing option to the currency field (#52528) (cherry picked from commit da07f84e4474a9873e2bcb4f8ce8bc97eb2d3b5d) Co-authored-by: El-Shafei H. --- .../advance_payment_ledger_entry.json | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.json b/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.json index 444a45ff8c1..1bf909117a8 100644 --- a/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.json +++ b/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.json @@ -50,6 +50,7 @@ "fieldname": "amount", "fieldtype": "Currency", "label": "Amount", + "options": "currency", "read_only": 1 }, { From 9b32c84462327fb0e6621e1d518a3897f77c6058 Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Fri, 23 Jan 2026 12:40:38 +0530 Subject: [PATCH 57/63] fix(gross-profit): handle returns outside sale period (cherry picked from commit 67d8223f73b7d744f5005c2c80adb51d8a86c5b2) --- .../report/gross_profit/gross_profit.py | 253 ++++++++++-------- 1 file changed, 148 insertions(+), 105 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index d2fe570fa3b..1df871f5d0e 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -5,15 +5,16 @@ from collections import OrderedDict import frappe from frappe import _, qb, scrub -from frappe.query_builder import Order +from frappe.query_builder import Case, Order +from frappe.query_builder.functions import Coalesce from frappe.utils import cint, flt, formatdate +from pypika.terms import ExistsCriterion from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_accounting_dimensions, get_dimension_with_children, ) from erpnext.accounts.report.financial_statements import get_cost_centers_with_children -from erpnext.controllers.queries import get_match_cond from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition from erpnext.stock.utils import get_incoming_rate @@ -851,129 +852,171 @@ class GrossProfitGenerator: return flt(last_purchase_rate[0][0]) if last_purchase_rate else 0 def load_invoice_items(self): - conditions = "" - if self.filters.company: - conditions += " and `tabSales Invoice`.company = %(company)s" - if self.filters.from_date: - conditions += " and posting_date >= %(from_date)s" - if self.filters.to_date: - conditions += " and posting_date <= %(to_date)s" + self.si_list = [] + + SalesInvoice = frappe.qb.DocType("Sales Invoice") + base_query = self.prepare_invoice_query() if self.filters.include_returned_invoices: - conditions += " and (is_return = 0 or (is_return=1 and return_against is null))" + invoice_query = base_query.where( + (SalesInvoice.is_return == 0) + | ((SalesInvoice.is_return == 1) & SalesInvoice.return_against.isnull()) + ) else: - conditions += " and is_return = 0" + invoice_query = base_query.where(SalesInvoice.is_return == 0) - if self.filters.item_group: - conditions += f" and {get_item_group_condition(self.filters.item_group)}" + self.si_list += invoice_query.run(as_dict=True) + self.prepare_vouchers_to_ignore() - if self.filters.sales_person: - conditions += """ - and exists(select 1 - from `tabSales Team` st - where st.parent = `tabSales Invoice`.name - and st.sales_person = %(sales_person)s) - """ + ret_invoice_query = base_query.where( + (SalesInvoice.is_return == 1) & SalesInvoice.return_against.isnotnull() + ) + if self.vouchers_to_ignore: + ret_invoice_query = base_query.where(SalesInvoice.return_against.notin(self.vouchers_to_ignore)) + + self.si_list += ret_invoice_query.run(as_dict=True) + + def prepare_invoice_query(self): + SalesInvoice = frappe.qb.DocType("Sales Invoice") + SalesInvoiceItem = frappe.qb.DocType("Sales Invoice Item") + Item = frappe.qb.DocType("Item") + SalesTeam = frappe.qb.DocType("Sales Team") + PaymentSchedule = frappe.qb.DocType("Payment Schedule") + + query = ( + frappe.qb.from_(SalesInvoice) + .join(SalesInvoiceItem) + .on(SalesInvoiceItem.parent == SalesInvoice.name) + .join(Item) + .on(Item.name == SalesInvoiceItem.item_code) + .where((SalesInvoice.docstatus == 1) & (SalesInvoice.is_opening != "Yes")) + ) + + query = self.apply_common_filters(query, SalesInvoice, SalesInvoiceItem, SalesTeam) + + query = query.select( + SalesInvoiceItem.parenttype, + SalesInvoiceItem.parent, + SalesInvoice.posting_date, + SalesInvoice.posting_time, + SalesInvoice.project, + SalesInvoice.update_stock, + SalesInvoice.customer, + SalesInvoice.customer_group, + SalesInvoice.customer_name, + SalesInvoice.territory, + SalesInvoiceItem.item_code, + SalesInvoice.base_net_total.as_("invoice_base_net_total"), + SalesInvoiceItem.item_name, + SalesInvoiceItem.description, + SalesInvoiceItem.warehouse, + SalesInvoiceItem.item_group, + SalesInvoiceItem.brand, + SalesInvoiceItem.so_detail, + SalesInvoiceItem.sales_order, + SalesInvoiceItem.dn_detail, + SalesInvoiceItem.delivery_note, + SalesInvoiceItem.stock_qty.as_("qty"), + SalesInvoiceItem.base_net_rate, + SalesInvoiceItem.base_net_amount, + SalesInvoiceItem.name.as_("item_row"), + SalesInvoice.is_return, + SalesInvoiceItem.cost_center, + SalesInvoiceItem.serial_and_batch_bundle, + ) if self.filters.group_by == "Sales Person": - sales_person_cols = """, sales.sales_person, - sales.allocated_percentage * `tabSales Invoice Item`.base_net_amount / 100 as allocated_amount, - sales.incentives - """ - sales_team_table = "left join `tabSales Team` sales on sales.parent = `tabSales Invoice`.name" - else: - sales_person_cols = "" - sales_team_table = "" + query = query.select( + SalesTeam.sales_person, + (SalesTeam.allocated_percentage * SalesInvoiceItem.base_net_amount / 100).as_( + "allocated_amount" + ), + SalesTeam.incentives, + ) + + query = query.left_join(SalesTeam).on(SalesTeam.parent == SalesInvoice.name) if self.filters.group_by == "Payment Term": - payment_term_cols = """,if(`tabSales Invoice`.is_return = 1, - '{}', - coalesce(schedule.payment_term, '{}')) as payment_term, - schedule.invoice_portion, - schedule.payment_amount """.format(_("Sales Return"), _("No Terms")) - payment_term_table = """ left join `tabPayment Schedule` schedule on schedule.parent = `tabSales Invoice`.name and - `tabSales Invoice`.is_return = 0 """ - else: - payment_term_cols = "" - payment_term_table = "" + query = query.select( + Case() + .when(SalesInvoice.is_return == 1, _("Sales Return")) + .else_(Coalesce(PaymentSchedule.payment_term, _("No Terms"))) + .as_("payment_term"), + PaymentSchedule.invoice_portion, + PaymentSchedule.payment_amount, + ) - if self.filters.get("sales_invoice"): - conditions += " and `tabSales Invoice`.name = %(sales_invoice)s" + query = query.left_join(PaymentSchedule).on( + (PaymentSchedule.parent == SalesInvoice.name) & (SalesInvoice.is_return == 0) + ) - if self.filters.get("item_code"): - conditions += " and `tabSales Invoice Item`.item_code = %(item_code)s" + query = query.orderby(SalesInvoice.posting_date, order=Order.desc).orderby( + SalesInvoice.posting_time, order=Order.desc + ) - if self.filters.get("cost_center"): + return query + + def apply_common_filters(self, query, SalesInvoice, SalesInvoiceItem, SalesTeam): + if self.filters.company: + query = query.where(SalesInvoice.company == self.filters.company) + + if self.filters.from_date: + query = query.where(SalesInvoice.posting_date >= self.filters.from_date) + + if self.filters.to_date: + query = query.where(SalesInvoice.posting_date <= self.filters.to_date) + + if self.filters.item_group: + query = query.where(get_item_group_condition(self.filters.item_group)) + + if self.filters.sales_person: + query = query.where( + ExistsCriterion( + frappe.qb.from_(SalesTeam) + .select(1) + .where( + (SalesTeam.parent == SalesInvoice.name) + & (SalesTeam.sales_person == self.filters.sales_person) + ) + ) + ) + + if self.filters.sales_invoice: + query = query.where(SalesInvoice.name == self.filters.sales_invoice) + + if self.filters.item_code: + query = query.where(SalesInvoiceItem.item_code == self.filters.item_code) + + if self.filters.cost_center: self.filters.cost_center = frappe.parse_json(self.filters.get("cost_center")) self.filters.cost_center = get_cost_centers_with_children(self.filters.cost_center) - conditions += " and `tabSales Invoice Item`.cost_center in %(cost_center)s" + query = query.where(SalesInvoiceItem.cost_center.isin(self.filters.cost_center)) - if self.filters.get("project"): + if self.filters.project: self.filters.project = frappe.parse_json(self.filters.get("project")) - conditions += " and `tabSales Invoice Item`.project in %(project)s" + query = query.where(SalesInvoiceItem.project.isin(self.filters.project)) - accounting_dimensions = get_accounting_dimensions(as_list=False) - if accounting_dimensions: - for dimension in accounting_dimensions: - if self.filters.get(dimension.fieldname): - if frappe.get_cached_value("DocType", dimension.document_type, "is_tree"): - self.filters[dimension.fieldname] = get_dimension_with_children( - dimension.document_type, self.filters.get(dimension.fieldname) - ) - conditions += ( - f" and `tabSales Invoice Item`.{dimension.fieldname} in %({dimension.fieldname})s" - ) - else: - conditions += ( - f" and `tabSales Invoice Item`.{dimension.fieldname} in %({dimension.fieldname})s" - ) + for dim in get_accounting_dimensions(as_list=False) or []: + if self.filters.get(dim.fieldname): + if frappe.get_cached_value("DocType", dim.document_type, "is_tree"): + self.filters[dim.fieldname] = get_dimension_with_children( + dim.document_type, self.filters.get(dim.fieldname) + ) + query = query.where(SalesInvoiceItem[dim.fieldname].isin(self.filters[dim.fieldname])) - if self.filters.get("warehouse"): - warehouse_details = frappe.db.get_value( - "Warehouse", self.filters.get("warehouse"), ["lft", "rgt"], as_dict=1 + if self.filters.warehouse: + lft, rgt = frappe.db.get_value("Warehouse", self.filters.warehouse, ["lft", "rgt"]) + WH = frappe.qb.DocType("Warehouse") + query = query.where( + SalesInvoiceItem.warehouse.isin( + frappe.qb.from_(WH).select(WH.name).where((WH.lft >= lft) & (WH.rgt <= rgt)) + ) ) - if warehouse_details: - conditions += f" and `tabSales Invoice Item`.warehouse in (select name from `tabWarehouse` wh where wh.lft >= {warehouse_details.lft} and wh.rgt <= {warehouse_details.rgt} and warehouse = wh.name)" - self.si_list = frappe.db.sql( - """ - select - `tabSales Invoice Item`.parenttype, `tabSales Invoice Item`.parent, - `tabSales Invoice`.posting_date, `tabSales Invoice`.posting_time, - `tabSales Invoice`.project, `tabSales Invoice`.update_stock, - `tabSales Invoice`.customer, `tabSales Invoice`.customer_group, `tabSales Invoice`.customer_name, - `tabSales Invoice`.territory, `tabSales Invoice Item`.item_code, - `tabSales Invoice`.base_net_total as "invoice_base_net_total", - `tabSales Invoice Item`.item_name, `tabSales Invoice Item`.description, - `tabSales Invoice Item`.warehouse, `tabSales Invoice Item`.item_group, - `tabSales Invoice Item`.brand, `tabSales Invoice Item`.so_detail, - `tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.dn_detail, - `tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.stock_qty as qty, - `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, - `tabSales Invoice Item`.name as "item_row", `tabSales Invoice`.is_return, - `tabSales Invoice Item`.cost_center, `tabSales Invoice Item`.serial_and_batch_bundle - {sales_person_cols} - {payment_term_cols} - from - `tabSales Invoice` inner join `tabSales Invoice Item` - on `tabSales Invoice Item`.parent = `tabSales Invoice`.name - join `tabItem` item on item.name = `tabSales Invoice Item`.item_code - {sales_team_table} - {payment_term_table} - where - `tabSales Invoice`.docstatus=1 and `tabSales Invoice`.is_opening!='Yes' {conditions} {match_cond} - order by - `tabSales Invoice`.posting_date desc, `tabSales Invoice`.posting_time desc""".format( - conditions=conditions, - sales_person_cols=sales_person_cols, - sales_team_table=sales_team_table, - payment_term_cols=payment_term_cols, - payment_term_table=payment_term_table, - match_cond=get_match_cond("Sales Invoice"), - ), - self.filters, - as_dict=1, - ) + return query + + def prepare_vouchers_to_ignore(self): + self.vouchers_to_ignore = tuple(row["parent"] for row in self.si_list) def get_delivery_notes(self): self.delivery_notes = frappe._dict({}) From d081a26608c003be23f22313a816015031867c0f Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Sat, 24 Jan 2026 01:25:18 +0530 Subject: [PATCH 58/63] fix: handle gross profit and percentage for return invoices (cherry picked from commit 51709f032fc5ec84e2fd74f8ca981351b36a4ed8) --- .../report/gross_profit/gross_profit.py | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 1df871f5d0e..0638ea3b4c1 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -204,7 +204,11 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_ data.append(row) - total_gross_profit = total_base_amount - total_buying_amount + total_gross_profit = flt( + total_base_amount + abs(total_buying_amount) + if total_buying_amount < 0 + else total_base_amount - total_buying_amount, + ) data.append( frappe._dict( { @@ -216,7 +220,7 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_ "buying_amount": total_buying_amount, "gross_profit": total_gross_profit, "gross_profit_%": flt( - (total_gross_profit / total_base_amount) * 100.0, + (total_gross_profit / abs(total_base_amount)) * 100.0, cint(frappe.db.get_default("currency_precision")) or 3, ) if total_base_amount @@ -249,9 +253,13 @@ def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_ data.append(row) - total_gross_profit = total_base_amount - total_buying_amount + total_gross_profit = flt( + total_base_amount + abs(total_buying_amount) + if total_buying_amount < 0 + else total_base_amount - total_buying_amount, + ) currency_precision = cint(frappe.db.get_default("currency_precision")) or 3 - gross_profit_percent = (total_gross_profit / total_base_amount * 100.0) if total_base_amount else 0 + gross_profit_percent = (total_gross_profit / abs(total_base_amount) * 100.0) if total_base_amount else 0 total_row = { group_columns[0]: "Total", @@ -582,10 +590,15 @@ class GrossProfitGenerator: base_amount += row.base_amount # calculate gross profit - row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision) + row.gross_profit = flt( + row.base_amount + abs(row.buying_amount) + if row.buying_amount < 0 + else row.base_amount - row.buying_amount, + self.currency_precision, + ) if row.base_amount: row.gross_profit_percent = flt( - (row.gross_profit / row.base_amount) * 100.0, + (row.gross_profit / abs(row.base_amount)) * 100.0, self.currency_precision, ) else: @@ -674,9 +687,14 @@ class GrossProfitGenerator: return new_row def set_average_gross_profit(self, new_row): - new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision) + new_row.gross_profit = flt( + new_row.base_amount + abs(new_row.buying_amount) + if new_row.buying_amount < 0 + else new_row.base_amount - new_row.buying_amount, + self.currency_precision, + ) new_row.gross_profit_percent = ( - flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) + flt(((new_row.gross_profit / abs(new_row.base_amount)) * 100.0), self.currency_precision) if new_row.base_amount else 0 ) From e8eaae4120265dd1f2b55462ea3cd047c6ad1001 Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Sat, 24 Jan 2026 01:43:05 +0530 Subject: [PATCH 59/63] test: validate return invoice profit and profit percentage (cherry picked from commit 4da3d430132fbd64ab6f2696f6006859e2afa496) --- .../report/gross_profit/test_gross_profit.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index 116cdca4d6c..4b22617607d 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -470,7 +470,7 @@ class TestGrossProfit(IntegrationTestCase): "selling_amount": -100.0, "buying_amount": 0.0, "gross_profit": -100.0, - "gross_profit_%": 100.0, + "gross_profit_%": -100.0, } gp_entry = [x for x in data if x.parent_invoice == sinv.name] report_output = {k: v for k, v in gp_entry[0].items() if k in expected_entry} @@ -649,21 +649,24 @@ class TestGrossProfit(IntegrationTestCase): def test_profit_for_later_period_return(self): month_start_date, month_end_date = get_first_day(nowdate()), get_last_day(nowdate()) + sales_inv_date = month_start_date + return_inv_date = add_days(month_end_date, 1) + # create sales invoice on month start date sinv = self.create_sales_invoice(qty=1, rate=100, do_not_save=True, do_not_submit=True) sinv.set_posting_time = 1 - sinv.posting_date = month_start_date + sinv.posting_date = sales_inv_date sinv.save().submit() # create credit note on next month start date cr_note = make_sales_return(sinv.name) cr_note.set_posting_time = 1 - cr_note.posting_date = add_days(month_end_date, 1) + cr_note.posting_date = return_inv_date cr_note.save().submit() # apply filters for invoiced period filters = frappe._dict( - company=self.company, from_date=month_start_date, to_date=month_end_date, group_by="Invoice" + company=self.company, from_date=month_start_date, to_date=month_start_date, group_by="Invoice" ) _, data = execute(filters=filters) @@ -675,7 +678,7 @@ class TestGrossProfit(IntegrationTestCase): self.assertEqual(total.get("gross_profit_%"), 100.0) # extend filters upto returned period - filters.update(to_date=add_days(month_end_date, 1)) + filters.update({"to_date": return_inv_date}) _, data = execute(filters=filters) total = data[-1] @@ -684,3 +687,13 @@ class TestGrossProfit(IntegrationTestCase): self.assertEqual(total.buying_amount, 0.0) self.assertEqual(total.gross_profit, 0.0) self.assertEqual(total.get("gross_profit_%"), 0.0) + + # apply filters only on returned period + filters.update({"from_date": return_inv_date, "to_date": return_inv_date}) + _, data = execute(filters=filters) + total = data[-1] + + self.assertEqual(total.selling_amount, -100.0) + self.assertEqual(total.buying_amount, 0.0) + self.assertEqual(total.gross_profit, -100.0) + self.assertEqual(total.get("gross_profit_%"), -100.0) From 345d25bdf1c33a8ad45a372c474ee2f3e645f747 Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Thu, 29 Jan 2026 00:50:32 +0530 Subject: [PATCH 60/63] test: validate sales person wise gross profit (cherry picked from commit 3ab978ab469f01934c888aa197db24075fd3ed96) --- .../report/gross_profit/test_gross_profit.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index 4b22617607d..cb4b3306137 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -697,3 +697,53 @@ class TestGrossProfit(IntegrationTestCase): self.assertEqual(total.buying_amount, 0.0) self.assertEqual(total.gross_profit, -100.0) self.assertEqual(total.get("gross_profit_%"), -100.0) + + def test_sales_person_wise_gross_profit(self): + sales_person = make_sales_person("_Test Sales Person") + + posting_date = get_first_day(nowdate()) + qty = 10 + rate = 100 + + sinv = self.create_sales_invoice(qty=qty, rate=rate, do_not_save=True, do_not_submit=True) + sinv.set_posting_time = 1 + sinv.posting_date = posting_date + sinv.append( + "sales_team", + { + "sales_person": sales_person.name, + "allocated_percentage": 100, + "allocated_amount": 1000.0, + "commission_rate": 5, + "incentives": 5, + }, + ) + sinv.save().submit() + + filters = frappe._dict( + company=self.company, from_date=posting_date, to_date=posting_date, group_by="Sales Person" + ) + + _, data = execute(filters=filters) + total = data[-1] + + self.assertEqual(total.selling_amount, 1000.0) + self.assertEqual(total.buying_amount, 0.0) + self.assertEqual(total.gross_profit, 1000.0) + self.assertEqual(total.get("gross_profit_%"), 100.0) + + +def make_sales_person(sales_person_name="_Test Sales Person"): + if not frappe.db.exists("Sales Person", {"sales_person_name": sales_person_name}): + sales_person_doc = frappe.get_doc( + { + "doctype": "Sales Person", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": sales_person_name, + } + ).insert(ignore_permissions=True) + else: + sales_person_doc = frappe.get_doc("Sales Person", {"sales_person_name": sales_person_name}) + + return sales_person_doc From d01ea27f2fb31442666a3fcd97b19b135afab80b Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Thu, 29 Jan 2026 17:55:13 +0530 Subject: [PATCH 61/63] test: fix test assertions to use index-based totals (cherry picked from commit fdfa7bc9635f5ecbef95c83d2499185a9816399d) --- erpnext/accounts/report/gross_profit/test_gross_profit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index cb4b3306137..159c1086018 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -727,10 +727,10 @@ class TestGrossProfit(IntegrationTestCase): _, data = execute(filters=filters) total = data[-1] - self.assertEqual(total.selling_amount, 1000.0) - self.assertEqual(total.buying_amount, 0.0) - self.assertEqual(total.gross_profit, 1000.0) - self.assertEqual(total.get("gross_profit_%"), 100.0) + self.assertEqual(total[5], 1000.0) + self.assertEqual(total[6], 0.0) + self.assertEqual(total[7], 1000.0) + self.assertEqual(total[8], 100.0) def make_sales_person(sales_person_name="_Test Sales Person"): From 0d02bbb01af0c392374b82ff41a0157f53a0a715 Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Tue, 10 Feb 2026 11:47:35 +0530 Subject: [PATCH 62/63] fix(gross-profit): handle item group filters (cherry picked from commit 047b2787915e42d7ccdbb863c2f5909f5c01f157) --- erpnext/accounts/report/gross_profit/gross_profit.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 0638ea3b4c1..9adf75945e0 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -890,7 +890,9 @@ class GrossProfitGenerator: (SalesInvoice.is_return == 1) & SalesInvoice.return_against.isnotnull() ) if self.vouchers_to_ignore: - ret_invoice_query = base_query.where(SalesInvoice.return_against.notin(self.vouchers_to_ignore)) + ret_invoice_query = ret_invoice_query.where( + SalesInvoice.return_against.notin(self.vouchers_to_ignore) + ) self.si_list += ret_invoice_query.run(as_dict=True) @@ -910,7 +912,7 @@ class GrossProfitGenerator: .where((SalesInvoice.docstatus == 1) & (SalesInvoice.is_opening != "Yes")) ) - query = self.apply_common_filters(query, SalesInvoice, SalesInvoiceItem, SalesTeam) + query = self.apply_common_filters(query, SalesInvoice, SalesInvoiceItem, SalesTeam, Item) query = query.select( SalesInvoiceItem.parenttype, @@ -974,7 +976,7 @@ class GrossProfitGenerator: return query - def apply_common_filters(self, query, SalesInvoice, SalesInvoiceItem, SalesTeam): + def apply_common_filters(self, query, SalesInvoice, SalesInvoiceItem, SalesTeam, Item): if self.filters.company: query = query.where(SalesInvoice.company == self.filters.company) @@ -985,7 +987,7 @@ class GrossProfitGenerator: query = query.where(SalesInvoice.posting_date <= self.filters.to_date) if self.filters.item_group: - query = query.where(get_item_group_condition(self.filters.item_group)) + query = query.where(get_item_group_condition(self.filters.item_group, Item)) if self.filters.sales_person: query = query.where( From ac7a25fff96998218f139af97d26a84fc60b49e5 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 10 Feb 2026 12:54:46 +0530 Subject: [PATCH 63/63] refactor: update labels for tax withholding reports columns to improve clarity (cherry picked from commit 2cfdcc1af47d32173608bb1afa2c55610ebeb9b3) --- .../tax_withholding_details.py | 18 +++++++++--------- .../tds_computation_summary.py | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index e485dac114b..ed4a223311b 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -154,17 +154,11 @@ def get_columns(filters): "width": 60, }, { - "label": _("Total Amount"), + "label": _("Taxable Amount"), "fieldname": "total_amount", "fieldtype": "Currency", "width": 120, }, - { - "label": _("Base Total"), - "fieldname": "base_total", - "fieldtype": "Currency", - "width": 120, - }, { "label": _("Tax Amount"), "fieldname": "tax_amount", @@ -172,10 +166,16 @@ def get_columns(filters): "width": 120, }, { - "label": _("Grand Total"), + "label": _("Grand Total (Company Currency)"), + "fieldname": "base_total", + "fieldtype": "Currency", + "width": 150, + }, + { + "label": _("Grand Total (Transaction Currency)"), "fieldname": "grand_total", "fieldtype": "Currency", - "width": 120, + "width": 170, }, { "label": _("Reference Date"), diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index 49bf556da66..59296602b3d 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -106,7 +106,7 @@ def get_columns(filters): "width": 120, }, { - "label": _("Total Amount"), + "label": _("Total Taxable Amount"), "fieldname": "total_amount", "fieldtype": "Float", "width": 120,