Merge pull request #21817 from akurungadam/develop-13

refactor(Healthcare): IP Admission and Discharge, Minor fixes
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
index ea4ae84..9ee865a 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
+++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json
@@ -12,7 +12,6 @@
  "engine": "InnoDB",
  "field_order": [
   "healthcare_service_unit_name",
-  "parent_healthcare_service_unit",
   "is_group",
   "service_unit_type",
   "allow_appointments",
@@ -20,8 +19,10 @@
   "inpatient_occupancy",
   "occupancy_status",
   "column_break_9",
-  "warehouse",
   "company",
+  "warehouse",
+  "tree_details_section",
+  "parent_healthcare_service_unit",
   "lft",
   "rgt",
   "old_parent"
@@ -51,7 +52,6 @@
    "depends_on": "eval:doc.inpatient_occupancy != 1 && doc.allow_appointments != 1",
    "fieldname": "is_group",
    "fieldtype": "Check",
-   "in_list_view": 1,
    "label": "Is Group"
   },
   {
@@ -63,12 +63,12 @@
    "options": "Healthcare Service Unit Type"
   },
   {
-   "bold": 1,
    "default": "0",
    "depends_on": "eval:doc.is_group != 1 && doc.inpatient_occupancy != 1",
    "fetch_from": "service_unit_type.allow_appointments",
    "fieldname": "allow_appointments",
    "fieldtype": "Check",
+   "in_list_view": 1,
    "label": "Allow Appointments",
    "no_copy": 1,
    "read_only": 1
@@ -90,6 +90,7 @@
    "fetch_from": "service_unit_type.inpatient_occupancy",
    "fieldname": "inpatient_occupancy",
    "fieldtype": "Check",
+   "in_list_view": 1,
    "label": "Inpatient Occupancy",
    "no_copy": 1,
    "read_only": 1,
@@ -101,7 +102,7 @@
    "fieldtype": "Select",
    "label": "Occupancy Status",
    "no_copy": 1,
-   "options": "\nVacant\nOccupied",
+   "options": "Vacant\nOccupied",
    "read_only": 1
   },
   {
@@ -157,10 +158,16 @@
    "options": "Healthcare Service Unit",
    "print_hide": 1,
    "report_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "tree_details_section",
+   "fieldtype": "Section Break",
+   "label": "Tree Details"
   }
  ],
  "links": [],
- "modified": "2020-03-26 16:13:08.675952",
+ "modified": "2020-05-20 18:26:56.065543",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare Service Unit",
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py
index 13cc43d..9e0417a 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py
+++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.py
@@ -22,10 +22,16 @@
 		super(HealthcareServiceUnit, self).on_update()
 		self.validate_one_root()
 
-	def validate(self):
+	def after_insert(self):
 		if self.is_group:
 			self.allow_appointments = 0
 			self.overlap_appointments = 0
 			self.inpatient_occupancy = 0
-		elif not self.allow_appointments:
-			self.overlap_appointments = 0
+		elif self.service_unit_type:
+			service_unit_type = frappe.get_doc('Healthcare Service Unit Type', self.service_unit_type)
+			self.allow_appointments = service_unit_type.allow_appointments
+			self.overlap_appointments = service_unit_type.overlap_appointments
+			self.inpatient_occupancy = service_unit_type.inpatient_occupancy
+			if self.inpatient_occupancy:
+				self.occupancy_status = 'Vacant'
+				self.overlap_appointments = 0
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json
index 5fa47d9..4b8503d 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.json
@@ -31,6 +31,7 @@
    "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Service Unit Type",
+   "no_copy": 1,
    "reqd": 1,
    "unique": 1
   },
@@ -40,8 +41,7 @@
    "depends_on": "eval:doc.inpatient_occupancy != 1",
    "fieldname": "allow_appointments",
    "fieldtype": "Check",
-   "label": "Allow Appointments",
-   "no_copy": 1
+   "label": "Allow Appointments"
   },
   {
    "bold": 1,
@@ -49,8 +49,7 @@
    "depends_on": "eval:doc.allow_appointments == 1 && doc.inpatient_occupany != 1",
    "fieldname": "overlap_appointments",
    "fieldtype": "Check",
-   "label": "Allow Overlap",
-   "no_copy": 1
+   "label": "Allow Overlap"
   },
   {
    "bold": 1,
@@ -58,8 +57,7 @@
    "depends_on": "eval:doc.allow_appointments != 1",
    "fieldname": "inpatient_occupancy",
    "fieldtype": "Check",
-   "label": "Inpatient Occupancy",
-   "no_copy": 1
+   "label": "Inpatient Occupancy"
   },
   {
    "bold": 1,
@@ -79,6 +77,7 @@
    "fieldname": "item",
    "fieldtype": "Link",
    "label": "Item",
+   "no_copy": 1,
    "options": "Item",
    "read_only": 1
   },
@@ -86,7 +85,8 @@
    "fieldname": "item_code",
    "fieldtype": "Data",
    "label": "Item Code",
-   "mandatory_depends_on": "eval: doc.is_billable == 1"
+   "mandatory_depends_on": "eval: doc.is_billable == 1",
+   "no_copy": 1
   },
   {
    "fieldname": "item_group",
@@ -138,7 +138,7 @@
   }
  ],
  "links": [],
