From abb88662c1ac89dccc42aa3ff3d9825c062a3fa3 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:21:48 +0530 Subject: [PATCH 01/28] fix: set up filters for dimensions (cherry picked from commit 2fd8de2f76212921aae604a8bdd21e6ae9c120fb) --- .../doctype/asset_capitalization/asset_capitalization.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js index 651b75d0a70..f6f593b93bf 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js @@ -11,6 +11,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s onload() { this.setup_queries(); + erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype); } refresh() { @@ -75,6 +76,14 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s }; }); + me.frm.set_query("cost_canter", function () { + return { + filters: { + company: me.frm.doc.company, + } + }; + }); + me.frm.set_query("item_code", "stock_items", function () { return erpnext.queries.item({ is_stock_item: 1 }); }); From b84ca04975f5daf691c04870409d3c24dc1cc9d2 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:26:47 +0530 Subject: [PATCH 02/28] fix: removed extra filter condition (cherry picked from commit 6fa29376a0b95029aa35ec10fd4cce915c8c6832) --- .../doctype/asset_capitalization/asset_capitalization.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js index f6f593b93bf..4e64a11ba9e 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js @@ -76,13 +76,6 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s }; }); - me.frm.set_query("cost_canter", function () { - return { - filters: { - company: me.frm.doc.company, - } - }; - }); me.frm.set_query("item_code", "stock_items", function () { return erpnext.queries.item({ is_stock_item: 1 }); From ecf0d0b3888854027bd2d7079e93a34c1b02e8f5 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:31:56 +0530 Subject: [PATCH 03/28] chore: linters check (cherry picked from commit 0d427933974c67a966edb4ba4aba0a422c49088a) --- .../assets/doctype/asset_capitalization/asset_capitalization.js | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js index 4e64a11ba9e..d9f2231b313 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js @@ -76,7 +76,6 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s }; }); - me.frm.set_query("item_code", "stock_items", function () { return erpnext.queries.item({ is_stock_item: 1 }); }); From 40abd82e2dd8308a686484b77deec714cea0d05a Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:11:50 +0530 Subject: [PATCH 04/28] fix: disable rename from warehouse (cherry picked from commit c1812f74e8b4b4efe43e195d312064204d976732) # Conflicts: # erpnext/stock/doctype/warehouse/warehouse.json --- erpnext/stock/doctype/warehouse/warehouse.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json index 7b0cade3ca4..d9f591ac3f8 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.json +++ b/erpnext/stock/doctype/warehouse/warehouse.json @@ -263,7 +263,11 @@ "idx": 1, "is_tree": 1, "links": [], +<<<<<<< HEAD "modified": "2024-01-24 16:27:28.299520", +======= + "modified": "2024-08-14 16:08:15.733597", +>>>>>>> c1812f74e8 (fix: disable rename from warehouse) "modified_by": "Administrator", "module": "Stock", "name": "Warehouse", @@ -320,6 +324,5 @@ "sort_field": "modified", "sort_order": "DESC", "states": [], - "title_field": "warehouse_name", "track_changes": 1 -} \ No newline at end of file +} From 3a1ad6e844e00f6ef12e56404c2efe1575add24b Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:37:36 +0530 Subject: [PATCH 05/28] fix: disable rename from warehouse --- erpnext/stock/doctype/warehouse/warehouse.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json index d9f591ac3f8..f2d157b0ae4 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.json +++ b/erpnext/stock/doctype/warehouse/warehouse.json @@ -263,11 +263,7 @@ "idx": 1, "is_tree": 1, "links": [], -<<<<<<< HEAD - "modified": "2024-01-24 16:27:28.299520", -======= "modified": "2024-08-14 16:08:15.733597", ->>>>>>> c1812f74e8 (fix: disable rename from warehouse) "modified_by": "Administrator", "module": "Stock", "name": "Warehouse", From aba54ba18feadade01f9ff9d2150259c15bfc13e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:03:01 +0530 Subject: [PATCH 06/28] fix: ignore pricing rule while making DN from Pick List (backport #42763) (#42768) fix: ignore pricing rule while making DN from Pick List (#42763) (cherry picked from commit 0db82ec93a5c6bc9da9bd72188a90f7dd6c8e3ce) Co-authored-by: rohitwaghchaure --- .../doctype/sales_order/sales_order.py | 4 ++ .../stock/doctype/pick_list/pick_list.json | 10 ++- erpnext/stock/doctype/pick_list/pick_list.py | 3 +- .../stock/doctype/pick_list/test_pick_list.py | 61 +++++++++++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 38a089fdb03..570677aad78 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -936,6 +936,10 @@ def make_delivery_note(source_name, target_doc=None, kwargs=None): } def set_missing_values(source, target): + if kwargs.get("ignore_pricing_rule"): + # Skip pricing rule when the dn is creating from the pick list + target.ignore_pricing_rule = 1 + target.run_method("set_missing_values") target.run_method("set_po_nos") target.run_method("calculate_taxes_and_totals") diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json index 0e466e44d1b..a5a46ff9187 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.json +++ b/erpnext/stock/doctype/pick_list/pick_list.json @@ -19,6 +19,7 @@ "consider_rejected_warehouses", "get_item_locations", "pick_manually", + "ignore_pricing_rule", "section_break_6", "scan_barcode", "column_break_13", @@ -200,11 +201,18 @@ "fieldname": "pick_manually", "fieldtype": "Check", "label": "Pick Manually" + }, + { + "default": "0", + "description": "If enabled then system won't apply the pricing rule on the delivery note which will be create from the pick list", + "fieldname": "ignore_pricing_rule", + "fieldtype": "Check", + "label": "Ignore Pricing Rule" } ], "is_submittable": 1, "links": [], - "modified": "2024-03-27 22:49:16.954637", + "modified": "2024-08-14 13:20:42.168827", "modified_by": "Administrator", "module": "Stock", "name": "Pick List", diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 8d7022c3581..0c93fd6c402 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -50,6 +50,7 @@ class PickList(Document): customer_name: DF.Data | None for_qty: DF.Float group_same_items: DF.Check + ignore_pricing_rule: DF.Check locations: DF.Table[PickListItem] material_request: DF.Link | None naming_series: DF.Literal["STO-PICK-.YYYY.-"] @@ -1144,7 +1145,7 @@ def create_dn_with_so(sales_dict, pick_list): for customer in sales_dict: for so in sales_dict[customer]: delivery_note = None - kwargs = {"skip_item_mapping": True} + kwargs = {"skip_item_mapping": True, "ignore_pricing_rule": pick_list.ignore_pricing_rule} delivery_note = create_delivery_note_from_sales_order(so, delivery_note, kwargs=kwargs) break if delivery_note: diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py index 9fc304e4e21..ef74ec9d627 100644 --- a/erpnext/stock/doctype/pick_list/test_pick_list.py +++ b/erpnext/stock/doctype/pick_list/test_pick_list.py @@ -1205,3 +1205,64 @@ class TestPickList(FrappeTestCase): pl_doc.submit() frappe.db.set_single_value("Stock Settings", "over_picking_allowance", 0) + + def test_ignore_pricing_rule_in_pick_list(self): + frappe.flags.print_stmt = False + warehouse = "_Test Warehouse - _TC" + item = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "batch_number_series": "IPR-PICKLT-.######", + "create_new_batch": 1, + } + ).name + + make_stock_entry( + item=item, + to_warehouse=warehouse, + qty=2, + basic_rate=100, + ) + + pricing_rule = frappe.get_doc( + { + "doctype": "Pricing Rule", + "title": "Same Free Item", + "price_or_product_discount": "Product", + "selling": 1, + "apply_on": "Item Code", + "items": [ + { + "item_code": item, + } + ], + "same_item": 1, + "is_recursive": 1, + "recurse_for": 2, + "free_qty": 1, + "company": "_Test Company", + "customer": "_Test Customer", + } + ) + + pricing_rule.save() + frappe.flags.print_stmt = True + + so = make_sales_order(item_code=item, qty=2, rate=100, do_not_save=True) + so.set_warehouse = warehouse + so.submit() + + self.assertEqual(len(so.items), 2) + self.assertTrue(so.items[1].is_free_item) + + pl = create_pick_list(so.name) + pl.ignore_pricing_rule = 1 + pl.save() + pl.submit() + + self.assertEqual(len(pl.locations), 1) + + delivery_note = create_delivery_note(pl.name) + + self.assertEqual(len(delivery_note.items), 1) From 114a5f8cca6db794f5672a0103ae42cb7a602793 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 14 Aug 2024 17:30:46 +0530 Subject: [PATCH 07/28] refactor: allow foreign currency accounts in customer group (cherry picked from commit 066e9358920d8409904b685f1054dba5c82420bc) --- .../doctype/customer_group/customer_group.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index 6d95d3bcb24..06f2f43374e 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -42,7 +42,6 @@ class CustomerGroup(NestedSet): def validate_currency_for_receivable_and_advance_account(self): for x in self.accounts: - company_default_currency = frappe.get_cached_value("Company", x.company, "default_currency") receivable_account_currency = None advance_account_currency = None @@ -56,21 +55,6 @@ class CustomerGroup(NestedSet): "Account", x.advance_account, "account_currency" ) - if receivable_account_currency and receivable_account_currency != company_default_currency: - frappe.throw( - _("Receivable Account: {0} must be in Company default currency: {1}").format( - frappe.bold(x.account), - frappe.bold(company_default_currency), - ) - ) - - if advance_account_currency and advance_account_currency != company_default_currency: - frappe.throw( - _("Advance Account: {0} must be in Company default currency: {1}").format( - frappe.bold(x.advance_account), frappe.bold(company_default_currency) - ) - ) - if ( receivable_account_currency and advance_account_currency From b2e108afccacc69726a00b5b8bedf66fc83cc5d3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 14 Aug 2024 17:31:19 +0530 Subject: [PATCH 08/28] refactor: allow foreign currency accounts in Supplier Group (cherry picked from commit 164498bafb0f7763011d62cc615d4018c95ae248) --- .../doctype/supplier_group/supplier_group.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.py b/erpnext/setup/doctype/supplier_group/supplier_group.py index fa0c6beac49..5e1cab40450 100644 --- a/erpnext/setup/doctype/supplier_group/supplier_group.py +++ b/erpnext/setup/doctype/supplier_group/supplier_group.py @@ -37,7 +37,6 @@ class SupplierGroup(NestedSet): def validate_currency_for_payable_and_advance_account(self): for x in self.accounts: - company_default_currency = frappe.get_cached_value("Company", x.company, "default_currency") payable_account_currency = None advance_account_currency = None @@ -49,21 +48,6 @@ class SupplierGroup(NestedSet): "Account", x.advance_account, "account_currency" ) - if payable_account_currency and payable_account_currency != company_default_currency: - frappe.throw( - _("Payable Account: {0} must be in Company default currency: {1}").format( - frappe.bold(x.account), - frappe.bold(company_default_currency), - ) - ) - - if advance_account_currency and advance_account_currency != company_default_currency: - frappe.throw( - _("Advance Account: {0} must be in Company default currency: {1}").format( - frappe.bold(x.advance_account), frappe.bold(company_default_currency) - ) - ) - if ( payable_account_currency and advance_account_currency From 0f9849e6727b4fef3e3bf75048de553714b08298 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:39:15 +0530 Subject: [PATCH 09/28] fix: not able to create the batch (backport #42784) (#42785) fix: not able to create the batch (#42784) (cherry picked from commit 32c4fab14f83dc5e2cec0c21395713e54d2537c9) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/batch/batch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/batch/batch.js b/erpnext/stock/doctype/batch/batch.js index 4ed428421ca..77e4e560acf 100644 --- a/erpnext/stock/doctype/batch/batch.js +++ b/erpnext/stock/doctype/batch/batch.js @@ -3,7 +3,7 @@ frappe.ui.form.on("Batch", { setup: (frm) => { - frm.fields_dict["item"].get_query = function (doc, cdt, cdn) { + frm.set_query("item", () => { return { query: "erpnext.controllers.queries.item_query", filters: { @@ -11,7 +11,7 @@ frappe.ui.form.on("Batch", { has_batch_no: 1, }, }; - }; + }); }, refresh: (frm) => { if (!frm.is_new()) { From e420fa97799ad27a7ddb97c604319774b39e0aca Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 16 Aug 2024 13:07:53 +0530 Subject: [PATCH 10/28] fix(patch): replace repost with direct sql to update 'against_voucher (cherry picked from commit 13bb48434fd6897dcef2a7d79333d5373bec0cdb) --- .../v14_0/update_pos_return_ledger_entries.py | 112 ++++++++++++++---- 1 file changed, 89 insertions(+), 23 deletions(-) diff --git a/erpnext/patches/v14_0/update_pos_return_ledger_entries.py b/erpnext/patches/v14_0/update_pos_return_ledger_entries.py index 60e867d1bcb..6a6d15e0b34 100644 --- a/erpnext/patches/v14_0/update_pos_return_ledger_entries.py +++ b/erpnext/patches/v14_0/update_pos_return_ledger_entries.py @@ -1,8 +1,64 @@ import frappe from frappe import qb +from erpnext.accounts.utils import update_voucher_outstanding -def execute(): + +def get_valid_against_voucher_ref(pos_returns): + sinv = qb.DocType("Sales Invoice") + res = ( + qb.from_(sinv) + .select(sinv.name, sinv.return_against) + .where(sinv.name.isin(pos_returns) & sinv.return_against.notnull()) + .orderby(sinv.name) + .run(as_dict=True) + ) + return res + + +def build_dict_of_valid_against_reference(pos_returns): + _against_ref_dict = frappe._dict() + res = get_valid_against_voucher_ref(pos_returns) + for x in res: + _against_ref_dict[x.name] = x.return_against + return _against_ref_dict + + +def fix_incorrect_against_voucher_ref(affected_pos_returns): + if affected_pos_returns: + valid_against_voucher_dict = build_dict_of_valid_against_reference(affected_pos_returns) + + gle = qb.DocType("GL Entry") + gles_with_invalid_against = ( + qb.from_(gle) + .select(gle.name, gle.voucher_no) + .where( + gle.voucher_no.isin(affected_pos_returns) + & gle.against_voucher.notnull() + & gle.against_voucher.eq(gle.voucher_no) + & gle.is_cancelled.eq(0) + ) + .run(as_dict=True) + ) + # Update GL + if gles_with_invalid_against: + for gl in gles_with_invalid_against: + frappe.db.set_value( + "GL Entry", + gl.name, + "against_voucher", + valid_against_voucher_dict[gl.voucher_no], + ) + + # Update Payment Ledger + ple = qb.DocType("Payment Ledger Entry") + for x in affected_pos_returns: + qb.update(ple).set(ple.against_voucher_no, valid_against_voucher_dict[x]).where( + ple.voucher_no.eq(x) & ple.delinked.eq(0) + ).run() + + +def get_pos_returns_with_invalid_against_ref(): sinv = qb.DocType("Sales Invoice") pos_returns_without_self = ( qb.from_(sinv) @@ -32,30 +88,40 @@ def execute(): .run() ) - _vouchers = list(set([x[0] for x in gl_against_references])) - invoice_return_against = ( + if gl_against_references: + _vouchers = list(set([x[0] for x in gl_against_references])) + invoice_return_against = ( + qb.from_(sinv) + .select(sinv.name, sinv.return_against) + .where(sinv.name.isin(_vouchers) & sinv.return_against.notnull()) + .orderby(sinv.name) + .run() + ) + + valid_references = set(invoice_return_against) + actual_references = set(gl_against_references) + + invalid_references = actual_references.difference(valid_references) + if invalid_references: + return [x[0] for x in invalid_references] + return None + + +def update_outstanding_for_affected(affected_pos_returns): + if affected_pos_returns: + sinv = qb.DocType("Sales Invoice") + pos_with_accounts = ( qb.from_(sinv) - .select(sinv.name, sinv.return_against) - .where(sinv.name.isin(_vouchers) & sinv.return_against.notnull()) - .orderby(sinv.name) - .run() + .select(sinv.return_against, sinv.debit_to, sinv.customer) + .where(sinv.name.isin(affected_pos_returns)) + .run(as_dict=True) ) - valid_references = set(invoice_return_against) - actual_references = set(gl_against_references) + for x in pos_with_accounts: + update_voucher_outstanding("Sales Invoice", x.return_against, x.debit_to, "Customer", x.customer) - invalid_references = actual_references.difference(valid_references) - if invalid_references: - # Repost Accounting Ledger - pos_for_reposting = ( - qb.from_(sinv) - .select(sinv.company, sinv.name) - .where(sinv.name.isin([x[0] for x in invalid_references])) - .run(as_dict=True) - ) - for x in pos_for_reposting: - ral = frappe.new_doc("Repost Accounting Ledger") - ral.company = x.company - ral.append("vouchers", {"voucher_type": "Sales Invoice", "voucher_no": x.name}) - ral.save().submit() +def execute(): + affected_pos_returns = get_pos_returns_with_invalid_against_ref() + fix_incorrect_against_voucher_ref(affected_pos_returns) + update_outstanding_for_affected(affected_pos_returns) From cfaad685a489214b31131d667a1b4374b41c30ff Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 16 Aug 2024 14:32:53 +0530 Subject: [PATCH 11/28] chore: update patches.txt (cherry picked from commit 1721175a207fde5e06d3f8646a766e4eb3b325b5) --- erpnext/patches.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 797e8cebc80..208c9e58d4f 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -357,7 +357,7 @@ erpnext.patches.v14_0.create_accounting_dimensions_in_reconciliation_tool erpnext.patches.v15_0.allow_on_submit_dimensions_for_repostable_doctypes erpnext.patches.v14_0.update_flag_for_return_invoices #2024-03-22 erpnext.patches.v15_0.create_accounting_dimensions_in_payment_request -erpnext.patches.v14_0.update_pos_return_ledger_entries +erpnext.patches.v14_0.update_pos_return_ledger_entries #2024-08-16 # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index # 2023-12-20 From 7cc7179b050edd87cda6519fd76c0e83a31aa909 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:54:14 +0530 Subject: [PATCH 12/28] fix: Auto Create Serial and Batch Bundle For Outward (backport #42778) (#42792) fix: Auto Create Serial and Batch Bundle For Outward (#42778) (cherry picked from commit 48c3b0d094cbc4109fe56bed5b4a333ac804a37d) Co-authored-by: rohitwaghchaure --- .../test_serial_and_batch_bundle.py | 51 +++++++++++++++++++ erpnext/stock/serial_batch_bundle.py | 10 +++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 32f3b4fb85b..5fe79384e6d 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -701,6 +701,57 @@ class TestSerialandBatchBundle(FrappeTestCase): serial_nos = get_serial_nos_from_bundle(se.items[0].serial_and_batch_bundle) self.assertEqual(serial_nos, serial_nos1) + def test_auto_create_serial_and_batch_bundle_for_outward_for_batch_item(self): + item_code = make_item( + "Test Auto Create Batch Bundle for Outward 1", + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "batch_number_series": "ACSBBO-TACSB-.#####", + }, + ).name + + if not frappe.db.exists("Batch", "ACSBBO-TACSB-00001"): + frappe.get_doc( + { + "doctype": "Batch", + "batch_id": "ACSBBO-TACSB-00001", + "item": item_code, + "company": "_Test Company", + } + ).insert(ignore_permissions=True) + + make_stock_entry( + item_code=item_code, + qty=10, + target="_Test Warehouse - _TC", + rate=500, + use_serial_batch_fields=True, + batch_no="ACSBBO-TACSB-00001", + ) + + dispatch = make_stock_entry( + item_code=item_code, + qty=10, + target="_Test Warehouse - _TC", + rate=500, + do_not_submit=True, + ) + + original_value = frappe.db.get_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward" + ) + + frappe.db.set_single_value("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0) + self.assertRaises(frappe.ValidationError, dispatch.submit) + + frappe.db.set_single_value("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 1) + dispatch.submit() + + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", original_value + ) + def get_batch_from_bundle(bundle): from erpnext.stock.serial_batch_bundle import get_batch_nos diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 07e46312d3e..71e664dd066 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -221,7 +221,15 @@ class SerialBatchBundle: not self.sle.is_cancelled and not self.sle.serial_and_batch_bundle and self.item_details.has_batch_no == 1 - and self.item_details.create_new_batch + and ( + self.item_details.create_new_batch + or ( + frappe.db.get_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward" + ) + and self.sle.actual_qty < 0 + ) + ) ): self.make_serial_batch_no_bundle() elif not self.sle.is_cancelled: From 751c20984f3e05944acdaa2ba73a7506e89badac Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Fri, 16 Aug 2024 18:54:06 +0200 Subject: [PATCH 13/28] fix: german translations --- erpnext/translations/de.csv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 12b2854862c..7ea406801dd 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -3728,6 +3728,7 @@ Subdivision,Teilgebiet, Submit Review,Bewertung abschicken, Submitted,Gebucht, Supplier Addresses And Contacts,Lieferanten-Adressen und Kontaktdaten, +Supplier Address Details,Vorschau Lieferantenadresse, Synchronize this account,Synchronisieren Sie dieses Konto, Tag,Etikett, Target Location is required while receiving Asset {0} from an employee,"Der Zielspeicherort ist erforderlich, wenn Asset {0} von einem Mitarbeiter empfangen wird", @@ -11472,7 +11473,7 @@ Shipment Parcel,Versandpaket, Shipment Parcel Template,Versandpaketvorlage, Shipment Type,Sendungstyp, Shipment details,Sendungsdetails, -Shipping Address Details,Lieferadressendetails, +Shipping Address Details,Vorschau Lieferadresse, Shipping Address Template,Vorlage Lieferadresse, Show Balances in Chart Of Accounts,Saldo in Kontenplan anzeigen, Show Barcode Field in Stock Transactions,Barcode-Feld in Lagerbewegungen anzeigen, From 4914481105bba3a665b63784e4b48c03342e3270 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:38:56 +0200 Subject: [PATCH 14/28] fix: translatability of boldened text (cherry picked from commit af0ae930ca0eb0bad2509797e54db76fe62c0339) # Conflicts: # erpnext/controllers/accounts_controller.py --- erpnext/accounts/doctype/account/account.py | 2 +- .../pos_closing_entry/pos_closing_entry.py | 10 +++------- .../accounts/doctype/pos_invoice/pos_invoice.py | 2 +- .../pos_invoice_merge_log.py | 11 +++++------ .../accounts/doctype/pricing_rule/pricing_rule.py | 5 +++-- .../doctype/purchase_invoice/purchase_invoice.py | 12 ++++++------ .../doctype/sales_invoice/sales_invoice.py | 6 +++--- .../tax_withholding_details.py | 2 +- erpnext/assets/doctype/asset/asset.py | 2 +- erpnext/controllers/accounts_controller.py | 15 +++++++++++---- erpnext/controllers/item_variant.py | 2 +- erpnext/controllers/selling_controller.py | 2 +- .../doctype/plaid_settings/plaid_settings.py | 2 +- erpnext/setup/doctype/company/company.py | 6 +++--- erpnext/stock/doctype/batch/batch.py | 4 ++-- erpnext/stock/doctype/stock_entry/stock_entry.py | 6 +++--- .../stock_reservation_entry.py | 5 +++-- .../doctype/stock_settings/stock_settings.py | 8 ++++---- .../service_level_agreement.py | 2 +- 19 files changed, 54 insertions(+), 50 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 69c1e16bb1e..1a5ee36b95a 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -202,7 +202,7 @@ class Account(NestedSet): msg = _( "There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report" ).format( - frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type + frappe.bold(_("Account Type")), doc_before_save.account_type, doc_before_save.account_type ) frappe.msgprint(msg) self.add_comment("Comment", msg) diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py index 9faf8693a8a..fda868cfe51 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py @@ -87,19 +87,15 @@ class POSClosingEntry(StatusUpdater): as_dict=1, )[0] if pos_invoice.consolidated_invoice: - invalid_row.setdefault("msg", []).append( - _("POS Invoice is {}").format(frappe.bold("already consolidated")) - ) + invalid_row.setdefault("msg", []).append(_("POS Invoice is already consolidated")) invalid_rows.append(invalid_row) continue if pos_invoice.pos_profile != self.pos_profile: invalid_row.setdefault("msg", []).append( - _("POS Profile doesn't matches {}").format(frappe.bold(self.pos_profile)) + _("POS Profile doesn't match {}").format(frappe.bold(self.pos_profile)) ) if pos_invoice.docstatus != 1: - invalid_row.setdefault("msg", []).append( - _("POS Invoice is not {}").format(frappe.bold("submitted")) - ) + invalid_row.setdefault("msg", []).append(_("POS Invoice is not submitted")) if pos_invoice.owner != self.user: invalid_row.setdefault("msg", []).append( _("POS Invoice isn't created by user {}").format(frappe.bold(self.owner)) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index ef4db1dac98..d517c9d6da2 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -188,7 +188,7 @@ class POSInvoice(SalesInvoice): def validate(self): if not cint(self.is_pos): frappe.throw( - _("POS Invoice should have {} field checked.").format(frappe.bold("Include Payment")) + _("POS Invoice should have the field {0} checked.").format(frappe.bold(_("Include Payment"))) ) # run on validate method of selling controller diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 2cf204dd347..aecdac0b3a1 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -97,16 +97,15 @@ class POSInvoiceMergeLog(Document): return_against_status = frappe.db.get_value("POS Invoice", return_against, "status") if return_against_status != "Consolidated": # if return entry is not getting merged in the current pos closing and if it is not consolidated - bold_unconsolidated = frappe.bold("not Consolidated") - msg = _("Row #{}: Original Invoice {} of return invoice {} is {}.").format( - d.idx, bold_return_against, bold_pos_invoice, bold_unconsolidated - ) + msg = _( + "Row #{}: The original Invoice {} of return invoice {} is not consolidated." + ).format(d.idx, bold_return_against, bold_pos_invoice) msg += " " msg += _( - "Original invoice should be consolidated before or along with the return invoice." + "The original invoice should be consolidated before or along with the return invoice." ) msg += "

" - msg += _("You can add original invoice {} manually to proceed.").format( + msg += _("You can add the original invoice {} manually to proceed.").format( bold_return_against ) frappe.throw(msg) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index de29ec0f004..1a1ff78a217 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -186,7 +186,8 @@ class PricingRule(Document): if not self.priority: throw( _("As the field {0} is enabled, the field {1} is mandatory.").format( - frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority") + frappe.bold(_("Apply Discount on Discounted Rate")), + frappe.bold(_("Priority")), ) ) @@ -194,7 +195,7 @@ class PricingRule(Document): throw( _( "As the field {0} is enabled, the value of the field {1} should be more than 1." - ).format(frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority")) + ).format(frappe.bold(_("Apply Discount on Discounted Rate")), frappe.bold(_("Priority"))) ) def validate_applicable_for_selling_or_buying(self): diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index c33b2c0ff17..78fc02999ef 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -377,16 +377,16 @@ class PurchaseInvoice(BuyingController): if account.report_type != "Balance Sheet": frappe.throw( _( - "Please ensure {} account is a Balance Sheet account. You can change the parent account to a Balance Sheet account or select a different account." - ).format(frappe.bold("Credit To")), + "Please ensure that the {0} account is a Balance Sheet account. You can change the parent account to a Balance Sheet account or select a different account." + ).format(frappe.bold(_("Credit To"))), title=_("Invalid Account"), ) if self.supplier and account.account_type != "Payable": frappe.throw( _( - "Please ensure {} account {} is a Payable account. Change the account type to Payable or select a different account." - ).format(frappe.bold("Credit To"), frappe.bold(self.credit_to)), + "Please ensure that the {0} account {1} is a Payable account. You can change the account type to Payable or select a different account." + ).format(frappe.bold(_("Credit To")), frappe.bold(self.credit_to)), title=_("Invalid Account"), ) @@ -634,7 +634,7 @@ class PurchaseInvoice(BuyingController): "To submit the invoice without purchase order please set {0} as {1} in {2}" ).format( frappe.bold(_("Purchase Order Required")), - frappe.bold("No"), + frappe.bold(_("No")), get_link_to_form("Buying Settings", "Buying Settings", "Buying Settings"), ) throw(msg, title=_("Mandatory Purchase Order")) @@ -655,7 +655,7 @@ class PurchaseInvoice(BuyingController): "To submit the invoice without purchase receipt please set {0} as {1} in {2}" ).format( frappe.bold(_("Purchase Receipt Required")), - frappe.bold("No"), + frappe.bold(_("No")), get_link_to_form("Buying Settings", "Buying Settings", "Buying Settings"), ) throw(msg, title=_("Mandatory Purchase Receipt")) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 5d6c8a353fb..1966a78ef49 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -514,7 +514,7 @@ class SalesInvoice(SellingController): ) if pos_closing_entry and pos_closing_entry[0]: msg = _("To cancel a {} you need to cancel the POS Closing Entry {}.").format( - frappe.bold("Consolidated Sales Invoice"), + frappe.bold(_("Consolidated Sales Invoice")), get_link_to_form("POS Closing Entry", pos_closing_entry[0]), ) frappe.throw(msg, title=_("Not Allowed")) @@ -858,7 +858,7 @@ class SalesInvoice(SellingController): if account.report_type != "Balance Sheet": msg = ( - _("Please ensure {} account is a Balance Sheet account.").format(frappe.bold("Debit To")) + _("Please ensure {} account is a Balance Sheet account.").format(frappe.bold(_("Debit To"))) + " " ) msg += _( @@ -869,7 +869,7 @@ class SalesInvoice(SellingController): if self.customer and account.account_type != "Receivable": msg = ( _("Please ensure {} account {} is a Receivable account.").format( - frappe.bold("Debit To"), frappe.bold(self.debit_to) + frappe.bold(_("Debit To")), frappe.bold(self.debit_to) ) + " " ) 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 276e95bd5d1..0c18dac7768 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -336,7 +336,7 @@ def get_tds_docs(filters): def get_tds_docs_query(filters, bank_accounts, tds_accounts): if not tds_accounts: frappe.throw( - _("No {0} Accounts found for this company.").format(frappe.bold("Tax Withholding")), + _("No {0} Accounts found for this company.").format(frappe.bold(_("Tax Withholding"))), title=_("Accounts Missing Error"), ) gle = frappe.qb.DocType("GL Entry") diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 1b9e911be5b..76eeca03ab5 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -669,7 +669,7 @@ class Asset(AccountsController): if not fixed_asset_account: frappe.throw( _("Set {0} in asset category {1} for company {2}").format( - frappe.bold("Fixed Asset Account"), + frappe.bold(_("Fixed Asset Account")), frappe.bold(self.asset_category), frappe.bold(self.company), ), diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 63d0404642a..ad9bafc93c0 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -233,8 +233,13 @@ class AccountsController(TransactionBase): ).format( frappe.bold(document_type), get_link_to_form(self.doctype, self.get("return_against")), +<<<<<<< HEAD frappe.bold("Update Outstanding for Self"), get_link_to_form("Payment Reconciliation", "Payment Reconciliation"), +======= + frappe.bold(_("Update Outstanding for Self")), + get_link_to_form("Payment Reconciliation"), +>>>>>>> af0ae930ca (fix: translatability of boldened text) ) ) @@ -1962,7 +1967,9 @@ class AccountsController(TransactionBase): def raise_missing_debit_credit_account_error(self, party_type, party): """Raise an error if debit to/credit to account does not exist.""" - db_or_cr = frappe.bold("Debit To") if self.doctype == "Sales Invoice" else frappe.bold("Credit To") + db_or_cr = ( + frappe.bold(_("Debit To")) if self.doctype == "Sales Invoice" else frappe.bold(_("Credit To")) + ) rec_or_pay = "Receivable" if self.doctype == "Sales Invoice" else "Payable" link_to_party = frappe.utils.get_link_to_form(party_type, party) @@ -3085,9 +3092,9 @@ def set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True) if not child_item.warehouse: frappe.throw( - _("Cannot find {} for item {}. Please set the same in Item Master or Stock Settings.").format( - frappe.bold("default warehouse"), frappe.bold(item.item_code) - ) + _( + "Cannot find a default warehouse for item {0}. Please set one in the Item Master or in Stock Settings." + ).format(frappe.bold(item.item_code)) ) set_child_tax_template_and_map(item, child_item, p_doc) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index cc6870f892a..5dace4af884 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -150,7 +150,7 @@ def validate_item_attribute_value(attributes_list, attribute, attribute_value, i ) msg += "
" + _( "To still proceed with editing this Attribute Value, enable {0} in Item Variant Settings." - ).format(frappe.bold("Allow Rename Attribute Value")) + ).format(frappe.bold(_("Allow Rename Attribute Value"))) frappe.throw(msg, InvalidItemAttributeValueError, title=_("Edit Not Allowed")) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index c1f565e7323..766e67be0f6 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -697,7 +697,7 @@ class SellingController(StockController): duplicate_items_msg = _("Item {0} entered multiple times.").format(frappe.bold(d.item_code)) duplicate_items_msg += "

" duplicate_items_msg += _("Please enable {} in {} to allow same item in multiple rows").format( - frappe.bold("Allow Item to Be Added Multiple Times in a Transaction"), + frappe.bold(_("Allow Item to Be Added Multiple Times in a Transaction")), get_link_to_form("Selling Settings", "Selling Settings"), ) if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1: diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index edfab4777a7..e187c075077 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -96,7 +96,7 @@ def add_bank_accounts(response, bank, company): frappe.throw( _( "Please setup and enable a group account with the Account Type - {0} for the company {1}" - ).format(frappe.bold("Bank"), company) + ).format(frappe.bold(_("Bank")), company) ) for account in response["accounts"]: diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index f79ea60f5c4..8028b8e6af4 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -203,7 +203,7 @@ class Company(NestedSet): ): frappe.throw( _("'{0}' should be in company currency {1}.").format( - frappe.bold("Default Advance Received Account"), frappe.bold(self.default_currency) + frappe.bold(_("Default Advance Received Account")), frappe.bold(self.default_currency) ) ) @@ -214,7 +214,7 @@ class Company(NestedSet): ): frappe.throw( _("'{0}' should be in company currency {1}.").format( - frappe.bold("Default Advance Paid Account"), frappe.bold(self.default_currency) + frappe.bold(_("Default Advance Paid Account")), frappe.bold(self.default_currency) ) ) @@ -447,7 +447,7 @@ class Company(NestedSet): ): frappe.throw( _("Set default {0} account for non stock items").format( - frappe.bold("Provisional Account") + frappe.bold(_("Provisional Account")) ) ) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index c539c315747..5d71ca06cb4 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -188,9 +188,9 @@ class Batch(Document): if has_expiry_date and not self.expiry_date: frappe.throw( msg=_("Please set {0} for Batched Item {1}, which is used to set {2} on Submit.").format( - frappe.bold("Shelf Life in Days"), + frappe.bold(_("Shelf Life in Days")), get_link_to_form("Item", self.item), - frappe.bold("Batch Expiry Date"), + frappe.bold(_("Batch Expiry Date")), ), title=_("Expiry Date Mandatory"), ) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 14e0fdf6388..83ae8d09f66 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -898,8 +898,8 @@ class StockEntry(StockController): ).format( item.idx, frappe.bold(label), - frappe.bold("Manufacture"), - frappe.bold("Material Consumption for Manufacture"), + frappe.bold(_("Manufacture")), + frappe.bold(_("Material Consumption for Manufacture")), ) ) @@ -909,7 +909,7 @@ class StockEntry(StockController): ): frappe.throw( _("Only one {0} entry can be created against the Work Order {1}").format( - frappe.bold("Manufacture"), frappe.bold(self.work_order) + frappe.bold(_("Manufacture")), frappe.bold(self.work_order) ) ) diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py index 9808d2dfe72..8316488e253 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -255,7 +255,7 @@ class StockReservationEntry(Document): if self.has_batch_no else _("Warehouse"), frappe.bold(self.warehouse), - frappe.bold("Stock Reservation Entry"), + frappe.bold(_("Stock Reservation Entry")), ) frappe.throw(msg) @@ -497,7 +497,8 @@ def validate_stock_reservation_settings(voucher: object) -> None: if not frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"): msg = _("Please enable {0} in the {1}.").format( - frappe.bold("Stock Reservation"), frappe.bold("Stock Settings") + frappe.bold(_("Stock Reservation")), + frappe.bold(_("Stock Settings")), ) frappe.throw(msg) diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py index c029b7bd1fb..229ff944750 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/stock_settings.py @@ -175,7 +175,7 @@ class StockSettings(Document): if self.allow_negative_stock and self.enable_stock_reservation: frappe.throw( _("As {0} is enabled, you can not enable {1}.").format( - frappe.bold("Stock Reservation"), frappe.bold("Allow Negative Stock") + frappe.bold(_("Stock Reservation")), frappe.bold(_("Allow Negative Stock")) ) ) @@ -187,7 +187,7 @@ class StockSettings(Document): if self.allow_negative_stock: frappe.throw( _("As {0} is enabled, you can not enable {1}.").format( - frappe.bold("Allow Negative Stock"), frappe.bold("Stock Reservation") + frappe.bold(_("Allow Negative Stock")), frappe.bold(_("Stock Reservation")) ) ) @@ -207,7 +207,7 @@ class StockSettings(Document): if bin_with_negative_stock: frappe.throw( _("As there are negative stock, you can not enable {0}.").format( - frappe.bold("Stock Reservation") + frappe.bold(_("Stock Reservation")) ) ) @@ -221,7 +221,7 @@ class StockSettings(Document): if has_reserved_stock: frappe.throw( _("As there are reserved stock, you cannot disable {0}.").format( - frappe.bold("Stock Reservation") + frappe.bold(_("Stock Reservation")) ) ) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index b140fdab51f..011a5bc371f 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -144,7 +144,7 @@ class ServiceLevelAgreement(Document): ): frappe.throw( _("{0} is not enabled in {1}").format( - frappe.bold("Track Service Level Agreement"), + frappe.bold(_("Track Service Level Agreement")), get_link_to_form("Support Settings", "Support Settings"), ) ) From dbd466b6b2afdff4a1b3816359cab55207c44318 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 17 Aug 2024 02:24:58 +0200 Subject: [PATCH 15/28] chore: resolve conflicts --- erpnext/controllers/accounts_controller.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index ad9bafc93c0..58e120e14b0 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -233,13 +233,8 @@ class AccountsController(TransactionBase): ).format( frappe.bold(document_type), get_link_to_form(self.doctype, self.get("return_against")), -<<<<<<< HEAD - frappe.bold("Update Outstanding for Self"), - get_link_to_form("Payment Reconciliation", "Payment Reconciliation"), -======= frappe.bold(_("Update Outstanding for Self")), - get_link_to_form("Payment Reconciliation"), ->>>>>>> af0ae930ca (fix: translatability of boldened text) + get_link_to_form("Payment Reconciliation", "Payment Reconciliation"), ) ) From 6f7fdbefac26b8098141880d3f3ea7e74a1b782c Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 17 Aug 2024 02:48:39 +0200 Subject: [PATCH 16/28] fix: german translations of "HR" --- erpnext/translations/de.csv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 7ea406801dd..5f6e6f761e0 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -1095,7 +1095,7 @@ Guardian1 Name,Guardian1 Namen, Guardian2 Email ID,Guardian2 E-Mail-ID, Guardian2 Mobile No,Guardian2 Mobil Nein, Guardian2 Name,Guardian2 Namen, -HR Manager,Leiter der Personalabteilung, +HR Manager,Personalwesen Leiter, HSN,HSN, HSN/SAC,HSN / SAC, Half Yearly,Halbjährlich, @@ -6028,10 +6028,10 @@ Hotel Room Reservation Item,Hotelzimmer-Reservierungselement, Hotel Settings,Hoteleinstellungen, Default Taxes and Charges,Standard-Steuern und -Abgaben, Default Invoice Naming Series,Standard-Rechnungsnummernkreis, -HR,HR, +HR,Personalwesen, Date on which this component is applied,"Datum, an dem diese Komponente angewendet wird", Salary Slip,Gehaltsabrechnung, -HR User,Nutzer Personalabteilung, +HR User,Personalwesen Benutzer, Job Applicant,Bewerber, Body,Körper, Appraisal Template,Bewertungsvorlage, @@ -9918,8 +9918,8 @@ Bank/Cash Account {0} doesn't belong to company {1},Das Bank- / Kassenkonto {0} Base Amount,Basisbetrag, Base Total Billed Amount,Insg. abgerechneter Betrag in Basiswährung, Base Total Costing Amount,Gesamtkosten in Basiswährung, -"Based on your HR Policy, select your leave allocation period's end date",Wählen Sie auf der Grundlage Ihrer HR-Richtlinien das Enddatum Ihres Abwesenheitskontingents aus, -"Based on your HR Policy, select your leave allocation period's start date",Wählen Sie auf der Grundlage Ihrer HR-Richtlinie das Startdatum Ihres Abwesenheitskontingents aus, +"Based on your HR Policy, select your leave allocation period's end date",Wählen Sie auf der Grundlage Ihrer Personal-Richtlinien das Enddatum Ihres Abwesenheitskontingents aus, +"Based on your HR Policy, select your leave allocation period's start date",Wählen Sie auf der Grundlage Ihrer Personal-Richtlinie das Startdatum Ihres Abwesenheitskontingents aus, Batch No is mandatory,Chargennummer ist obligatorisch, Batch No {0} does not exists,Charge Nr. {0} existiert nicht, Batch No {0} is linked with Item {1} which has serial no. Please scan serial no instead.,"Die Chargennummer {0} ist mit dem Artikel {1} verknüpft, der eine Seriennummer hat. Bitte scannen Sie stattdessen die Seriennummer.", From 0344442d42cbdbe8db2401f1c35d18f13674f786 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 14:55:41 +0530 Subject: [PATCH 17/28] perf: data import for stock entries (backport #42711) (#42819) perf: data import for stock entries (#42711) (cherry picked from commit 151128046440ee32f8bf8056942c47f65b033365) Co-authored-by: rohitwaghchaure --- .../doctype/stock_entry/test_stock_entry.py | 70 ++++++++++++++++++- .../test_stock_ledger_entry.py | 3 + erpnext/stock/stock_ledger.py | 6 ++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index a680b7733d3..a9529cc2ede 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -4,7 +4,7 @@ from frappe.permissions import add_user_permission, remove_user_permission from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import add_days, flt, nowtime, today +from frappe.utils import add_days, cstr, flt, get_time, getdate, nowtime, today from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.stock.doctype.item.test_item import ( @@ -1780,6 +1780,74 @@ class TestStockEntry(FrappeTestCase): frappe.db.set_value("Serial and Batch Bundle", sbb, "type_of_transaction", "Inward") self.assertRaises(frappe.ValidationError, se.submit) + def test_stock_entry_for_same_posting_date_and_time(self): + warehouse = "_Test Warehouse - _TC" + item_code = "Test Stock Entry For Same Posting Datetime 1" + make_item(item_code, {"is_stock_item": 1}) + posting_date = nowdate() + posting_time = nowtime() + + for index in range(25): + se = make_stock_entry( + item_code=item_code, + qty=1, + to_warehouse=warehouse, + posting_date=posting_date, + posting_time=posting_time, + do_not_submit=True, + purpose="Material Receipt", + basic_rate=100, + ) + + se.append( + "items", + { + "item_code": item_code, + "item_name": se.items[0].item_name, + "description": se.items[0].description, + "t_warehouse": se.items[0].t_warehouse, + "basic_rate": 100, + "qty": 1, + "stock_qty": 1, + "conversion_factor": 1, + "expense_account": se.items[0].expense_account, + "cost_center": se.items[0].cost_center, + "uom": se.items[0].uom, + "stock_uom": se.items[0].stock_uom, + }, + ) + + se.remarks = f"The current number is {cstr(index)}" + + se.submit() + + sles = frappe.get_all( + "Stock Ledger Entry", + fields=[ + "posting_date", + "posting_time", + "actual_qty", + "qty_after_transaction", + "incoming_rate", + "stock_value_difference", + "stock_value", + ], + filters={"item_code": item_code, "warehouse": warehouse}, + order_by="creation", + ) + + self.assertEqual(len(sles), 50) + i = 0 + for sle in sles: + i += 1 + self.assertEqual(getdate(sle.posting_date), getdate(posting_date)) + self.assertEqual(get_time(sle.posting_time), get_time(posting_time)) + self.assertEqual(sle.actual_qty, 1) + self.assertEqual(sle.qty_after_transaction, i) + self.assertEqual(sle.incoming_rate, 100) + self.assertEqual(sle.stock_value_difference, 100) + self.assertEqual(sle.stock_value, 100 * i) + def make_serialized_item(**args): args = frappe._dict(args) diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py index 069192fdb16..587b25ea154 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py @@ -1043,6 +1043,8 @@ class TestStockLedgerEntry(FrappeTestCase, StockTestMixin): self.assertEqual(50, _get_stock_credit(final_consumption)) def test_tie_breaking(self): + from erpnext.stock.doctype.repost_item_valuation.repost_item_valuation import repost_entries + frappe.flags.dont_execute_stock_reposts = True self.addCleanup(frappe.flags.pop, "dont_execute_stock_reposts") @@ -1085,6 +1087,7 @@ class TestStockLedgerEntry(FrappeTestCase, StockTestMixin): self.assertEqual([10, 11], ordered_qty_after_transaction()) first.cancel() + repost_entries() self.assertEqual([1], ordered_qty_after_transaction()) backdated = make_stock_entry( diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 693481dfba8..0961d9bd35e 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -647,6 +647,7 @@ class update_entries_after: and ( posting_datetime = %(posting_datetime)s ) + and creation = %(creation)s order by creation ASC for update @@ -1526,6 +1527,11 @@ def get_previous_sle_of_current_voucher(args, operator="<", exclude_current_vouc voucher_no = args.get("voucher_no") voucher_condition = f"and voucher_no != '{voucher_no}'" + elif args.get("creation"): + creation = args.get("creation") + operator = "<=" + voucher_condition = f"and creation < '{creation}'" + sle = frappe.db.sql( f""" select *, posting_datetime as "timestamp" From b24de3e35b5a9eb34390c866fde35dc9b4ea1fe7 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:34:24 +0530 Subject: [PATCH 18/28] fix: dropping index to improve performance (backport #42820) (#42821) fix: dropping index to improve performance (#42820) fix: droping index to improve peformance (cherry picked from commit 5404b21c7ddbb7701be6b622d972e724fac167c1) Co-authored-by: rohitwaghchaure --- erpnext/patches.txt | 1 + .../drop_index_posting_datetime_from_sle.py | 16 ++++++++++++++++ .../stock_ledger_entry/stock_ledger_entry.py | 1 - 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v15_0/drop_index_posting_datetime_from_sle.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 208c9e58d4f..bece96d64e8 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -371,3 +371,4 @@ erpnext.patches.v15_0.update_warehouse_field_in_asset_repair_consumed_item_docty erpnext.patches.v15_0.update_asset_repair_field_in_stock_entry erpnext.patches.v15_0.update_total_number_of_booked_depreciations erpnext.patches.v15_0.do_not_use_batchwise_valuation +erpnext.patches.v15_0.drop_index_posting_datetime_from_sle diff --git a/erpnext/patches/v15_0/drop_index_posting_datetime_from_sle.py b/erpnext/patches/v15_0/drop_index_posting_datetime_from_sle.py new file mode 100644 index 00000000000..40b0b2d6759 --- /dev/null +++ b/erpnext/patches/v15_0/drop_index_posting_datetime_from_sle.py @@ -0,0 +1,16 @@ +import click +import frappe + + +def execute(): + table = "tabStock Ledger Entry" + index = "posting_datetime_creation_index" + + if not frappe.db.has_index(table, index): + return + + try: + frappe.db.sql_ddl(f"ALTER TABLE `{table}` DROP INDEX `{index}`") + click.echo(f"✓ dropped {index} index from {table}") + except Exception: + frappe.log_error("Failed to drop index") diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 319303dbbb0..cff1886d7fe 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -351,4 +351,3 @@ def on_doctype_update(): frappe.db.add_index("Stock Ledger Entry", ["voucher_no", "voucher_type"]) frappe.db.add_index("Stock Ledger Entry", ["batch_no", "item_code", "warehouse"]) frappe.db.add_index("Stock Ledger Entry", ["warehouse", "item_code"], "item_warehouse") - frappe.db.add_index("Stock Ledger Entry", ["posting_datetime", "creation"]) From 9e9de4c99e9f628469f93442c68a2fe8e69002fd Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:43:22 +0200 Subject: [PATCH 19/28] fix: backport german translations from develop --- erpnext/translations/de.csv | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 5f6e6f761e0..b9d790d2428 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -11816,3 +11816,103 @@ will be,wird sein, {} is a child company.,{} ist ein untergeordnetes Unternehmen., {} {} is already linked with another {},{} {} ist bereits mit einem anderen {} verknüpft, {} {} is already linked with {} {},{} {} ist bereits mit {} {} verknüpft, +A Transaction Deletion Document: {0} is triggered for {0},Eine Transaktion Löschungsdokument: {0} wird für {0} ausgelöst, +About Us Settings,"Einstellungen zu ""Über uns""", +Allow Internal Transfers at Arm's Length Price,Interne Übertragungen zum Fremdvergleichspreis zulassen, +Asset decapitalized after Asset Capitalization {0} was submitted,"Vermögenswert freigegeben, nachdem Anlagenaktivierung {0} gebucht wurde", +Auto Email Report,Auto Email-Bericht, +Auto close Opportunity Replied after the no. of days mentioned above,Automatische Schließungschaltung antwortete nach der oben genannten Anzahl von Tagen, +Avg Rate (Balance Stock),Durchschnittliche Rate (Lagerbestand), +Billing Interval in Subscription Plan must be Month to follow calendar months,"Abrechnungsintervall im Abonnementplan muss ""Monat"" sein, um Kalendermonate zu folgen", +Bulk Update,Massen-Update, +Can't disable batch wise valuation for active batches.,Sie können die chargenweise Bewertung für aktive Chargen nicht deaktivieren., +Can't disable batch wise valuation for items with FIFO valuation method.,Sie können die chargenweise Bewertung für Artikel mit FIFO-Bewertungsmethode nicht deaktivieren., +Cannot disable batch wise valuation for FIFO valuation method.,Sie können die chargenweise Bewertung für die FIFO-Bewertungsmethode nicht deaktivieren., +Cannot enqueue multi docs for one company. {0} is already queued/running for company: {1},Mehrere Dokumente für ein Unternehmen können nicht in die Warteschlange gestellt werden. {0} ist bereits in die Warteschlange gestellt/wird für das Unternehmen ausgeführt: {1}, +Contact Us Settings,Einstellungen zu „Kontaktieren Sie uns“, +Create Journal Entries,Buchungssätze erstellen, +Create a variant with the template image.,Eine Variante mit dem Vorlagenbild erstellen., +Create in Draft Status,In Entwurfsstatus erstellen, +Custom delimiters,Benutzerdefinierte Trennzeichen, +Deleted Documents,Gelöschte Dokumente, +Delimiter options,Trennzeichenoptionen, +Dependent Task {0} is not a Template Task,Abhängige Aufgabe {0} ist keine Vorlage einer Aufgabe, +Depreciation Entry Posting Status,Buchungsstatus des Abschreibungseintrags, +Depreciation Schedule View,Ansicht Abschreibungsplan, +Depreciation cannot be calculated for fully depreciated assets,Für vollständig abgeschriebene Vermögensgegenstände kann keine Abschreibung berechnet werden, +Do Not Use Batch-wise Valuation,Keine chargenweise Bewertung verwenden, +Domain Settings,Domäneneinstellungen, +Email Domain,E-Mail-Domain, +Enable Immutable Ledger,Unveränderliches Hauptbuch aktivieren, +Enable it if users want to consider rejected materials to dispatch.,"Aktivieren Sie diese Option, wenn Benutzer zurückgewiesenes Material für den Versand berücksichtigen möchten.", +Excess Materials Consumed,Überschüssige Materialien verbraucht, +Excess Transfer,Überschuss-Übertragung, +FIFO Queue vs Qty After Transaction Comparison,Vergleich zwischen FIFO-Warteschlange und Menge nach Transaktion, +"For the {0}, the quantity is required to make the return entry","Für die {0} ist die Menge erforderlich, um die Retoure zu erstellen", +"If enabled, the item rate won't adjust to the valuation rate during internal transfers, but accounting will still use the valuation rate.","Falls aktiviert, wird der Artikelkurs bei internen Transfers nicht an den Bewertungskurs angepasst, aber die Buchhaltung verwendet weiterhin den Wertansatz.", +"If enabled, the system will use the moving average valuation method to calculate the valuation rate for the batched items and will not consider the individual batch-wise incoming rate.","Falls aktiviert, verwendet das System die Bewertungsmethode des gleitenden Durchschnitts zur Berechnung des Wertansatzes für die chargenweisen Artikel und berücksichtigt nicht den individuellen chargenweisen Eingangskurs.", +Job Worker,Unterauftragnehmer, +Job Worker Address,Unterauftragnehmer Adresse, +Job Worker Address Details,Vorschau Adresse Unterauftragnehmer, +Job Worker Contact,Vertrag des Unterauftragnehmers, +Job Worker Delivery Note,Lieferschein des Unterauftragnehmers, +Job Worker Name,Name des Unterauftragnehmer, +Job Worker Warehouse,Lagerhaus des Unterauftragnehmers, +"Learn about Common Party","Erfahren Sie mehr über die Verknüpfung von Kunden und Lieferanten", +Notification,Benachrichtigung, +Notification Settings,Benachrichtigungseinstellungen, +Offsetting for Accounting Dimension,Verrechnung für Buchhaltungsdimension, +Only Include Allocated Payments,Nur zugeordnete Zahlungen einbeziehen, +Only one {0} entry can be created against the Work Order {1},Nur ein {0} Eintrag kann gegen den Arbeitsauftrag {1} erstellt werden, +Over Picking Allowance,Überkommissionierzugabe, +Over Transfer Allowance,Überschlusstransferzugabe, +Overbilling of {} ignored because you have {} role.,"Überhöhte Abrechnung von {} wurde ignoriert, weil Sie die Rolle {} haben.", +Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.,Job für Zahlungsabgleich: {0} läuft für diese Partei. Kann jetzt nicht abgleichen., +Payment Request created from Sales Order or Purchase Order will be in Draft status. When disabled document will be in unsaved state.,"Eine Zahlungsanforderung, die aus einem Auftrag oder einer Bestellung erstellt wurde, wird im Entwurfsstatus sein. Wenn deaktiviert, wird das Dokument in ungespeichertem Zustand sein.", +Payment Request took too long to respond. Please try requesting for payment again.,"Zahlungsaufforderung hat zu lange gedauert, um zu antworten. Bitte versuchen Sie die Zahlung erneut anzufragen.", +Payment Terms Status for Sales Order,Status für Zahlungsbedingungen für Aufträge, +Pipeline By,Pipeline von, +Please enable Use Old Serial / Batch Fields to make_bundle,"Bitte aktivieren Sie ""Alte Serien-/Batchfelder verwenden"" für make_bundle", +Print Style,Druckstil, +Reconcile All Serial Nos / Batches,Alle Seriennummern/Chargen abgleichen, +Reset Company Default Values,Standardwerte des Unternehmens zurücksetzen, +Reset Raw Materials Table,Tabelle Rohstoffe zurücksetzen, +Return Against Subcontracting Receipt,Retoure gegen Unterauftragsbeleg, +Return Components,Komponenten zurückgeben, +Returned Against,Zurückgegeben gegen, +Returned exchange rate is neither integer not float.,Der zurückgegebene Wechselkurs ist weder Integer noch Float., +Round Off Tax Amount,Steuerbetrag abrunden, +Rounding Loss Allowance,Rundungsverlusttoleranz, +Rounding Loss Allowance should be between 0 and 1,Rundungsverlusttoleranz muss zwischen 0 und 1 sein, +Row #{0}: Rejected Warehouse is mandatory for the rejected Item {1},Zeile #{0}: Ausschusslager ist für den abgelehnten Artikel {1} obligatorisch, +Row #{0}: You cannot use the inventory dimension '{1}' in Stock Reconciliation to modify the quantity or valuation rate. Stock reconciliation with inventory dimensions is intended solely for performing opening entries.,"Zeile #{0}: Sie können die Bestandsdimension '{1}' in der Bestandsabgleich nicht verwenden, um die Menge oder den Wertansatz zu ändern. Die Bestandsabgleich mit Bestandsdimensionen ist ausschließlich für die Durchführung von Eröffnungsbuchungen vorgesehen.", +Row {0}: Packed Qty must be equal to {1} Qty.,Zeile {0}: Verpackte Menge muss gleich der {1} Menge sein., +Row {0}: Total Number of Depreciations cannot be less than or equal to Opening Number of Booked Depreciations,Zeile {0}: Die Gesamtzahl der Abschreibungen kann nicht kleiner oder gleich der Anzahl der gebuchten Abschreibungen zu Beginn sein, +SCO Supplied Item,Artikel beigestellt für Unterauftrag, +SLA Fulfilled On Status,SLA erfüllt am Status, +SLA will be applied if {1} is set as {2}{3},"SLA wird angewendet, wenn {1} als {2}{3} eingestellt ist", +SMS Settings,SMS-Einstellungen, +SO Total Qty,Kd.-Auftr.-Gesamtmenge, +"Sales Order {0} already exists against Customer's Purchase Order {1}. To allow multiple Sales Orders, Enable {2} in {3}","Auftrag {0} existiert bereits für die Kundenbestellung {1}. Um mehrere Verkaufsaufträge zuzulassen, aktivieren Sie {2} in {3}", +"Scorecard variables can be used, as well as: +{total_score} (the total score from that period), +{period_number} (the number of periods to present day) +","Variablen der Bewertung können verwendet werden, sowie: +{total_score} (die Gesamtpunktzahl aus diesem Zeitraum), +{period_number} (die Anzahl der Zeiträume bis zum heutigen Tag) +", +Select Accounting Dimension.,Buchhaltungsdimension auswählen, +Select Corrective Operation,Nacharbeit auswählen, +Select Date of Birth. This will validate Employees age and prevent hiring of under-age staff.,Wählen Sie Geburtsdatum. Damit wird das Alter der Mitarbeiter überprüft und die Einstellung von minderjährigen Mitarbeitern verhindert., +"Select Date of joining. It will have impact on the first salary calculation, Leave allocation on pro-rata bases.",Wählen Sie Eintrittsdatum. Es wirkt sich auf die erste Gehaltsberechnung und die Zuteilung von Abwesenheiten auf Pro-rata-Basis aus., +Select Dimension,Dimension auswählen, +Select Items for Quality Inspection,Artikel für die Qualitätsprüfung auswählen, +Select Job Worker Address,Unterauftragnehmer Adresse auswählen, +Service Expenses,Wartungsaufwand, +Service Level Agreement for {0} {1} already exists.,Service Level Agreement für {0} {1} existiert bereits., +System Settings,Systemverwaltung, +Website Script,Webseiten-Skript, +Website Theme,Webseiten-Thema, +Workflow Action,Workflow-Aktion, +Workflow State,Workflow-Status, +{0} is not running. Cannot trigger events for this Document,{0} läuft nicht. Ereignisse für dieses Dokument können nicht ausgelöst werden, From cd5994017c6960d6d357784e111e3e825a8cad18 Mon Sep 17 00:00:00 2001 From: creative-paramu Date: Sun, 30 Jun 2024 20:37:09 +0530 Subject: [PATCH 20/28] fix: bank reconcilation tool cost center company filter adding (cherry picked from commit 6e2ac09821c7a5de93a12dfb4289ec0be9582e8a) --- .../public/js/bank_reconciliation_tool/dialog_manager.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js index 6ff38f91082..1ce6fea0c9e 100644 --- a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js +++ b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js @@ -374,6 +374,13 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager { label: "Cost Center", options: "Cost Center", depends_on: "eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'", + get_query: () => { + return { + filters: { + company: this.company, + }, + }; + }, }, { fieldtype: "Section Break", From b96361e837d1303d42b22cf7a29910c9bf2d2078 Mon Sep 17 00:00:00 2001 From: Parameshwari Palanisamy <101092028+creative-paramu@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:15:37 +0530 Subject: [PATCH 21/28] refactor: update dialog_manager.js (cherry picked from commit 6d19aae423c9684740a2b08ddcbc20f13da6e849) --- erpnext/public/js/bank_reconciliation_tool/dialog_manager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js index 1ce6fea0c9e..bab25b6eca2 100644 --- a/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js +++ b/erpnext/public/js/bank_reconciliation_tool/dialog_manager.js @@ -377,6 +377,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager { get_query: () => { return { filters: { + is_group: 0, company: this.company, }, }; From f547befeb9f366311f2d9c874498193745d825c3 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 18 Jul 2024 12:14:53 +0530 Subject: [PATCH 22/28] fix: Create Sales Order from Quotation for Prospect (cherry picked from commit 2f63fae31da75425f01f5c7c8d57d72514b3eb9f) # Conflicts: # erpnext/selling/doctype/quotation/quotation.py --- erpnext/crm/doctype/prospect/test_prospect.py | 20 ++++++ .../selling/doctype/customer/customer.json | 9 +++ erpnext/selling/doctype/customer/customer.py | 1 + .../selling/doctype/quotation/quotation.py | 61 +++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index c3930ee6c93..286b91e2086 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -27,6 +27,26 @@ class TestProspect(unittest.TestCase): address_doc.reload() self.assertEqual(address_doc.has_link("Prospect", prospect_doc.name), True) + def test_make_customer_from_prospect(self): + from erpnext.crm.doctype.prospect.prospect import make_customer as make_customer_from_prospect + + frappe.delete_doc_if_exists("Customer", "_Test Prospect") + + prospect = frappe.get_doc({ + "doctype": "Prospect", + "company_name": "_Test Prospect", + "customer_group": "_Test Customer Group", + }) + prospect.insert() + + customer = make_customer_from_prospect("_Test Prospect") + + self.assertEqual(customer.doctype, "Customer") + self.assertEqual(customer.company_name, "_Test Prospect") + self.assertEqual(customer.customer_group, "_Test Customer Group") + + customer.company = "_Test Company" + customer.insert() def make_prospect(**args): args = frappe._dict(args) diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index af32f4ecf84..59f082431b8 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -21,6 +21,7 @@ "gender", "lead_name", "opportunity_name", + "prospect_name", "account_manager", "image", "defaults_tab", @@ -570,6 +571,14 @@ { "fieldname": "column_break_nwor", "fieldtype": "Column Break" + }, + { + "fieldname": "prospect_name", + "fieldtype": "Link", + "label": "From Prospect", + "no_copy": 1, + "options": "Prospect", + "print_hide": 1 } ], "icon": "fa fa-user", diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 71f0022df14..9bd9b5e760a 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -77,6 +77,7 @@ class Customer(TransactionBase): payment_terms: DF.Link | None portal_users: DF.Table[PortalUser] primary_address: DF.Text | None + prospect_name: DF.Link | None represents_company: DF.Link | None sales_team: DF.Table[SalesTeam] salutation: DF.Link | None diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index f9442204df1..f48f8a88712 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -516,6 +516,7 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): if not customer_name: from erpnext.crm.doctype.lead.lead import _make_customer +<<<<<<< HEAD customer_doclist = _make_customer(lead_name, ignore_permissions=ignore_permissions) customer = frappe.get_doc(customer_doclist) customer.flags.ignore_permissions = ignore_permissions @@ -535,6 +536,25 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): except frappe.MandatoryError as e: mandatory_fields = e.args[0].split(":")[1].split(",") mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] +======= + # Check if a Customer already exists for the Lead or Prospect. + existing_customer = None + if quotation.quotation_to == "Lead": + existing_customer = frappe.db.get_value("Customer", {"lead_name": quotation.party_name}) + elif quotation.quotation_to == "Prospect": + existing_customer = frappe.db.get_value("Customer", {"prospect_name": quotation.party_name}) + + if existing_customer: + return frappe.get_doc("Customer", existing_customer) + + # If no Customer exists, create a new Customer or Prospect. + if quotation.quotation_to == "Lead": + return create_customer_from_lead(quotation.party_name, ignore_permissions=ignore_permissions) + elif quotation.quotation_to == "Prospect": + return create_customer_from_prospect(quotation.party_name, ignore_permissions=ignore_permissions) + + return None +>>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) frappe.local.message_log = [] lead_link = frappe.utils.get_link_to_form("Lead", lead_name) @@ -545,8 +565,49 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): message += "
  • " + "
  • ".join(mandatory_fields) + "
" message += _("Please create Customer from Lead {0}.").format(lead_link) +<<<<<<< HEAD frappe.throw(message, title=_("Mandatory Missing")) else: return customer_name else: return frappe.get_doc("Customer", quotation.get("party_name")) +======= +def create_customer_from_lead(lead_name, ignore_permissions=False): + from erpnext.crm.doctype.lead.lead import _make_customer + + customer = _make_customer(lead_name, ignore_permissions=ignore_permissions) + customer.flags.ignore_permissions = ignore_permissions + + try: + customer.insert() + return customer + except frappe.MandatoryError as e: + handle_mandatory_error(e, customer, lead_name) + + +def create_customer_from_prospect(prospect_name, ignore_permissions=False): + from erpnext.crm.doctype.prospect.prospect import make_customer as make_customer_from_prospect + + customer = make_customer_from_prospect(prospect_name) + customer.flags.ignore_permissions = ignore_permissions + + try: + customer.insert() + return customer + except frappe.MandatoryError as e: + handle_mandatory_error(e, customer, prospect_name) + + +def handle_mandatory_error(e, customer, lead_name): + from frappe.utils import get_link_to_form + + mandatory_fields = e.args[0].split(":")[1].split(",") + mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] + + frappe.local.message_log = [] + message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" + message += "
  • " + "
  • ".join(mandatory_fields) + "
" + message += _("Please create Customer from Lead {0}.").format(get_link_to_form("Lead", lead_name)) + + frappe.throw(message, title=_("Mandatory Missing")) +>>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) From 549dc286d03a7ae267b5e2742704dd9f023ee363 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 18 Jul 2024 12:24:52 +0530 Subject: [PATCH 23/28] fix: update the testcase format (cherry picked from commit 29d50b770e3d8de745a75cecbf18c0d745c4de6f) --- erpnext/crm/doctype/prospect/test_prospect.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index 286b91e2086..e89bade19a1 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -32,11 +32,13 @@ class TestProspect(unittest.TestCase): frappe.delete_doc_if_exists("Customer", "_Test Prospect") - prospect = frappe.get_doc({ - "doctype": "Prospect", - "company_name": "_Test Prospect", - "customer_group": "_Test Customer Group", - }) + prospect = frappe.get_doc( + { + "doctype": "Prospect", + "company_name": "_Test Prospect", + "customer_group": "_Test Customer Group", + } + ) prospect.insert() customer = make_customer_from_prospect("_Test Prospect") From 33542cb9097751492204d6ec3b0fe3573dbddf36 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 18 Jul 2024 12:26:23 +0530 Subject: [PATCH 24/28] fix: update the testcase format (cherry picked from commit ee44022249c39bc17d9cbf29c854c64c41f9a911) --- erpnext/crm/doctype/prospect/test_prospect.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index e89bade19a1..47e38515cac 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -50,6 +50,7 @@ class TestProspect(unittest.TestCase): customer.company = "_Test Company" customer.insert() + def make_prospect(**args): args = frappe._dict(args) From 5d7fb1d9457c276d6bd91c66546f001f56fdb728 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:31:49 +0530 Subject: [PATCH 25/28] fix: create SO from Quot for Prospect --conflicts --- .../selling/doctype/quotation/quotation.py | 63 ++++--------------- 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index f48f8a88712..bf2c166069f 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -347,8 +347,8 @@ def make_sales_order(source_name: str, target_doc=None): return _make_sales_order(source_name, target_doc) -def _make_sales_order(source_name, target_doc=None, customer_group=None, ignore_permissions=False): - customer = _make_customer(source_name, ignore_permissions, customer_group) +def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): + customer = _make_customer(source_name, ignore_permissions) ordered_items = frappe._dict( frappe.db.get_all( "Sales Order Item", @@ -502,41 +502,17 @@ def _make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): return doclist -def _make_customer(source_name, ignore_permissions=False, customer_group=None): +def _make_customer(source_name, ignore_permissions=False): quotation = frappe.db.get_value( - "Quotation", source_name, ["order_type", "party_name", "customer_name"], as_dict=1 + "Quotation", + source_name, + ["order_type", "quotation_to", "party_name", "customer_name"], + as_dict=1, ) - if quotation and quotation.get("party_name"): - if not frappe.db.exists("Customer", quotation.get("party_name")): - lead_name = quotation.get("party_name") - customer_name = frappe.db.get_value( - "Customer", {"lead_name": lead_name}, ["name", "customer_name"], as_dict=True - ) - if not customer_name: - from erpnext.crm.doctype.lead.lead import _make_customer + if quotation.quotation_to == "Customer": + return frappe.get_doc("Customer", quotation.party_name) -<<<<<<< HEAD - customer_doclist = _make_customer(lead_name, ignore_permissions=ignore_permissions) - customer = frappe.get_doc(customer_doclist) - customer.flags.ignore_permissions = ignore_permissions - customer.customer_group = customer_group - - try: - customer.insert() - return customer - except frappe.NameError: - if frappe.defaults.get_global_default("cust_master_name") == "Customer Name": - customer.run_method("autoname") - customer.name += "-" + lead_name - customer.insert() - return customer - else: - raise - except frappe.MandatoryError as e: - mandatory_fields = e.args[0].split(":")[1].split(",") - mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] -======= # Check if a Customer already exists for the Lead or Prospect. existing_customer = None if quotation.quotation_to == "Lead": @@ -554,24 +530,8 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): return create_customer_from_prospect(quotation.party_name, ignore_permissions=ignore_permissions) return None ->>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) - frappe.local.message_log = [] - lead_link = frappe.utils.get_link_to_form("Lead", lead_name) - message = ( - _("Could not auto create Customer due to the following missing mandatory field(s):") - + "
" - ) - message += "
  • " + "
  • ".join(mandatory_fields) + "
" - message += _("Please create Customer from Lead {0}.").format(lead_link) -<<<<<<< HEAD - frappe.throw(message, title=_("Mandatory Missing")) - else: - return customer_name - else: - return frappe.get_doc("Customer", quotation.get("party_name")) -======= def create_customer_from_lead(lead_name, ignore_permissions=False): from erpnext.crm.doctype.lead.lead import _make_customer @@ -605,9 +565,10 @@ def handle_mandatory_error(e, customer, lead_name): mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] frappe.local.message_log = [] - message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" + message = ( + _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" + ) message += "
  • " + "
  • ".join(mandatory_fields) + "
" message += _("Please create Customer from Lead {0}.").format(get_link_to_form("Lead", lead_name)) frappe.throw(message, title=_("Mandatory Missing")) ->>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) From ec0201cb85f0c46a92993c6082b51507091dffd9 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:34:27 +0530 Subject: [PATCH 26/28] fix: create SO from Quot for Prospect --conflicts --- erpnext/selling/doctype/quotation/quotation.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index bf2c166069f..2a4b04b9db5 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -565,9 +565,7 @@ def handle_mandatory_error(e, customer, lead_name): mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] frappe.local.message_log = [] - message = ( - _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" - ) + message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" message += "
  • " + "
  • ".join(mandatory_fields) + "
" message += _("Please create Customer from Lead {0}.").format(get_link_to_form("Lead", lead_name)) From 1040198ce1a4077ec88d9f36adb7db792779e2ab Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:24:31 +0530 Subject: [PATCH 27/28] perf: asset creation from purchase receipt (cherry picked from commit 6e84fc5143f8bbc36babbd608aff161f65550bc5) --- erpnext/assets/doctype/asset/asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 76eeca03ab5..db37e54ada8 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -904,7 +904,7 @@ def transfer_asset(args): @frappe.whitelist() def get_item_details(item_code, asset_category, gross_purchase_amount): - asset_category_doc = frappe.get_doc("Asset Category", asset_category) + asset_category_doc = frappe.get_cached_doc("Asset Category", asset_category) books = [] for d in asset_category_doc.finance_books: books.append( From ae6c1a30ac0f8d99de5d4a3868ca8c328fcd1e46 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:03:23 +0530 Subject: [PATCH 28/28] refactor: brand js and allow quick entry (backport #42829) (#42830) * refactor: brand js and allow quick entry (#42829) * refactor: brand js and allow quick entry * refactor: brand js and allow quick entry --prettier * refactor: brand js and allow quick entry --prettier (cherry picked from commit a1183f01652567dc4d7fdfa250dfd428cfe1dcda) # Conflicts: # erpnext/setup/doctype/brand/brand.json * refactor: brand js and allow quick entry --refactor --------- Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com> --- erpnext/setup/doctype/brand/brand.js | 56 +++++++------------------- erpnext/setup/doctype/brand/brand.json | 5 ++- 2 files changed, 17 insertions(+), 44 deletions(-) diff --git a/erpnext/setup/doctype/brand/brand.js b/erpnext/setup/doctype/brand/brand.js index 5d16d734e0f..99b4ace6cd2 100644 --- a/erpnext/setup/doctype/brand/brand.js +++ b/erpnext/setup/doctype/brand/brand.js @@ -3,22 +3,14 @@ frappe.ui.form.on("Brand", { setup: (frm) => { - frm.fields_dict["brand_defaults"].grid.get_field("default_warehouse").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("default_warehouse", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { filters: { company: row.company }, }; - }; + }); - frm.fields_dict["brand_defaults"].grid.get_field("default_discount_account").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("default_discount_account", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { filters: { @@ -27,13 +19,9 @@ frappe.ui.form.on("Brand", { is_group: 0, }, }; - }; + }); - frm.fields_dict["brand_defaults"].grid.get_field("buying_cost_center").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("buying_cost_center", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { filters: { @@ -41,25 +29,17 @@ frappe.ui.form.on("Brand", { company: row.company, }, }; - }; + }); - frm.fields_dict["brand_defaults"].grid.get_field("expense_account").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("expense_account", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { query: "erpnext.controllers.queries.get_expense_account", filters: { company: row.company }, }; - }; + }); - frm.fields_dict["brand_defaults"].grid.get_field("default_provisional_account").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("default_provisional_account", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { filters: { @@ -68,13 +48,9 @@ frappe.ui.form.on("Brand", { is_group: 0, }, }; - }; + }); - frm.fields_dict["brand_defaults"].grid.get_field("selling_cost_center").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("selling_cost_center", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { filters: { @@ -82,18 +58,14 @@ frappe.ui.form.on("Brand", { company: row.company, }, }; - }; + }); - frm.fields_dict["brand_defaults"].grid.get_field("income_account").get_query = function ( - doc, - cdt, - cdn - ) { + frm.set_query("income_account", "brand_defaults", function (doc, cdt, cdn) { const row = locals[cdt][cdn]; return { query: "erpnext.controllers.queries.get_income_account", filters: { company: row.company }, }; - }; + }); }, }); diff --git a/erpnext/setup/doctype/brand/brand.json b/erpnext/setup/doctype/brand/brand.json index 45b4db81f1f..8511d221551 100644 --- a/erpnext/setup/doctype/brand/brand.json +++ b/erpnext/setup/doctype/brand/brand.json @@ -56,10 +56,11 @@ "idx": 1, "image_field": "image", "links": [], - "modified": "2021-03-01 15:57:30.005783", + "modified": "2024-08-20 14:10:21.377962", "modified_by": "Administrator", "module": "Setup", "name": "Brand", + "naming_rule": "By fieldname", "owner": "Administrator", "permissions": [ { @@ -108,4 +109,4 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "ASC" -} \ No newline at end of file +}