Merge pull request #22323 from deepeshgarg007/item_tax_map

fix: Do not copy Item Tax template from SO to PO
diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml
index d36b115..8f67858 100644
--- a/.github/workflows/docker-release.yml
+++ b/.github/workflows/docker-release.yml
@@ -11,4 +11,4 @@
     - name: curl
       run: |
         apk add curl bash
-        curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Travis-API-Version: 3" -H "Authorization: token ${{ secrets.TRAVIS_CI_TOKEN }}" -d '{"request":{"branch":"master"}}' https://api.travis-ci.org/repo/frappe%2Ffrappe_docker/requests
+        curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Travis-API-Version: 3" -H "Authorization: token ${{ secrets.TRAVIS_CI_TOKEN }}" -d '{"request":{"branch":"master"}}' https://api.travis-ci.com/repo/frappe%2Ffrappe_docker/requests
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.json b/erpnext/accounts/doctype/cost_center/cost_center.json
index c9bbbab..e7fa954 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.json
+++ b/erpnext/accounts/doctype/cost_center/cost_center.json
@@ -146,7 +146,7 @@
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-04-29 16:09:30.025214",
+ "modified": "2020-06-17 16:09:30.025214",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Cost Center",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 7145fea..13f5cb0 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1376,6 +1376,12 @@
    "read": 1,
    "role": "Purchase Manager",
    "write": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts User"
   }
  ],
  "search_fields": "status, transaction_date, supplier,grand_total",
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 1712369..813286f 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -118,7 +118,7 @@
 		self.assertEqual(po.get("items")[0].amount, 1400)
 		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
 
-	
+
 	def test_add_new_item_in_update_child_qty_rate(self):
 		po = create_purchase_order(do_not_save=1)
 		po.items[0].qty = 4
@@ -144,7 +144,7 @@
 		self.assertEquals(len(po.get('items')), 2)
 		self.assertEqual(po.status, 'To Receive and Bill')
 
-	
+
 	def test_remove_item_in_update_child_qty_rate(self):
 		po = create_purchase_order(do_not_save=1)
 		po.items[0].qty = 4
@@ -185,6 +185,23 @@
 		self.assertEquals(len(po.get('items')), 1)
 		self.assertEqual(po.status, 'To Receive and Bill')
 
+	def test_update_child_qty_rate_perm(self):
+		po = create_purchase_order(item_code= "_Test Item", qty=4)
+
+		user = 'test@example.com'
+		test_user = frappe.get_doc('User', user)
+		test_user.add_roles("Accounts User")
+		frappe.set_user(user)
+
+		# update qty
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': po.items[0].name}])
+		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Purchase Order', trans_item, po.name)
+
+		# add new item
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 100, 'qty' : 2}])
+		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Purchase Order', trans_item, po.name)
+		frappe.set_user("Administrator")
+
 	def test_update_qty(self):
 		po = create_purchase_order()
 
@@ -689,7 +706,7 @@
 		po.save()
 		self.assertEqual(po.schedule_date, add_days(nowdate(), 2))
 
