Script error Tutorial ERPNext

I’m on the part of create button to send e-mail of the tutorial of app development.

File “/home/frappe/frappe-bench/apps/frappe/frappe/desk/form/save.py”, line 22, in savedocs
doc.save()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 230, in save
return self._save(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 263, in _save
self.run_before_save_methods()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 771, in run_before_save_methods
self.run_method(“validate”)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 666, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 891, in composer
return composed(self, method, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 874, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 660, in
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/meeting/meeting/meeting/doctype/meeting/meeting.py”, line 16, in validate
if attendee.attendee in found:
NameError: global name ‘found’ is not defined

Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 55, in application
response = frappe.handler.handle()
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 21, in handle
data = execute_cmd(cmd)
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 52, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 907, in call
return fn(*args, **newargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/desk/form/save.py”, line 22, in savedocs
doc.save()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 230, in save
return self._save(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 263, in _save
self.run_before_save_methods()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 771, in run_before_save_methods
self.run_method(“validate”)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 666, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 891, in composer
return composed(self, method, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 874, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 660, in
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/meeting/meeting/meeting/doctype/meeting/meeting.py”, line 16, in validate
if attendee.attendee in found:
NameError: global name ‘found’ is not defined

Can you share your meeting.py code? Looks like found isn’t declared before line 16.

Sure!

frappe.ui.form.on(“meeting”, {
send_email: function(frm) {
if (frm.doc.status === “Planned”) {
frappe.call({
method: “meeting.api.send_invitation_emails”,
args: {
meeting: frm.doc.name
}
});
}
},
});

frappe.ui.form.on(“meeting attendee”, {
attendee: function(frm, cdt, cdn) {
var attendee = frappe.model.get_doc(cdt, cdn);
if (attendee.attendee){
//if attendee, get full name
frappe.call({
method: “meeting.meeting.doctype.meeting.meeting.get_full_name”,
args: {
attendee: attendee.attendee
},
callback: function®{
frappe.model.set_value(cdt, cdn, “full_name”, r.message);
}
});
}
else {
//if no attendee clear full name
frappe.model.set_value(cdt, cdn, “full_name”, null);
}
},
});

This is the meeting.js file that you have posted. Please post the meeting.py file. That’s where the error points to.

meeting.py:
class meeting(Document):
def validate(self):
for attendee in self.attendees:
if not attendee.full_name:
attendee.full_name = get_full_name(attendee.attendee)

        if attendee.attendee in found:
            frappe.throw(_("Attendee {0} entered twice").format(attendee.attendee))

        found.append(attendee.attendee)

#mark this function
@frappe.whitelist()
def get_full_name(attendee):
user = frappe.get_doc(“User”, attendee)

#concatenate by name if it has value
return " ".join(filter(None, [user.first_name, user.middle_name, user.last_name]))

api.py:
import frappe

@frappe.whitelist()
def send_invitation_email(meeting):
meeting = frappe.get_doc(“meeting”, meeting)
meeting.check_permission(“email”)
if meeting.status == “Planned”:
frappe.sendmail(
recipients = [d.attendee for d in meeting.attendees],
sender = frappe.session.user,
subject = meeting.title,
message = meeting.invitation_message,
reference_doctype = meeting.doctype,
reference_name = meeting.name,
as_bulk = True
)

    meeting.status = "Invitation Sent"
    meeting.save()

    frappe.msgprint(_("Invitation Sent"))

else:
    frappe.msgprint(_("Meeting Status must be Planned"))

What’s @frappe.whitelist() ?

Hi
whitelisted methods allows you to call them from client side.
https://frappe.github.io/frappe/user/en/guides/basics/frappe_ajax_call

For your issue, simply add a found list

found = []

That should fix the first error you had.

Where i add this?

Anywhere before line 16 in the same method validate

The same error…
Code:
class meeting(Document):
def validate(self):
for attendee in self.attendees:
if not attendee.full_name:
attendee.full_name = get_full_name(attendee.attendee)

        if attendee.attendee in found:
            frappe.throw(_("Attendee {0} entered twice").format(attendee.attendee))
            found = []

        found.append(attendee.attendee)

'#mark this function
@frappe.whitelist()
def get_full_name(attendee):
user = frappe.get_doc(“User”, attendee)

#concatenate by name if it has value
return " ".join(filter(None, [user.first_name, user.middle_name, user.last_name]))'

It needs to be before found is previously referenced. Put it after the for attendee in self.attendee:

I’d suggest you take a course in python programming. It looks like a lot of the errors you’re having a related to python syntax.The forum here is a really good resource for working with the frappe and erpnext libraries, but isn’t meant to be for debugging everyones python or javascript code.

1 Like

Actually, thats not the place to add!
You are accessing the variable before its declared.
Add found right after def validate

def validate(self):
    found = []
    ...

Remove found = [] after the frappe.throw statement.

Hope it helps!