How to create user with a particular role (on Workflow Submit/Approval) using Server Side Scripting?

Hello,

I am trying to create a user with the a role ‘Vendor’ using server side scripting. I tried with the following code, but it’s not working. I don’t see any errors but there is a sound that pops up.

# Check if a user with this email address already exists
if frappe.db.exists("User", doc.vendor_email):
    frappe.msgprint(_("A user with this email address already exists."))
else:
    user = frappe.get_doc({
        "doctype": "User",
        "email": doc.vendor_email,
        "first_name": doc.vendor_name,
        "roles": [
            {
                "doctype": "Has Role", 
                "role": "Vendor"
            }
        ]
    }).insert()
    
    frappe.msgprint("A user was created with email "+ doc.vendor_email);

Can you please help me make this work? I just started tinkering around with frappe last week. Thanks

Already have a very similar use-case, I use module profiles and role profiles instead of hard coding anything just for scalability.
Commented out things that you might/might not need.

Tested and works on both V13 and V14

Trigger: Before Submit

if frappe.db.exists("User", doc.vendor_email):
    frappe.msgprint("The email address " + doc.vendor_email + " is already in use.")

#Might also want to validate the email address using regex here.

else:
aa = frappe.get_doc({
    "doctype": "User",
    "first_name": doc.vendor_name,
   #"last_name": "",
    "email": doc.vendor_email,
   #"username": doc.username,
   #"send_welcome_email": 0,
   #"module_profile": doc.module_profiles,
    "roles": [
        {
            "role": doc.role_profile_name
            #To hard code it, create a role profile with only the role vendor
        }
    ]
})
aa.flags.ignore_mandatory = True;
aa.run_method("onload");
aa.run_method("set_missing_value");
aa.insert();
#aa.new_password = doc.get_password("password");
aa.save();
frappe.msgprint("A user with the email " + doc.vendor_email + " has been created");
1 Like

Thank you for taking your time to reply. I tried this code but unfortunately it is still not working. Is there anything that needs to be taken care of in the role permissions or somewhere else before implementing this solution?

On the user doc that is created use add_roles function.

user = frappe.get_doc(
			{
				"doctype": "User",
				"first_name": self.first_name,
				"last_name": self.last_name,
				"email": self.email,
				"user_type": "Website User",
				"gender": self.sex,
				"phone": self.phone,
				"mobile_no": self.mobile,
				"birth_date": self.dob,
			}
		)
		user.flags.ignore_permissions = True
		user.enabled = True
		user.send_welcome_email = True
		user.add_roles("Patient")
		self.db_set("user_id", user.name)
1 Like

Hi,

Based on your suggestion, I tried with the following code but it is till not working. Please advise.]

if frappe.db.exists("User", doc.vendor_email):
    frappe.msgprint("The email address " + doc.vendor_email + " is already in use.")

#Might also want to validate the email address using regex here.

else:
    aa = frappe.get_doc({
        "doctype": "User",
        "first_name": doc.vendor_name,
        "email": doc.vendor_email
    });
    aa.enabled = True;
    aa.user_type = "System User"
    aa.flags.ignore_permissions = True;
    aa.add_roles("Vendor");
    aa.insert();
    aa.save();
    aa.submit();

    frappe.msgprint("A user with the email " + doc.vendor_email + " has been created");

use something like this

def create_user(self, method, role=None):
    if frappe.db.exists("User", {'mobile_no': self.cell_number}):
        frappe.throw(_("Mobile No already allocated to another User"))
    if frappe.db.exists("User", {'email': self.personal_email}):
        frappe.throw(_("Email ID is already allocated to another User"))
    new_user = frappe.get_doc({
        "doctype": "User",
        "first_name": self.first_name,
        "last_name": self.last_name,
        "email": self.personal_email,
        "send_welcome_email": 0,
        "gender": self.gender,
        "phone": self.cell_number,
        "mobile_no": self.cell_number,
        "username": self.cell_number,
        "role_profile_name": 'Employee',
        "roles": [{"doctype": "Has Role", "role": 'Employee'}]
    })
    try:
        new_user.insert(ignore_permissions=True)
    except:
        frappe.log_error(
            title="User creation error while creating new employee",
            message=frappe.get_traceback()
        )
1 Like

Thank you everyone for helping me out. I was able to finally achieve what I needed using the following code.

if frappe.db.exists("User", doc.vendor_email):
    frappe.msgprint("The email address " + doc.vendor_email + " is already in use.")


else:
    new_user = frappe.get_doc({
        "doctype": "User",
        "first_name": doc.vendor_name,
        "email": doc.vendor_email,
        "send_welcome_email": 0,
        "roles": [{"doctype": "Has Role", "role": 'Vendor'}]
    })
    try:
        new_user.insert(ignore_permissions=True)
    except:
        frappe.log_error(
            title="User creation error while creating new vendor",
            message=frappe.get_traceback()
        )