-	
+
 	def test_po_optional_blanket_order(self):
 		"""
 			Expected result: Blanket order Ordered Quantity should only be affected on Purchase Order with against_blanket_order = 1.
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index eecb143..f54b593 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1137,8 +1137,8 @@
 	child_item.item_name = item.item_name
 	child_item.description = item.description
 	child_item.delivery_date = trans_item.get('delivery_date') or p_doc.delivery_date
+	child_item.conversion_factor = flt(trans_item.get('conversion_factor')) or get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
 	child_item.uom = item.stock_uom
-	child_item.conversion_factor = get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
 	child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True)
 	if not child_item.warehouse:
 		frappe.throw(_("Cannot find {} for item {}. Please set the same in Item Master or Stock Settings.")
@@ -1157,8 +1157,8 @@
 	child_item.item_name = item.item_name
 	child_item.description = item.description
 	child_item.schedule_date = trans_item.get('schedule_date') or p_doc.schedule_date
+	child_item.conversion_factor = flt(trans_item.get('conversion_factor')) or get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
 	child_item.uom = item.stock_uom
-	child_item.conversion_factor = get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
 	child_item.base_rate = 1 # Initiallize value will update in parent validation
 	child_item.base_amount = 1 # Initiallize value will update in parent validation
 	return child_item
@@ -1190,6 +1190,26 @@
 
 @frappe.whitelist()
 def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
+	def check_permissions(doc, perm_type='create'):
+		try:
+			doc.check_permission(perm_type)
+		except:
+			action = "add" if perm_type == 'create' else "update"
+			frappe.throw(_("You do not have permissions to {} items in a Sales Order.").format(action), title=_("Insufficient Permissions"))
+
+	def get_new_child_item(item_row):
+		if parent_doctype == "Sales Order":
+			return set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_row)
+		if parent_doctype == "Purchase Order":
+			return set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_row)
+
+	def validate_quantity(child_item, d):
+		if parent_doctype == "Sales Order" and flt(d.get("qty")) < flt(child_item.delivered_qty):
+			frappe.throw(_("Cannot set quantity less than delivered quantity"))
+
+		if parent_doctype == "Purchase Order" and flt(d.get("qty")) < flt(child_item.received_qty):
+			frappe.throw(_("Cannot set quantity less than received quantity"))
+
 	data = json.loads(trans_items)
 
 	sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
@@ -1201,20 +1221,29 @@
 		new_child_flag = False
 		if not d.get("docname"):
 			new_child_flag = True
-			if parent_doctype == "Sales Order":
-				child_item  = set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, d)
-			if parent_doctype == "Purchase Order":
-				child_item = set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, d)
+			check_permissions(parent, 'create')
+			child_item = get_new_child_item(d)
 		else:
+			check_permissions(parent, 'write')
 			child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
-			if flt(child_item.get("rate")) == flt(d.get("rate")) and flt(child_item.get("qty")) == flt(d.get("qty")):
+
+			prev_rate, new_rate = flt(child_item.get("rate")), flt(d.get("rate"))
+			prev_qty, new_qty = flt(child_item.get("qty")), flt(d.get("qty"))
+			prev_con_fac, new_con_fac = flt(child_item.get("conversion_factor")), flt(d.get("conversion_factor"))
+
+			if parent_doctype == 'Sales Order':
+				prev_date, new_date = child_item.get("delivery_date"), d.get("delivery_date")
+			elif parent_doctype == 'Purchase Order':
+				prev_date, new_date = child_item.get("schedule_date"), d.get("schedule_date")
+
+			rate_unchanged = prev_rate == new_rate
+			qty_unchanged = prev_qty == new_qty
+			conversion_factor_unchanged = prev_con_fac == new_con_fac
+			date_unchanged = prev_date == new_date if prev_date and new_date else False # in case of delivery note etc
+			if rate_unchanged and qty_unchanged and conversion_factor_unchanged and date_unchanged:
 				continue
 
-		if parent_doctype == "Sales Order" and flt(d.get("qty")) < flt(child_item.delivered_qty):
-			frappe.throw(_("Cannot set quantity less than delivered quantity"))
-
-		if parent_doctype == "Purchase Order" and flt(d.get("qty")) < flt(child_item.received_qty):
-			frappe.throw(_("Cannot set quantity less than received quantity"))
+		validate_quantity(child_item, d)
 
 		child_item.qty = flt(d.get("qty"))
 		precision = child_item.precision("rate") or 2
@@ -1225,6 +1254,18 @@
 		else:
 			child_item.rate = flt(d.get("rate"))
 
+		if d.get("conversion_factor"):
+			if child_item.stock_uom == child_item.uom:
+				child_item.conversion_factor = 1
+			else:
+				child_item.conversion_factor = flt(d.get('conversion_factor'))
+
+		if d.get("delivery_date") and parent_doctype == 'Sales Order':
+			child_item.delivery_date = d.get('delivery_date')
+
+		if d.get("schedule_date") and parent_doctype == 'Purchase Order':
+			child_item.schedule_date = d.get('schedule_date')
+
 		if flt(child_item.price_list_rate):
 			if flt(child_item.rate) > flt(child_item.price_list_rate):
 				#  if rate is greater than price_list_rate, set margin
diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py
index 50b17ab..1f95e00 100644
--- a/erpnext/controllers/item_variant.py
+++ b/erpnext/controllers/item_variant.py
@@ -102,7 +102,7 @@
 			frappe.throw(_("{0} is not a valid Value for Attribute {1} of Item {2}.").format(
 				frappe.bold(attribute_value), frappe.bold(attribute), frappe.bold(item)), InvalidItemAttributeValueError, title=_("Invalid Value"))
 		else:
-			msg = _("The value {0} is already assigned to an exisiting Item {1}.").format(
+			msg = _("The value {0} is already assigned to an existing Item {1}.").format(
 				frappe.bold(attribute_value), frappe.bold(item))
 			msg += "<br>" + _("To still proceed with editing this Attribute Value, enable {0} in Item Variant Settings.").format(frappe.bold("Allow Rename Attribute Value"))
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 2888c76..759c6cd 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -227,7 +227,9 @@
 
 	def check_expense_account(self, item):
 		if not item.get("expense_account"):
-			frappe.throw(_("Expense Account not set for Item {0}. Please set an Expense Account for the item in the Items table").format(item.item_code))
+			frappe.throw(_("Row #{0}: Expense Account not set for Item {1}. Please set an Expense \
+				Account in the Items table").format(item.idx, frappe.bold(item.item_code)),
+				title=_("Expense Account Missing"))
 
 		else:
 			is_expense_account = frappe.db.get_value("Account",
diff --git a/erpnext/education/doctype/fee_structure/fee_structure.js b/erpnext/education/doctype/fee_structure/fee_structure.js
index 7606565..f09d2ef 100644
--- a/erpnext/education/doctype/fee_structure/fee_structure.js
+++ b/erpnext/education/doctype/fee_structure/fee_structure.js
@@ -9,6 +9,14 @@
 	},
 
 	onload: function(frm) {
+		frm.set_query("academic_term", function() {
+			return {
+				"filters": {
+					"academic_year": frm.doc.academic_year
+				}
+			};
+		});
+
 		frm.set_query("receivable_account", function(doc) {
 			return {
 				filters: {
diff --git a/erpnext/education/doctype/fee_structure/fee_structure.json b/erpnext/education/doctype/fee_structure/fee_structure.json
index 8ff6851..67e4637 100644
--- a/erpnext/education/doctype/fee_structure/fee_structure.json
+++ b/erpnext/education/doctype/fee_structure/fee_structure.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "allow_rename": 1,
  "autoname": "naming_series:",
@@ -11,8 +12,8 @@
   "program",
   "student_category",
   "column_break_2",
-  "academic_term",
   "academic_year",
+  "academic_term",
   "section_break_4",
   "components",
   "section_break_6",
@@ -157,7 +158,8 @@
  ],
  "icon": "fa fa-flag",
  "is_submittable": 1,
- "modified": "2019-05-26 09:04:17.765758",
+ "links": [],
+ "modified": "2020-06-16 15:34:57.295010",
  "modified_by": "Administrator",
  "module": "Education",
  "name": "Fee Structure",
diff --git a/erpnext/education/doctype/student_admission/student_admission.json b/erpnext/education/doctype/student_admission/student_admission.json
index b3c10d4..1096888 100644
--- a/erpnext/education/doctype/student_admission/student_admission.json
+++ b/erpnext/education/doctype/student_admission/student_admission.json
@@ -1,398 +1,119 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 1, 
- "allow_import": 0, 
- "allow_rename": 1, 
- "autoname": "", 
- "beta": 0, 
- "creation": "2016-09-13 03:05:27.154713", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 1, 
+ "actions": [],
+ "allow_guest_to_view": 1,
+ "allow_rename": 1,
+ "creation": "2016-09-13 03:05:27.154713",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "title",
+  "route",
+  "column_break_3",
+  "academic_year",
+  "admission_start_date",
+  "admission_end_date",
+  "published",
+  "enable_admission_application",
+  "section_break_5",
+  "program_details",
+  "introduction"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "label": "Title"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "", 
-   "fieldname": "route", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Route", 
-   "length": 0, 
-   "no_copy": 1, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
+   "fieldname": "route",
+   "fieldtype": "Data",
+   "label": "Route",
+   "no_copy": 1,
    "unique": 1
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "application_form_route", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Application Form Route", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "academic_year",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Academic Year",
+   "no_copy": 1,
+   "options": "Academic Year",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "academic_year", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 1, 
-   "label": "Academic Year", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Academic Year", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "admission_start_date",
+   "fieldtype": "Date",
+   "label": "Admission Start Date",
+   "no_copy": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "admission_start_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Admission Start Date", 
-   "length": 0, 
-   "no_copy": 1, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "admission_end_date",
+   "fieldtype": "Date",
+   "label": "Admission End Date",
+   "no_copy": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "admission_end_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Admission End Date", 
-   "length": 0, 
-   "no_copy": 1, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "fieldname": "published",
+   "fieldtype": "Check",
+   "label": "Publish on website"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "published", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Publish on website", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "label": "Eligibility and Details"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_5", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Eligibility and Details", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "program_details",
+   "fieldtype": "Table",
+   "label": "Eligibility and Details",
+   "options": "Student Admission Program"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "program_details", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Eligibility and Details", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Admission Program", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "introduction",
+   "fieldtype": "Text Editor",
+   "label": "Introduction"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "introduction", 
-   "fieldtype": "Text Editor", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Introduction", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "default": "0",
+   "fieldname": "enable_admission_application",
+   "fieldtype": "Check",
+   "label": "Enable Admission Application"
   }
- ], 
- "has_web_view": 1, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_published_field": "published", 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2017-11-10 18:57:34.570376", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Admission", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "has_web_view": 1,
+ "is_published_field": "published",
+ "links": [],
+ "modified": "2020-06-15 20:18:38.591626",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Admission",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Academics User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "share": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "route": "admissions", 
- "show_name_in_global_search": 1, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "title", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "restrict_to_domain": "Education",
+ "route": "admissions",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "title"
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_admission/templates/student_admission.html b/erpnext/education/doctype/student_admission/templates/student_admission.html
index 25afaca..e5a9ead 100644
--- a/erpnext/education/doctype/student_admission/templates/student_admission.html
+++ b/erpnext/education/doctype/student_admission/templates/student_admission.html
@@ -43,8 +43,8 @@
 				<thead>
 					<tr class="active">
 						<th style="width: 90px">Program/Std.</th>
-						<th style="width: 170px">Minumum Age(DOB)</th>
-						<th style="width: 170px">Maximum Age(DOB)</th>
+						<th style="width: 170px">Minumum Age</th>
+						<th style="width: 170px">Maximum Age</th>
 						<th style="width: 100px">Application Fee</th>
 					</tr>
 				</thead>
@@ -52,8 +52,8 @@
 					{% for row in program_details %}
 						<tr>
 							<td>{{ row.program }}</td>
-							<td>{{ row.minimum_age }}</td>
-							<td>{{ row.maximum_age }}</td>
+							<td>{{ row.min_age }}</td>
+							<td>{{ row.max_age }}</td>
 							<td>{{ row.application_fee }}</td>
 						</tr>
 					{% endfor %}
@@ -61,12 +61,11 @@
 			</table>
 		</div>
 	{% endif %}
-
-	{%- if application_form_route -%}
+	{%- if doc.enable_admission_application -%}
 		<br>
 		<p>
 			<a class='btn btn-primary'
-			href='/{{ doc.application_form_route }}?new=1'>
+			href='/student-applicant?new=1&student_admission={{doc.name}}'>
 			{{ _("Apply Now") }}</a>
 		</p>
 	{% endif %}
diff --git a/erpnext/education/doctype/student_admission/test_student_admission.js b/erpnext/education/doctype/student_admission/test_student_admission.js
index ed794b2..3a0bb0b 100644
--- a/erpnext/education/doctype/student_admission/test_student_admission.js
+++ b/erpnext/education/doctype/student_admission/test_student_admission.js
@@ -11,7 +11,7 @@
 				{admission_start_date: '2016-04-20'},
 				{admission_end_date: '2016-05-31'},
 				{title: '2016-17 Admissions'},
-				{application_form_route: 'student-applicant'},
+				{enable_admission_application: 1},
 				{introduction: 'Test intro'},
 				{program_details: [
 					[
@@ -28,7 +28,7 @@
 			assert.ok(cur_frm.doc.admission_start_date == '2016-04-20');
 			assert.ok(cur_frm.doc.admission_end_date == '2016-05-31');
 			assert.ok(cur_frm.doc.title == '2016-17 Admissions');
-			assert.ok(cur_frm.doc.application_form_route == 'student-applicant');
+			assert.ok(cur_frm.doc.enable_admission_application == 1);
 			assert.ok(cur_frm.doc.introduction == 'Test intro');
 			assert.ok(cur_frm.doc.program_details[0].program == 'Standard Test', 'Program correctly selected');
 			assert.ok(cur_frm.doc.program_details[0].application_fee == 1000);
diff --git a/erpnext/education/doctype/student_admission_program/student_admission_program.json b/erpnext/education/doctype/student_admission_program/student_admission_program.json
index 97b1bba..e9f041e 100644
--- a/erpnext/education/doctype/student_admission_program/student_admission_program.json
+++ b/erpnext/education/doctype/student_admission_program/student_admission_program.json
@@ -1,237 +1,77 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "", 
- "beta": 0, 
- "creation": "2017-09-15 12:59:43.207923", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2017-09-15 12:59:43.207923",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "program",
+  "min_age",
+  "max_age",
+  "column_break_4",
+  "application_fee",
+  "applicant_naming_series"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "program", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Program", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Program", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "program",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Program",
+   "options": "Program",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "minimum_age", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Minimum Age", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "maximum_age", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Maximum Age", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "application_fee",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Application Fee",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_4", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "applicant_naming_series",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Naming Series (for Student Applicant)",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "application_fee", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Application Fee", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "min_age",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Minimum Age",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "applicant_naming_series", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Naming Series (for Student Applicant)", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "max_age",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Maximum Age",
+   "show_days": 1,
+   "show_seconds": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:37:17.408427", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Admission Program", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-06-10 23:06:30.037404",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Admission Program",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Education",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_applicant/student_applicant.py b/erpnext/education/doctype/student_applicant/student_applicant.py
index ab94780..2113482 100644
--- a/erpnext/education/doctype/student_applicant/student_applicant.py
+++ b/erpnext/education/doctype/student_applicant/student_applicant.py
@@ -6,7 +6,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import getdate
+from frappe.utils import getdate, add_years, nowdate, date_diff
 
 class StudentApplicant(Document):
 	def autoname(self):
@@ -31,6 +31,7 @@
 	def validate(self):
 		self.validate_dates()
 		self.title = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name]))
+
 		if self.student_admission and self.program and self.date_of_birth:
 			self.validation_from_student_admission()
 
@@ -48,16 +49,16 @@
 			frappe.throw(_("Please select Student Admission which is mandatory for the paid student applicant"))
 
 	def validation_from_student_admission(self):
+		
 		student_admission = get_student_admission_data(self.student_admission, self.program)
 
-		# different validation for minimum and maximum age so that either min/max can also work independently.
-		if student_admission and student_admission.minimum_age and \
-			getdate(student_admission.minimum_age) < getdate(self.date_of_birth):
-				frappe.throw(_("Not eligible for the admission in this program as per DOB"))
+		if student_admission and student_admission.min_age and \
+			date_diff(nowdate(), add_years(getdate(self.date_of_birth), student_admission.min_age)) < 0:
+				frappe.throw(_("Not eligible for the admission in this program as per Date Of Birth"))
 
-		if student_admission and student_admission.maximum_age and \
-			getdate(student_admission.maximum_age) > getdate(self.date_of_birth):
-				frappe.throw(_("Not eligible for the admission in this program as per DOB"))
+		if student_admission and student_admission.max_age and \
+			date_diff(nowdate(), add_years(getdate(self.date_of_birth), student_admission.max_age)) > 0:
+				frappe.throw(_("Not eligible for the admission in this program as per Date Of Birth"))
 
 
 	def on_payment_authorized(self, *args, **kwargs):
@@ -65,10 +66,12 @@
 
 
 def get_student_admission_data(student_admission, program):
+
 	student_admission = frappe.db.sql("""select sa.admission_start_date, sa.admission_end_date,
