feat: bulk questionnaire sending
diff --git a/erpnext/hr/doctype/exit_interview/exit_interview.js b/erpnext/hr/doctype/exit_interview/exit_interview.js
index 31c9610..849e854 100644
--- a/erpnext/hr/doctype/exit_interview/exit_interview.js
+++ b/erpnext/hr/doctype/exit_interview/exit_interview.js
@@ -23,29 +23,15 @@
},
send_exit_questionnaire: function(frm) {
- frappe.db.get_value('HR Settings', 'HR Settings',
- ['exit_questionnaire_web_form', 'exit_questionnaire_notification_template'], (r) => {
- if (!r.exit_questionnaire_web_form || !r.exit_questionnaire_notification_template) {
- frappe.throw({
- message: __('Please set {0} and {1} in {2}.',
- ['Exit Questionnaire Web Form'.bold(),
- 'Notification Template'.bold(),
- '<a href="/app/hr-settings" target="_blank">HR Settings</a>']
- ),
- title: __('Settings Missing')
- });
- } else {
- frappe.call({
- method: 'erpnext.hr.doctype.exit_interview.exit_interview.send_exit_questionnaire',
- args: {
- 'exit_interview': frm.doc.name
- },
- callback: function(r) {
- if (!r.exc) {
- frm.refresh_field('questionnaire_email_sent');
- }
- }
- });
+ frappe.call({
+ method: 'erpnext.hr.doctype.exit_interview.exit_interview.send_exit_questionnaire',
+ args: {
+ 'interviews': [frm.doc]
+ },
+ callback: function(r) {
+ if (!r.exc) {
+ frm.refresh_field('questionnaire_email_sent');
+ }
}
});
}
diff --git a/erpnext/hr/doctype/exit_interview/exit_interview.json b/erpnext/hr/doctype/exit_interview/exit_interview.json
index d4d4aac..4b39640 100644
--- a/erpnext/hr/doctype/exit_interview/exit_interview.json
+++ b/erpnext/hr/doctype/exit_interview/exit_interview.json
@@ -87,8 +87,7 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Date",
- "mandatory_depends_on": "eval:doc.status==='Scheduled';",
- "reqd": 1
+ "mandatory_depends_on": "eval:doc.status==='Scheduled';"
},
{
"fieldname": "exit_questionnaire_section",
@@ -174,6 +173,7 @@
"fieldtype": "Check",
"in_standard_filter": 1,
"label": "Questionnaire Email Sent",
+ "no_copy": 1,
"read_only": 1
},
{
@@ -218,7 +218,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-12-05 17:49:44.839277",
+ "modified": "2021-12-05 18:56:34.856854",
"modified_by": "Administrator",
"module": "HR",
"name": "Exit Interview",
diff --git a/erpnext/hr/doctype/exit_interview/exit_interview.py b/erpnext/hr/doctype/exit_interview/exit_interview.py
index 878380b..b2ada4d 100644
--- a/erpnext/hr/doctype/exit_interview/exit_interview.py
+++ b/erpnext/hr/doctype/exit_interview/exit_interview.py
@@ -38,28 +38,76 @@
@frappe.whitelist()
-def send_exit_questionnaire(exit_interview):
- exit_interview = frappe.get_doc('Exit Interview', exit_interview)
- context = exit_interview.as_dict()
+def send_exit_questionnaire(interviews):
+ interviews = get_interviews(interviews)
+ validate_questionnaire_settings()
- employee = frappe.get_doc('Employee', exit_interview.employee)
- context.update(employee.as_dict())
+ email_success = []
+ email_failure = []
- email = get_employee_email(employee)
- template_name = frappe.db.get_single_value('HR Settings', 'exit_questionnaire_notification_template')
- template = frappe.get_doc('Email Template', template_name)
+ for exit_interview in interviews:
+ interview = frappe.get_doc('Exit Interview', exit_interview.get('name'))
+ if interview.get('questionnaire_email_sent'):
+ continue
- if email:
- frappe.sendmail(
- recipients=email,
- subject=template.subject,
- message=frappe.render_template(template.response, context),
- reference_doctype=exit_interview.doctype,
- reference_name=exit_interview.name
+ employee = frappe.get_doc('Employee', interview.employee)
+ email = get_employee_email(employee)
+
+ context = interview.as_dict()
+ context.update(employee.as_dict())
+ template_name = frappe.db.get_single_value('HR Settings', 'exit_questionnaire_notification_template')
+ template = frappe.get_doc('Email Template', template_name)
+
+ if email:
+ frappe.sendmail(
+ recipients=email,
+ subject=template.subject,
+ message=frappe.render_template(template.response, context),
+ reference_doctype=interview.doctype,
+ reference_name=interview.name
+ )
+ interview.db_set('questionnaire_email_sent', True)
+ interview.notify_update()
+ email_success.append(email)
+ else:
+ email_failure.append(get_link_to_form('Employee', employee.name))
+
+ show_email_summary(email_success, email_failure)
+
+
+def get_interviews(interviews):
+ import json
+
+ if isinstance(interviews, str):
+ interviews = json.loads(interviews)
+
+ if not len(interviews):
+ frappe.throw(_('Atleast one interview has to be selected.'))
+
+ return interviews
+
+
+def validate_questionnaire_settings():
+ settings = frappe.db.get_value('HR Settings', 'HR Settings',
+ ['exit_questionnaire_web_form', 'exit_questionnaire_notification_template'], as_dict=True)
+
+ if not settings.exit_questionnaire_web_form or not settings.exit_questionnaire_notification_template:
+ frappe.throw(
+ message=_('Please set {0} and {1} in {2}.').format(
+ frappe.bold('Exit Questionnaire Web Form'),
+ frappe.bold('Notification Template'),
+ get_link_to_form('HR Settings', 'HR Settings')),
+ title=_('Settings Missing')
)
- frappe.msgprint(_('Exit Questionnaire sent to {0}').format(email),
- title='Success', indicator='green')
- exit_interview.db_set('questionnaire_email_sent', True)
- exit_interview.notify_update()
- else:
- frappe.msgprint(_('Email IDs for employee not found.'))
\ No newline at end of file
+
+
+def show_email_summary(email_success, email_failure):
+ message = ''
+ if email_success:
+ message += _('{0}: {1}').format(
+ frappe.bold('Sent Successfully'), ', '.join(email_success))
+ if email_failure:
+ message += + '<br><br>' + _('{0} due to missing email information for employee(s): {1}').format(
+ frappe.bold('Sending Failed'), ', '.join(email_failure))
+
+ frappe.msgprint(message, title=_('Exit Questionnaire'), indicator='blue', is_minimizable=True, wide=True)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/exit_interview/exit_interview_list.js b/erpnext/hr/doctype/exit_interview/exit_interview_list.js
new file mode 100644
index 0000000..93d7b21
--- /dev/null
+++ b/erpnext/hr/doctype/exit_interview/exit_interview_list.js
@@ -0,0 +1,27 @@
+frappe.listview_settings['Exit Interview'] = {
+ has_indicator_for_draft: 1,
+ get_indicator: function(doc) {
+ let status_color = {
+ 'Pending': 'orange',
+ 'Scheduled': 'yellow',
+ 'Completed': 'green',
+ 'Cancelled': 'red',
+ };
+ return [__(doc.status), status_color[doc.status], 'status,=,'+doc.status];
+ },
+
+ onload: function(listview) {
+ if (frappe.boot.user.can_write.includes('Exit Interview')) {
+ listview.page.add_action_item(__('Send Exit Questionnaires'), function() {
+ const interviews = listview.get_checked_items();
+ frappe.call({
+ method: 'erpnext.hr.doctype.exit_interview.exit_interview.send_exit_questionnaire',
+ freeze: true,
+ args: {
+ 'interviews': interviews
+ }
+ });
+ });
+ }
+ }
+};