mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-30 18:34:48 +00:00
feat: bulk questionnaire sending
This commit is contained in:
@@ -23,29 +23,15 @@ frappe.ui.form.on('Exit Interview', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
send_exit_questionnaire: function(frm) {
|
send_exit_questionnaire: function(frm) {
|
||||||
frappe.db.get_value('HR Settings', 'HR Settings',
|
frappe.call({
|
||||||
['exit_questionnaire_web_form', 'exit_questionnaire_notification_template'], (r) => {
|
method: 'erpnext.hr.doctype.exit_interview.exit_interview.send_exit_questionnaire',
|
||||||
if (!r.exit_questionnaire_web_form || !r.exit_questionnaire_notification_template) {
|
args: {
|
||||||
frappe.throw({
|
'interviews': [frm.doc]
|
||||||
message: __('Please set {0} and {1} in {2}.',
|
},
|
||||||
['Exit Questionnaire Web Form'.bold(),
|
callback: function(r) {
|
||||||
'Notification Template'.bold(),
|
if (!r.exc) {
|
||||||
'<a href="/app/hr-settings" target="_blank">HR Settings</a>']
|
frm.refresh_field('questionnaire_email_sent');
|
||||||
),
|
}
|
||||||
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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,8 +87,7 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Date",
|
"label": "Date",
|
||||||
"mandatory_depends_on": "eval:doc.status==='Scheduled';",
|
"mandatory_depends_on": "eval:doc.status==='Scheduled';"
|
||||||
"reqd": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "exit_questionnaire_section",
|
"fieldname": "exit_questionnaire_section",
|
||||||
@@ -174,6 +173,7 @@
|
|||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Questionnaire Email Sent",
|
"label": "Questionnaire Email Sent",
|
||||||
|
"no_copy": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-12-05 17:49:44.839277",
|
"modified": "2021-12-05 18:56:34.856854",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Exit Interview",
|
"name": "Exit Interview",
|
||||||
|
|||||||
@@ -38,28 +38,76 @@ class ExitInterview(Document):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def send_exit_questionnaire(exit_interview):
|
def send_exit_questionnaire(interviews):
|
||||||
exit_interview = frappe.get_doc('Exit Interview', exit_interview)
|
interviews = get_interviews(interviews)
|
||||||
context = exit_interview.as_dict()
|
validate_questionnaire_settings()
|
||||||
|
|
||||||
employee = frappe.get_doc('Employee', exit_interview.employee)
|
email_success = []
|
||||||
context.update(employee.as_dict())
|
email_failure = []
|
||||||
|
|
||||||
email = get_employee_email(employee)
|
for exit_interview in interviews:
|
||||||
template_name = frappe.db.get_single_value('HR Settings', 'exit_questionnaire_notification_template')
|
interview = frappe.get_doc('Exit Interview', exit_interview.get('name'))
|
||||||
template = frappe.get_doc('Email Template', template_name)
|
if interview.get('questionnaire_email_sent'):
|
||||||
|
continue
|
||||||
|
|
||||||
if email:
|
employee = frappe.get_doc('Employee', interview.employee)
|
||||||
frappe.sendmail(
|
email = get_employee_email(employee)
|
||||||
recipients=email,
|
|
||||||
subject=template.subject,
|
context = interview.as_dict()
|
||||||
message=frappe.render_template(template.response, context),
|
context.update(employee.as_dict())
|
||||||
reference_doctype=exit_interview.doctype,
|
template_name = frappe.db.get_single_value('HR Settings', 'exit_questionnaire_notification_template')
|
||||||
reference_name=exit_interview.name
|
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)
|
def show_email_summary(email_success, email_failure):
|
||||||
exit_interview.notify_update()
|
message = ''
|
||||||
else:
|
if email_success:
|
||||||
frappe.msgprint(_('Email IDs for employee not found.'))
|
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)
|
||||||
27
erpnext/hr/doctype/exit_interview/exit_interview_list.js
Normal file
27
erpnext/hr/doctype/exit_interview/exit_interview_list.js
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user