-		sap.program, sap.minimum_age, sap.maximum_age, sap.applicant_naming_series
+		sap.program, sap.min_age, sap.max_age, sap.applicant_naming_series
 		from `tabStudent Admission` sa, `tabStudent Admission Program` sap
 		where sa.name = sap.parent and sa.name = %s and sap.program = %s""", (student_admission, program), as_dict=1)
+
 	if student_admission:
 		return student_admission[0]
 	else:
diff --git a/erpnext/education/web_form/student_applicant/student_applicant.json b/erpnext/education/web_form/student_applicant/student_applicant.json
index b1ad754..1810f07 100644
--- a/erpnext/education/web_form/student_applicant/student_applicant.json
+++ b/erpnext/education/web_form/student_applicant/student_applicant.json
@@ -1,200 +1,248 @@
 {
- "accept_payment": 0, 
- "allow_comments": 0, 
- "allow_delete": 0, 
- "allow_edit": 1, 
- "allow_incomplete": 0, 
- "allow_multiple": 1, 
- "allow_print": 0, 
- "amount": 0.0, 
- "amount_based_on_field": 0, 
- "creation": "2016-09-22 13:10:10.792735", 
- "doc_type": "Student Applicant", 
- "docstatus": 0, 
- "doctype": "Web Form", 
- "idx": 0, 
- "is_standard": 1, 
- "login_required": 1, 
- "max_attachment_size": 0, 
- "modified": "2017-02-21 05:44:46.022738", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "student-applicant", 
- "owner": "Administrator", 
- "payment_button_label": "Buy Now", 
- "published": 1, 
- "route": "student-applicant", 
- "show_sidebar": 1, 
- "sidebar_items": [], 
- "success_url": "/student-applicant", 
- "title": "Student Applicant", 
+ "accept_payment": 0,
+ "allow_comments": 0,
+ "allow_delete": 0,
+ "allow_edit": 1,
+ "allow_incomplete": 0,
+ "allow_multiple": 1,
+ "allow_print": 0,
+ "amount": 0.0,
+ "amount_based_on_field": 0,
+ "creation": "2016-09-22 13:10:10.792735",
+ "doc_type": "Student Applicant",
+ "docstatus": 0,
+ "doctype": "Web Form",
+ "idx": 0,
+ "is_standard": 1,
+ "login_required": 1,
+ "max_attachment_size": 0,
+ "modified": "2020-06-11 22:53:45.875310",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "student-applicant",
+ "owner": "Administrator",
+ "payment_button_label": "Buy Now",
+ "published": 1,
+ "route": "student-applicant",
+ "route_to_success_link": 0,
+ "show_attachments": 0,
+ "show_in_grid": 0,
+ "show_sidebar": 1,
+ "sidebar_items": [],
+ "success_url": "/student-applicant",
+ "title": "Student Applicant",
  "web_form_fields": [
   {
-   "fieldname": "first_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "First Name", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 1
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "first_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "First Name",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 1,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "middle_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Middle Name", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "middle_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Middle Name",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "last_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Last Name", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "last_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Last Name",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "image", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Image", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "image",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Image",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "program", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "label": "Program", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Program", 
-   "read_only": 0, 
-   "reqd": 1
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "program",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Program",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Program",
+   "read_only": 0,
+   "reqd": 1,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "academic_year", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "label": "Academic Year", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Academic Year", 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "academic_year",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Academic Year",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Academic Year",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "date_of_birth", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "label": "Date of Birth", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "date_of_birth",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "label": "Date of Birth",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "blood_group", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "label": "Blood Group", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "\nA+\nA-\nB+\nB-\nO+\nO-\nAB+\nAB-", 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "blood_group",
+   "fieldtype": "Select",
+   "hidden": 0,
+   "label": "Blood Group",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "\nA+\nA-\nB+\nB-\nO+\nO-\nAB+\nAB-",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "student_email_id", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Student Email ID", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "student_email_id",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Student Email ID",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "student_mobile_number", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Student Mobile Number", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "student_mobile_number",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Student Mobile Number",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "default": "INDIAN", 
-   "fieldname": "nationality", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Nationality", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "", 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "default": "INDIAN",
+   "fieldname": "nationality",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Nationality",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "address_line_1", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Address Line 1", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "address_line_1",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Address Line 1",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "address_line_2", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Address Line 2", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "address_line_2",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Address Line 2",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "pincode", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Pincode", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "pincode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Pincode",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "guardians", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "label": "Guardians", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Student Guardian", 
-   "read_only": 0, 
-   "reqd": 0
-  }, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "guardians",
+   "fieldtype": "Table",
+   "hidden": 0,
+   "label": "Guardians",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Student Guardian",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
   {
-   "fieldname": "siblings", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "label": "Siblings", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Student Sibling", 
-   "read_only": 0, 
-   "reqd": 0
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "siblings",
+   "fieldtype": "Table",
+   "hidden": 0,
+   "label": "Siblings",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Student Sibling",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "student_admission",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Student Admission",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Student Admission",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
   }
  ]
 }
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
index 1b0c9f6..6dedaa8 100644
--- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
+++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
@@ -73,10 +73,16 @@
 
 	if customer_exists:
 		frappe.rename_doc("Customer", old_name, customer_name)
-		billing_address = frappe.get_doc("Address", {"woocommerce_email": customer_woo_com_email, "address_type": "Billing"})
-		shipping_address = frappe.get_doc("Address", {"woocommerce_email": customer_woo_com_email, "address_type": "Shipping"})
-		rename_address(billing_address, customer)
-		rename_address(shipping_address, customer)
+		for address_type in ("Billing", "Shipping",):
+			try:
+				address = frappe.get_doc("Address", {"woocommerce_email": customer_woo_com_email, "address_type": address_type})
+				rename_address(address, customer)
+			except (
+				frappe.DoesNotExistError,
+				frappe.DuplicateEntryError,
+				frappe.ValidationError,
+			):
+				pass
 	else:
 		create_address(raw_billing_data, customer, "Billing")
 		create_address(raw_shipping_data, customer, "Shipping")
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
index 64c3b2d..25ffd28 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
@@ -8,6 +8,7 @@
 from frappe import _
 from frappe.model.document import Document
 from frappe.utils import get_request_session
+from requests.exceptions import HTTPError
 from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
 from erpnext.erpnext_integrations.utils import get_webhook_address
 from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log
@@ -29,19 +30,24 @@
 		webhooks = ["orders/create", "orders/paid", "orders/fulfilled"]
 		# url = get_shopify_url('admin/webhooks.json', self)
 		created_webhooks = [d.method for d in self.webhooks]
-		url = get_shopify_url('admin/api/2019-04/webhooks.json', self)
+		url = get_shopify_url('admin/api/2020-04/webhooks.json', self)
 		for method in webhooks:
 			session = get_request_session()
 			try:
-				d = session.post(url, data=json.dumps({
+				res = session.post(url, data=json.dumps({
 					"webhook": {
 						"topic": method,
 						"address": get_webhook_address(connector_name='shopify_connection', method='store_request_data'),
 						"format": "json"
 						}
 					}), headers=get_header(self))
-				d.raise_for_status()
-				self.update_webhook_table(method, d.json())
+				res.raise_for_status()
+				self.update_webhook_table(method, res.json())
+
+			except HTTPError as e:
+				error_message = res.json().get('errors', e)
+				make_shopify_log(status="Warning", exception=error_message, rollback=True)
+
 			except Exception as e:
 				make_shopify_log(status="Warning", exception=e, rollback=True)
 
@@ -50,13 +56,18 @@
 		deleted_webhooks = []
 
 		for d in self.webhooks:
-			url = get_shopify_url('admin/api/2019-04/webhooks/{0}.json'.format(d.webhook_id), self)
+			url = get_shopify_url('admin/api/2020-04/webhooks/{0}.json'.format(d.webhook_id), self)
 			try:
 				res = session.delete(url, headers=get_header(self))
 				res.raise_for_status()
 				deleted_webhooks.append(d)
+
+			except HTTPError as e:
+				error_message = res.json().get('errors', e)
+				make_shopify_log(status="Warning", exception=error_message, rollback=True)
+
 			except Exception as e:
-				frappe.log_error(message=frappe.get_traceback(), title=e)
+				frappe.log_error(message=e, title='Shopify Webhooks Issue')
 
 		for d in deleted_webhooks:
 			self.remove(d)
@@ -125,4 +136,3 @@
 	}
 
 	create_custom_fields(custom_fields)
-
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py
index bde1011..f9f0bb3 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py
@@ -8,7 +8,7 @@
 shopify_variants_attr_list = ["option1", "option2", "option3"]
 
 def sync_item_from_shopify(shopify_settings, item):
-	url = get_shopify_url("admin/api/2019-04/products/{0}.json".format(item.get("product_id")), shopify_settings)
+	url = get_shopify_url("admin/api/2020-04/products/{0}.json".format(item.get("product_id")), shopify_settings)
 	session = get_request_session()
 
 	try:
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
index 0c13b6a..3dc7c1e 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
@@ -70,6 +70,7 @@
 	if frappe.db.get_value('Item', item, 'is_stock_item'):
 		frappe.throw(_(msg))
 
+@frappe.whitelist()
 def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
 	fields = ['name', 'practitioner_name', 'mobile_phone']
 
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 9d7cdc2..742cc8e 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -238,6 +238,9 @@
 		"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel",
 		"on_trash": "erpnext.regional.check_deletion_permission"
 	},
+	"Purchase Invoice": {
+		"on_submit": "erpnext.regional.india.utils.make_reverse_charge_entries"
+	},
 	"Payment Entry": {
 		"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status"],
 		"on_trash": "erpnext.regional.check_deletion_permission"
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 2543eec..7d31a1c 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -119,6 +119,7 @@
 					"description": d.description,
 					"time_in_mins": d.time_in_mins,
 					"batch_size": d.batch_size,
+					"operating_cost": d.operating_cost,
 					"idx": d.idx
 				})
 				child.hour_rate = flt(d.hour_rate / self.conversion_rate, 2)
diff --git a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json
index 3ca851d..0350e2c 100644
--- a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json
+++ b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json
@@ -78,6 +78,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:parent.doctype == 'BOM'",
    "fieldname": "base_hour_rate",
    "fieldtype": "Currency",
    "label": "Base Hour Rate(Company Currency)",
@@ -87,6 +88,7 @@
   },
   {
    "default": "5",
+   "depends_on": "eval:parent.doctype == 'BOM'",
    "fieldname": "base_operating_cost",
    "fieldtype": "Currency",
    "label": "Operating Cost(Company Currency)",
@@ -108,12 +110,12 @@
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2019-07-16 22:35:55.374037",
- "modified_by": "govindsmenokee@gmail.com",
+ "modified": "2020-06-16 17:01:11.128420",
+ "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "BOM Operation",
  "owner": "Administrator",
  "permissions": [],
  "sort_field": "modified",
  "sort_order": "DESC"
-}
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/routing/routing.js b/erpnext/manufacturing/doctype/routing/routing.js
index 6cfd0ba..d7589fa 100644
--- a/erpnext/manufacturing/doctype/routing/routing.js
+++ b/erpnext/manufacturing/doctype/routing/routing.js
@@ -44,7 +44,6 @@
 				name: d.workstation
 			},
 			callback: function (data) {
-				frappe.model.set_value(d.doctype, d.name, "base_hour_rate", data.message.hour_rate);
 				frappe.model.set_value(d.doctype, d.name, "hour_rate", data.message.hour_rate);
 				frm.events.calculate_operating_cost(frm, d);
 			}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 279c453..d74dc24 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -699,3 +699,4 @@
 erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
 erpnext.patches.v13_0.update_sla_enhancements
 erpnext.patches.v12_0.update_address_template_for_india
+erpnext.patches.v13_0.update_issue_metrics
diff --git a/erpnext/patches/v13_0/update_issue_metrics.py b/erpnext/patches/v13_0/update_issue_metrics.py
new file mode 100644
index 0000000..6d76235
--- /dev/null
+++ b/erpnext/patches/v13_0/update_issue_metrics.py
@@ -0,0 +1,33 @@
+from __future__ import unicode_literals
+import frappe
+
+from frappe.core.doctype.communication.communication import set_avg_response_time
+from erpnext.support.doctype.issue.issue import set_resolution_time, set_user_resolution_time
+
+def execute():
+	if frappe.db.exists('DocType', 'Issue'):
+		frappe.reload_doctype('Issue')
+
+		count = 0
+		for parent in frappe.get_all('Issue', order_by='creation desc'):
+			parent_doc = frappe.get_doc('Issue', parent.name)
+
+			communication = frappe.get_all('Communication', filters={
+				'reference_doctype': 'Issue',
+				'reference_name': parent.name,
+				'communication_medium': 'Email',
+				'sent_or_received': 'Sent'
+			}, order_by = 'creation asc', limit=1)
+
+			if communication:
+				communication_doc = frappe.get_doc('Communication', communication[0].name)
+				set_avg_response_time(parent_doc, communication_doc)
+
+			if parent_doc.status in ['Closed', 'Resolved']:
+				set_resolution_time(parent_doc)
+				set_user_resolution_time(parent_doc)
+
+			# commit after every 100 records
+			count += 1
+			if count % 100 == 0:
+				frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 2cd79b5..bcab0d8 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -487,7 +487,14 @@
 			fieldtype: 'Date',
 			fieldname: frm.doc.doctype == 'Sales Order' ? "delivery_date" : "schedule_date",
 			in_list_view: 1,
-			label: frm.doc.doctype == 'Sales Order' ? __("Delivery Date") : __("Reqd by date")
+			label: frm.doc.doctype == 'Sales Order' ? __("Delivery Date") : __("Reqd by date"),
+			reqd: 1
+		})
+		fields.splice(3, 0, {
+			fieldtype: 'Float',
+			fieldname: "conversion_factor",
+			in_list_view: 1,
+			label: __("Conversion Factor")
 		})
 	}
 
@@ -536,6 +543,7 @@
 			"item_code": d.item_code,
 			"delivery_date": d.delivery_date,
 			"schedule_date": d.schedule_date,
+			"conversion_factor": d.conversion_factor,
 			"qty": d.qty,
 			"rate": d.rate,
 		});
diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss
index 735b417..617e916 100644
--- a/erpnext/public/scss/website.scss
+++ b/erpnext/public/scss/website.scss
@@ -81,4 +81,10 @@
 
 .place-order-container {
 	text-align: right;
+}
+
+.kb-card {
+	.card-body > .card-title {
+		line-height: 1.3;
+	}
 }
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.js b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.js
index ded3a51..cf2644e 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.js
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.js
@@ -2,4 +2,13 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Quality Procedure', {
+	refresh: function(frm) {
+		frm.set_query("procedure","processes", (frm) =>{
+			return {
+				filters: {
+					name: ["not in", [frm.parent_quality_procedure, frm.name]]
+				}
+			};
+		});
+	}
 });
\ No newline at end of file
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
index 6df116c..b3c0d94 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_rename": 1,
  "autoname": "format:PRC-{quality_procedure_name}",
  "creation": "2018-10-06 00:06:29.756804",
  "doctype": "DocType",
@@ -72,7 +73,7 @@
  ],
  "is_tree": 1,
  "links": [],
- "modified": "2020-03-18 18:09:29.371627",
+ "modified": "2020-06-17 17:25:03.434953",
  "modified_by": "Administrator",
  "module": "Quality Management",
  "name": "Quality Procedure",
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
index d29710d..1952e57 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
@@ -11,18 +11,18 @@
 	nsm_parent_field = 'parent_quality_procedure'
 
 	def before_save(self):
-		for process in self.processes:
-			if process.procedure:
-				doc = frappe.get_doc("Quality Procedure", process.procedure)
-				if doc.parent_quality_procedure:
-					frappe.throw(_("{0} already has a Parent Procedure {1}.").format(process.procedure, doc.parent_quality_procedure))
-				self.is_group = 1
+		self.check_for_incorrect_child()
 
 	def on_update(self):
 		self.set_parent()
 
 	def after_insert(self):
 		self.set_parent()
+		#if Child is Added through Tree View.
+		if self.parent_quality_procedure:
+			parent_quality_procedure = frappe.get_doc("Quality Procedure", self.parent_quality_procedure)
+			parent_quality_procedure.append("processes", {"procedure": self.name})
+			parent_quality_procedure.save()
 
 	def on_trash(self):
 		if self.parent_quality_procedure:
@@ -43,10 +43,20 @@
 
 	def set_parent(self):
 		for process in self.processes:
+			# Set parent for only those children who don't have a parent
+			parent_quality_procedure = frappe.db.get_value("Quality Procedure", process.procedure, "parent_quality_procedure")
+			if not parent_quality_procedure and process.procedure:
+				frappe.db.set_value(self.doctype, process.procedure, "parent_quality_procedure", self.name)
+
+	def check_for_incorrect_child(self):
+		for process in self.processes:
 			if process.procedure:
-				doc = frappe.get_doc("Quality Procedure", process.procedure)
-				doc.parent_quality_procedure = self.name
-				doc.save(ignore_permissions=True)
+				# Check if any child process belongs to another parent.
+				parent_quality_procedure = frappe.db.get_value("Quality Procedure", process.procedure, "parent_quality_procedure")
+				if parent_quality_procedure and parent_quality_procedure != self.name:
+					frappe.throw(_("{0} already has a Parent Procedure {1}.".format(frappe.bold(process.procedure), frappe.bold(parent_quality_procedure))),
+						title=_("Invalid Child Procedure"))
+				self.is_group = 1
 
 @frappe.whitelist()
 def get_children(doctype, parent=None, parent_quality_procedure=None, is_root=False):
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js
index 6df6f65..ef48ab6 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js
@@ -16,6 +16,7 @@
 		},
 	],
 	breadcrumb: "Setup",
+	disable_add_node: true,
 	root_label: "All Quality Procedures",
 	get_tree_root: false,
 	menu_items: [
diff --git a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json
index 0a67fa5..3925dbb 100644
--- a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json
+++ b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json
@@ -1,6 +1,8 @@
 {
+ "actions": [],
  "creation": "2019-05-26 00:10:00.248885",
  "doctype": "DocType",
+ "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
   "process_description",
@@ -23,7 +25,8 @@
   }
  ],
  "istable": 1,
- "modified": "2019-05-26 22:05:49.007189",
+ "links": [],
+ "modified": "2020-06-17 15:44:38.937915",
  "modified_by": "Administrator",
  "module": "Quality Management",
  "name": "Quality Procedure Process",
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html
index 35f9cf6..888b2da 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html
@@ -52,7 +52,7 @@
 			<td class="disabled"></td>
 			<td class="disabled"></td>
 		<tr>
-			<td>(d) {{__("Inward Supplies(liable to reverse charge")}}</td>
+			<td>(d) {{__("Inward Supplies(liable to reverse charge)")}}</td>
 			<td class="right">{{ flt(data.sup_details.isup_rev.txval, 2) }}</td>
 			<td class="right">{{ flt(data.sup_details.isup_rev.iamt, 2) }}</td>
 			<td class="right">{{ flt(data.sup_details.isup_rev.camt, 2) }}</td>
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 9e7a023..619734f 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -158,7 +158,7 @@
 
 		self.prepare_data("Sales Invoice", outward_supply_tax_amounts, "sup_details", "osup_det", ["Registered Regular"])
 		self.prepare_data("Sales Invoice", outward_supply_tax_amounts, "sup_details", "osup_zero", ["SEZ", "Deemed Export", "Overseas"])
-		self.prepare_data("Purchase Invoice", inward_supply_tax_amounts, "sup_details", "isup_rev", ["Registered Regular"], reverse_charge="Y")
+		self.prepare_data("Purchase Invoice", inward_supply_tax_amounts, "sup_details", "isup_rev", ["Unregistered", "Overseas"], reverse_charge="Y")
 		self.report_dict["sup_details"]["osup_nil_exmp"]["txval"] = flt(self.get_nil_rated_supply_value(), 2)
 		self.set_itc_details(itc_details)
 
@@ -192,31 +192,27 @@
 		for d in self.report_dict["itc_elg"]["itc_avl"]:
 
 			itc_type = itc_type_map.get(d["ty"])
-			gst_category = "Registered Regular"
+			gst_category = ["Registered Regular"]
 
 			if d["ty"] == 'ISRC':
 				reverse_charge = "Y"
+				itc_type = 'All Other ITC'
+				gst_category = ['Unregistered', 'Overseas']
 			else:
 				reverse_charge = "N"
 
 			for account_head in self.account_heads:
+				for category in gst_category:
+					for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]:
+						d[key[0]] += flt(itc_details.get((category, itc_type, reverse_charge, account_head.get(key[1])), {}).get("amount"), 2)
 
-				d["iamt"] += flt(itc_details.get((gst_category, itc_type, reverse_charge, account_head.get('igst_account')), {}).get("amount"), 2)
-				d["camt"] += flt(itc_details.get((gst_category, itc_type, reverse_charge, account_head.get('cgst_account')), {}).get("amount"), 2)
-				d["samt"] += flt(itc_details.get((gst_category, itc_type, reverse_charge, account_head.get('sgst_account')), {}).get("amount"), 2)
-				d["csamt"] += flt(itc_details.get((gst_category, itc_type, reverse_charge, account_head.get('cess_account')), {}).get("amount"), 2)
-
-			net_itc["iamt"] += flt(d["iamt"], 2)
-			net_itc["camt"] += flt(d["camt"], 2)
-			net_itc["samt"] += flt(d["samt"], 2)
-			net_itc["csamt"] += flt(d["csamt"], 2)
+			for key in ['iamt', 'camt', 'samt', 'csamt']:
+				net_itc[key] += flt(d[key], 2)
 
 		for account_head in self.account_heads:
 			itc_inelg = self.report_dict["itc_elg"]["itc_inelg"][1]
-			itc_inelg["iamt"] = flt(itc_details.get(("Ineligible", "N", account_head.get("igst_account")), {}).get("amount"), 2)
-			itc_inelg["camt"] = flt(itc_details.get(("Ineligible", "N", account_head.get("cgst_account")), {}).get("amount"), 2)
-			itc_inelg["samt"] = flt(itc_details.get(("Ineligible", "N", account_head.get("sgst_account")), {}).get("amount"), 2)
-			itc_inelg["csamt"] = flt(itc_details.get(("Ineligible", "N", account_head.get("cess_account")), {}).get("amount"), 2)
+			for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]:
+				itc_inelg[key[0]] = flt(itc_details.get(("Ineligible", "N", account_head.get(key[1])), {}).get("amount"), 2)
 
 	def prepare_data(self, doctype, tax_details, supply_type, supply_category, gst_category_list, reverse_charge="N"):
 
@@ -274,17 +270,16 @@
 			""" #nosec
 			.format(doctype = doctype), (self.month_no, self.year, reverse_charge, self.company, self.gst_details.get("gstin"))))
 