- "modified": "2020-01-30 16:06:00.624496",
+ "modified": "2020-05-20 15:31:09.627516",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare Service Unit Type",
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
index 286ecc0..bb86eaa 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
@@ -10,6 +10,22 @@
 
 class HealthcareServiceUnitType(Document):
 	def validate(self):
+		if self.allow_appointments and self.inpatient_occupancy:
+			frappe.msgprint(
+				_('Healthcare Service Unit Type cannot have both {0} and {1}').format(
+					frappe.bold('Allow Appointments'), frappe.bold('Inpatient Occupancy')),
+				raise_exception=1, title=_('Validation Error'), indicator='red'
+			)
+		elif not self.allow_appointments and not self.inpatient_occupancy:
+			frappe.msgprint(
+				_('Healthcare Service Unit Type must allow atleast one among {0} and {1}').format(
+					frappe.bold('Allow Appointments'), frappe.bold('Inpatient Occupancy')),
+				raise_exception=1, title=_('Validation Error'), indicator='red'
+			)
+
+		if not self.allow_appointments:
+			self.overlap_appointments = 0
+
 		if self.is_billable:
 			if self.disabled:
 				frappe.db.set_value('Item', self.item, 'disabled', 1)
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
index 67c12f6..971e166 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
@@ -2,22 +2,37 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Inpatient Record', {
+	setup: function(frm) {
+		frm.get_field('drug_prescription').grid.editable_fields = [
+			{fieldname: 'drug_code', columns: 2},
+			{fieldname: 'drug_name', columns: 2},
+			{fieldname: 'dosage', columns: 2},
+			{fieldname: 'period', columns: 2}
+		];
+	},
 	refresh: function(frm) {
-		if(!frm.doc.__islocal && frm.doc.status == "Admission Scheduled"){
+		if (!frm.doc.__islocal && (frm.doc.status == 'Admission Scheduled' || frm.doc.status == 'Admitted')) {
+			frm.enable_save();
+		} else {
+			frm.disable_save();
+		}
+
+		if (!frm.doc.__islocal && frm.doc.status == 'Admission Scheduled') {
 			frm.add_custom_button(__('Admit'), function() {
 				admit_patient_dialog(frm);
 			} );
-			frm.set_df_property("btn_transfer", "hidden", 1);
 		}
-		if(!frm.doc.__islocal && frm.doc.status == "Discharge Scheduled"){
+
+		if (!frm.doc.__islocal && frm.doc.status == 'Discharge Scheduled') {
 			frm.add_custom_button(__('Discharge'), function() {
 				discharge_patient(frm);
 			} );
-			frm.set_df_property("btn_transfer", "hidden", 0);
 		}
-		if(!frm.doc.__islocal && (frm.doc.status == "Discharged" || frm.doc.status == "Discharge Scheduled")){
+		if (!frm.doc.__islocal && frm.doc.status != 'Admitted') {
 			frm.disable_save();
-			frm.set_df_property("btn_transfer", "hidden", 1);
+			frm.set_df_property('btn_transfer', 'hidden', 1);
+		} else {
+			frm.set_df_property('btn_transfer', 'hidden', 0);
 		}
 	},
 	btn_transfer: function(frm) {
@@ -25,39 +40,47 @@
 	}
 });
 
-var discharge_patient = function(frm) {
+let discharge_patient = function(frm) {
 	frappe.call({
 		doc: frm.doc,
-		method: "discharge",
+		method: 'discharge',
 		callback: function(data) {
-			if(!data.exc){
+			if (!data.exc) {
 				frm.reload_doc();
 			}
 		},
 		freeze: true,
-		freeze_message: "Process Discharge"
+		freeze_message: __('Processing Inpatient Discharge')
 	});
 };
 
-var admit_patient_dialog = function(frm){
-	var dialog = new frappe.ui.Dialog({
+let admit_patient_dialog = function(frm) {
+	let dialog = new frappe.ui.Dialog({
 		title: 'Admit Patient',
 		width: 100,
 		fields: [
-			{fieldtype: "Link", label: "Service Unit Type", fieldname: "service_unit_type", options: "Healthcare Service Unit Type"},
-			{fieldtype: "Link", label: "Service Unit", fieldname: "service_unit", options: "Healthcare Service Unit", reqd: 1},
-			{fieldtype: "Datetime", label: "Admission Datetime", fieldname: "check_in", reqd: 1},
-			{fieldtype: "Date", label: "Expected Discharge", fieldname: "expected_discharge"}
+			{fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type',
+				options: 'Healthcare Service Unit Type', default: frm.doc.admission_service_unit_type
+			},
+			{fieldtype: 'Link', label: 'Service Unit', fieldname: 'service_unit',
+				options: 'Healthcare Service Unit', reqd: 1
+			},
+			{fieldtype: 'Datetime', label: 'Admission Datetime', fieldname: 'check_in',
+				reqd: 1, default: frappe.datetime.now_datetime()
+			},
+			{fieldtype: 'Date', label: 'Expected Discharge', fieldname: 'expected_discharge',
+				default: frm.doc.expected_length_of_stay ? frappe.datetime.add_days(frappe.datetime.now_datetime(), frm.doc.expected_length_of_stay) : ''
+			}
 		],
-		primary_action_label: __("Admit"),
+		primary_action_label: __('Admit'),
 		primary_action : function(){
-			var service_unit = dialog.get_value('service_unit');
-			var check_in = dialog.get_value('check_in');
-			var expected_discharge = null;
-			if(dialog.get_value('expected_discharge')){
+			let service_unit = dialog.get_value('service_unit');
+			let check_in = dialog.get_value('check_in');
+			let expected_discharge = null;
+			if (dialog.get_value('expected_discharge')) {
 				expected_discharge = dialog.get_value('expected_discharge');
 			}
-			if(!service_unit && !check_in){
+			if (!service_unit && !check_in) {
 				return;
 			}
 			frappe.call({
@@ -69,32 +92,33 @@
 					'expected_discharge': expected_discharge
 				},
 				callback: function(data) {
-					if(!data.exc){
+					if (!data.exc) {
 						frm.reload_doc();
 					}
 				},
 				freeze: true,
-				freeze_message: "Process Admission"
+				freeze_message: __('Processing Patient Admission')
 			});
 			frm.refresh_fields();
 			dialog.hide();
 		}
 	});
 
-	dialog.fields_dict["service_unit_type"].get_query = function(){
+	dialog.fields_dict['service_unit_type'].get_query = function() {
 		return {
 			filters: {
-				"inpatient_occupancy": 1,
-				"allow_appointments": 0
+				'inpatient_occupancy': 1,
+				'allow_appointments': 0
 			}
 		};
 	};
-	dialog.fields_dict["service_unit"].get_query = function(){
+	dialog.fields_dict['service_unit'].get_query = function() {
 		return {
 			filters: {
-				"is_group": 0,
-				"service_unit_type": dialog.get_value("service_unit_type"),
-				"occupancy_status" : "Vacant"
+				'is_group': 0,
+				'company': frm.doc.company,
+				'service_unit_type': dialog.get_value('service_unit_type'),
+				'occupancy_status' : 'Vacant'
 			}
 		};
 	};
@@ -102,21 +126,21 @@
 	dialog.show();
 };
 
-var transfer_patient_dialog = function(frm){
-	var dialog = new frappe.ui.Dialog({
+let transfer_patient_dialog = function(frm) {
+	let dialog = new frappe.ui.Dialog({
 		title: 'Transfer Patient',
 		width: 100,
 		fields: [
-			{fieldtype: "Link", label: "Leave From", fieldname: "leave_from", options: "Healthcare Service Unit", reqd: 1, read_only:1},
-			{fieldtype: "Link", label: "Service Unit Type", fieldname: "service_unit_type", options: "Healthcare Service Unit Type"},
-			{fieldtype: "Link", label: "Transfer To", fieldname: "service_unit", options: "Healthcare Service Unit", reqd: 1},
-			{fieldtype: "Datetime", label: "Check In", fieldname: "check_in", reqd: 1}
+			{fieldtype: 'Link', label: 'Leave From', fieldname: 'leave_from', options: 'Healthcare Service Unit', reqd: 1, read_only:1},
+			{fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type', options: 'Healthcare Service Unit Type'},
+			{fieldtype: 'Link', label: 'Transfer To', fieldname: 'service_unit', options: 'Healthcare Service Unit', reqd: 1},
+			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1}
 		],
-		primary_action_label: __("Transfer"),
-		primary_action : function(){
-			var service_unit = null;
-			var check_in = dialog.get_value('check_in');
-			var leave_from = null;
+		primary_action_label: __('Transfer'),
+		primary_action : function() {
+			let service_unit = null;
+			let check_in = dialog.get_value('check_in');
+			let leave_from = null;
 			if(dialog.get_value('leave_from')){
 				leave_from = dialog.get_value('leave_from');
 			}
@@ -135,47 +159,47 @@
 					'leave_from': leave_from
 				},
 				callback: function(data) {
-					if(!data.exc){
+					if (!data.exc) {
 						frm.reload_doc();
 					}
 				},
 				freeze: true,
-				freeze_message: "Process Transfer"
+				freeze_message: __('Process Transfer')
 			});
 			frm.refresh_fields();
 			dialog.hide();
 		}
 	});
 
-	dialog.fields_dict["leave_from"].get_query = function(){
+	dialog.fields_dict['leave_from'].get_query = function(){
 		return {
-			query : "erpnext.healthcare.doctype.inpatient_record.inpatient_record.get_leave_from",
+			query : 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.get_leave_from',
 			filters: {docname:frm.doc.name}
 		};
 	};
-	dialog.fields_dict["service_unit_type"].get_query = function(){
+	dialog.fields_dict['service_unit_type'].get_query = function(){
 		return {
 			filters: {
-				"inpatient_occupancy": 1,
-				"allow_appointments": 0
+				'inpatient_occupancy': 1,
+				'allow_appointments': 0
 			}
 		};
 	};
-	dialog.fields_dict["service_unit"].get_query = function(){
+	dialog.fields_dict['service_unit'].get_query = function(){
 		return {
 			filters: {
-				"is_group": 0,
-				"service_unit_type": dialog.get_value("service_unit_type"),
-				"occupancy_status" : "Vacant"
+				'is_group': 0,
+				'service_unit_type': dialog.get_value('service_unit_type'),
+				'occupancy_status' : 'Vacant'
 			}
 		};
 	};
 
 	dialog.show();
 
-	var not_left_service_unit = null;
-	for(let inpatient_occupancy in frm.doc.inpatient_occupancies){
-		if(frm.doc.inpatient_occupancies[inpatient_occupancy].left != 1){
+	let not_left_service_unit = null;
+	for (let inpatient_occupancy in frm.doc.inpatient_occupancies) {
+		if (frm.doc.inpatient_occupancies[inpatient_occupancy].left != 1) {
 			not_left_service_unit = frm.doc.inpatient_occupancies[inpatient_occupancy].service_unit;
 		}
 	}
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json
index c1b516d..5ced845 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json
@@ -22,17 +22,41 @@
   "scheduled_date",
   "admitted_datetime",
   "expected_discharge",
-  "discharge_date",
   "references",
-  "cb_admission",
-  "admission_practitioner",
   "admission_encounter",
-  "cb_discharge",
-  "discharge_practitioner",
-  "discharge_encounter",
+  "admission_practitioner",
+  "medical_department",
+  "admission_ordered_for",
+  "expected_length_of_stay",
+  "admission_service_unit_type",
+  "cb_admission",
+  "primary_practitioner",
+  "secondary_practitioner",
+  "admission_instruction",
+  "encounter_details_section",
+  "chief_complaint",
+  "column_break_29",
+  "diagnosis",
+  "medication_section",
+  "drug_prescription",
+  "investigations_section",
+  "lab_test_prescription",
+  "procedures_section",
+  "procedure_prescription",
+  "rehabilitation_section",
+  "therapy_plan",
+  "therapies",
   "sb_inpatient_occupancy",
   "inpatient_occupancies",
   "btn_transfer",
+  "sb_discharge_details",
+  "discharge_ordered_date",
+  "discharge_practitioner",
+  "discharge_encounter",
+  "discharge_date",
+  "cb_discharge",
+  "discharge_instructions",
+  "followup_date",
   "sb_discharge_note",
   "discharge_note"
  ],
@@ -54,7 +78,8 @@
    "in_list_view": 1,
    "label": "Patient",
    "options": "Patient",
-   "reqd": 1
+   "reqd": 1,
+   "set_only_once": 1
   },
   {
    "fetch_from": "patient.patient_name",
@@ -109,10 +134,30 @@
    "read_only": 1
   },
   {
+   "fieldname": "medical_department",
+   "fieldtype": "Link",
+   "label": "Medical Department",
+   "options": "Medical Department",
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "primary_practitioner",
+   "fieldtype": "Link",
+   "label": "Healthcare Practitioner (Primary)",
+   "options": "Healthcare Practitioner"
+  },
+  {
+   "fieldname": "secondary_practitioner",
+   "fieldtype": "Link",
+   "label": "Healthcare Practitioner (Secondary)",
+   "options": "Healthcare Practitioner"
+  },
+  {
    "fieldname": "column_break_8",
    "fieldtype": "Column Break"
   },
   {
+   "default": "Admission Scheduled",
    "fieldname": "status",
    "fieldtype": "Select",
    "in_list_view": 1,
@@ -126,37 +171,45 @@
    "fieldtype": "Date",
    "in_list_view": 1,
    "label": "Admission Schedule Date",
+   "read_only": 1,
    "reqd": 1
   },
   {
-   "default": "Today",
+   "fieldname": "admission_ordered_for",
+   "fieldtype": "Date",
+   "label": "Admission Ordered For",
+   "read_only": 1
+  },
+  {
    "fieldname": "admitted_datetime",
    "fieldtype": "Datetime",
    "in_list_view": 1,
-   "label": "Admitted Datetime"
+   "label": "Admitted Datetime",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:(doc.expected_length_of_stay > 0)",
+   "fieldname": "expected_length_of_stay",
+   "fieldtype": "Int",
+   "label": "Expected Length of Stay",
+   "set_only_once": 1
   },
   {
    "fieldname": "expected_discharge",
    "fieldtype": "Date",
    "in_list_view": 1,
-   "label": "Expected Discharge"
-  },
-  {
-   "fieldname": "discharge_date",
-   "fieldtype": "Date",
-   "in_list_view": 1,
-   "label": "Discharge Date"
+   "label": "Expected Discharge",
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "references",
    "fieldtype": "Section Break",
-   "label": "References"
+   "label": "Admission Order Details"
   },
   {
    "fieldname": "cb_admission",
-   "fieldtype": "Column Break",
-   "label": "Admission"
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "admission_practitioner",
@@ -173,9 +226,21 @@
    "read_only": 1
   },
   {
+   "fieldname": "chief_complaint",
+   "fieldtype": "Table MultiSelect",
+   "label": "Chief Complaint",
+   "options": "Patient Encounter Symptom",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "admission_instruction",
+   "fieldtype": "Small Text",
+   "label": "Admission Instruction",
+   "set_only_once": 1
+  },
+  {
    "fieldname": "cb_discharge",
-   "fieldtype": "Column Break",
-   "label": "Discharge"
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "discharge_practitioner",
@@ -192,11 +257,58 @@
    "read_only": 1
   },
   {
+   "collapsible": 1,
+   "fieldname": "medication_section",
+   "fieldtype": "Section Break",
+   "label": "Medications",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "drug_prescription",
+   "fieldtype": "Table",
+   "options": "Drug Prescription",
+   "permlevel": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "investigations_section",
+   "fieldtype": "Section Break",
+   "label": "Investigations",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "lab_test_prescription",
+   "fieldtype": "Table",
+   "options": "Lab Prescription",
+   "permlevel": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "procedures_section",
+   "fieldtype": "Section Break",
+   "label": "Procedures",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "procedure_prescription",
+   "fieldtype": "Table",
+   "options": "Procedure Prescription",
+   "permlevel": 1
+  },
+  {
+   "depends_on": "eval:(doc.status != \"Admission Scheduled\")",
    "fieldname": "sb_inpatient_occupancy",
    "fieldtype": "Section Break",
    "label": "Inpatient Occupancy"
   },
   {
+   "fieldname": "admission_service_unit_type",
+   "fieldtype": "Link",
+   "label": "Admission Service Unit Type",
+   "options": "Healthcare Service Unit Type",
+   "read_only": 1
+  },
+  {
    "fieldname": "inpatient_occupancies",
    "fieldtype": "Table",
    "options": "Inpatient Occupancy",
@@ -208,14 +320,15 @@
    "label": "Transfer"
   },
   {
-   "depends_on": "eval:doc.status != \"Admission Scheduled\"",
+   "depends_on": "eval:(doc.status == \"Discharge Scheduled\" || doc.status == \"Discharged\")",
    "fieldname": "sb_discharge_note",
    "fieldtype": "Section Break",
-   "label": "Discharge Note"
+   "label": "Discharge Notes"
   },
   {
    "fieldname": "discharge_note",
-   "fieldtype": "Text Editor"
+   "fieldtype": "Text Editor",
+   "permlevel": 1
   },
   {
    "fetch_from": "admission_encounter.company",
@@ -224,10 +337,81 @@
    "in_standard_filter": 1,
    "label": "Company",
    "options": "Company"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:(doc.status == \"Admitted\")",
+   "fieldname": "encounter_details_section",
+   "fieldtype": "Section Break",
+   "label": "Encounter Impression",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "column_break_29",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "diagnosis",
+   "fieldtype": "Table MultiSelect",
+   "label": "Diagnosis",
+   "options": "Patient Encounter Diagnosis",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "followup_date",
+   "fieldtype": "Date",
+   "label": "Follow Up Date"
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "eval:(doc.status == \"Discharge Scheduled\" || doc.status == \"Discharged\")",
+   "fieldname": "sb_discharge_details",
+   "fieldtype": "Section Break",
+   "label": "Discharge Detials"
+  },
+  {
+   "fieldname": "discharge_instructions",
+   "fieldtype": "Small Text",
+   "label": "Discharge Instructions"
+  },
+  {
+   "fieldname": "discharge_ordered_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Discharge Ordered Date",
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "rehabilitation_section",
+   "fieldtype": "Section Break",
+   "label": "Rehabilitation",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "therapy_plan",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Therapy Plan",
+   "options": "Therapy Plan",
+   "permlevel": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "therapies",
+   "fieldtype": "Table",
+   "options": "Therapy Plan Detail",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "discharge_date",
+   "fieldtype": "Date",
+   "label": "Discharge Date",
+   "read_only": 1
   }
  ],
  "links": [],
- "modified": "2020-04-07 13:13:39.351977",
+ "modified": "2020-05-21 02:26:22.144575",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Inpatient Record",
@@ -244,6 +428,42 @@
    "role": "Healthcare Administrator",
    "share": 1,
    "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Physician",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Nursing User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "role": "Physician",
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Nursing User"
   }
  ],
  "restrict_to_domain": "Healthcare",
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
index 835b38b..cf63b65 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
@@ -3,7 +3,7 @@
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, json
 from frappe import _
 from frappe.utils import today, now_datetime, getdate
 from frappe.model.document import Document
@@ -11,8 +11,12 @@
 
 class InpatientRecord(Document):
 	def after_insert(self):
-		frappe.db.set_value("Patient", self.patient, "inpatient_status", "Admission Scheduled")
-		frappe.db.set_value("Patient", self.patient, "inpatient_record", self.name)
+		frappe.db.set_value('Patient', self.patient, 'inpatient_record', self.name)
+		frappe.db.set_value('Patient', self.patient, 'inpatient_status', self.status)
+
+		if self.admission_encounter: # Update encounter
+			frappe.db.set_value('Patient Encounter', self.admission_encounter, 'inpatient_record', self.name)
+			frappe.db.set_value('Patient Encounter', self.admission_encounter, 'inpatient_status', self.status)
 
 	def validate(self):
 		self.validate_dates()
@@ -22,13 +26,10 @@
 			frappe.db.set_value("Patient", self.patient, "inpatient_record", None)
 
 	def validate_dates(self):
-		if (getdate(self.scheduled_date) < getdate(today())) or \
-			(getdate(self.admitted_datetime) < getdate(today())):
-				frappe.throw(_("Scheduled and Admitted dates can not be less than today"))
 		if (getdate(self.expected_discharge) < getdate(self.scheduled_date)) or \
-			(getdate(self.discharge_date) < getdate(self.scheduled_date)):
-			frappe.throw(_("Expected and Discharge dates cannot be less than Admission Schedule date"))
-	
+			(getdate(self.discharge_ordered_date) < getdate(self.scheduled_date)):
+			frappe.throw(_('Expected and Discharge dates cannot be less than Admission Schedule date'))
+
 	def validate_already_scheduled_or_admitted(self):
 		query = """
 			select name, status
@@ -59,37 +60,76 @@
 		if service_unit:
 			transfer_patient(self, service_unit, check_in)
 
+
 @frappe.whitelist()
-def schedule_inpatient(patient, encounter_id, practitioner):
-	patient_obj = frappe.get_doc('Patient', patient)
+def schedule_inpatient(args):
+	admission_order = json.loads(args) # admission order via Encounter
+	if not admission_order or not admission_order['patient'] or not admission_order['admission_encounter']:
+		frappe.throw(_('Missing required details, did not create Inpatient Record'))
+
 	inpatient_record = frappe.new_doc('Inpatient Record')
-	inpatient_record.patient = patient
-	inpatient_record.patient_name = patient_obj.patient_name
-	inpatient_record.gender = patient_obj.sex
-	inpatient_record.blood_group = patient_obj.blood_group
-	inpatient_record.dob = patient_obj.dob
-	inpatient_record.mobile = patient_obj.mobile
-	inpatient_record.email = patient_obj.email
-	inpatient_record.phone = patient_obj.phone
-	inpatient_record.status = "Admission Scheduled"
+
+	# Admission order details
+	set_details_from_ip_order(inpatient_record, admission_order)
+
+	# Patient details
+	patient = frappe.get_doc('Patient', admission_order['patient'])
+	inpatient_record.patient = patient.name
+	inpatient_record.patient_name = patient.patient_name
+	inpatient_record.gender = patient.sex
+	inpatient_record.blood_group = patient.blood_group
+	inpatient_record.dob = patient.dob
+	inpatient_record.mobile = patient.mobile
+	inpatient_record.email = patient.email
+	inpatient_record.phone = patient.phone
 	inpatient_record.scheduled_date = today()
-	inpatient_record.admission_practitioner = practitioner
-	inpatient_record.admission_encounter = encounter_id
+
+	# Set encounter detials
+	encounter = frappe.get_doc('Patient Encounter', admission_order['admission_encounter'])
+	if encounter and encounter.symptoms: # Symptoms
+		set_ip_child_records(inpatient_record, 'chief_complaint', encounter.symptoms)
+
+	if encounter and encounter.diagnosis: # Diagnosis
+		set_ip_child_records(inpatient_record, 'diagnosis', encounter.diagnosis)
+
+	if encounter and encounter.drug_prescription: # Medication
+		set_ip_child_records(inpatient_record, 'drug_prescription', encounter.drug_prescription)
+
+	if encounter and encounter.lab_test_prescription: # Lab Tests
+		set_ip_child_records(inpatient_record, 'lab_test_prescription', encounter.lab_test_prescription)
+
+	if encounter and encounter.procedure_prescription: # Procedure Prescription
+		set_ip_child_records(inpatient_record, 'procedure_prescription', encounter.procedure_prescription)
+
+	if encounter and encounter.therapies: # Therapies
+		inpatient_record.therapy_plan = encounter.therapy_plan
+		set_ip_child_records(inpatient_record, 'therapies', encounter.therapies)
+
+	inpatient_record.status = 'Admission Scheduled'
 	inpatient_record.save(ignore_permissions = True)
 
 @frappe.whitelist()
-def schedule_discharge(patient, encounter_id=None, practitioner=None):
-	inpatient_record_id = frappe.db.get_value('Patient', patient, 'inpatient_record')
+def schedule_discharge(args):
+	discharge_order = json.loads(args)
+	inpatient_record_id = frappe.db.get_value('Patient', discharge_order['patient'], 'inpatient_record')
 	if inpatient_record_id:
-		inpatient_record = frappe.get_doc("Inpatient Record", inpatient_record_id)
-		inpatient_record.discharge_practitioner = practitioner
-		inpatient_record.discharge_encounter = encounter_id
-		inpatient_record.status = "Discharge Scheduled"
-
+		inpatient_record = frappe.get_doc('Inpatient Record', inpatient_record_id)
 		check_out_inpatient(inpatient_record)
-
+		set_details_from_ip_order(inpatient_record, discharge_order)
+		inpatient_record.status = 'Discharge Scheduled'
 		inpatient_record.save(ignore_permissions = True)
-	frappe.db.set_value("Patient", patient, "inpatient_status", "Discharge Scheduled")
+		frappe.db.set_value('Patient', discharge_order['patient'], 'inpatient_status', inpatient_record.status)
+		frappe.db.set_value('Patient Encounter', inpatient_record.discharge_encounter, 'inpatient_status', inpatient_record.status)
+
+def set_details_from_ip_order(inpatient_record, ip_order):
+	for key in ip_order:
+		inpatient_record.set(key, ip_order[key])
+
+def set_ip_child_records(inpatient_record, inpatient_record_child, encounter_child):
+	for item in encounter_child:
+		table = inpatient_record.append(inpatient_record_child)
+		for df in table.meta.get('fields'):
+			table.set(df.fieldname, item.get(df.fieldname))
 
 def check_out_inpatient(inpatient_record):
 	if inpatient_record.inpatient_occupancies:
@@ -128,7 +168,7 @@
 
 	if pending_invoices:
 		frappe.throw(_("Can not mark Inpatient Record Discharged, there are Unbilled Invoices {0}").format(", "
-			.join(pending_invoices)))
+			.join(pending_invoices)), title=_('Unbilled Invoices'))
 
 def get_pending_doc(doc, doc_name_list, pending_invoices):
 	if doc_name_list:
@@ -144,19 +184,19 @@
 	return pending_invoices
 
 def get_inpatient_docs_not_invoiced(doc, inpatient_record):
-	return frappe.db.get_list(doc, filters = {"patient": inpatient_record.patient,
-					"inpatient_record": inpatient_record.name, "invoiced": 0})
+	return frappe.db.get_list(doc, filters = {'patient': inpatient_record.patient,
+					'inpatient_record': inpatient_record.name, 'docstatus': 1, 'invoiced': 0})
 
 def admit_patient(inpatient_record, service_unit, check_in, expected_discharge=None):
 	inpatient_record.admitted_datetime = check_in
-	inpatient_record.status = "Admitted"
+	inpatient_record.status = 'Admitted'
 	inpatient_record.expected_discharge = expected_discharge
 
 	inpatient_record.set('inpatient_occupancies', [])
 	transfer_patient(inpatient_record, service_unit, check_in)
 
-	frappe.db.set_value("Patient", inpatient_record.patient, "inpatient_status", "Admitted")
-	frappe.db.set_value("Patient", inpatient_record.patient, "inpatient_record", inpatient_record.name)
+	frappe.db.set_value('Patient', inpatient_record.patient, 'inpatient_status', 'Admitted')
+	frappe.db.set_value('Patient', inpatient_record.patient, 'inpatient_record', inpatient_record.name)
 
 def transfer_patient(inpatient_record, service_unit, check_in):
 	item_line = inpatient_record.append('inpatient_occupancies', {})
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
index b8a400c..ac35acc 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -39,9 +39,9 @@
   "section_break_16",
   "mode_of_payment",
   "billing_item",
+  "invoiced",
   "column_break_2",
   "paid_amount",
-  "invoiced",
   "ref_sales_invoice",
   "section_break_3",
   "referring_practitioner",
@@ -348,7 +348,7 @@
   }
  ],
  "links": [],
- "modified": "2020-04-27 21:36:06.404062",
+ "modified": "2020-05-21 03:04:21.400893",
  "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 9eb6e77..512fb48 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -447,7 +447,7 @@
 		"""
 			SELECT
 				t.therapy_type, t.name, t.parent, e.practitioner,
-				e.encounter_date, e.therapy_plan, e.visit_department
+				e.encounter_date, e.therapy_plan, e.medical_department
 			FROM
 				`tabPatient Encounter` e, `tabTherapy Plan Detail` t
 			WHERE
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
index 2410f8e..edcee99 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
@@ -180,35 +180,114 @@
 	}
 });
 
-let schedule_inpatient = function(frm) {
-	frappe.call({
-		method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_inpatient',
-		args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
-		callback: function(data) {
-			if (!data.exc) {
-				frm.reload_doc();
+var schedule_inpatient = function(frm) {
+	var dialog = new frappe.ui.Dialog({
+		title: 'Patient Admission',
+		fields: [
+			{fieldtype: 'Link', label: 'Medical Department', fieldname: 'medical_department', options: 'Medical Department', reqd: 1},
+			{fieldtype: 'Link', label: 'Healthcare Practitioner (Primary)', fieldname: 'primary_practitioner', options: 'Healthcare Practitioner', reqd: 1},
+			{fieldtype: 'Link', label: 'Healthcare Practitioner (Secondary)', fieldname: 'secondary_practitioner', options: 'Healthcare Practitioner'},
+			{fieldtype: 'Column Break'},
+			{fieldtype: 'Date', label: 'Admission Ordered For', fieldname: 'admission_ordered_for', default: 'Today'},
+			{fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type', options: 'Healthcare Service Unit Type'},
+			{fieldtype: 'Int', label: 'Expected Length of Stay', fieldname: 'expected_length_of_stay'},
+			{fieldtype: 'Section Break'},
+			{fieldtype: 'Long Text', label: 'Admission Instructions', fieldname: 'admission_instruction'}
+		],
+		primary_action_label: __('Order Admission'),
+		primary_action : function() {
+			var args = {
+				patient: frm.doc.patient,
+				admission_encounter: frm.doc.name,
+				referring_practitioner: frm.doc.practitioner,
+				company: frm.doc.company,
+				medical_department: dialog.get_value('medical_department'),
+				primary_practitioner: dialog.get_value('primary_practitioner'),
+				secondary_practitioner: dialog.get_value('secondary_practitioner'),
+				admission_ordered_for: dialog.get_value('admission_ordered_for'),
+				admission_service_unit_type: dialog.get_value('service_unit_type'),
+				expected_length_of_stay: dialog.get_value('expected_length_of_stay'),
+				admission_instruction: dialog.get_value('admission_instruction')
 			}
-		},
-		freeze: true,
-		freeze_message: __('Process Inpatient Scheduling')
+			frappe.call({
+				method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_inpatient',
+				args: {
+					args: args
+				},
+				callback: function(data) {
+					if (!data.exc) {
+						frm.reload_doc();
+					}
+				},
+				freeze: true,
+				freeze_message: 'Scheduling Patient Admission'
+			});
+			frm.refresh_fields();
+			dialog.hide();
+		}
 	});
+
+	dialog.set_values({
+		'medical_department': frm.doc.medical_department,
+		'primary_practitioner': frm.doc.practitioner,
+	});
+
+	dialog.fields_dict['service_unit_type'].get_query = function() {
+		return {
+			filters: {
+				'inpatient_occupancy': 1,
+				'allow_appointments': 0
+			}
+		};
+	};
+
+	dialog.show();
+	dialog.$wrapper.find('.modal-dialog').css('width', '800px');
 };
 
-let schedule_discharge = function(frm) {
-	frappe.call({
-		method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_discharge',
-		args: {patient: frm.doc.patient, encounter_id: frm.doc.name, practitioner: frm.doc.practitioner},
-		callback: function(data) {
-			if (!data.exc) {
-				frm.reload_doc();
+var schedule_discharge = function(frm) {
+	var dialog = new frappe.ui.Dialog ({
+		title: 'Inpatient Discharge',
+		fields: [
+			{fieldtype: 'Date', label: 'Discharge Ordered Date', fieldname: 'discharge_ordered_date', default: 'Today', read_only: 1},
+			{fieldtype: 'Date', label: 'Followup Date', fieldname: 'followup_date'},
+			{fieldtype: 'Column Break'},
+			{fieldtype: 'Small Text', label: 'Discharge Instructions', fieldname: 'discharge_instructions'},
+			{fieldtype: 'Section Break', label:'Discharge Summary'},
+			{fieldtype: 'Long Text', label: 'Discharge Note', fieldname: 'discharge_note'}
+		],
+		primary_action_label: __('Order Discharge'),
+		primary_action : function() {
+			var args = {
+				patient: frm.doc.patient,
+				discharge_encounter: frm.doc.name,
+				discharge_practitioner: frm.doc.practitioner,
+				discharge_ordered_date: dialog.get_value('discharge_ordered_date'),
+				followup_date: dialog.get_value('followup_date'),
+				discharge_instructions: dialog.get_value('discharge_instructions'),
+				discharge_note: dialog.get_value('discharge_note')
 			}
-		},
-		freeze: true,
-		freeze_message: 'Process Discharge'
+			frappe.call ({
+				method: 'erpnext.healthcare.doctype.inpatient_record.inpatient_record.schedule_discharge',
+				args: {args},
+				callback: function(data) {
+					if(!data.exc){
+						frm.reload_doc();
+					}
+				},
+				freeze: true,
+				freeze_message: 'Scheduling Inpatient Discharge'
+			});
+			frm.refresh_fields();
+			dialog.hide();
+		}
 	});
+
+	dialog.show();
+	dialog.$wrapper.find('.modal-dialog').css('width', '800px');
 };
 
-let create_medical_record = function (frm) {
+let create_medical_record = function(frm) {
 	if (!frm.doc.patient) {
 		frappe.throw(__('Please select patient'));
 	}
@@ -221,7 +300,7 @@
 	frappe.new_doc('Patient Medical Record');
 };
 
-let create_vital_signs = function (frm) {
+let create_vital_signs = function(frm) {
 	if (!frm.doc.patient) {
 		frappe.throw(__('Please select patient'));
 	}
@@ -233,7 +312,7 @@
 	frappe.new_doc('Vital Signs');
 };
 
-let create_procedure = function (frm) {
+let create_procedure = function(frm) {
 	if (!frm.doc.patient) {
 		frappe.throw(__('Please select patient'));
 	}
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
index 05eec87..15675f4 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json
@@ -52,6 +52,7 @@
  ],
  "fields": [
   {
+   "allow_on_submit": 1,
    "fieldname": "inpatient_record",
    "fieldtype": "Link",
    "label": "Inpatient Record",
@@ -296,6 +297,7 @@
    "read_only": 1
   },
   {
+   "allow_on_submit": 1,
    "fieldname": "inpatient_status",
    "fieldtype": "Data",
    "label": "Inpatient Status",
@@ -326,7 +328,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-27 21:58:29.789797",
+ "modified": "2020-05-16 21:00:08.644531",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Patient Encounter",