Automating Unique Customer Name Generation for Walk-In Customers in ERPNext

I run a shop where new customers frequently arrive. Instead of creating a generic “Walk-In” customer, I’d like to automatically generate unique customer names for walk-ins.

To achieve this, I have created a “Walk-In Customer Group” and intend to write a script (most likely a Server Script) that generates the customer name automatically when I’m adding a new walk-in. The name should include the date and time (e.g., Walk-In|2024-Dec-23|15:03:01).

Here’s what I’ve done so far:

  1. I enabled Server Scripts on my server for the site and verified that it is working correctly.
    
  2. I navigated to the Server Script section in ERPNext and created a new script with the following parameters:
    
  • Script Type: “DocType Event”
  • Reference Document Type: “Customer”
  • DocType Event: “Before Save”

The script I created is as follows:

def before_save(doc, method):
    # Check if the customer belongs to the "Walk-in Customer Group"
    if doc.customer_group == "Walk-in Customer Group":
        # Get the current date and time
        current_datetime = frappe.utils.now()
        
        # Generate the prefix
        prefix = "WALK-IN"
        
        # If the customer name is empty, generate a new name
        if not doc.customer_name:
            # Format the new customer name with the prefix and datetime
            new_name = f"{prefix}-{current_datetime}"
            doc.customer_name = new_name

However this did not generate a Customer name.
Can you help me?

I also tried with the event “Before Validate” and again it did not work

Should it be a Client Script, given that I am creating new clients in my browser?

Hello,
No you shouldn’t do it through a client script, however that is not the way to create server scripts through Frappe’s UI.

  • Create a server script doc
  • Set the trigger as before_insert
  • Attach the related doctype (Customer)

In your script, you don’t have to define before insert method since you already set it as a trigger. Simply you would write something like this


current_date = frappe.utils.today().replace('-', '')

last_customer = frappe.get_last_doc("Customer", 
            filters={"customer_name": ["like", f"WALK-IN-{current_date}-%"]},
            order_by="customer_name desc"
        )
        
if last_customer:
   last_num = int(last_customer.customer_name.split('-')[-1])
   new_num = str(last_num + 1).zfill(3)
else:
   new_num = '001'

doc.customer_name = f'WALK-IN-{current_date}-{new_num}'
    

Note: indentation might be wrong I am using my phone

Why go through all this trouble? Why not just set up a naming series for the Customer doctype?

In Selling Settings, you can set the “Customer Naming By” to “Naming Series”. Then set up your naming series in “Document Naming Settings”.

Hi Yamen,

Thanks for your response. It was very helpful.

I edited the code and added a custom Check box called Generate Customer Name, which when checked it provides a generated number using the mechanism that you provided.

One last question. The code only seems to work if I use “Before Insert” and only if I have entered manually a Customer name which it overrides. Otherwise the code does not get passed the Mandatory field check which detects that teh Name field is empty

I wanted to make this run without the need to enter a dummy name. It does not work on “Before Validate” or “Before Save” as they both fail on that same Mandatory field detection of empty customer name

This is the current code:

# Check if the customer belongs to the "Walk-in Customer Group" and the customer_name is empty
if doc.custom_generate_customer_name == True and doc.cusomer_group == "Walk-in Customer Group":
    # Get the current date in YYYYMMDD format
    current_date = frappe.utils.today().replace('-', '')

    # Find the last customer with a similar name pattern
    last_customer = frappe.db.get_value(
        "Customer",
        filters={"customer_name": ["like", f"WALK-IN-{current_date}-%"]},
        fieldname="customer_name",
        order_by="customer_name DESC"
    )

    # Determine the next sequence number
    if last_customer:
        # Extract the sequence number from the last customer's name
        last_num = int(last_customer.split('-')[-1])
        new_num = str(last_num + 1).zfill(3)
    else:
        # Start from 001 if no matching customers exist
        new_num = '001'

    # Assign the new customer name
    doc.customer_name = f'WALK-IN-{current_date}-{new_num}'

Many thanks

Because it is not always the case that I want a customer name to be auto-generated.

  • If it is a walk-in customer, then I want it auto-generated.

  • If it is a retail or business customer that shares their information with me, then I want to be able to enter their details manually.

You can try using this
https://docs.frappe.io/framework/user/en/api/document#frapperename_doc

Regarding the naming series solution, I think the naming rule doctype can achieve a similar result check this

Then you could create multiple options for your naming series and then select which one to use when entering the details.

If you want more granularity, then you could create a server script with autoname.