-	def get_itc_details(self, reverse_charge='N'):
-
+	def get_itc_details(self):
 		itc_amount = frappe.db.sql("""
 			select s.gst_category, sum(t.tax_amount_after_discount_amount) as tax_amount, t.account_head, s.eligibility_for_itc, s.reverse_charge
 			from `tabPurchase Invoice` s , `tabPurchase Taxes and Charges` t
-			where s.docstatus = 1 and t.parent = s.name and s.reverse_charge = %s
+			where s.docstatus = 1 and t.parent = s.name
 			and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s
 			and s.company_gstin = %s
 			group by t.account_head, s.gst_category, s.eligibility_for_itc
 			""",
-			(reverse_charge, self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
+			(self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
 
 		itc_details = {}
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 3085a31..9fe29eb 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -9,6 +9,8 @@
 from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
 from erpnext.regional.india import number_state_mapping
 from six import string_types
+from erpnext.accounts.general_ledger import make_gl_entries
+from erpnext.accounts.utils import get_account_currency
 
 def validate_gstin_for_india(doc, method):
 	if hasattr(doc, 'gst_state') and doc.gst_state:
@@ -658,5 +660,53 @@
 			elif val:
 				gst_accounts[val] = acc
 
-
 	return gst_accounts
+
+def make_reverse_charge_entries(doc, method):
+	country = frappe.get_cached_value('Company', doc.company, 'country')
+
+	if country != 'India':
+		return
+
+	if doc.reverse_charge == 'Y':
+		gl_entries = []
+		gst_accounts = get_gst_accounts(doc.company)
+		gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
+			+ gst_accounts.get('igst_account')
+
+		for tax in doc.get('taxes'):
+			if tax.category not in ("Total", "Valuation and Total"):
+				continue
+
+			if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
+				account_currency = get_account_currency(tax.account_head)
+
+				gl_entries.append(doc.get_gl_dict(
+					{
+						"account": tax.account_head,
+						"cost_center": tax.cost_center,
+						"posting_date": doc.posting_date,
+						"against": doc.supplier,
+						"credit": tax.base_tax_amount_after_discount_amount,
+						"credits_in_account_currency": tax.base_tax_amount_after_discount_amount \
+							if account_currency==doc.company_currency \
+							else tax.tax_amount_after_discount_amount
+					}, account_currency, item=tax)
+				)
+
+				gl_entries.append(doc.get_gl_dict(
+					{
+						"account": doc.credit_to if doc.doctype == 'Purchase Invoice' else doc.debit_to,
+						"cost_center": doc.cost_center,
+						"posting_date": doc.posting_date,
+						"party_type": 'Supplier',
+						"party": doc.supplier,
+						"against": tax.account_head,
+						"debit": tax.base_tax_amount_after_discount_amount,
+						"debit_in_account_currency": tax.base_tax_amount_after_discount_amount \
+							if account_currency==doc.company_currency \
+							else tax.tax_amount_after_discount_amount
+					}, account_currency, item=doc)
+				)
+
+		make_gl_entries(gl_entries)
\ No newline at end of file
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index ac3bc20..682dfed 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -339,6 +339,7 @@
 
 	return lp_details
 
+@frappe.whitelist()
 def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
 	from erpnext.controllers.queries import get_fields
 
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index b8b0d40..74e742f 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -400,6 +400,23 @@
 		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 2, 'docname': so.items[0].name}])
 		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
 
