Merge branch 'rmehta-bcornwellmott-confirm_training' into develop
diff --git a/erpnext/docs/user/manual/en/human-resources/training.md b/erpnext/docs/user/manual/en/human-resources/training.md
index 39b9790..2aa0679 100644
--- a/erpnext/docs/user/manual/en/human-resources/training.md
+++ b/erpnext/docs/user/manual/en/human-resources/training.md
@@ -9,22 +9,23 @@
### Inviting Employees for Event
You can invite your employees to attend the event. You can do so by selecting the employees to be invited in the employee table.
+
By default the status of the employee will be 'Open'.
-The system shall notify the employee with status 'Open' by sending a email to the office email address of the employee as mentioned in the employee master if you have selected 'Send Email' checkbox.
-The status is changed to 'Invited' when an invitation email is sent to the employee by the system.
-When an Employee confirms his/her presence for the event you can change the status to 'Confirmed'.
<img class="screenshot" alt="Employee" src="/docs/assets/img/human-resources/training_event_employee.png">
+When you submit the Training Event, a notifcation will be sent to the employee notifying that the Training has been scheduled. This is sent via Email Alert "Training Scheduled". You can modifiy this Email Alert to customize the message.
+
### Training Result
-After compleation of the training Employee Wise training results can be stored based on the Feedback received from the Trainer.
+After compleation of the training Employee-wise training results can be stored based on the Feedback received from the Trainer.
<img class="screenshot" alt="Employee" src="/docs/assets/img/human-resources/training_result.png">
+When the Training Result is submitted, all the employees will receive an email notifying them that they must share their feedback via "Training Feedback". This is also managed via an Email Alert, so you can customize this alert too.
-### Trainig Feedback
+### Training Feedback
-Collect feedback regarding the event from your Employees using Training Feedback.
+Employees can then share their feedback via Training Feedback.
<img class="screenshot" alt="Employee" src="/docs/assets/img/human-resources/training_feedback.png">
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index a078ef2..03626cd 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -289,3 +289,15 @@
})
user.insert()
return user.name
+
+def get_employee_emails(employee_list):
+ '''Returns list of employee emails either based on user_id or company_email'''
+ employee_emails = []
+ for employee in employee_list:
+ if not employee:
+ continue
+ user, email = frappe.db.get_value('Employee', employee, ['user_id', 'company_email'])
+ if user or email:
+ employee_emails.append(user or email)
+
+ return employee_emails
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_event/test_training_event.js b/erpnext/hr/doctype/training_event/tests/test_training_event.js
similarity index 100%
rename from erpnext/hr/doctype/training_event/test_training_event.js
rename to erpnext/hr/doctype/training_event/tests/test_training_event.js
diff --git a/erpnext/hr/doctype/training_event/tests/test_training_event_attandance.js b/erpnext/hr/doctype/training_event/tests/test_training_event_attandance.js
new file mode 100644
index 0000000..6364308
--- /dev/null
+++ b/erpnext/hr/doctype/training_event/tests/test_training_event_attandance.js
@@ -0,0 +1,40 @@
+QUnit.module('hr');
+
+QUnit.test("test: Training Event", function (assert) {
+ // number of asserts
+ assert.expect(1);
+ let done = assert.async();
+
+ frappe.run_serially([
+ // insert a new Training Event
+ () => frappe.set_route("List", "Training Event", "List"),
+ () => frappe.new_doc("Training Event"),
+ () => frappe.timeout(1),
+ () => frappe.click_link('Edit in full page'),
+ () => cur_frm.set_value("event_name", "Test Event " + frappe.utils.get_random(10)),
+ () => cur_frm.set_value("start_time", "2017-07-26, 2:00 pm PDT"),
+ () => cur_frm.set_value("end_time", "2017-07-26, 2:30 pm PDT"),
+ () => cur_frm.set_value("introduction", "This is a test report"),
+ () => cur_frm.set_value("location", "Fake office"),
+ () => frappe.click_button('Add Row'),
+ () => frappe.db.get_value('Employee', {'employee_name':'Test Employee 1'}, 'name'),
+ (r) => {
+ console.log(r);
+ return cur_frm.fields_dict.employees.grid.grid_rows[0].doc.employee = r.message.name;
+ },
+ () => {
+ return cur_frm.fields_dict.employees.grid.grid_rows[0].doc.attendance = "Optional";
+ },
+ () => frappe.click_button('Save'),
+ () => frappe.timeout(2),
+ () => frappe.click_button('Submit'),
+ () => frappe.timeout(2),
+ () => frappe.click_button('Yes'),
+ () => frappe.timeout(1),
+ () => {
+ assert.equal(cur_frm.doc.docstatus, 1);
+ },
+ () => done()
+ ]);
+
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_event/training_event.js b/erpnext/hr/doctype/training_event/training_event.js
index ebe0c79..6a6e8fe 100644
--- a/erpnext/hr/doctype/training_event/training_event.js
+++ b/erpnext/hr/doctype/training_event/training_event.js
@@ -18,4 +18,4 @@
});
}
}
-});
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_event/training_event.json b/erpnext/hr/doctype/training_event/training_event.json
index 03b58b4..7be9d97 100644
--- a/erpnext/hr/doctype/training_event/training_event.json
+++ b/erpnext/hr/doctype/training_event/training_event.json
@@ -25,7 +25,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 0,
"label": "Event Name",
"length": 0,
@@ -55,7 +55,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 1,
"label": "Event Status",
"length": 0,
@@ -115,12 +115,12 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 1,
"label": "Type",
"length": 0,
"no_copy": 0,
- "options": "Seminar\nTheory\nWorkshop\nConference\nExam\nInternet",
+ "options": "Seminar\nTheory\nWorkshop\nConference\nExam\nInternet\nSelf-Study",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -386,7 +386,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 1,
"label": "Location",
"length": 0,
@@ -583,37 +583,6 @@
},
{
"allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Will send an email about the event to employees with status 'Open'",
- "fieldname": "send_email",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Send Email",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -672,6 +641,37 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "employee_emails",
+ "fieldtype": "Small Text",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Employee Emails",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Email",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
}
],
"has_web_view": 0,
@@ -684,7 +684,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-05-29 06:13:38.411039",
+ "modified": "2017-08-11 03:11:25.768563",
"modified_by": "Administrator",
"module": "HR",
"name": "Training Event",
diff --git a/erpnext/hr/doctype/training_event/training_event.py b/erpnext/hr/doctype/training_event/training_event.py
index 27ae8cf..cc56841 100644
--- a/erpnext/hr/doctype/training_event/training_event.py
+++ b/erpnext/hr/doctype/training_event/training_event.py
@@ -3,24 +3,10 @@
# For license information, please see license.txt
from __future__ import unicode_literals
-import frappe
-from frappe import _
from frappe.model.document import Document
+from erpnext.hr.doctype.employee.employee import get_employee_emails
class TrainingEvent(Document):
- def on_update(self):
- self.invite_employee()
-
- def on_update_after_submit(self):
- self.invite_employee()
-
- def invite_employee(self):
- if self.event_status == "Scheduled" and self.send_email:
- subject = _("""You are invited for to attend {0} - {1} scheduled from {2} to {3} at {4}."""\
- .format(self.type, self.event_name, self.start_time, self.end_time, self.location))
-
- for emp in self.employees:
- if emp.status== "Open":
- frappe.sendmail(frappe.db.get_value("Employee", emp.employee, "company_email"), \
- subject=subject, content= self.introduction)
- emp.status= "Invited"
\ No newline at end of file
+ def validate(self):
+ self.employee_emails = ', '.join(get_employee_emails([d.employee
+ for d in self.employees]))
diff --git a/erpnext/hr/doctype/training_event_employee/training_event_employee.json b/erpnext/hr/doctype/training_event_employee/training_event_employee.json
index 575d0e7..a8a72b1 100644
--- a/erpnext/hr/doctype/training_event_employee/training_event_employee.json
+++ b/erpnext/hr/doctype/training_event_employee/training_event_employee.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -11,6 +12,7 @@
"editable_grid": 1,
"fields": [
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -21,6 +23,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Employee",
@@ -40,6 +43,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -50,6 +54,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Employee Name",
@@ -69,6 +74,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -79,6 +85,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
@@ -96,6 +103,7 @@
"unique": 0
},
{
+ "allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -107,12 +115,44 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Status",
"length": 0,
"no_copy": 1,
- "options": "Open\nInvited\nConfirmed\nAttended\nWithdrawn",
+ "options": "Open\nInvited\nCompleted\nFeedback Submitted",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "attendance",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Attendance",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Mandatory\nOptional",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -126,17 +166,17 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
- "in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-12-14 11:43:40.996578",
+ "modified": "2017-08-11 03:36:22.738253",
"modified_by": "Administrator",
"module": "HR",
"name": "Training Event Employee",
@@ -146,7 +186,9 @@
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
+ "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
+ "track_changes": 0,
"track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_feedback/training_feedback.py b/erpnext/hr/doctype/training_feedback/training_feedback.py
index 2a0403b..20a3bc5 100644
--- a/erpnext/hr/doctype/training_feedback/training_feedback.py
+++ b/erpnext/hr/doctype/training_feedback/training_feedback.py
@@ -5,6 +5,19 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
+from frappe import _
class TrainingFeedback(Document):
- pass
+ def validate(self):
+ training_event = frappe.get_doc("Training Event", self.training_event)
+ if training_event.docstatus != 1:
+ frappe.throw(_('{0} must be submitted').format(_('Training Event')))
+
+ def on_submit(self):
+ training_event = frappe.get_doc("Training Event", self.training_event)
+ for e in training_event.employees:
+ if e.employee == self.employee:
+ training_event.status = 'Feedback Submitted'
+ break
+
+ training_event.update_after_submit()
diff --git a/erpnext/hr/doctype/training_result/test_training_result.js b/erpnext/hr/doctype/training_result/test_training_result.js
new file mode 100644
index 0000000..cb1d7fb
--- /dev/null
+++ b/erpnext/hr/doctype/training_result/test_training_result.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Training Result", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Training Result
+ () => frappe.tests.make('Training Result', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/hr/doctype/training_result/training_result.json b/erpnext/hr/doctype/training_result/training_result.json
index e5fbb5f..41142b5 100644
--- a/erpnext/hr/doctype/training_result/training_result.json
+++ b/erpnext/hr/doctype/training_result/training_result.json
@@ -26,7 +26,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 0,
"label": "Training Event",
"length": 0,
@@ -133,6 +133,37 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "employee_emails",
+ "fieldtype": "Small Text",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Employee Emails",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Email",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
}
],
"has_web_view": 0,
@@ -145,7 +176,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-06-15 08:16:01.566531",
+ "modified": "2017-08-11 03:53:21.283968",
"modified_by": "Administrator",
"module": "HR",
"name": "Training Result",
diff --git a/erpnext/hr/doctype/training_result/training_result.py b/erpnext/hr/doctype/training_result/training_result.py
index 36c3cb9..7cdc51f 100644
--- a/erpnext/hr/doctype/training_result/training_result.py
+++ b/erpnext/hr/doctype/training_result/training_result.py
@@ -6,19 +6,27 @@
import frappe
from frappe import _
from frappe.model.document import Document
+from erpnext.hr.doctype.employee.employee import get_employee_emails
class TrainingResult(Document):
+ def validate(self):
+ training_event = frappe.get_doc("Training Event", self.training_event)
+ if training_event.docstatus != 1:
+ frappe.throw(_('{0} must be submitted').format(_('Training Event')))
+
+ self.employee_emails = ', '.join(get_employee_emails([d.employee
+ for d in self.employees]))
+
def on_submit(self):
- self.send_result()
-
- def send_result(self):
- for emp in self.employees:
- message = "Thank You for attending {0}.".format(self.training_event)
- if emp.grade:
- message = message + "Your grade: {0}".format(emp.grade)
- frappe.sendmail(frappe.db.get_value("Employee", emp.employee, "company_email"), \
- subject=_("{0} Results".format(self.training_event)), \
- content=message)
+ training_event = frappe.get_doc("Training Event", self.training_event)
+ training_event.status = 'Completed'
+ for e in self.employees:
+ for e1 in training_event.employees:
+ if e1.employee == e.employee:
+ e1.status = 'Completed'
+ break
+
+ training_event.save()
@frappe.whitelist()
def get_employees(training_event):
diff --git a/erpnext/hr/email_alert/__init__.py b/erpnext/hr/email_alert/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/email_alert/__init__.py
diff --git a/erpnext/hr/email_alert/training_feedback/__init__.py b/erpnext/hr/email_alert/training_feedback/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/email_alert/training_feedback/__init__.py
diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.html b/erpnext/hr/email_alert/training_feedback/training_feedback.html
new file mode 100644
index 0000000..fd8fef9
--- /dev/null
+++ b/erpnext/hr/email_alert/training_feedback/training_feedback.html
@@ -0,0 +1,6 @@
+<p>{{ _("Hello") }},</p>
+
+<p>You attended training {{ frappe.utils.get_link_to_form(
+ "Training Event", doc.training_event) }}</p>
+
+<p>{{ _("Please share your feedback to the training by clicking on 'Training Feedback' and then 'New'") }}</p>
\ No newline at end of file
diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.json b/erpnext/hr/email_alert/training_feedback/training_feedback.json
new file mode 100644
index 0000000..51f6ced
--- /dev/null
+++ b/erpnext/hr/email_alert/training_feedback/training_feedback.json
@@ -0,0 +1,24 @@
+{
+ "attach_print": 0,
+ "creation": "2017-08-11 03:17:11.769210",
+ "days_in_advance": 0,
+ "docstatus": 0,
+ "doctype": "Email Alert",
+ "document_type": "Training Result",
+ "enabled": 1,
+ "event": "Submit",
+ "idx": 0,
+ "is_standard": 1,
+ "message": "<h3>{{_(\"Training Event\")}}</h3>\n<p>{{ message }}</p>\n\n<h4>{{_(\"Details\")}}</h4>\n{{_(\"Event Name\")}}: <a href=\"{{ event_link }}\">{{ name }}</a>\n<br>{{_(\"Event Location\")}}: {{ location }}\n<br>{{_(\"Start Time\")}}: {{ start_time }}\n<br>{{_(\"End Time\")}}: {{ end_time }}\n<br>{{_(\"Attendance\")}}: {{ attendance }}\n",
+ "modified": "2017-08-11 04:26:58.194793",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Training Feedback",
+ "owner": "Administrator",
+ "recipients": [
+ {
+ "email_by_document_field": "employee_emails"
+ }
+ ],
+ "subject": "Please Share your Feedback For {{ doc.training_event }}"
+}
\ No newline at end of file
diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.md b/erpnext/hr/email_alert/training_feedback/training_feedback.md
new file mode 100644
index 0000000..bcadf7d
--- /dev/null
+++ b/erpnext/hr/email_alert/training_feedback/training_feedback.md
@@ -0,0 +1,9 @@
+<h3>{{_("Training Event")}}</h3>
+<p>{{ message }}</p>
+
+<h4>{{_("Details")}}</h4>
+{{_("Event Name")}}: <a href="{{ event_link }}">{{ name }}</a>
+<br>{{_("Event Location")}}: {{ location }}
+<br>{{_("Start Time")}}: {{ start_time }}
+<br>{{_("End Time")}}: {{ end_time }}
+<br>{{_("Attendance")}}: {{ attendance }}
diff --git a/erpnext/hr/email_alert/training_feedback/training_feedback.py b/erpnext/hr/email_alert/training_feedback/training_feedback.py
new file mode 100644
index 0000000..2334f8b
--- /dev/null
+++ b/erpnext/hr/email_alert/training_feedback/training_feedback.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+
+import frappe
+
+def get_context(context):
+ # do your magic here
+ pass
diff --git a/erpnext/hr/email_alert/training_scheduled/__init__.py b/erpnext/hr/email_alert/training_scheduled/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/email_alert/training_scheduled/__init__.py
diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.html b/erpnext/hr/email_alert/training_scheduled/training_scheduled.html
new file mode 100644
index 0000000..b1aeb2c
--- /dev/null
+++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.html
@@ -0,0 +1,9 @@
+<h3>{{_("Training Event")}}</h3>
+
+<p>{{ doc.introduction }}</p>
+
+<h4>{{_("Details")}}</h4>
+{{_("Event Name")}}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}
+<br>{{_("Event Location")}}: {{ doc.location }}
+<br>{{_("Start Time")}}: {{ doc.start_time }}
+<br>{{_("End Time")}}: {{ doc.end_time }}
diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.json b/erpnext/hr/email_alert/training_scheduled/training_scheduled.json
new file mode 100644
index 0000000..e1631f8
--- /dev/null
+++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.json
@@ -0,0 +1,24 @@
+{
+ "attach_print": 0,
+ "creation": "2017-08-11 03:13:40.519614",
+ "days_in_advance": 0,
+ "docstatus": 0,
+ "doctype": "Email Alert",
+ "document_type": "Training Event",
+ "enabled": 1,
+ "event": "Submit",
+ "idx": 0,
+ "is_standard": 1,
+ "message": "<h3>{{_(\"Training Event\")}}</h3>\n\n<p>{{ doc.introduction }}</p>\n\n<h4>{{_(\"Details\")}}</h4>\n{{_(\"Event Name\")}}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}\n<br>{{_(\"Event Location\")}}: {{ doc.location }}\n<br>{{_(\"Start Time\")}}: {{ doc.start_time }}\n<br>{{_(\"End Time\")}}: {{ doc.end_time }}\n",
+ "modified": "2017-08-13 22:49:42.338881",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Training Scheduled",
+ "owner": "Administrator",
+ "recipients": [
+ {
+ "email_by_document_field": "employee_emails"
+ }
+ ],
+ "subject": "Training Scheduled: {{ doc.name }}"
+}
\ No newline at end of file
diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.md b/erpnext/hr/email_alert/training_scheduled/training_scheduled.md
new file mode 100644
index 0000000..bcadf7d
--- /dev/null
+++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.md
@@ -0,0 +1,9 @@
+<h3>{{_("Training Event")}}</h3>
+<p>{{ message }}</p>
+
+<h4>{{_("Details")}}</h4>
+{{_("Event Name")}}: <a href="{{ event_link }}">{{ name }}</a>
+<br>{{_("Event Location")}}: {{ location }}
+<br>{{_("Start Time")}}: {{ start_time }}
+<br>{{_("End Time")}}: {{ end_time }}
+<br>{{_("Attendance")}}: {{ attendance }}
diff --git a/erpnext/hr/email_alert/training_scheduled/training_scheduled.py b/erpnext/hr/email_alert/training_scheduled/training_scheduled.py
new file mode 100644
index 0000000..2334f8b
--- /dev/null
+++ b/erpnext/hr/email_alert/training_scheduled/training_scheduled.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+
+import frappe
+
+def get_context(context):
+ # do your magic here
+ pass
diff --git a/erpnext/templates/emails/training_event.html b/erpnext/templates/emails/training_event.html
new file mode 100644
index 0000000..51c232d
--- /dev/null
+++ b/erpnext/templates/emails/training_event.html
@@ -0,0 +1,21 @@
+<h3>{{_("Training Event")}}</h3>
+<p>{{ message }}</p>
+
+<h4>{{_("Details")}}</h4>
+{{_("Event Name")}}: <a href="{{ event_link }}">{{ name }}</a>
+<br>{{_("Event Location")}}: {{ location }}
+<br>{{_("Start Time")}}: {{ start_time }}
+<br>{{_("End Time")}}: {{ end_time }}
+<br>{{_("Attendance")}}: {{ attendance }}
+
+<h4>{{_("Update Response")}}</h4>
+{% if not self_study %}
+<p>{{_("Please update your status for this training event")}}:</p>
+<form action="{{ confirm_link }}"><input style="display:inline-block" type="submit" value="Confirm Attendance" /></form>
+<form action="{{ reject_link }}"><input style="display:inline-block" type="submit" value="Reject Invitation" /></form>
+{% else %}
+<p>{{_("Please confirm once you have completed your training")}}:</p>
+<form action="{{ complete_link }}"><input style="display:inline-block" type="submit" value="Completed Training" /></form>
+{% endif %}
+<p>{{_("Thank you")}},<br>
+{{ user_fullname }}</p>
diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt
index 880263f..313554b 100644
--- a/erpnext/tests/ui/tests.txt
+++ b/erpnext/tests/ui/tests.txt
@@ -70,7 +70,8 @@
erpnext/hr/doctype/appraisal/test_appraisal.js
erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js
erpnext/hr/doctype/expense_claim/test_expense_claim.js
-erpnext/hr/doctype/training_event/test_training_event.js
+erpnext/hr/doctype/training_event/tests/test_training_event.js
+erpnext/hr/doctype/training_event/tests/test_training_event_attendance.js
erpnext/hr/doctype/training_result_employee/test_training_result.js
erpnext/hr/doctype/training_feedback/test_training_feedback.js
erpnext/hr/doctype/loan_type/test_loan_type.js