Repository: frappe/frappe

Issue:
error on webform when read only field connected to link field in doctype
I have created a web form for a doctype. Unfortunately, one field where its value is taken from another field is not recognized when entered using webform.  refer to this issue on forum: https://discuss.erpnext.com/t/default-value-from-other-field-in-web-form/17432


Discussion:

Resolving patch:
diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py
--- a/frappe/model/base_document.py
+++ b/frappe/model/base_document.py
@@ -426,6 +426,7 @@ def get_msg(df):
 		return missing
 
 	def get_invalid_links(self, is_submittable=False):
+		'''Returns list of invalid links and also updates fetch values if not set'''
 		def get_msg(df, docname):
 			if self.parentfield:
 				return "{} #{}: {}: {}".format(_("Row"), self.idx, _(df.label), docname)
@@ -434,6 +435,7 @@ def get_msg(df, docname):
 
 		invalid_links = []
 		cancelled_links = []
+
 		for df in (self.meta.get_link_fields()
 				 + self.meta.get("fields", {"fieldtype":"Dynamic Link"})):
 			docname = self.get(df.fieldname)
@@ -449,15 +451,38 @@ def get_msg(df, docname):
 						frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))
 
 				# MySQL is case insensitive. Preserve case of the original docname in the Link Field.
-				value = frappe.db.get_value(doctype, docname, "name", cache=True)
+
+				# get a map of values ot fetch along with this link query
+				# that are mapped as link_fieldname.source_fieldname in Options of
+				# Readonly or Data or Text type fields
+				fields_to_fetch = [
+					_df for _df in self.meta.get_fields_to_fetch(df.fieldname)
+						 if not self.get(_df.fieldname)
+				]
+
+				if not fields_to_fetch:
+					# cache a single value type
+					values = frappe._dict(name=frappe.db.get_value(doctype, docname,
+						'name', cache=True))
+				else:
+					values_to_fetch = ['name'] + [_df.options.split('.')[-1]
+						for _df in fields_to_fetch]
+
+					# don't cache if fetching other values too
+					values = frappe.db.get_value(doctype, docname,
+						values_to_fetch, as_dict=True)
+
 				if frappe.get_meta(doctype).issingle:
-					value = doctype
+					values.name = doctype
+
+				setattr(self, df.fieldname, values.name)
 
-				setattr(self, df.fieldname, value)
+				for _df in fields_to_fetch:
+					setattr(self, _df.fieldname, values[_df.options.split('.')[-1]])
 
 				notify_link_count(doctype, docname)
 
-				if not value:
+				if not values.name:
 					invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
 
 				elif (df.fieldname != "amended_from"
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -155,6 +155,22 @@ def get_search_fields(self):
 
 		return search_fields
 
+	def get_fields_to_fetch(self, link_fieldname):
+		'''Returns a list of docfield objects for fields whose values
+		are to be fetched and updated for a particular link field
+
+		These fields are of type Data, Link, Text, Readonly and their
+		options property is set as `link_fieldname`.`source_fieldname`'''
+
+		out = []
+		for df in self.fields:
+			if df.fieldtype in ('Data', 'Read Only', 'Text', 'Small Text',
+				'Text Editor', 'Code') and df.options and \
+				df.options.startswith(link_fieldname + '.'):
+				out.append(df)
+
+		return out
+
 	def get_list_fields(self):
 		list_fields = ["name"] + [d.fieldname \
 			for d in self.fields if (d.in_list_view and d.fieldtype in type_map)]


Test patch:
diff --git a/frappe/desk/doctype/todo/test_todo.py b/frappe/desk/doctype/todo/test_todo.py
--- a/frappe/desk/doctype/todo/test_todo.py
+++ b/frappe/desk/doctype/todo/test_todo.py
@@ -9,4 +9,8 @@
 # test_records = frappe.get_test_records('ToDo')
 
 class TestToDo(unittest.TestCase):
-	pass
+	def test_fetch(self):
+		todo = frappe.get_doc(dict(doctype='ToDo', description='test todo',
+			assigned_by='Administrator')).insert()
+		self.assertEquals(todo.assigned_by_full_name,
+			frappe.db.get_value('User', todo.assigned_by, 'full_name'))