+	def test_update_child_qty_rate_perm(self):
+		so = make_sales_order(item_code= "_Test Item", qty=4)
+
+		user = 'test@example.com'
+		test_user = frappe.get_doc('User', user)
+		test_user.add_roles("Accounts User")
+		frappe.set_user(user)
+
+		# update qty
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': so.items[0].name}])
+		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
+
+		# add new item
+		trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 100, 'qty' : 2}])
+		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
+		frappe.set_user("Administrator")
+
 	def test_warehouse_user(self):
 		frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com")
 		frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com")
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index e593499..eff17f8 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -769,22 +769,23 @@
    "label": "Against Blanket Order"
   },
   {
-    "fieldname": "bom_no",
-    "fieldtype": "Link",
-    "label": "BOM No",
-    "no_copy": 1,
-    "options": "BOM",
-    "print_hide": 1
-   },
-   {
-    "fieldname": "manufacturing_section_section",
-    "fieldtype": "Section Break",
-    "label": "Manufacturing Section"
-   }
+   "fieldname": "bom_no",
+   "fieldtype": "Link",
+   "label": "BOM No",
+   "no_copy": 1,
+   "options": "BOM",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "manufacturing_section_section",
+   "fieldtype": "Section Break",
+   "label": "Manufacturing Section"
+  }
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2020-05-15 18:13:43.006493",
+ "links": [],
+ "modified": "2020-05-29 20:54:32.309460",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order Item",
diff --git a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
index e78d0ff..f15f63d 100644
--- a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
+++ b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
@@ -5,7 +5,7 @@
 import calendar
 import frappe
 from frappe import _
