Auto naming through Server script - ERPNext
In some ERP customizations, you may want the Item Code to follow a dynamic, logic-based naming series that reflects business parameters like brand, business group, or purchase group.
Goals
- Automatically generate item_code using logic based on business_group, purchase_group, and brand_code.
- Maintain a custom_temp_item_name field to temporarily store the user-entered name.
- Ensure item_name does not get overwritten by the new item_code.
- Optionally store and manage series tracking outside of the Item table.
Step 1: Server Script for Custom Naming (Before Insert)
Script Name: Item-auto-name
Trigger: Before Insert
Target Doctype: Item
This script builds a naming series prefix using the first letters of business_group, purchase_group, and full brand_code, then queries the DB to determine the last used code and increments from there.
# Build the prefixfirst_letter_business_group = (doc.business_group or "")[:1].upper()first_letter_purchase_group = (doc.purchase_group or "")[:1].upper()brand_code = (doc.brand_code or "").upper()series_digits = 6series_prefix = f"{first_letter_business_group}{first_letter_purchase_group}{brand_code} "# Find the last matching item_codelast_item = frappe.db.sql("""SELECT name FROM `tabItem`WHERE name LIKE %sORDER BY LENGTH(name) DESC, name DESCLIMIT 1""",(series_prefix + "%",),as_dict=True)if last_item:last_name = last_item[0]["name"]last_number = last_name.replace(series_prefix, "")try:next_number = int(last_number) + 1except ValueError:next_number = 1else:next_number = 1# Assign new item_codedoc.item_code = f"{series_prefix}{str(next_number).zfill(series_digits)}"
Step 2: Client Script to Copy
item_name
to Temp Field
ERPNext automatically sets item_name = item_code during the insert process. To preserve what the user originally typed in item_name, we copy it live into a custom field.
Custom Field Required: custom_temp_item_name (Data type)
Client Script: item-copy-item-name-to-temp
frappe.ui.form.on('Item', {item_name: function(frm, cdt, cdn) {let row = locals[cdt][cdn];frappe.model.set_value(cdt, cdn, 'custom_temp_item_name', row.item_name);}});
Step 3: Server Script to Restore Name (Before Validate)
During validation, restore the original item_name from the custom_temp_item_name field.
Script Name: item-before-validate
Trigger: Before Validate
doc.item_name = doc.custom_temp_item_name
Optional Enhancement: Use a Custom DocType to Track Series
Server Scripts do not support frappe.model.naming.set_name_by_naming_series() directly. To decouple naming logic from the Item table and avoid SQL queries, you can manage the series in a separate DocType.
Example Custom DocType:
Item Series Tracker
Fields:
- prefix (Data, unique key)
- last_number (Int)
Sample Usage in Server Script:
prefix = f"{first_letter_business_group}{first_letter_purchase_group}{brand_code}"series_doc = frappe.get_doc('Item Series Tracker', prefix) if frappe.db.exists('Item Series Tracker', prefix) else frappe.get_doc({'doctype': 'Item Series Tracker','prefix': prefix,'last_number': 0})series_doc.last_number += 1series_doc.save()doc.item_code = f"{prefix} {str(series_doc.last_number).zfill(series_digits)}"
This approach:
- Avoids raw SQL.
- Gives you versionable, audit-friendly control over series.
- Supports concurrency-safe item code generation.
----------------------------------------
Feature Recommendation: Support Naming Functions in Server Scripts
Problem Statement
Currently, server scripts in Frappe do not support built-in naming utilities like:
- frappe.model.naming.make_autoname()
- frappe.model.naming.set_name_by_naming_series()
This limitation forces developers to either:
- Write raw SQL queries to simulate naming series (which is risky and hard to scale), or
- Fall back to custom apps and hooks (e.g., before_insert or autoname in Python), which requires full developer access and a deployment cycle.
However, naming logic is often a business-level decision, not a developer decision.
Why Naming Should Be a Server Script Feature
- Business users and consultants often define naming patterns — based on attributes like region, brand, group, or fiscal year — without needing full app-level control.
- Server Scripts are designed for low-code/no-code flexibility and should allow complete document initialization — including naming.
- This enables faster prototyping, testing, and iteration, especially on hosted Frappe Cloud instances where app installation is restricted.
Suggested Solutions
- Allow frappe.model.naming methods in server script , especially:
- make_autoname
- set_name_by_naming_series

Aysha Mehrin Musthafa
Functional Consultant at ERPGulf
No comments yet. Start a new discussion.