Improve email format for training event, add ui test
diff --git a/erpnext/hr/doctype/training_event/test_training_event.js b/erpnext/hr/doctype/training_event/test_training_event.js
new file mode 100644
index 0000000..c831094
--- /dev/null
+++ b/erpnext/hr/doctype/training_event/test_training_event.js
@@ -0,0 +1,36 @@
+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"),
+		() => 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"),
+		() => cur_frm.set_value("send_email", 0),
+		() => frappe.click_button('Add Row'),
+		() => {
+ 			cur_frm.fields_dict.employees.grid.grid_rows[0].doc.attendance = "Optional";
+ 		},
+		() => frappe.click_button('Save'),
+		() => frappe.timeout(1),
+		() => frappe.click_button('Submit'),
+		() => frappe.timeout(1),
+		() => frappe.click_button('Yes'),
+		() => frappe.timeout(1),
+		() => {
+			assert.equal(cur_frm.doc.docstatus, 1);
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hr/doctype/training_event/training_event.js b/erpnext/hr/doctype/training_event/training_event.js
index ebe0c79..86a4eaf 100644
--- a/erpnext/hr/doctype/training_event/training_event.js
+++ b/erpnext/hr/doctype/training_event/training_event.js
@@ -17,5 +17,37 @@
 				frappe.set_route("List", "Training Feedback");
 			});
 		}
+	},
+	onload: function(frm) {
+		var params = getSearchParameters();
+		if (params.hasOwnProperty('employee') && params.hasOwnProperty('status')) {
+			var newTemp = frm.doc.employees.filter(function(obj) {
+				return obj.name == params.employee
+			});
+			if (newTemp) {
+				newTemp[0].status = params.status;
+				frm.refresh_field("employees");
+				frappe.msgprint(__(frm.doc.name + ": Status for " + newTemp[0].employee_name +
+					" is updated to " + newTemp[0].status));
+				frappe.route_options = {};
+				frappe.set_route("List", "Training Event");
+			}
+		}
 	}
 });
+
+function getSearchParameters() {
+	var prmstr = window.location.href.split('?')[2];
+	return prmstr != null && prmstr != "" ? transformToAssocArray(prmstr) : {};
+}
+
+function transformToAssocArray( prmstr ) {
+    var params = {};
+    var prmarr = prmstr.split("&");
+    for ( var i = 0; i < prmarr.length; i++) {
+        var tmparr = prmarr[i].split("=");
+        params[tmparr[0]] = tmparr[1];
+    }
+    return params;
+}
+
diff --git a/erpnext/hr/doctype/training_event/training_event.json b/erpnext/hr/doctype/training_event/training_event.json
index 03b58b4..0b13bc2 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, 
@@ -614,6 +614,37 @@
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "eval:doc.send_email", 
+   "fieldname": "include_attachments", 
+   "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": "Include Attachments", 
+   "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, 
@@ -684,7 +715,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-05-29 06:13:38.411039", 
+ "modified": "2017-07-25 01:43:53.189382", 
  "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..f2860c7 100644
--- a/erpnext/hr/doctype/training_event/training_event.py
+++ b/erpnext/hr/doctype/training_event/training_event.py
@@ -6,14 +6,21 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
+from frappe.desk.form.load import get_attachments
+from frappe.core.doctype.communication.email import make
+from frappe.utils.user import get_user_fullname
+from frappe.utils import get_url_to_form
+
+STANDARD_USERS = ("Guest", "Administrator")
 
 class TrainingEvent(Document):
 	def on_update(self):
-		self.invite_employee()
-	
+		if self.docstatus == 1:
+			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}."""\
@@ -21,6 +28,57 @@
 
 			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
+					self.send_training_mail(emp)
+					emp.status= "Invited"
+
+	def get_link(self, employee, status):
+		return get_url_to_form("Training Event",self.name) + "?employee=" + employee + "&status=" + status
+
+	def send_training_mail(self, data):
+		full_name = get_user_fullname(frappe.session['user'])
+		if full_name == "Guest":
+			full_name = "Administrator"
+
+		args = {
+			'message': frappe.render_template(self.introduction, data.as_dict()),
+			'confirm_link': self.get_link(data.name, "Confirmed"),
+			'reject_link': self.get_link(data.name, "Withdrawn"),
+			'complete_link': self.get_link(data.name, "Attended"),
+			'event_link': get_url_to_form("Training Event",self.name),
+			'self_study': 1 if self.type == "Self-Study" else 0,
+			'attendance': data.attendance,
+			'user_fullname': full_name
+		}
+
+		args.update(self.as_dict())
+		subject = _("Training Event")
+		template = "templates/emails/training_event.html"
+		sender = frappe.session.user not in STANDARD_USERS and frappe.session.user or None
+		message = frappe.get_template(template).render(args)
+		attachments = self.get_attachments()
+
+		self.send_invitation_email(data, sender, subject, message, attachments)
+
+	def send_invitation_email(self, data, sender, subject, message, attachments):
+		email = frappe.db.get_value("Employee", data.employee, "company_email")
+		if email:
+			make(subject = subject, content=message,recipients=email,
+				sender=sender,attachments = attachments, send_email=True,
+					doctype=self.doctype, name=self.name)["name"]
+			frappe.msgprint(_("Email sent to {0}").format(data.employee_name))
+
+	def get_attachments(self):
+		if self.include_attachments:
+			attachments = [d.name for d in get_attachments(self.doctype, self.name)]
+		else:
+			attachments = []
+		return attachments
+
+@frappe.whitelist(allow_guest=True)
+def set_response(event, response):
+	doc = frappe.get_doc('Training Event Employee', event)
+
+	if doc:
+		doc.status = response
+		doc.save()
+		frappe.msgprint("Status for this training event as been updated")
\ No newline at end of file
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..b2f51f7 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,6 +115,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": "Status", 
@@ -124,19 +133,50 @@
    "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, 
+   "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, 
  "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-07-25 01:41:28.915089", 
  "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/templates/emails/training_event.html b/erpnext/templates/emails/training_event.html
new file mode 100644
index 0000000..6e733fb
--- /dev/null
+++ b/erpnext/templates/emails/training_event.html
@@ -0,0 +1,20 @@
+<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>
+<p>{{_("Please update your status for this training event")}}:</p>
+{% if not self_study %}
+<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 %}
+<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 0bc61fa..38074d0 100644
--- a/erpnext/tests/ui/tests.txt
+++ b/erpnext/tests/ui/tests.txt
@@ -29,6 +29,7 @@
 erpnext/projects/doctype/project/project_timesheet.js
 erpnext/hr/doctype/holiday_list/test_holiday_list.js
 erpnext/hr/doctype/branch/test_branch.js
+<<<<<<< a5cb9ae8bdd7c810bf3241ea7525d378b91b05a4
 erpnext/hr/doctype/leave_block_list/test_leave_block_list.js
 erpnext/hr/doctype/department/test_department.js
 erpnext/hr/doctype/designation/test_designation.js
@@ -82,4 +83,6 @@
 erpnext/buying/doctype/supplier/test_supplier.js
 erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js
 erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js
-erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
\ No newline at end of file
+erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
+erpnext/manufacturing/doctype/bom/test_bom.js
+erpnext/hr/doctype/training_event/test_training_event.js