diff --git a/frappe/core/doctype/communication/email.py b/frappe/core/doctype/communication/email.py index 49e2f11ed0..7e0d12dda3 100755 --- a/frappe/core/doctype/communication/email.py +++ b/frappe/core/doctype/communication/email.py @@ -61,6 +61,10 @@ def make(doctype=None, name=None, content=None, subject=None, sent_or_received = }) comm.insert(ignore_permissions=True) + if not doctype: + # if no reference given, then send it against the communication + comm.db_set(dict(reference_doctype='Communication', reference_name=comm.name)) + # if not committed, delayed task doesn't find the communication frappe.db.commit() diff --git a/frappe/database.py b/frappe/database.py index 474038377e..29dea0e6cc 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -586,7 +586,7 @@ class Database: :param dt: DocType name. :param dn: Document name. - :param field: Property / field name. + :param field: Property / field name or dictionary of values to be updated :param value: Value to be updated. :param modified: Use this as the `modified` timestamp. :param modified_by: Set this user as `modified_by`. @@ -598,28 +598,39 @@ class Database: if not modified_by: modified_by = frappe.session.user + if update_modified: + to_update = {"modified": modified, "modified_by": modified_by} + + if isinstance(field, dict): + to_update.update(field) + else: + to_update.update({field: val}) + if dn and dt!=dn: + # with table conditions, values = self.build_conditions(dn) - values.update({"val": val, "modified": modified, "modified_by": modified_by}) + values.update(to_update) - if update_modified: - self.sql("""update `tab{0}` set `{1}`=%(val)s, modified=%(modified)s, modified_by=%(modified_by)s where - {2}""".format(dt, field, conditions), values, debug=debug) - else: - self.sql("""update `tab{0}` set `{1}`=%(val)s where - {2}""".format(dt, field, conditions), values, debug=debug) + set_values = [] + for key in to_update: + set_values.append('`{0}`=%({0})s'.format(key)) + self.sql("""update `tab{0}` + set {1} where {2}""".format(dt, ', '.join(set_values), conditions), + values, debug=debug) else: - self.sql("delete from tabSingles where field=%s and doctype=%s", (field, dt)) - self.sql("insert into tabSingles(doctype, field, value) values (%s, %s, %s)", - (dt, field, val), debug=debug) - - if update_modified and (field not in ("modified", "modified_by")): - self.set_value(dt, dn, "modified", modified) - self.set_value(dt, dn, "modified_by", modified_by) - + # for singles + keys = to_update.keys() + self.sql(''' + delete from tabSingles + where field in ({0}) and + doctype=%s'''.format(', '.join(['%s']*len(keys))), + keys + [dt], debug=debug) + for key, value in to_update.iteritems(): + self.sql('''insert into tabSingles(doctype, field, value) values (%s, %s, %s)''', + (dt, key, value), debug=debug) if dt in self.value_cache: del self.value_cache[dt] diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 63bc2c30ed..fbf04e1d31 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -386,7 +386,7 @@ class EmailAccount(Document): # set in_reply_to of current communication if parent_doctype=='Communication': - communication.in_reply_to = in_reply_to + communication.in_reply_to = parent_name if parent.reference_name: # the true parent is the communication parent diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 57645a2b29..7a29a16f5a 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -54,8 +54,8 @@ class TestEmailAccount(unittest.TestCase): frappe.delete_doc("File", existing_file.name) delete_file_from_filesystem(existing_file) - with open(os.path.join(os.path.dirname(__file__), "test_mails", "incoming-2.raw"), "r") as f: - test_mails = [f.read()] + with open(os.path.join(os.path.dirname(__file__), "test_mails", "incoming-2.raw"), "r") as testfile: + test_mails = [testfile.read()] email_account = frappe.get_doc("Email Account", "_Test Email Account 1") email_account.receive(test_mails=test_mails) diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 4121a9ec46..f80f267961 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -360,8 +360,21 @@ class BaseDocument(object): # this is used to preserve traceback raise frappe.UniqueValidationError, (self.doctype, self.name, e), traceback - def db_set(self, fieldname, value, update_modified=True): - self.set(fieldname, value) + def db_set(self, fieldname, value=None, update_modified=True): + '''Set a value in the document object, update the timestamp and update the database. + + WARNING: This method does not trigger controller validations and should + be used very carefully. + + :param fieldname: fieldname of the property to be updated, or a {"field":"value"} dictionary + :param value: value of the property to be updated + :param update_modified: default True. updates the `modified` and `modified_by` properties + ''' + if isinstance(fieldname, dict): + self.update(fieldname) + else: + self.set(fieldname, value) + if update_modified and (self.doctype, self.name) not in frappe.flags.currently_saving: # don't update modified timestamp if called from post save methods # like on_update or on_submit