feat: Healthcare Domain Workspace with chart and shortcuts
diff --git a/erpnext/healthcare/desk_page/healthcare/healthcare.json b/erpnext/healthcare/desk_page/healthcare/healthcare.json
index 0160cd4..d948cee 100644
--- a/erpnext/healthcare/desk_page/healthcare/healthcare.json
+++ b/erpnext/healthcare/desk_page/healthcare/healthcare.json
@@ -1,28 +1,50 @@
 {
  "cards": [
   {
-   "icon": "icon-cog",
-   "links": "[\n    {\n        \"label\": \"Healthcare Settings\",\n        \"name\": \"Healthcare Settings\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Medical Department\",\n        \"name\": \"Medical Department\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Appointment Type\",\n        \"name\": \"Appointment Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Prescription Dosage\",\n        \"name\": \"Prescription Dosage\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Prescription Duration\",\n        \"name\": \"Prescription Duration\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Complaint\",\n        \"name\": \"Complaint\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Diagnosis\",\n        \"name\": \"Diagnosis\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Lab Test Sample\",\n        \"name\": \"Lab Test Sample\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Lab Test UOM\",\n        \"name\": \"Lab Test UOM\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Antibiotic\",\n        \"name\": \"Antibiotic\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Sensitivity\",\n        \"name\": \"Sensitivity\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Lab Test Template\",\n        \"name\": \"Lab Test Template\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Clinical Procedure Template\",\n        \"name\": \"Clinical Procedure Template\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Healthcare Service Unit Type\",\n        \"name\": \"Healthcare Service Unit Type\",\n        \"type\": \"doctype\"\n    }\n]",
-   "title": "Settings"
-  },
-  {
-   "icon": "icon-list",
-   "links": "[\n    {\n        \"label\": \"Lab Test\",\n        \"name\": \"Lab Test\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Sample Collection\",\n        \"name\": \"Sample Collection\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Lab Test Report\",\n        \"name\": \"Lab Test Report\",\n        \"type\": \"report\"\n    }\n]",
-   "title": "Laboratory"
-  },
-  {
-   "icon": "icon-list",
-   "links": "[\n    {\n        \"label\": \"Patient\",\n        \"name\": \"Patient\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Healthcare Practitioner\",\n        \"name\": \"Healthcare Practitioner\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Practitioner Schedule\",\n        \"name\": \"Practitioner Schedule\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Medical Code Standard\",\n        \"name\": \"Medical Code Standard\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Medical Code\",\n        \"name\": \"Medical Code\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Healthcare Service Unit\",\n        \"name\": \"Healthcare Service Unit\",\n        \"type\": \"doctype\"\n    }\n]",
+   "icon": "",
+   "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient\",\n\t\t\"label\": \"Patient\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Practitioner\",\n\t\t\"label\":\"Healthcare Practitioner\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Practitioner Schedule\",\n\t\t\"label\": \"Practitioner Schedule\",\n\t\t\"onboard\": 1\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Department\",\n\t\t\"label\": \"Medical Department\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Service Unit Type\",\n\t\t\"label\": \"Healthcare Service Unit Type\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Service Unit\",\n\t\t\"label\": \"Healthcare Service Unit\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Code Standard\",\n\t\t\"label\": \"Medical Code Standard\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Medical Code\",\n\t\t\"label\": \"Medical Code\"\n\t}\n]",
    "title": "Masters"
   },
   {
+   "icon": "",
+   "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Appointment Type\",\n\t\t\"label\": \"Appointment Type\"\n    },\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Clinical Procedure Template\",\n\t\t\"label\": \"Clinical Procedure Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Prescription Dosage\",\n\t\t\"label\": \"Prescription Dosage\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Prescription Duration\",\n\t\t\"label\": \"Prescription Duration\"\n\t},\n\t{\n\t    \"type\": \"doctype\",\n\t\t\"name\": \"Antibiotic\",\n\t\t\"label\": \"Antibiotic\"\n\t}\n]",
+   "title": "Consultation Setup"
+  },
+  {
    "icon": "icon-star",
-   "links": "[\n    {\n        \"label\": \"Patient Appointment\",\n        \"name\": \"Patient Appointment\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Patient Encounter\",\n        \"name\": \"Patient Encounter\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Record Patient Vitals\",\n        \"label\": \"Vital Signs\",\n        \"name\": \"Vital Signs\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Patient History\",\n        \"name\": \"patient_history\",\n        \"type\": \"page\"\n    },\n    {\n        \"label\": \"Appointment Analytics\",\n        \"name\": \"appointment-analytic\",\n        \"type\": \"page\"\n    },\n    {\n        \"label\": \"Clinical Procedure\",\n        \"name\": \"Clinical Procedure\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Inpatient Record\",\n        \"name\": \"Inpatient Record\",\n        \"type\": \"doctype\"\n    }\n]",
+   "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Appointment\",\n\t\t\"label\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Clinical Procedure\",\n\t\t\"label\": \"Clinical Procedure\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Encounter\",\n\t\t\"label\": \"Patient Encounter\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Vital Signs\",\n\t\t\"label\": \"Vital Signs\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Complaint\",\n\t\t\"label\": \"Complaint\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Diagnosis\",\n\t\t\"label\": \"Diagnosis\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Fee Validity\",\n\t\t\"label\": \"Fee Validity\"\n\t}\n]",
    "title": "Consultation"
+  },
+  {
+   "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Healthcare Settings\",\n\t\t\"label\": \"Healthcare Settings\",\n\t\t\"onboard\": 1\n\t}\n]",
+   "title": "Settings"
+  },
+  {
+   "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test Template\",\n\t\t\"label\": \"Lab Test Template\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test Sample\",\n\t\t\"label\": \"Lab Test Sample\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test UOM\",\n\t\t\"label\": \"Lab Test UOM\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Sensitivity\",\n\t\t\"label\": \"Sensitivity\"\n\t}\n]",
+   "title": "Laboratory Setup"
+  },
+  {
+   "links": "[\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Lab Test\",\n\t\t\"label\": \"Lab Test\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Sample Collection\",\n\t\t\"label\": \"Sample Collection\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Dosage Form\",\n\t\t\"label\": \"Dosage Form\"\n\t}\n]",
+   "title": "Laboratory"
+  },
+  {
+   "links": "[\n\t{\n\t\t\"type\": \"page\",\n\t\t\"name\": \"patient_history\",\n\t\t\"label\": \"Patient History\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Patient Medical Record\",\n\t\t\"label\": \"Patient Medical Record\"\n\t},\n\t{\n\t\t\"type\": \"doctype\",\n\t\t\"name\": \"Inpatient Record\",\n\t\t\"label\": \"Inpatient Record\"\n\t}\n]",
+   "title": "Records and History"
+  },
+  {
+   "links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t}\n]",
+   "title": "Reports"
   }
  ],
  "category": "Domains",
- "charts": [],
+ "charts": [
+  {
+   "chart_name": "Patient Appointments",
+   "label": "Patient Appointments",
+   "size": "Full"
+  }
+ ],
+ "charts_label": "",
  "creation": "2020-03-02 17:23:17.919682",
  "developer_mode_only": 0,
  "disable_user_customization": 0,
@@ -30,7 +52,7 @@
  "doctype": "Desk Page",
  "idx": 0,
  "label": "Healthcare",
- "modified": "2020-03-05 11:27:25.682521",
+ "modified": "2020-03-12 17:24:45.970847",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare",
@@ -38,5 +60,37 @@
  "pin_to_bottom": 0,
  "pin_to_top": 0,
  "restrict_to_domain": "Healthcare",
- "shortcuts": []
+ "shortcuts": [
+  {
+   "format": "{} Open",
+   "is_query_report": 0,
+   "link_to": "Patient Appointment",
+   "stats_filter": "{\n    \"status\": \"Open\"\n}",
+   "type": "DocType"
+  },
+  {
+   "format": "{} Active",
+   "is_query_report": 0,
+   "link_to": "Patient",
+   "stats_filter": "{\n    \"status\": \"Active\"\n}",
+   "type": "DocType"
+  },
+  {
+   "format": "{} Vacant",
+   "is_query_report": 0,
+   "link_to": "Healthcare Service Unit",
+   "stats_filter": "{\n    \"occupancy_status\": \"Vacant\"\n}",
+   "type": "DocType"
+  },
+  {
+   "is_query_report": 0,
+   "link_to": "Healthcare Practitioner",
+   "type": "DocType"
+  },
+  {
+   "is_query_report": 0,
+   "link_to": "patient_history",
+   "type": "Page"
+  }
+ ]
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index d329e5d..c12ae86 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -432,11 +432,12 @@
 	where ct.patient='{0}' and pp.parent=ct.name and pp.appointment_booked=0
 	order by ct.creation desc""".format(patient))
 
+
 def update_appointment_status():
 	# update the status of appointments daily
+	appointments = frappe.get_all('Patient Appointment', {
+		'status': ('not in', ['Closed', 'Cancelled'])
+	}, as_dict=1)
 
-	frappe.db.sql("""update `tabPatient Appointment` set status = 'Open'
-		where appointment_date = CURDATE() and status = 'Scheduled'""")
-
-	frappe.db.sql("""update `tabPatient Appointment` set status = 'Expired'
-		where appointment_date < CURDATE() and status NOT IN ('Closed', 'Cancelled')""")
\ No newline at end of file
+	for appointment in appointments:
+		frappe.get_doc('Patient Appointment', appointment.name).set_status()
\ No newline at end of file
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 639621c..4bf0bdb 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -471,50 +471,50 @@
 
 @frappe.whitelist()
 def get_children(doctype, parent, company, is_root=False):
-	parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
+	parent_fieldname = "parent_" + doctype.lower().replace(" ", "_")
 	fields = [
-		'name as value',
-		'is_group as expandable',
-		'lft',
-		'rgt'
+		"name as value",
+		"is_group as expandable",
+		"lft",
+		"rgt"
 	]
-	# fields = [ 'name', 'is_group', 'lft', 'rgt' ]
-	filters = [['ifnull(`{0}`,'')'.format(parent_fieldname), '=', '' if is_root else parent]]
+	# fields = [ "name", "is_group", "lft", "rgt" ]
+	filters = [["ifnull(`{0}`,'')".format(parent_fieldname), "=", "" if is_root else parent]]
 
 	if is_root:
-		fields += ['service_unit_type'] if doctype == 'Healthcare Service Unit' else []
-		filters.append(['company', '=', company])
+		fields += ["service_unit_type"] if doctype == "Healthcare Service Unit" else []
+		filters.append(["company", "=", company])
 
 	else:
-		fields += ['service_unit_type', 'allow_appointments', 'inpatient_occupancy', 'occupancy_status'] if doctype == 'Healthcare Service Unit' else []
-		fields += [parent_fieldname + ' as parent']
+		fields += ["service_unit_type", "allow_appointments", "inpatient_occupancy", "occupancy_status"] if doctype == "Healthcare Service Unit" else []
+		fields += [parent_fieldname + " as parent"]
 
 	hc_service_units = frappe.get_list(doctype, fields=fields, filters=filters)
 
-	if doctype == 'Healthcare Service Unit':
+	if doctype == "Healthcare Service Unit":
 		for each in hc_service_units:
-			occupancy_msg = ''
-			if each['expandable'] == 1:
+			occupancy_msg = ""
+			if each["expandable"] == 1:
 				occupied = False
 				vacant = False
-				child_list = frappe.db.sql('''
+				child_list = frappe.db.sql("""
 					select name, occupancy_status from `tabHealthcare Service Unit`
 					where inpatient_occupancy = 1 and
-					lft > %s and rgt < %s''',
-					(each['lft'], each['rgt']))
+					lft > %s and rgt < %s""",
+					(each["lft"], each["rgt"]))
 				for child in child_list:
 					if not occupied:
 						occupied = 0
-					if child[1] == 'Occupied':
+					if child[1] == "Occupied":
 						occupied += 1
 					if not vacant:
 						vacant = 0
-					if child[1] == 'Vacant':
+					if child[1] == "Vacant":
 						vacant += 1
 				if vacant and occupied:
 					occupancy_total = vacant + occupied
-					occupancy_msg = str(occupied) + ' Occupied out of ' + str(occupancy_total)
-			each['occupied_out_of_vacant'] = occupancy_msg
+					occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
+			each["occupied_out_of_vacant"] = occupancy_msg
 	return hc_service_units