mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-02 09:14:35 +00:00
fix: stop storing "{supplier_name}" / "{customer_name}" as the document title
Purchase Order, Sales Order and Subcontracting Order point title_field at the party name field, so Document.set_title_field() never rendered their title template and every new record stored the placeholder verbatim. On Purchase Order the field is also mandatory, so the junk value is guaranteed. Drop the dead defaults (and Purchase Order's reqd, which would otherwise make an always-empty field mandatory) and backfill the affected rows.
This commit is contained in:
@@ -171,14 +171,12 @@
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "{supplier_name}",
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Title",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"reqd": 1
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
@@ -1309,7 +1307,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-31 17:19:40.816883",
|
||||
"modified": "2026-07-28 12:20:11.284370",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -162,7 +162,7 @@ class PurchaseOrder(BuyingController):
|
||||
taxes_and_charges_deducted: DF.Currency
|
||||
tc_name: DF.Link | None
|
||||
terms: DF.TextEditor | None
|
||||
title: DF.Data
|
||||
title: DF.Data | None
|
||||
to_date: DF.Date | None
|
||||
total: DF.Currency
|
||||
total_net_weight: DF.Float
|
||||
|
||||
@@ -444,3 +444,4 @@ erpnext.patches.v16_0.crm_settings_handle_allowed_users_for_frappe_crm
|
||||
erpnext.patches.v16_0.backfill_pick_list_transferred_qty
|
||||
erpnext.patches.v16_0.access_control_for_project_users
|
||||
erpnext.patches.v16_0.rename_ar_ap_ageing_filter
|
||||
erpnext.patches.v15_0.fix_titles
|
||||
|
||||
20
erpnext/patches/v15_0/fix_titles.py
Normal file
20
erpnext/patches/v15_0/fix_titles.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
"""
|
||||
These doctypes point `title_field` at the party name field, so their `title`
|
||||
default was never rendered and got stored as the literal template string.
|
||||
"""
|
||||
|
||||
for doctype, source_field in (
|
||||
("Purchase Order", "supplier_name"),
|
||||
("Subcontracting Order", "supplier_name"),
|
||||
("Sales Order", "customer_name"),
|
||||
):
|
||||
table = frappe.qb.DocType(doctype)
|
||||
(
|
||||
frappe.qb.update(table)
|
||||
.set(table.title, table[source_field])
|
||||
.where(table.title == f"{{{source_field}}}")
|
||||
).run()
|
||||
@@ -187,7 +187,6 @@
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "{customer_name}",
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -1680,7 +1679,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-03-06 15:33:49.059029",
|
||||
"modified": "2026-07-28 12:20:44.130918",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "{supplier_name}",
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -465,7 +464,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-12-06 15:21:49.924146",
|
||||
"modified": "2026-07-28 12:21:09.663812",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Subcontracting",
|
||||
"name": "Subcontracting Order",
|
||||
|
||||
@@ -49,3 +49,18 @@ class TestInit(unittest.TestCase):
|
||||
from frappe.tests.test_patches import check_patch_files
|
||||
|
||||
check_patch_files("erpnext")
|
||||
|
||||
def test_no_unrendered_title_templates(self):
|
||||
modules = frappe.get_all("Module Def", filters={"app_name": "erpnext"}, pluck="name")
|
||||
for doctype in frappe.get_all("DocType", filters={"module": ("in", modules)}, pluck="name"):
|
||||
meta = frappe.get_meta(doctype)
|
||||
field = meta.get_field("title")
|
||||
if not field or not field.default or "{" not in field.default:
|
||||
continue
|
||||
|
||||
self.assertEqual(
|
||||
meta.title_field,
|
||||
"title",
|
||||
f"{doctype}: title default {field.default!r} is stored verbatim because "
|
||||
"Document.set_title_field() only renders it when title_field is 'title'",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user