I am working on a custom frappe app and I am trying to achieve something really simple. To reuse Address and Contact as seen on some ERPNext DocTypes.
I have included the necessary fields in my custom DocType Organization. I have also done the following:
in organization.py:
from future import unicode_literals
import frappe
import frappe
from frappe.model.document import Document
from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address
class Organization(Document):
def onload(self):
"""Load address and contacts in `__onload`"""
load_address_and_contact(self)
def on_update(self):
self.create_primary_contact()
self.create_primary_address()
def on_trash(self):
delete_contact_and_address('Organization', self.name)
def create_primary_contact(self):
if not self.org_primary_contact:
if self.mobile_no or self.email_id:
contact = make_contact(self)
self.db_set('org_primary_contact', contact.name)
self.db_set('mobile_no', self.mobile_no)
self.db_set('email_id', self.email_id)
def create_primary_address(self):
if self.flags.is_new_doc and self.get('address_line1'):
make_address(self)
def make_contact(args, is_primary_contact=1):
contact = frappe.get_doc({
'doctype': 'Contact',
'first_name': args.get('name'),
'is_primary_contact': is_primary_contact,
'links': [{
'link_doctype': args.get('doctype'),
'link_name': args.get('name')
}]
})
if args.get('email_id'):
contact.add_email(args.get('email_id'), is_primary=True)
if args.get('mobile_no'):
contact.add_phone(args.get('mobile_no'), is_primary_mobile_no=True)
contact.insert()
return contact
def make_address(args, is_primary_address=1):
reqd_fields = []
for field in ['city', 'country']:
if not args.get(field):
reqd_fields.append( '<li>' + field.title() + '</li>')
if reqd_fields:
msg = _("Following fields are mandatory to create address:")
frappe.throw("{0} <br><br> <ul>{1}</ul>".format(msg, '\n'.join(reqd_fields)),
title = _("Missing Values Required"))
address = frappe.get_doc({
'doctype': 'Address',
'address_title': args.get('name'),
'address_line1': args.get('address_line1'),
'address_line2': args.get('address_line2'),
'city': args.get('city'),
'state': args.get('state'),
'pincode': args.get('pincode'),
'country': args.get('country'),
'links': [{
'link_doctype': args.get('doctype'),
'link_name': args.get('name')
}]
}).insert()
return address
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_primary_contact(doctype, txt, searchfield, start, page_len, filters):
organization = filters.get('organization')
return frappe.db.sql("""
select `tabContact`.name from `tabContact`, `tabDynamic Link`
where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(organization)s
and `tabDynamic Link`.link_doctype = 'Organization'
and `tabContact`.name like %(txt)s
""", {
'organization': organization,
'txt': '%%%s%%' % txt
})
and in organization.js
frappe.ui.form.on(‘Organization’, {
setup: function(frm) {
frm.set_query('org_primary_contact', function(doc) {
return {
query: "cpm.setup.doctype.organization.organization.get_primary_contact",
filters: {
'organization': doc.name
}
}
})
frm.set_query('org_primary_address', function(doc) {
return {
filters: {
'link_doctype': 'Organization',
'link_name': doc.name
}
}
});
},
refresh: function(frm) {
frappe.dynamic_link = {doc: frm.doc, fieldname: 'org_name', doctype: 'Organization'}
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
if(!frm.doc.__islocal) {
frappe.contacts.render_address_and_contact(frm);
} else {
frappe.contacts.clear_address_and_contact(frm);
}
},
party_primary_address: function(frm){
if(frm.doc.org_primary_address){
frappe.call({
method: 'frappe.contacts.doctype.address.address.get_address_display',
args: {
"address_dict": frm.doc.org_primary_address
},
callback: function(r) {
frm.set_value("primary_address", r.message);
}
});
}
if(!frm.doc.org_primary_address){
frm.set_value("primary_address", "");
}
},
party_primary_contact: function(frm){
if(!frm.doc.org_primary_contact){
frm.set_value("mobile_no", "");
frm.set_value("email_id", "");
}
},
});
Still the Add new Contact and Add new Address buttons are not rendering. Also Primary Contact filter raises the error
AttributeError: module ‘cpm.setup.doctype.organization.organization’ has no attribute ‘get_primary_contact’
What am I doing wrong here? Help please. Thanks.