Try ERPNext Buy Support Partners Foundation Foundation Members

[v12] timeline_links on Communication doctype... when using frappe.core.doctype.communication.email.make

Hey all,

Been using from frappe.core.doctype.communication.email import make since v10 days and during migration to v12 have noticed I’m getting an error relating to sending emails and attaching the communication to a Sales Order. The errors I’m getting when using console are:

from frappe.core.doctype.communication.email import make as send_email
send_email(doctype='Sales Order', name='SO-2019-00001', content='test message', recipients='myemailaddress@mydomain.com', send_email=True)

call stack:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/frappe/frappe-bench/apps/frappe/frappe/commands/utils.py in <module>()
----> 1 send_email(doctype='Sales Order', name='SO-2019-00001', content='test message', recipients='myemailaddress@mydomain.com', send_email=True)

/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/communication/email.py in make(doctype, name, content, subject, sent_or_received, sender, sender_full_name, recipients, communication_medium, send_email, print_html, print_format, attachments, send_me_a_copy, cc, bcc, flags, read_receipt, print_letterhead, email_template)
     71                 "read_receipt":read_receipt,
     72                 "has_attachment": 1 if attachments else 0
---> 73 	}).insert(ignore_permissions=True)
     74
     75         comm.save(ignore_permissions=True)

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py in insert(self, ignore_permissions, ignore_links, ignore_if_duplicate, ignore_mandatory)
    226
    227                 self.flags.in_insert = True
--> 228                 self.run_before_save_methods()
    229                 self._validate()
    230                 self.set_docstatus()

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py in run_before_save_methods(self)
    884                 if self._action=="save":
    885                         self.run_method("before_validate")
--> 886                         self.run_method("validate")
    887                         self.run_method("before_save")
    888                 elif self._action=="submit":

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py in run_method(self, method, *args, **kwargs)
    784
    785                 fn.__name__ = str(method)
--> 786                 out = Document.hook(fn)(self, *args, **kwargs)
    787
    788                 self.run_notifications(method)

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py in composer(self, *args, **kwargs)
   1054
   1055                         composed = compose(f, *hooks)
-> 1056                         return composed(self, method, *args, **kwargs)
   1057
   1058                 return composer

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py in runner(self, method, *args, **kwargs)
   1037                 def compose(fn, *hooks):
   1038                         def runner(self, method, *args, **kwargs):
-> 1039                                 add_to_return_value(self, fn(self, *args, **kwargs))
   1040                                 for f in hooks:
   1041                                         add_to_return_value(self, f(self, method, *args, **kwargs))

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py in <lambda>(self, *args, **kwargs)
    778
    779                 if hasattr(self, method) and hasattr(getattr(self, method), "__call__"):
--> 780                         fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
    781                 else:
    782                         # hack! to run hooks even if method does not exist

/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/communication/communication.py in validate(self)
     63                 if self.communication_medium == "Email":
     64                         self.parse_email_for_timeline_links()
---> 65                         self.set_timeline_links()
     66                         self.deduplicate_timeline_links()
     67

/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/communication/communication.py in set_timeline_links(self)
    261                 contacts = get_contacts([self.sender, self.recipients, self.cc, self.bcc])
    262                 for contact_name in contacts:
--> 263                         self.add_link('Contact', contact_name)
    264
    265                         #link contact's dynamic links to communication

/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/communication/communication.py in add_link(self, link_doctype, link_name, autosave)
    286 			{
    287                                 "link_doctype": link_doctype,
--> 288                                 "link_name": link_name
    289 			}
    290 		)

/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py in append(self, key, value)
    147                         if not self.__dict__.get(key):
    148                                 self.__dict__[key] = []
--> 149                         value = self._init_child(value, key)
    150                         self.__dict__[key].append(value)
    151

/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py in _init_child(self, value, key)
    182                 if not isinstance(value, BaseDocument):
    183                         if "doctype" not in value or value['doctype'] is None:
--> 184                                 value["doctype"] = self.get_table_field_doctype(key)
    185                                 if not value["doctype"]:
    186                                         raise AttributeError(key)

/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py in get_table_field_doctype(self, fieldname)
    296
    297         def get_table_field_doctype(self, fieldname):
--> 298                 return self.meta.get_field(fieldname).options
    299
    300         def get_parentfield_of_doctype(self, doctype):

AttributeError: 'NoneType' object has no attribute 'options'

It would seem its trying to access the timeline_links property of the Communication doctype, and not getting the options.

can you help?

Might have solved this one by simply forcing another version-12 update, must have been in the most recent patch. v12.0.15