-from frappe.utils import cint, cstr
+from frappe.utils import cint, cstr, getdate
 
 def execute(filters=None):
 	common_columns = [
@@ -160,7 +160,7 @@
 	return columns, data, None, None, None, 1
 
 def get_customer_stats(filters, tree_view=False):
-	""" Calculates number of new and repeated customers. """
+	""" Calculates number of new and repeated customers and revenue. """
 	company_condition = ''
 	if filters.get('company'):
 		company_condition = ' and company=%(company)s'
@@ -174,14 +174,14 @@
 		filters, as_dict=1):
 
 		key = si.territory if tree_view else si.posting_date.strftime('%Y-%m')
+		new_or_repeat = 'new' if si.customer not in customers else 'repeat'
 		customers_in.setdefault(key, {'new': [0, 0.0], 'repeat': [0, 0.0]})
 
-		if not si.customer in customers:
-			customers_in[key]['new'][0] += 1
-			customers_in[key]['new'][1] += si.base_grand_total
+		# if filters.from_date <= si.posting_date.strftime('%Y-%m-%d'):
+		if getdate(filters.from_date) <= getdate(si.posting_date):
+				customers_in[key][new_or_repeat][0] += 1
+				customers_in[key][new_or_repeat][1] += si.base_grand_total
+		if new_or_repeat == 'new':
 			customers.append(si.customer)
-		else:
-			customers_in[key]['repeat'][0] += 1
-			customers_in[key]['repeat'][1] += si.base_grand_total
 
 	return customers_in
diff --git a/erpnext/support/doctype/support_settings/support_settings.json b/erpnext/support/doctype/support_settings/support_settings.json
index 1c1b0c3..5d3d3ac 100644
--- a/erpnext/support/doctype/support_settings/support_settings.json
+++ b/erpnext/support/doctype/support_settings/support_settings.json
@@ -1,5 +1,5 @@
 {
- "actions": [],
+ "actions": "",
  "creation": "2017-02-17 13:07:35.686409",
  "doctype": "DocType",
  "editable_grid": 1,
@@ -22,6 +22,10 @@
   "post_description_key",
   "post_route_key",
   "post_route_string",
+  "greetings_section_section",
+  "greeting_title",
+  "column_break_19",
+  "greeting_subtitle",
   "search_apis_sb",
   "search_apis"
  ],
@@ -127,11 +131,40 @@
    "fieldname": "allow_resetting_service_level_agreement",
    "fieldtype": "Check",
    "label": "Allow Resetting Service Level Agreement"
+  },
+  {
+   "default": "We're here to help",
+   "fieldname": "greeting_title",
+   "fieldtype": "Data",
+   "label": "Greeting Title",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "column_break_19",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "default": "Browse help topics",
+   "fieldname": "greeting_subtitle",
+   "fieldtype": "Data",
+   "label": "Greeting Subtitle",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "greetings_section_section",
+   "fieldtype": "Section Break",
+   "label": "Greetings Section",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
  "issingle": 1,
  "links": [],
- "modified": "2020-06-05 17:56:17.491684",
+ "modified": "2020-06-11 13:08:38.473616",
  "modified_by": "Administrator",
  "module": "Support",
  "name": "Support Settings",
diff --git a/erpnext/templates/generators/student_admission.html b/erpnext/templates/generators/student_admission.html
index ae70df8..8b15344 100644
--- a/erpnext/templates/generators/student_admission.html
+++ b/erpnext/templates/generators/student_admission.html
@@ -14,12 +14,12 @@
 
 {%- if introduction -%}
 <div>{{ introduction }}</div>
-{% endif %}
+{% endif %} 
 
-{%- if application_form_route -%}
+{%- if doc.enable_admission_application -%}
 <p>
 	<a class='btn btn-primary'
-	href='/{{ doc.application_form_route }}'>
+	href='/student-applicant'>
 	{{ _("Apply Now") }}</a>
 </p>
 {% endif %}
diff --git a/erpnext/www/support/__init__.py b/erpnext/www/support/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/www/support/__init__.py
diff --git a/erpnext/www/support/index.html b/erpnext/www/support/index.html
new file mode 100644
index 0000000..93da503
--- /dev/null
+++ b/erpnext/www/support/index.html
@@ -0,0 +1,58 @@
+{% extends "templates/web.html" %}
+
+{% block content %}
+<section class="section section-padding-top section-padding-bottom">
+	<div class='container'>
+		<div class="hero-content">
+			<h1 class="hero-title">{{ greeting_title or _("We're here to help!") }}</h1>
+			{% if greeting_subtitle %}
+			<p class="hero-subtitle">{{ greeting_subtitle }}</p>
+			{% endif %}
+		</div>
+	</div>
+</section>
+
+{% if favorite_article_list %}
+<section class="section section-padding-top section-padding-bottom bg-light">
+	<div class='container'>
+		<h2>{{ _("Frequently Read Articles") }}</h2>
+		<div class="row">
+			{% for favorite_article in favorite_article_list %}
+			<div class="mt-4 col-12 col-sm-6 col-lg-4">
+				<div class="card card-md h-100 kb-card">
+					<div class="card-body">
+						<h6 class="card-subtitle mb-2 text-uppercase small text-muted">
+							{{ favorite_article['category'] }}</h6>
+						<h3 class="card-title">{{ favorite_article['title'] }}</h3>
+						<p class="card-text">{{ favorite_article['description'] }}</p>
+					</div>
+					<a href="{{ favorite_article['route'] }}" class="stretched-link"></a>
+				</div>
+			</div>
+			{% endfor %}
+		</div>
+	</div>
+</section>
+{% endif %}
+
+{% if help_article_list %}
+<section class="section section-padding-top section-padding-bottom">
+	<div class='container'>
+		<h2>{{ _("Help Articles") }}</h2>
+		<div class="row">
+			{% for item in help_article_list %}
+			<div class="mt-5 col-12 col-sm-6 col-lg-4">
+				<h5>{{ item['category'].name }}</h5>
+				<div>
+					{% for article in item['articles'] %}
+					<a href="{{ article.route }}" class="mt-2 d-block">{{ article.title }}</a>
+					{% endfor %}
+				</div>
+			</div>
+			{% endfor %}
+		</div>
+	</div>
+</section>
+{% endif %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/support/index.py b/erpnext/www/support/index.py
new file mode 100644
index 0000000..5d26743
--- /dev/null
+++ b/erpnext/www/support/index.py
@@ -0,0 +1,74 @@
+from __future__ import unicode_literals
+import frappe
+
+def get_context(context):
+	context.no_cache = 1
+	context.align_greeting = ''
+	setting = frappe.get_doc("Support Settings")
+
+	context.greeting_title = setting.greeting_title
+	context.greeting_subtitle = setting.greeting_subtitle
+	
+	# Support content
+	favorite_articles = get_favorite_articles_by_page_view()
+	if len(favorite_articles) < 6:
+		name_list = []
+		if favorite_articles:
+			for article in favorite_articles:
+				name_list.append(article.name)
+		for record in (frappe.get_all("Help Article", 
+			fields=["title", "content", "route", "category"], 
+			filters={"name": ['not in', tuple(name_list)], "published": 1}, 
+			order_by="creation desc", limit=(6-len(favorite_articles)))):
+			favorite_articles.append(record)
+		
+	context.favorite_article_list = get_favorite_articles(favorite_articles)
+	context.help_article_list = get_help_article_list()
+	
+def get_favorite_articles_by_page_view():
+	return frappe.db.sql(
+			"""
+			SELECT
+				t1.name as name,
+				t1.title as title,
+				t1.content as content,
+				t1.route as route,
+				t1.category as category,
+				count(t1.route) as count 
+			FROM `tabHelp Article` AS t1 
+				INNER JOIN
+				`tabWeb Page View` AS t2 
+			ON t1.route = t2.path 
+			WHERE t1.published = 1
+			GROUP BY route 
+			ORDER BY count DESC
+			LIMIT 6;
+			""", as_dict=True)
+
+def get_favorite_articles(favorite_articles):
+	favorite_article_list=[]
+	for article in favorite_articles:
+		description = frappe.utils.strip_html(article.content)
+		if len(description) > 120:
+			description = description[:120] + '...'
+		favorite_article_dict = {
+			'title': article.title,
+			'description': description,
+			'route': article.route,
+			'category': article.category,
+		}
+		favorite_article_list.append(favorite_article_dict)
+	return favorite_article_list
+
+def get_help_article_list():
+	help_article_list=[]
+	category_list = frappe.get_all("Help Category", fields="name")
+	for category in category_list:
+		help_articles = frappe.get_all("Help Article", fields="*", filters={"category": category.name, "published": 1}, order_by="modified desc", limit=5)
+		if help_articles:
+			help_aricles_per_caetgory = {
+				'category': category,
+				'articles': help_articles,
+			}
+			help_article_list.append(help_aricles_per_caetgory)
+	return help_article_list
\ No newline at end of file