[fix] copy item variant values on save and make non no_copy fields as not editable. fixes frappe/erpnext#4253 (#8837)

diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 3402619..460f1c3 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -65,7 +65,8 @@
 			frm.page.set_inner_btn_group_as_primary(__("Make"));
 		}
 		if (frm.doc.variant_of) {
-			frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set", [frm.doc.variant_of]), true);
+			frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set", 
+				[frm.doc.variant_of]), true);
 		}
 
 		if (frappe.defaults.get_default("item_naming_by")!="Naming Series" || frm.doc.variant_of) {
@@ -96,6 +97,8 @@
 			}
 			frappe.set_route('Form', 'Item', new_item.name);
 		});
+
+		frm.trigger('make_variant_fields_read_only');
 	},
 
 	validate: function(frm){
@@ -106,6 +109,16 @@
 		refresh_field("image_view");
 	},
 
+	make_variant_fields_read_only: function(frm) {
+		if(frm.doc.variant_of) {
+			frm.meta.fields.forEach(function(df) {
+				if (!df.no_copy) {
+					frm.toggle_enable(df.fieldname, false);
+				}
+			});
+		}
+	},
+
 	is_fixed_asset: function(frm) {
 		if (frm.doc.is_fixed_asset) {
 			frm.set_value("is_stock_item", 0);
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index f864171..ef85dd9 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -86,6 +86,7 @@
 		self.validate_has_variants()
 		self.validate_attributes()
 		self.validate_variant_attributes()
+		self.copy_variant_attributes()
 		self.validate_website_image()
 		self.make_thumbnail()
 		self.validate_fixed_asset()
@@ -616,7 +617,9 @@
 				template_item.save()
 
 	def update_variants(self):
-		if self.has_variants and not self.flags.dont_update_variants:
+		if self.flags.dont_update_variants: 
+			return
+		if self.has_variants:
 			updated = []
 			variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name })
 			for d in variants:
@@ -625,7 +628,7 @@
 				variant.save()
 				updated.append(d.item_code)
 			if updated:
-				frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
+				frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))			
 
 	def validate_has_variants(self):
 		if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
@@ -670,6 +673,12 @@
 
 			validate_item_variant_attributes(self, args)
 
+	def copy_variant_attributes(self):
+		'''Copy attributes from template (if they have been changed before saving)'''
+		if self.variant_of:
+			template = frappe.get_doc('Item', self.variant_of)
+			copy_attributes_to_variant(template, self)
+
 def get_timeline_data(doctype, name):
 	'''returns timeline data based on stock ledger entry'''
 	out = {}