fix: appointment reminders not working
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
index c2fba68..ea0075c 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -30,12 +30,12 @@
   "appointment_datetime",
   "duration",
   "section_break_16",
-  "invoiced",
-  "ref_sales_invoice",
-  "column_break_2",
   "mode_of_payment",
   "paid_amount",
   "company",
+  "column_break_2",
+  "invoiced",
+  "ref_sales_invoice",
   "section_break_3",
   "notes",
   "referring_practitioner",
@@ -83,7 +83,6 @@
    "read_only": 1
   },
   {
-   "default": "Scheduled",
    "depends_on": "eval:!doc.__islocal",
    "fieldname": "status",
    "fieldtype": "Select",
@@ -202,9 +201,9 @@
   {
    "fieldname": "appointment_datetime",
    "fieldtype": "Datetime",
-   "hidden": 1,
-   "label": "Date TIme",
+   "label": "Appointment Datetime",
    "print_hide": 1,
+   "read_only": 1,
    "report_hide": 1,
    "search_index": 1
   },
@@ -227,6 +226,7 @@
    "default": "0",
    "fieldname": "invoiced",
    "fieldtype": "Check",
+   "in_filter": 1,
    "label": "Invoiced",
    "read_only": 1,
    "search_index": 1
@@ -279,7 +279,7 @@
   }
  ],
  "links": [],
- "modified": "2020-02-10 22:38:55.401247",
+ "modified": "2020-02-24 21:29:28.374886",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Patient Appointment",
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 76feb22..4ae079a 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -18,6 +18,7 @@
 class PatientAppointment(Document):
 	def validate(self):
 		self.validate_overlaps()
+		self.set_appointment_datetime()
 
 	def after_insert(self):
 		invoice_appointment(self)
@@ -59,6 +60,9 @@
 				overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
 			frappe.throw(_(overlapping_details))
 
+	def set_appointment_datetime(self):
+		self.appointment_datetime = "%s %s" % (self.appointment_date, self.appointment_time or "00:00:00")
+
 	def update_prescription_details(self):
 		if self.procedure_prescription:
 			frappe.db.set_value('Procedure Prescription', self.procedure_prescription, 'appointment_booked', 1)
@@ -151,6 +155,7 @@
 	else:
 		frappe.msgprint(_('Appointment Cancelled'))
 
+
 def validate_appointment_in_fee_validity(appointment, valid_end_date, ref_invoice):
 	valid_days = frappe.db.get_single_value('Healthcare Settings', 'valid_days')
 	max_visit = frappe.db.get_single_value('Healthcare Settings', 'max_visit')
@@ -172,6 +177,7 @@
 			return True
 	return False
 
+
 def cancel_sales_invoice(sales_invoice):
 	if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
 		if len(sales_invoice.items) == 1:
@@ -179,6 +185,7 @@
 			return True
 	return False
 
+
 def check_si_item_exists(appointment):
 	return frappe.db.exists(
 		'Sales Invoice Item',
@@ -188,6 +195,7 @@
 		}
 	)
 
+
 def check_sales_invoice_exists(appointment):
 	si_item = check_si_item_exists(appointment)
 	if si_item:
@@ -195,6 +203,7 @@
 		return sales_invoice
 	return False
 
+
 @frappe.whitelist()
 def get_availability_data(date, practitioner):
 	"""
@@ -223,6 +232,7 @@
 
 	return {'slot_details': slot_details}
 
+
 def check_employee_wise_availability(date, practitioner_doc):
 	employee = None
 	if practitioner_doc.employee:
@@ -245,6 +255,7 @@
 			else:
 				frappe.throw(_('{0} is on Leave on {1}').format(practitioner_doc.name, date))
 
+
 def get_available_slots(practitioner_schedules, date):
 	available_slots = []
 	slot_details = []
@@ -315,6 +326,7 @@
 		message = frappe.db.get_single_value('Healthcare Settings', 'appointment_confirmation_msg')
 		send_message(doc, message)
 
+
 @frappe.whitelist()
 def make_encounter(source_name, target_doc=None):
 	doc = get_mapped_doc('Patient Appointment', source_name, {
@@ -331,25 +343,26 @@
 			]
 		}
 	}, target_doc)
-
 	return doc
 
-def remind_appointment():
+
+def send_appointment_reminder():
 	if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_reminder'):
-		remind_before = datetime.datetime.strptime(frappe.get_single_value('Healthcare Settings', 'remind_before'), '%H:%M:%S')
+		remind_before = datetime.datetime.strptime(frappe.db.get_single_value('Healthcare Settings', 'remind_before'), '%H:%M:%S')
 		reminder_dt = datetime.datetime.now() + datetime.timedelta(
 			hours=remind_before.hour, minutes=remind_before.minute, seconds=remind_before.second)
 
-		appointment_list = frappe.db.sql(
-			'select name from `tabPatient Appointment` where start_dt between %s and %s and reminded = 0 ',
-			(datetime.datetime.now(), reminder_dt)
-		)
+		appointment_list = frappe.db.get_all('Patient Appointment', {
+			'appointment_datetime': ['between', (datetime.datetime.now(), reminder_dt)],
+			'reminded': 0,
+			'status': ['!=', 'Cancelled']
+		})
 
-		for i in range(0, len(appointment_list)):
-			doc = frappe.get_doc('Patient Appointment', appointment_list[i][0])
+		for appointment in appointment_list:
+			doc = frappe.get_doc('Patient Appointment', appointment.name)
 			message = frappe.db.get_single_value('Healthcare Settings', 'appointment_reminder_msg')
 			send_message(doc, message)
-			frappe.db.set_value('Patient Appointment', doc.name, 'reminded',1)
+			frappe.db.set_value('Patient Appointment', doc.name, 'reminded', 1)
 
 def send_message(doc, message):
 	patient = frappe.get_doc('Patient', doc.patient)
@@ -363,6 +376,7 @@
 		number = [patient.mobile]
 		send_sms(number, message)
 
+
 @frappe.whitelist()
 def get_events(start, end, filters=None):
 	"""Returns events for Gantt / Calendar view rendering.
@@ -372,7 +386,7 @@
 	:param filters: Filters (JSON).
 	"""
 	from frappe.desk.calendar import get_event_conditions
-	conditions = get_event_conditions("Patient Appointment", filters)
+	conditions = get_event_conditions('Patient Appointment', filters)
 
 	data = frappe.db.sql("""
 		select
@@ -394,6 +408,7 @@
 
 	return data
 
+
 @frappe.whitelist()
 def get_procedure_prescribed(patient):
 	return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 774c917..bc3dffa 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -273,7 +273,8 @@
 
 scheduler_events = {
 	"all": [
-		"erpnext.projects.doctype.project.project.project_status_update_reminder"
+		"erpnext.projects.doctype.project.project.project_status_update_reminder",
+		"erpnext.healthcare_healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder"
 	],
 	"hourly": [
 		'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',