Merge pull request #17696 from Anurag810/warehouse_type

feat: Added Warehouse Type master
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 2bb2c00..858359e 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -314,13 +314,11 @@
 
 		self.save()
 
-	@property
 	def is_postpaid_to_invoice(self):
 		return getdate(nowdate()) > getdate(self.current_invoice_end) or \
 			(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
 			not self.has_outstanding_invoice()
 
-	@property
 	def is_prepaid_to_invoice(self):
 		if not self.generate_invoice_at_period_start:
 			return False
@@ -340,7 +338,7 @@
 		2. Change the `Subscription` status to 'Past Due Date'
 		3. Change the `Subscription` status to 'Cancelled'
 		"""
-		if self.is_postpaid_to_invoice or self.is_prepaid_to_invoice:
+		if self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice():
 			self.generate_invoice()
 			if self.current_invoice_is_past_due():
 				self.status = 'Past Due Date'
diff --git a/erpnext/education/doctype/student_group/student_group.js b/erpnext/education/doctype/student_group/student_group.js
index 5373df9..c29c134 100644
--- a/erpnext/education/doctype/student_group/student_group.js
+++ b/erpnext/education/doctype/student_group/student_group.js
@@ -19,6 +19,7 @@
 						'academic_term': frm.doc.academic_term,
 						'program': frm.doc.program,
 						'batch': frm.doc.batch,
+						'student_category': frm.doc.student_category,
 						'course': frm.doc.course,
 						'student_group': frm.doc.name
 					}
@@ -92,6 +93,7 @@
 						"group_based_on": frm.doc.group_based_on,
 						"program": frm.doc.program,
 						"batch" : frm.doc.batch,
+						"student_category" : frm.doc.student_category,
 						"course": frm.doc.course
 					},
 					callback: function(r) {
@@ -119,4 +121,4 @@
 			frappe.msgprint(__("Select students manually for the Activity based Group"));
 		}
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/education/doctype/student_group/student_group.json b/erpnext/education/doctype/student_group/student_group.json
index 0af1565..44b38b1 100644
--- a/erpnext/education/doctype/student_group/student_group.json
+++ b/erpnext/education/doctype/student_group/student_group.json
@@ -1,552 +1,161 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:student_group_name", 
- "beta": 0, 
- "creation": "2015-09-07 12:55:52.072792", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 0, 
- "engine": "InnoDB", 
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:student_group_name",
+ "creation": "2015-09-07 12:55:52.072792",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+  "academic_year",
+  "group_based_on",
+  "student_group_name",
+  "max_strength",
+  "column_break_3",
+  "academic_term",
+  "program",
+  "batch",
+  "student_category",
+  "course",
+  "disabled",
+  "section_break_6",
+  "get_students",
+  "students",
+  "section_break_12",
+  "instructors"
+ ],
  "fields": [
   {
-   "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": 0, 
-   "in_standard_filter": 1, 
-   "label": "Academic Year", 
-   "length": 0, 
-   "no_copy": 0, 
-   "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": 0, 
-   "search_index": 0, 
-   "set_only_once": 1, 
-   "unique": 0
-  }, 
+   "fieldname": "academic_year",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Academic Year",
+   "options": "Academic Year",
+   "set_only_once": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "group_based_on", 
-   "fieldtype": "Select", 
-   "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": "Group Based on", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "\nBatch\nCourse\nActivity", 
-   "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": "group_based_on",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Group Based on",
+   "options": "\nBatch\nCourse\nActivity",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "", 
-   "fieldname": "student_group_name", 
-   "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": "Student Group Name", 
-   "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": "student_group_name",
+   "fieldtype": "Data",
+   "label": "Student Group Name",
+   "reqd": 1,
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "Set 0 for no limit", 
-   "fieldname": "max_strength", 
-   "fieldtype": "Int", 
-   "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": "Max Strength", 
-   "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
-  }, 
+   "description": "Set 0 for no limit",
+   "fieldname": "max_strength",
+   "fieldtype": "Int",
+   "label": "Max Strength"
+  },
   {
-   "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": "column_break_3",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "academic_term", 
-   "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 Term", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Academic Term", 
-   "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_term",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Academic Term",
+   "options": "Academic Term"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "", 
-   "fieldname": "program", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "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, 
-   "unique": 0
-  }, 
+   "fieldname": "program",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "label": "Program",
+   "options": "Program"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "", 
-   "fieldname": "batch", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Batch", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Batch Name", 
-   "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": "batch",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "label": "Batch",
+   "options": "Student Batch Name"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:doc.group_based_on == 'Course'", 
-   "fieldname": "course", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 1, 
-   "label": "Course", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Course", 
-   "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
-  }, 
+   "depends_on": "eval:doc.group_based_on == 'Course'",
+   "fieldname": "course",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "in_standard_filter": 1,
+   "label": "Course",
+   "options": "Course"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "disabled", 
-   "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": "Disabled", 
-   "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": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "collapsible_depends_on": "", 
-   "columns": 0, 
-   "depends_on": "eval:!doc.__islocal", 
-   "fieldname": "section_break_6", 
-   "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": "Students", 
-   "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
-  }, 
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break",
+   "label": "Students"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "get_students", 
-   "fieldtype": "Button", 
-   "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": "Get Students", 
-   "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": "get_students",
+   "fieldtype": "Button",
+   "label": "Get Students"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "students", 
-   "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": "Students", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Group Student", 
-   "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
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "students",
+   "fieldtype": "Table",
+   "label": "Students",
+   "options": "Student Group Student"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_12", 
-   "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": "Instructors", 
-   "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_12",
+   "fieldtype": "Section Break",
+   "label": "Instructors"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "instructors", 
-   "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": "Instructors", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Group Instructor", 
-   "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": "instructors",
+   "fieldtype": "Table",
+   "label": "Instructors",
+   "options": "Student Group Instructor"
+  },
+  {
+   "fieldname": "student_category",
+   "fieldtype": "Link",
+   "label": "Student Category",
+   "options": "Student Category"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "menu_index": 0, 
- "modified": "2018-07-26 04:17:10.836912", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Group", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "modified": "2019-04-26 10:52:57.303951",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Group",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Instructor", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "read": 1,
+   "role": "Instructor"
+  },
   {
-   "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", 
- "search_fields": "program, batch, course", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "restrict_to_domain": "Education",
+ "search_fields": "program, batch, course",
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py
index 465a72d..aba1b5f 100644
--- a/erpnext/education/doctype/student_group/student_group.py
+++ b/erpnext/education/doctype/student_group/student_group.py
@@ -30,7 +30,7 @@
 			frappe.throw(_("""Cannot enroll more than {0} students for this student group.""").format(self.max_strength))
 
 	def validate_students(self):
-		program_enrollment = get_program_enrollment(self.academic_year, self.academic_term, self.program, self.batch, self.course)
+		program_enrollment = get_program_enrollment(self.academic_year, self.academic_term, self.program, self.batch, self.student_category, self.course)
 		students = [d.student for d in program_enrollment] if program_enrollment else []
 		for d in self.students:
 			if not frappe.db.get_value("Student", d.student, "enabled") and d.active and not self.disabled:
@@ -60,8 +60,8 @@
 				roll_no_list.append(d.group_roll_number)
 
 @frappe.whitelist()
-def get_students(academic_year, group_based_on, academic_term=None, program=None, batch=None, course=None):
-	enrolled_students = get_program_enrollment(academic_year, academic_term, program, batch, course)
+def get_students(academic_year, group_based_on, academic_term=None, program=None, batch=None, student_category=None, course=None):
+	enrolled_students = get_program_enrollment(academic_year, academic_term, program, batch, student_category, course)
 
 	if enrolled_students:
 		student_list = []
@@ -76,7 +76,7 @@
 		frappe.msgprint(_("No students found"))
 		return []
 
-def get_program_enrollment(academic_year, academic_term=None, program=None, batch=None, course=None):
+def get_program_enrollment(academic_year, academic_term=None, program=None, batch=None, student_category=None, course=None):
 	
 	condition1 = " "
 	condition2 = " "
@@ -86,6 +86,8 @@
 		condition1 += " and pe.program = %(program)s"
 	if batch:
 		condition1 += " and pe.student_batch_name = %(batch)s"
+	if student_category:
+		condition1 += " and pe.student_category = %(student_category)s"
 	if course:
 		condition1 += " and pe.name = pec.parent and pec.course = %(course)s"
 		condition2 = ", `tabProgram Enrollment Course` pec"
@@ -100,14 +102,14 @@
 		order by
 			pe.student_name asc
 		'''.format(condition1=condition1, condition2=condition2),
-		({"academic_year": academic_year, "academic_term":academic_term, "program": program, "batch": batch, "course": course}), as_dict=1)
+                ({"academic_year": academic_year, "academic_term":academic_term, "program": program, "batch": batch, "student_category": student_category, "course": course}), as_dict=1)
 
 
 @frappe.whitelist()
 def fetch_students(doctype, txt, searchfield, start, page_len, filters):
 	if filters.get("group_based_on") != "Activity":
 		enrolled_students = get_program_enrollment(filters.get('academic_year'), filters.get('academic_term'),
-			filters.get('program'), filters.get('batch'))
+			filters.get('program'), filters.get('batch'), filters.get('student_category'))
 		student_group_student = frappe.db.sql_list('''select student from `tabStudent Group Student` where parent=%s''',
 			(filters.get('student_group')))
 		students = ([d.student for d in enrolled_students if d.student not in student_group_student]
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
index 8256097..7f4b7ba 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
@@ -107,10 +107,18 @@
 
 def setup_custom_fields():
 	custom_fields = {
-		"Customer": [dict(fieldname='shopify_customer_id', label='Shopify Customer Id',
-			fieldtype='Data', insert_after='series', read_only=1, print_hide=1)],
-		"Address": [dict(fieldname='shopify_address_id', label='Shopify Address Id',
-			fieldtype='Data', insert_after='fax', read_only=1, print_hide=1)],
+		"Customer": [
+			dict(fieldname='shopify_customer_id', label='Shopify Customer Id',
+				fieldtype='Data', insert_after='series', read_only=1, print_hide=1)
+		],
+		"Supplier": [
+			dict(fieldname='shopify_supplier_id', label='Shopify Supplier Id',
+				fieldtype='Data', insert_after='supplier_name', read_only=1, print_hide=1)
+		],
+		"Address": [
+			dict(fieldname='shopify_address_id', label='Shopify Address Id',
+				fieldtype='Data', insert_after='fax', read_only=1, print_hide=1)
+		],
 		"Item": [
 			dict(fieldname='shopify_variant_id', label='Shopify Variant Id',
 				fieldtype='Data', insert_after='item_code', read_only=1, print_hide=1),
@@ -119,16 +127,20 @@
 			dict(fieldname='shopify_description', label='Shopify Description',
 				fieldtype='Text Editor', insert_after='description', read_only=1, print_hide=1)
 		],
-		"Sales Order": [dict(fieldname='shopify_order_id', label='Shopify Order Id',
-			fieldtype='Data', insert_after='title', read_only=1, print_hide=1)],
+		"Sales Order": [
+			dict(fieldname='shopify_order_id', label='Shopify Order Id',
+				fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
+		],
 		"Delivery Note":[
 			dict(fieldname='shopify_order_id', label='Shopify Order Id',
 				fieldtype='Data', insert_after='title', read_only=1, print_hide=1),
 			dict(fieldname='shopify_fulfillment_id', label='Shopify Fulfillment Id',
 				fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
 		],
-		"Sales Invoice": [dict(fieldname='shopify_order_id', label='Shopify Order Id',
-			fieldtype='Data', insert_after='title', read_only=1, print_hide=1)]
+		"Sales Invoice": [
+			dict(fieldname='shopify_order_id', label='Shopify Order Id',
+				fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
+		]
 	}
 
 	create_custom_fields(custom_fields)
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 125a8ae..6bba0c5 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -119,7 +119,7 @@
 			if not self.salary_slip_based_on_timesheet:
 				self.get_date_details()
 			self.validate_dates()
-			joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
+			joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
 				["date_of_joining", "relieving_date"])
 
 			self.get_leave_details(joining_date, relieving_date)
@@ -183,7 +183,7 @@
 
 	def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None, for_preview=0):
 		if not joining_date:
-			joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
+			joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
 				["date_of_joining", "relieving_date"])
 
 		working_days = date_diff(self.end_date, self.start_date) + 1
@@ -300,9 +300,6 @@
 
 		self.rounded_total = rounded(self.net_pay)
 
-		if self.net_pay < 0:
-			frappe.throw(_("Net Pay cannnot be negative"))
-
 	def calculate_component_amounts(self):
 		if not getattr(self, '_salary_structure_doc', None):
 			self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure)
@@ -313,6 +310,7 @@
 		self.add_employee_benefits(payroll_period)
 		self.add_additional_salary_components()
 		self.add_tax_components(payroll_period)
+		self.set_component_amounts_based_on_payment_days()
 
 	def add_structure_components(self):
 		data = self.get_data_for_eval()
@@ -404,14 +402,18 @@
 
 	def add_tax_components(self, payroll_period):
 		# Calculate variable_based_on_taxable_salary after all components updated in salary slip
-		struct_tax_components = [d.salary_component for d in self._salary_structure_doc.get("deductions")
-			if d.variable_based_on_taxable_salary == 1 and not d.formula and not d.amount]
+		tax_components, other_deduction_components = [], []
+		for d in self._salary_structure_doc.get("deductions"):
+			if d.variable_based_on_taxable_salary == 1 and not d.formula and not flt(d.amount):
+				tax_components.append(d.salary_component)
+			else:
+				other_deduction_components.append(d.salary_component)
 
-		if not struct_tax_components:
-			struct_tax_components = [d.name for d in
-				frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})]
+		if not tax_components:
+			tax_components = [d.name for d in frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})
+				if d.name not in other_deduction_components]
 
-		for d in struct_tax_components:
+		for d in tax_components:
 			tax_amount = self.calculate_variable_based_on_taxable_salary(d, payroll_period)
 			tax_row = self.get_salary_slip_row(d)
 			self.update_component_row(tax_row, tax_amount, "deductions")
@@ -477,8 +479,7 @@
 		future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1)
 
 		# get taxable_earnings, addition_earnings for current actual payment days
-		self.set_component_amounts_based_on_payment_days()
-		current_taxable_earnings_for_payment_days = self.get_taxable_earnings()
+		current_taxable_earnings_for_payment_days = self.get_taxable_earnings(based_on_payment_days=1)
 		current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings
 		current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income
 		current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax
@@ -501,7 +502,6 @@
 
 		# Structured tax amount
 		total_structured_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings_without_full_tax_addl_components)
-
 		current_structured_tax_amount = (total_structured_tax_amount - previous_total_paid_taxes) / remaining_sub_periods
 
 		# Total taxable earnings with additional earnings with full tax
@@ -560,25 +560,39 @@
 
 		return total_tax_paid
 
-	def get_taxable_earnings(self, only_flexi=0):
+	def get_taxable_earnings(self, based_on_payment_days=0):
+		joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
+			["date_of_joining", "relieving_date"])
+
+		if not relieving_date:
+			relieving_date = getdate(self.end_date)
+
+		if not joining_date:
+			frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(self.employee_name)))
+
 		taxable_earnings = 0
 		additional_income = 0
 		additional_income_with_full_tax = 0
 		flexi_benefits = 0
 
 		for earning in self.earnings:
+			if based_on_payment_days:
+				amount, additional_amount = self.get_amount_based_on_payment_days(earning, joining_date, relieving_date)
+			else:
+				amount, additional_amount = earning.amount, earning.additional_amount
+
 			if earning.is_tax_applicable:
-				if flt(earning.additional_amount):
-					taxable_earnings += (earning.amount - earning.additional_amount)
-					additional_income += earning.additional_amount
+				if additional_amount:
+					taxable_earnings += (amount - additional_amount)
+					additional_income += additional_amount
 					if earning.deduct_full_tax_on_selected_payroll_date:
-						additional_income_with_full_tax += earning.additional_amount
+						additional_income_with_full_tax += additional_amount
 					continue
 
 				if earning.is_flexible_benefit:
-					flexi_benefits += earning.amount
+					flexi_benefits += amount
 				else:
-					taxable_earnings += earning.amount
+					taxable_earnings += amount
 
 		return frappe._dict({
 			"taxable_earnings": taxable_earnings,
@@ -587,6 +601,26 @@
 			"flexi_benefits": flexi_benefits
 		})
 
+	def get_amount_based_on_payment_days(self, row, joining_date, relieving_date):
+		amount, additional_amount = row.amount, row.additional_amount
+		if (self.salary_structure and
+			cint(row.depends_on_payment_days) and cint(self.total_working_days) and
+			(not self.salary_slip_based_on_timesheet or
+				getdate(self.start_date) < joining_date or
+				getdate(self.end_date) > relieving_date
+			)):
+			additional_amount = flt((flt(row.additional_amount) * flt(self.payment_days)
+				/ cint(self.total_working_days)), row.precision("additional_amount"))
+			amount = flt((flt(row.default_amount) * flt(self.payment_days)
+				/ cint(self.total_working_days)), row.precision("amount")) + additional_amount
+
+		elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(row.depends_on_payment_days):
+			amount, additional_amount = 0, 0
+		elif not row.amount:
+			amount = row.default_amount + row.additional_amount
+
+		return amount, additional_amount
+
 	def calculate_unclaimed_taxable_benefits(self, payroll_period):
 		# get total sum of benefits paid
 		total_benefits_paid = flt(frappe.db.sql("""
@@ -688,7 +722,7 @@
 		return total
 
 	def set_component_amounts_based_on_payment_days(self):
-		joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
+		joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
 			["date_of_joining", "relieving_date"])
 
 		if not relieving_date:
@@ -699,22 +733,7 @@
 
 		for component_type in ("earnings", "deductions"):
 			for d in self.get(component_type):
-				if (self.salary_structure and
-					cint(d.depends_on_payment_days) and cint(self.total_working_days) and
-					(not self.salary_slip_based_on_timesheet or
-						getdate(self.start_date) < joining_date or
-						getdate(self.end_date) > relieving_date
-					)):
-
-					d.amount = flt(
-						(flt(d.default_amount + d.additional_amount) * flt(self.payment_days)
-						/ cint(self.total_working_days))
-					, d.precision("amount"))
-
-				elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(d.depends_on_payment_days):
-					d.amount = 0
-				elif not d.amount:
-					d.amount = d.default_amount + d.additional_amount
+				d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
 
 	def set_loan_repayment(self):
 		self.set('loans', [])
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index b7e0782..b333f4f 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -442,7 +442,8 @@
 			"formula": 'base*.1',
 			"type": "Deduction",
 			"amount_based_on_formula": 1,
-			"depends_on_payment_days": 0
+			"depends_on_payment_days": 0,
+			"variable_based_on_taxable_salary": 1
 		}
 	]
 	if not test_tax: