Merge pull request #21509 from ruchamahabal/fix-healthcare-v13-beta

fix: Healthcare Fixes
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index 5f36bdd..87c22cc 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -80,6 +80,7 @@
 							frappe.call({
 								method: 'complete_procedure',
 								doc: frm.doc,
+								freeze: true,
 								callback: function(r) {
 									if (r.message) {
 										frappe.show_alert({
@@ -87,8 +88,8 @@
 												['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
 											indicator: 'green'
 										});
-										frm.reload_doc();
 									}
+									frm.reload_doc();
 								}
 							});
 						}
@@ -111,9 +112,10 @@
 											frappe.call({
 												doc: frm.doc,
 												method: 'make_material_receipt',
+												freeze: true,
 												callback: function(r) {
 													if (!r.exc) {
-														cur_frm.reload_doc();
+														frm.reload_doc();
 														let doclist = frappe.model.sync(r.message);
 														frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
 													}
@@ -122,7 +124,7 @@
 										}
 									);
 								} else {
-									cur_frm.reload_doc();
+									frm.reload_doc();
 								}
 							}
 						}
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
index db3afc8..b7d7a62 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
@@ -87,7 +87,8 @@
 			else:
 				frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
 
-		frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed')
+		self.db_set('status', 'Completed')
+
 		if self.consume_stock and self.items:
 			return stock_entry
 
@@ -245,9 +246,9 @@
 
 
 def insert_clinical_procedure_to_medical_record(doc):
-	subject = cstr(doc.procedure_template)
+	subject = frappe.bold(_("Clinical Procedure conducted: ")) + cstr(doc.procedure_template) + "<br>"
 	if doc.practitioner:
-		subject += ' ' + doc.practitioner
+		subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
 	if subject and doc.notes:
 		subject += '<br/>' + doc.notes
 
diff --git a/erpnext/healthcare/doctype/exercise_type/exercise_type.js b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
index f450c9b..68db047 100644
--- a/erpnext/healthcare/doctype/exercise_type/exercise_type.js
+++ b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
@@ -24,6 +24,8 @@
 
 		this.exercise_cards = $('<div class="exercise-cards"></div>').appendTo(this.wrapper);
 
+		this.row = $('<div class="exercise-row"></div>').appendTo(this.wrapper);
+
 		let me = this;
 
 		this.exercise_toolbar.find(".btn-add")
@@ -32,7 +34,7 @@
 				me.show_add_card_dialog(frm);
 			});
 
-		if (frm.doc.steps_table.length > 0) {
+		if (frm.doc.steps_table && frm.doc.steps_table.length > 0) {
 			this.make_cards(frm);
 			this.make_buttons(frm);
 		}
@@ -41,7 +43,6 @@
 	make_cards: function(frm) {
 		var me = this;
 		$(me.exercise_cards).empty();
-		this.row = $('<div class="exercise-row"></div>').appendTo(me.exercise_cards);
 
 		$.each(frm.doc.steps_table, function(i, step) {
 			$(repl(`
@@ -78,6 +79,7 @@
 				frm.doc.steps_table.pop(id);
 				frm.refresh_field('steps_table');
 				$('#col-'+id).remove();
+				frm.dirty();
 			}, 300);
 		});
 	},
@@ -106,7 +108,10 @@
 			],
 			primary_action: function() {
 				let data = d.get_values();
-				let i = frm.doc.steps_table.length;
+				let i = 0;
+				if (frm.doc.steps_table) {
+					i = frm.doc.steps_table.length;
+				}
 				$(repl(`
 					<div class="exercise-col col-sm-4" id="%(col_id)s">
 						<div class="card h-100 exercise-card" id="%(card_id)s">
@@ -165,9 +170,10 @@
 				frm.doc.steps_table[id].image = data.image;
 				frm.doc.steps_table[id].description = data.step_description;
 				refresh_field('steps_table');
+				frm.dirty();
 				new_dialog.hide();
 			},
-			primary_action_label: __("Save"),
+			primary_action_label: __("Edit"),
 		});
 
 		new_dialog.set_values({
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py
index 4e4015d..ea8ce25 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.py
@@ -288,23 +288,23 @@
 	table_row = False
 	subject = cstr(doc.lab_test_name)
 	if doc.practitioner:
-		subject += " "+ doc.practitioner
+		subject += frappe.bold(_("Healthcare Practitioner: "))+ doc.practitioner + "<br>"
 	if doc.normal_test_items:
 		item = doc.normal_test_items[0]
 		comment = ""
 		if item.lab_test_comment:
 			comment = str(item.lab_test_comment)
-		table_row = item.lab_test_name
+		table_row = frappe.bold(_("Lab Test Conducted: ")) + item.lab_test_name
 
 		if item.lab_test_event:
-			table_row += " " + item.lab_test_event
+			table_row += frappe.bold(_("Lab Test Event: ")) + item.lab_test_event
 
 		if item.result_value:
-			table_row += " " + item.result_value
+			table_row += " " + frappe.bold(_("Lab Test Result: ")) + item.result_value
 
 		if item.normal_range:
-			table_row += " normal_range("+item.normal_range+")"
-		table_row += " "+comment
+			table_row += " " + _("Normal Range:") + item.normal_range
+		table_row += " " + comment
 
 	elif doc.special_test_items:
 		item = doc.special_test_items[0]
@@ -316,12 +316,12 @@
 		item = doc.sensitivity_test_items[0]
 
 		if item.antibiotic and item.antibiotic_sensitivity:
-			table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
+			table_row = item.antibiotic + " " + item.antibiotic_sensitivity
 
 	if table_row:
-		subject += "<br/>"+table_row
+		subject += "<br>" + table_row
 	if doc.lab_test_comment:
-		subject += "<br/>"+ cstr(doc.lab_test_comment)
+		subject += "<br>" + cstr(doc.lab_test_comment)
 
 	medical_record = frappe.new_doc("Patient Medical Record")
 	medical_record.patient = doc.patient
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index 767643b..1734c28 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -18,6 +18,9 @@
 	def after_insert(self):
 		insert_encounter_to_medical_record(self)
 
+	def on_submit(self):
+		update_encounter_medical_record(self)
+
 	def on_cancel(self):
 		if self.appointment:
 			frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
@@ -66,22 +69,26 @@
 	frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
 
 def set_subject_field(encounter):
-	subject = encounter.practitioner + '\n'
+	subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + '<br>'
 	if encounter.symptoms:
-		subject += _('Symptoms: ') + cstr(encounter.symptoms) + '\n'
+		subject += frappe.bold(_('Symptoms: ')) + '<br>'
+		for entry in encounter.symptoms:
+			subject += cstr(entry.complaint) + '<br>'
 	else:
-		subject +=  _('No Symptoms') + '\n'
+		subject += frappe.bold(_('No Symptoms')) + '<br>'
 
 	if encounter.diagnosis:
-		subject += _('Diagnosis: ') + cstr(encounter.diagnosis) + '\n'
+		subject += frappe.bold(_('Diagnosis: ')) + '<br>'
+		for entry in encounter.diagnosis:
+			subject += cstr(entry.diagnosis) + '<br>'
 	else:
-		subject += _('No Diagnosis') + '\n'
+		subject += frappe.bold(_('No Diagnosis')) + '<br>'
 
 	if encounter.drug_prescription:
-		subject += '\n' + _('Drug(s) Prescribed.')
+		subject += '<br>' + _('Drug(s) Prescribed.')
 	if encounter.lab_test_prescription:
-		subject += '\n' + _('Test(s) Prescribed.')
+		subject += '<br>' + _('Test(s) Prescribed.')
 	if encounter.procedure_prescription:
-		subject += '\n' + _('Procedure(s) Prescribed.')
+		subject += '<br>' + _('Procedure(s) Prescribed.')
 
 	return subject
diff --git a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
index 3655e24..ed82355 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
+++ b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
@@ -57,7 +57,7 @@
   },
   {
    "fieldname": "subject",
-   "fieldtype": "Small Text",
+   "fieldtype": "Text Editor",
    "ignore_xss_filter": 1,
    "label": "Subject"
   },
@@ -125,7 +125,7 @@
  ],
  "in_create": 1,
  "links": [],
- "modified": "2020-03-23 19:26:59.308383",
+ "modified": "2020-04-29 12:26:57.679402",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Patient Medical Record",
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
index 201264f..c19be17 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -21,8 +21,14 @@
 				self.status = 'Completed'
 
 	def set_totals(self):
-		total_sessions = sum([int(d.no_of_sessions) for d in self.get('therapy_plan_details')])
-		total_sessions_completed = sum([int(d.sessions_completed) for d in self.get('therapy_plan_details')])
+		total_sessions = 0
+		total_sessions_completed = 0
+		for entry in self.therapy_plan_details:
+			if entry.no_of_sessions:
+				total_sessions += entry.no_of_sessions
+			if entry.sessions_completed:
+				total_sessions_completed += entry.sessions_completed
+
 		self.db_set('total_sessions', total_sessions)
 		self.db_set('total_sessions_completed', total_sessions_completed)
 
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.js b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
index bb67575..abe4def 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.js
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
@@ -13,23 +13,92 @@
 
 	refresh: function(frm) {
 		if (!frm.doc.__islocal) {
-			let target = 0;
-			let completed = 0;
-			$.each(frm.doc.exercises, function(_i, e) {
-				target += e.counts_target;
-				completed += e.counts_completed;
-			});
-			frm.dashboard.add_indicator(__('Counts Targetted: {0}', [target]), 'blue');
-			frm.dashboard.add_indicator(__('Counts Completed: {0}', [completed]), (completed < target) ? 'orange' : 'green');
+			frm.dashboard.add_indicator(__('Counts Targeted: {0}', [frm.doc.total_counts_targeted]), 'blue');
+			frm.dashboard.add_indicator(__('Counts Completed: {0}', [frm.doc.total_counts_completed]),
+				(frm.doc.total_counts_completed < frm.doc.total_counts_targeted) ? 'orange' : 'green');
 		}
 
 		if (frm.doc.docstatus === 1) {
-			frm.add_custom_button(__('Patient Assessment'),function() {
+			frm.add_custom_button(__('Patient Assessment'), function() {
 				frappe.model.open_mapped_doc({
 					method: 'erpnext.healthcare.doctype.patient_assessment.patient_assessment.create_patient_assessment',
 					frm: frm,
 				})
 			}, 'Create');
+
+			frm.add_custom_button(__('Sales Invoice'), function() {
+				frappe.model.open_mapped_doc({
+					method: 'erpnext.healthcare.doctype.therapy_session.therapy_session.invoice_therapy_session',
+					frm: frm,
+				})
+			}, 'Create');
+		}
+	},
+
+	patient: function(frm) {
+		if (frm.doc.patient) {
+			frappe.call({
+				'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
+				args: {
+					patient: frm.doc.patient
+				},
+				callback: function (data) {
+					let age = '';
+					if (data.message.dob) {
+						age = calculate_age(data.message.dob);
+					} else if (data.message.age) {
+						age = data.message.age;
+						if (data.message.age_as_on) {
+							age = __('{0} as on {1}', [age, data.message.age_as_on]);
+						}
+					}
+					frm.set_value('patient_age', age);
+					frm.set_value('gender', data.message.sex);
+					frm.set_value('patient_name', data.message.patient_name);
+				}
+			});
+		} else {
+			frm.set_value('patient_age', '');
+			frm.set_value('gender', '');
+			frm.set_value('patient_name', '');
+		}
+	},
+
+	appointment: function(frm) {
+		if (frm.doc.appointment) {
+			frappe.call({
+				'method': 'frappe.client.get',
+				args: {
+					doctype: 'Patient Appointment',
+					name: frm.doc.appointment
+				},
+				callback: function(data) {
+					let values = {
+						'patient':data.message.patient,
+						'therapy_type': data.message.therapy_type,
+						'therapy_plan': data.message.therapy_plan,
+						'practitioner': data.message.practitioner,
+						'department': data.message.department,
+						'start_date': data.message.appointment_date,
+						'start_time': data.message.appointment_time,
+						'service_unit': data.message.service_unit,
+						'company': data.message.company
+					};
+					frm.set_value(values);
+				}
+			});
+		} else {
+			let values = {
+				'patient': '',
+				'therapy_type': '',
+				'therapy_plan': '',
+				'practitioner': '',
+				'department': '',
+				'start_date': '',
+				'start_time': '',
+				'service_unit': '',
+			};
+			frm.set_value(values);
 		}
 	},
 
@@ -44,6 +113,8 @@
 				callback: function(data) {
 					frm.set_value('duration', data.message.default_duration);
 					frm.set_value('rate', data.message.rate);
+					frm.set_value('service_unit', data.message.healthcare_service_unit);
+					frm.set_value('department', data.message.medical_department);
 					frm.doc.exercises = [];
 					$.each(data.message.exercises, function(_i, e) {
 						let exercise = frm.add_child('exercises');
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.json b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
index 5ff7196..00d74a0 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.json
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
@@ -9,9 +9,11 @@
   "naming_series",
   "appointment",
   "patient",
+  "patient_name",
   "patient_age",
   "gender",
   "column_break_5",
+  "company",
   "therapy_plan",
   "therapy_type",
   "practitioner",
@@ -20,7 +22,6 @@
   "duration",
   "rate",
   "location",
-  "company",
   "column_break_12",
   "service_unit",
   "start_date",
@@ -28,6 +29,10 @@
   "invoiced",
   "exercises_section",
   "exercises",
+  "section_break_23",
+  "total_counts_targeted",
+  "column_break_25",
+  "total_counts_completed",
   "amended_from"
  ],
  "fields": [
@@ -159,7 +164,8 @@
    "fieldname": "company",
    "fieldtype": "Link",
    "label": "Company",
-   "options": "Company"
+   "options": "Company",
+   "reqd": 1
   },
   {
    "default": "0",
@@ -173,11 +179,38 @@
    "fieldtype": "Data",
    "label": "Patient Age",
    "read_only": 1
+  },
+  {
+   "fieldname": "total_counts_targeted",
+   "fieldtype": "Int",
+   "label": "Total Counts Targeted",
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_counts_completed",
+   "fieldtype": "Int",
+   "label": "Total Counts Completed",
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_23",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_25",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "patient.patient_name",
+   "fieldname": "patient_name",
+   "fieldtype": "Data",
+   "label": "Patient Name",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-21 13:16:46.378798",
+ "modified": "2020-04-29 16:49:16.286006",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Therapy Session",
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.py b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
index 45d2ee6..9650183 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.py
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
@@ -6,10 +6,17 @@
 import frappe
 from frappe.model.document import Document
 from frappe.model.mapper import get_mapped_doc
+from frappe import _
+from frappe.utils import cstr, getdate
+from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
 
 class TherapySession(Document):
+	def validate(self):
+		self.set_total_counts()
+
 	def on_submit(self):
 		self.update_sessions_count_in_therapy_plan()
+		insert_session_medical_record(self)
 
 	def on_cancel(self):
 		self.update_sessions_count_in_therapy_plan(on_cancel=True)
@@ -24,6 +31,18 @@
 					entry.sessions_completed += 1
 		therapy_plan.save()
 
+	def set_total_counts(self):
+		target_total = 0
+		counts_completed = 0
+		for entry in self.exercises:
+			if entry.counts_target:
+				target_total += entry.counts_target
+			if entry.counts_completed:
+				counts_completed += entry.counts_completed
+
+		self.db_set('total_counts_targeted', target_total)
+		self.db_set('total_counts_completed', counts_completed)
+
 
 @frappe.whitelist()
 def create_therapy_session(source_name, target_doc=None):
@@ -52,4 +71,62 @@
 			}
 		}, target_doc, set_missing_values)
 
-	return doc
\ No newline at end of file
+	return doc
+
+
+@frappe.whitelist()
+def invoice_therapy_session(source_name, target_doc=None):
+	def set_missing_values(source, target):
+		target.customer = frappe.db.get_value('Patient', source.patient, 'customer')
+		target.due_date = getdate()
+		target.debit_to = get_receivable_account(source.company)
+		item = target.append('items', {})
+		item = get_therapy_item(source, item)
+		target.set_missing_values(for_validate=True)
+
+	doc = get_mapped_doc('Therapy Session', source_name, {
+			'Therapy Session': {
+				'doctype': 'Sales Invoice',
+				'field_map': [
+					['patient', 'patient'],
+					['referring_practitioner', 'practitioner'],
+					['company', 'company'],
+					['due_date', 'start_date']
+				]
+			}
+		}, target_doc, set_missing_values)
+
+	return doc
+
+
+def get_therapy_item(therapy, item):
+	item.item_code = frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
+	item.description = _('Therapy Session Charges: {0}').format(therapy.practitioner)
+	item.income_account = get_income_account(therapy.practitioner, therapy.company)
+	item.cost_center = frappe.get_cached_value('Company', therapy.company, 'cost_center')
+	item.rate = therapy.rate
+	item.amount = therapy.rate
+	item.qty = 1
+	item.reference_dt = 'Therapy Session'
+	item.reference_dn = therapy.name
+	return item
+
+
+def insert_session_medical_record(doc):
+	subject = frappe.bold(_('Therapy: ')) + cstr(doc.therapy_type) + '<br>'
+	if doc.therapy_plan:
+		subject += frappe.bold(_('Therapy Plan: ')) + cstr(doc.therapy_plan) + '<br>'
+	if doc.practitioner:
+		subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
+	subject += frappe.bold(_('Total Counts Targeted: ')) + cstr(doc.total_counts_targeted) + '<br>'
+	subject += frappe.bold(_('Total Counts Completed: ')) + cstr(doc.total_counts_completed) + '<br>'
+
+	medical_record = frappe.new_doc('Patient Medical Record')
+	medical_record.patient = doc.patient
+	medical_record.subject = subject
+	medical_record.status = 'Open'
+	medical_record.communication_date = doc.start_date
+	medical_record.reference_doctype = 'Therapy Session'
+	medical_record.reference_name = doc.name
+	medical_record.reference_owner = doc.owner
+	medical_record.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.py b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
index 959e850..b0e78e8 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.py
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
@@ -35,17 +35,17 @@
 
 def set_subject_field(doc):
 	subject = ''
-	if(doc.temperature):
-		subject += _('Temperature: ') + '\n'+ cstr(doc.temperature) + '. '
-	if(doc.pulse):
-		subject += _('Pulse: ') + '\n' + cstr(doc.pulse) + '. '
-	if(doc.respiratory_rate):
-		subject += _('Respiratory Rate: ') + '\n' + cstr(doc.respiratory_rate) + '. '
-	if(doc.bp):
-		subject += _('BP: ') + '\n' + cstr(doc.bp) + '. '
-	if(doc.bmi):
-		subject += _('BMI: ') + '\n' + cstr(doc.bmi) + '. '
-	if(doc.nutrition_note):
-		subject += _('Note: ') + '\n' + cstr(doc.nutrition_note) + '. '
+	if doc.temperature:
+		subject += frappe.bold(_('Temperature: ')) + cstr(doc.temperature) + '<br>'
+	if doc.pulse:
+		subject += frappe.bold(_('Pulse: ')) + cstr(doc.pulse) + '<br>'
+	if doc.respiratory_rate:
+		subject += frappe.bold(_('Respiratory Rate: ')) + cstr(doc.respiratory_rate) + '<br>'
+	if doc.bp:
+		subject += frappe.bold(_('BP: ')) + cstr(doc.bp) + '<br>'
+	if doc.bmi:
+		subject += frappe.bold(_('BMI: ')) + cstr(doc.bmi) + '<br>'
+	if doc.nutrition_note:
+		subject += frappe.bold(_('Note: ')) + cstr(doc.nutrition_note) + '<br>'
 
 	return subject