Payroll Entry (#11936) (#11968)

* add functions for tracking related salary slips

* PEP 8 style

* put buttons into Make based on context

* add function to test for bank entry journal

* refeactor `add_bank_entry_button`

* "View Salary Slips" made a standalone secondary button

* set_inner_btn_group for Make Bank Entry

* refresh button after journal is submitted

* edit javascript test case

* codacy

* fix as per review

* no longer use $c
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.js b/erpnext/hr/doctype/payroll_entry/payroll_entry.js
index a26283d..3f00166 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.js
@@ -10,24 +10,73 @@
 	},
 
 	refresh: function(frm) {
-		if (frm.doc.docstatus==1) {
-			if(frm.doc.payment_account) {
-				frm.add_custom_button("Make Bank Entry", function() {
-					make_bank_entry(frm);
-				});
-			}
-
-			frm.add_custom_button("Submit Salary Slip", function() {
-				submit_salary_slip(frm);
-			});
-
-			frm.add_custom_button("View Salary Slip", function() {
-				frappe.set_route('List', 'Salary Slip',
-					{posting_date: frm.doc.posting_date});
-			});
+		if (frm.doc.docstatus == 1) {
+			if (frm.custom_buttons) frm.clear_custom_buttons();
+			frm.events.add_context_buttons(frm);
 		}
 	},
 
+	add_context_buttons: function(frm) {
+		frappe.call({
+			method: 'erpnext.hr.doctype.payroll_entry.payroll_entry.payroll_entry_has_created_slips',
+			args: {
+				'name': frm.doc.name
+			},
+			callback: function(r) {
+				if(r.message) {
+					frm.events.add_salary_slip_buttons(frm, r.message);
+					if(r.message.submitted){
+						frm.events.add_bank_entry_button(frm);
+					}
+				}
+			}
+		});
+	},
+
+	add_salary_slip_buttons: function(frm, slip_status) {
+		if (!slip_status.draft && !slip_status.submitted) {
+			return;
+		} else {
+			frm.add_custom_button("View Salary Slips",
+				function() {
+					frappe.set_route(
+						'List', 'Salary Slip', {posting_date: frm.doc.posting_date}
+					);
+				}
+			);
+		}
+
+		if (slip_status.draft) {
+			frm.add_custom_button("Submit Salary Slip",
+				function() {
+					submit_salary_slip(frm);
+				},
+				__('Make')
+			);
+			frm.page.set_inner_btn_group_as_primary(__('Make'));
+		}
+	},
+
+	add_bank_entry_button: function(frm) {
+		frappe.call({
+			method: 'erpnext.hr.doctype.payroll_entry.payroll_entry.payroll_entry_has_bank_entries',
+			args: {
+				'name': frm.doc.name
+			},
+			callback: function(r) {
+				if (r.message && !r.message.submitted) {
+					frm.add_custom_button("Bank Entry",
+						function() {
+							make_bank_entry(frm);
+						},
+						__('Make')
+					);
+					frm.page.set_inner_btn_group_as_primary(__('Make'));
+				}
+			}
+		});
+	},
+
 	setup: function (frm) {
 		frm.set_query("payment_account", function () {
 			var account_types = ["Bank", "Cash"];
@@ -132,9 +181,25 @@
 
 // Submit salary slips
 
-let submit_salary_slip = function (frm) {
-	var doc = frm.doc;
-	return $c('runserverobj', { 'method': 'submit_salary_slips', 'docs': doc });
+const submit_salary_slip = function (frm) {
+	frappe.confirm(__('This will create a Journal Entry. Do you want to proceed?'),
+		function() {
+			frappe.call({
+				method: 'submit_salary_slips',
+				args: {},
+				callback: function() {frm.events.refresh(frm);},
+				doc: frm.doc,
+				freeze: true,
+				freeze_message: 'Creating Journal Entries...'
+			});
+		},
+		function() {
+			if(frappe.dom.freeze_count) {
+				frappe.dom.unfreeze();
+				frm.events.refresh(frm);
+			}
+		}
+	);
 };
 
 cur_frm.cscript.get_employee_details = function (doc) {
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
index 2f5fae4..0b4e3bf 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
@@ -461,4 +461,54 @@
 		frappe.msgprint("Could not submit any Salary Slip <br>\
 			Possible reasons: <br>\
 			1. Net pay is less than 0. <br>\
-			2. Company Email Address specified in employee master is not valid. <br>")
\ No newline at end of file
+			2. Company Email Address specified in employee master is not valid. <br>")
+
+
+def get_salary_slip_list(name, docstatus, as_dict=0):
+	payroll_entry = frappe.get_doc('Payroll Entry', name)
+
+	salary_slip_list = frappe.db.sql(
+		"select t1.name, t1.salary_structure from `tabSalary Slip` t1 "
+		"where t1.docstatus = %s "
+		"and t1.start_date >= %s "
+		"and t1.end_date <= %s",
+		(docstatus, payroll_entry.start_date, payroll_entry.end_date),
+		as_dict=as_dict
+	)
+
+	return salary_slip_list
+
+
+@frappe.whitelist()
+def payroll_entry_has_created_slips(name):
+	response = {}
+
+	draft_salary_slips = get_salary_slip_list(name, docstatus=0)
+	submitted_salary_slips = get_salary_slip_list(name, docstatus=1)
+
+	response['draft'] = 1 if draft_salary_slips else 0
+	response['submitted'] = 1 if submitted_salary_slips else 0
+
+	return response
+
+
+def get_payroll_entry_bank_entries(payroll_entry_name):
+	journal_entries = frappe.db.sql(
+		'select name from `tabJournal Entry Account` '
+		'where reference_type="Payroll Entry" '
+		'and reference_name=%s and docstatus=1',
+		payroll_entry_name,
+		as_dict=1
+	)
+
+	return journal_entries
+
+
+@frappe.whitelist()
+def payroll_entry_has_bank_entries(name):
+	response = {}
+
+	bank_entries = get_payroll_entry_bank_entries(name)
+	response['submitted'] = 1 if bank_entries else 0
+
+	return response
diff --git a/erpnext/hr/doctype/payroll_entry/test_payroll_entry.js b/erpnext/hr/doctype/payroll_entry/test_payroll_entry.js
index c109aab..05cd66f 100644
--- a/erpnext/hr/doctype/payroll_entry/test_payroll_entry.js
+++ b/erpnext/hr/doctype/payroll_entry/test_payroll_entry.js
@@ -38,8 +38,9 @@
 
 		() => frappe.set_route('Form', 'Payroll Entry', docname),
 		() => frappe.timeout(2),
-		() => frappe.click_button('Submit Salary Slip'),
-		() => frappe.timeout(3),
+		() => frappe.click_button('Make'),
+		() => frappe.click_dropdown_item('Submit Salary Slip'),
+		() => frappe.timeout(5),
 
 		() => frappe.click_button('Close'),
 		() => frappe.timeout(1),