Merge pull request #17350 from nabinhait/item-tax-patch

fix: create account if not exists in item tax patch
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 44af743..90a0ef4 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -369,6 +369,7 @@
 
 	set_pos_data: function() {
 		if(this.frm.doc.is_pos) {
+			this.frm.set_value("allocate_advances_automatically", this.frm.doc.is_pos ? 0 : 1);
 			if(!this.frm.doc.company) {
 				this.frm.set_value("is_pos", 0);
 				frappe.msgprint(__("Please specify Company to proceed"));
diff --git a/erpnext/config/education.py b/erpnext/config/education.py
index d5f9e2d..4efaaa6 100644
--- a/erpnext/config/education.py
+++ b/erpnext/config/education.py
@@ -35,6 +35,10 @@
 				},
 				{
 					"type": "doctype",
+					"name": "Web Academy Applicant"
+				},
+				{
+					"type": "doctype",
 					"name": "Student Admission"
 				},
 				{
@@ -182,12 +186,16 @@
 			"items": [
 				{
 					"type": "doctype",
+					"name": "Program",
+				},
+				{
+					"type": "doctype",
 					"name": "Course",
 					"onboard": 1,
 				},
 				{
 					"type": "doctype",
-					"name": "Program"
+					"name": "Topic",
 				},
 				{
 					"type": "doctype",
@@ -202,6 +210,40 @@
 			]
 		},
 		{
+			"label": _("Content Masters"),
+			"items": [
+				{
+					"type": "doctype",
+					"name": "Article"
+				},
+				{
+					"type": "doctype",
+					"name": "Video"
+				},
+				{
+					"type": "doctype",
+					"name": "Quiz"
+				}
+			]
+		},
+		{
+			"label": _("LMS Activity"),
+			"items": [
+				{
+					"type": "doctype",
+					"name": "Course Enrollment"
+				},
+				{
+					"type": "doctype",
+					"name": "Course Activity"
+				},
+				{
+					"type": "doctype",
+					"name": "Quiz Activity"
+				}
+			]
+		},
+		{
 			"label": _("Settings"),
 			"items": [
 				{
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 63ea259..90dc086 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -89,7 +89,7 @@
 			self.validate_paid_amount()
 
 		if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
-			if cint(self.allocate_advances_automatically):
+			if cint(self.allocate_advances_automatically) and not cint(self.is_pos):
 				self.set_advances()
 
 			if self.is_return:
diff --git a/erpnext/domains/education.py b/erpnext/domains/education.py
index c640576..55e4eed 100644
--- a/erpnext/domains/education.py
+++ b/erpnext/domains/education.py
@@ -14,7 +14,7 @@
 		'Student Attendance Tool',
 		'Student Applicant'
 	],
-	'default_portal_role': 'Guardian',
+	'default_portal_role': 'LMS User',
 	'restricted_roles': [
 		'Student',
 		'Instructor',
diff --git a/erpnext/education/api.py b/erpnext/education/api.py
index 30d5588..1a19716 100644
--- a/erpnext/education/api.py
+++ b/erpnext/education/api.py
@@ -38,7 +38,7 @@
 	program_enrollment.student = student.name
 	program_enrollment.student_name = student.title
 	program_enrollment.program = frappe.db.get_value("Student Applicant", source_name, "program")
-	frappe.publish_realtime('enroll_student_progress', {"progress": [4, 4]}, user=frappe.session.user)	
+	frappe.publish_realtime('enroll_student_progress', {"progress": [2, 4]}, user=frappe.session.user)
 	return program_enrollment
 
 
@@ -69,7 +69,7 @@
 
 	present = json.loads(students_present)
 	absent = json.loads(students_absent)
-	
+
 	for d in present:
 		make_attendance_records(d["student"], d["student_name"], "Present", course_schedule, student_group, date)
 
@@ -89,7 +89,7 @@
 	:param status: Status (Present/Absent)
 	"""
 	student_attendance = frappe.get_doc({
-		"doctype": "Student Attendance", 
+		"doctype": "Student Attendance",
 		"student": student,
 		"course_schedule": course_schedule,
 		"student_group": student_group,
@@ -112,7 +112,7 @@
 
 	:param student: Student.
 	"""
-	guardians = frappe.get_list("Student Guardian", fields=["guardian"] , 
+	guardians = frappe.get_list("Student Guardian", fields=["guardian"] ,
 		filters={"parent": student})
 	return guardians
 
@@ -353,7 +353,7 @@
 		for guard in get_student_guardians(stud.student):
 			email = frappe.db.get_value("Guardian", guard.guardian, "email_address")
 			if email:
-				email_list.append(email)	
+				email_list.append(email)
 	add_subscribers(name, email_list)
 
 @frappe.whitelist()
diff --git a/erpnext/education/doctype/article/__init__.py b/erpnext/education/doctype/article/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/article/__init__.py
diff --git a/erpnext/education/doctype/article/article.js b/erpnext/education/doctype/article/article.js
new file mode 100644
index 0000000..4c9c6f0
--- /dev/null
+++ b/erpnext/education/doctype/article/article.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Article', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/article/article.json b/erpnext/education/doctype/article/article.json
new file mode 100644
index 0000000..c30cd18
--- /dev/null
+++ b/erpnext/education/doctype/article/article.json
@@ -0,0 +1,230 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "field:title",
+ "beta": 0,
+ "creation": "2018-10-17 05:45:38.471670",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "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": "Title",
+   "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,
+   "translatable": 0,
+   "unique": 1
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "author",
+   "fieldtype": "Data",
+   "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": "Author",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "content",
+   "fieldtype": "Text Editor",
+   "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": "Content",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "publish_date",
+   "fieldtype": "Date",
+   "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": "Publish Date",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-11-25 19:06:56.016865",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Article",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/article/article.py b/erpnext/education/doctype/article/article.py
new file mode 100644
index 0000000..7dc850b
--- /dev/null
+++ b/erpnext/education/doctype/article/article.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class Article(Document):
+
+
+	def get_article(self):
+		pass
+
+
diff --git a/erpnext/education/doctype/article/test_article.js b/erpnext/education/doctype/article/test_article.js
new file mode 100644
index 0000000..9dbf063
--- /dev/null
+++ b/erpnext/education/doctype/article/test_article.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: Article", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Article
+		() => frappe.tests.make('Article', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/article/test_article.py b/erpnext/education/doctype/article/test_article.py
new file mode 100644
index 0000000..2fce07f
--- /dev/null
+++ b/erpnext/education/doctype/article/test_article.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestArticle(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/content_activity/__init__.py b/erpnext/education/doctype/content_activity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/content_activity/__init__.py
diff --git a/erpnext/education/doctype/content_activity/content_activity.json b/erpnext/education/doctype/content_activity/content_activity.json
new file mode 100644
index 0000000..b4c95da
--- /dev/null
+++ b/erpnext/education/doctype/content_activity/content_activity.json
@@ -0,0 +1,141 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2018-10-16 03:55:53.283893", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "content", 
+   "fieldtype": "Link", 
+   "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": "Content", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Content", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_from": "content.content_type", 
+   "fieldname": "content_type", 
+   "fieldtype": "Data", 
+   "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": "Content Type", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "last_activity", 
+   "fieldtype": "Datetime", 
+   "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": "Last Activity ", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2018-10-16 03:55:58.202436", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Content Activity", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/content_activity/content_activity.py b/erpnext/education/doctype/content_activity/content_activity.py
new file mode 100644
index 0000000..2ae7a5c
--- /dev/null
+++ b/erpnext/education/doctype/content_activity/content_activity.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class ContentActivity(Document):
+	pass
diff --git a/erpnext/education/doctype/content_question/__init__.py b/erpnext/education/doctype/content_question/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/content_question/__init__.py
diff --git a/erpnext/education/doctype/content_question/content_question.js b/erpnext/education/doctype/content_question/content_question.js
new file mode 100644
index 0000000..7615f5e
--- /dev/null
+++ b/erpnext/education/doctype/content_question/content_question.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Content Question', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/content_question/content_question.json b/erpnext/education/doctype/content_question/content_question.json
new file mode 100644
index 0000000..d390e8e
--- /dev/null
+++ b/erpnext/education/doctype/content_question/content_question.json
@@ -0,0 +1,76 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2018-10-15 14:35:40.728454", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "question_link", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Question Link", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Question", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2018-10-15 14:41:31.729083", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Content Question", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/content_question/content_question.py b/erpnext/education/doctype/content_question/content_question.py
new file mode 100644
index 0000000..b239d21
--- /dev/null
+++ b/erpnext/education/doctype/content_question/content_question.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class ContentQuestion(Document):
+	pass
diff --git a/erpnext/education/doctype/content_question/test_content_question.js b/erpnext/education/doctype/content_question/test_content_question.js
new file mode 100644
index 0000000..cc869a8
--- /dev/null
+++ b/erpnext/education/doctype/content_question/test_content_question.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: Content Question", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Content Question
+		() => frappe.tests.make('Content Question', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/content_question/test_content_question.py b/erpnext/education/doctype/content_question/test_content_question.py
new file mode 100644
index 0000000..268b9be
--- /dev/null
+++ b/erpnext/education/doctype/content_question/test_content_question.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestContentQuestion(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/course/course.json b/erpnext/education/doctype/course/course.json
index 15360f8..072e8b4 100644
--- a/erpnext/education/doctype/course/course.json
+++ b/erpnext/education/doctype/course/course.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
@@ -15,10 +16,12 @@
  "fields": [
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "course_name", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -41,14 +44,17 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "department", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -72,14 +78,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "parent_course", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -102,14 +111,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "column_break_3", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -131,14 +143,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "course_code", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -161,14 +176,17 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "unique": 0
+   "translatable": 0, 
+   "unique": 1
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "course_abbreviation", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -191,14 +209,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_6", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -220,16 +241,53 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "topics", 
+   "fieldtype": "Table", 
+   "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": "Topics", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Course Topic", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "course_intro", 
-   "fieldtype": "Text Editor", 
+   "fieldtype": "Small Text", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -250,14 +308,50 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "hero_image", 
+   "fieldtype": "Attach Image", 
+   "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": "Hero Image", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "assessment", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -280,14 +374,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "default_grading_scale", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -311,14 +408,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "assessment_criteria", 
    "fieldtype": "Table", 
    "hidden": 0, 
@@ -342,21 +442,20 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }
  ], 
  "has_web_view": 0, 
- "hide_heading": 0, 
  "hide_toolbar": 0, 
  "idx": 0, 
- "image_view": 0, 
  "in_create": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-11-10 19:06:28.909585", 
+ "modified": "2019-04-09 11:35:27.354877", 
  "modified_by": "Administrator", 
  "module": "Education", 
  "name": "Course", 
@@ -365,7 +464,6 @@
  "permissions": [
   {
    "amend": 0, 
-   "apply_user_permissions": 0, 
    "cancel": 0, 
    "create": 1, 
    "delete": 1, 
@@ -385,7 +483,6 @@
   }, 
   {
    "amend": 0, 
-   "apply_user_permissions": 0, 
    "cancel": 0, 
    "create": 1, 
    "delete": 1, 
@@ -397,7 +494,7 @@
    "print": 1, 
    "read": 1, 
    "report": 1, 
-   "role": "HR Manager", 
+   "role": "Instructor", 
    "set_user_permissions": 0, 
    "share": 1, 
    "submit": 0, 
@@ -406,12 +503,12 @@
  ], 
  "quick_entry": 0, 
  "read_only": 0, 
- "read_only_onload": 0, 
  "restrict_to_domain": "Education", 
  "search_fields": "course_name", 
  "show_name_in_global_search": 1, 
  "sort_field": "modified", 
  "sort_order": "DESC", 
  "track_changes": 0, 
- "track_seen": 0
+ "track_seen": 0, 
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/course/course.py b/erpnext/education/doctype/course/course.py
index 69d2fca..987823a 100644
--- a/erpnext/education/doctype/course/course.py
+++ b/erpnext/education/doctype/course/course.py
@@ -10,7 +10,7 @@
 class Course(Document):
 	def validate(self):
 		self.validate_assessment_criteria()
-	
+
 	def validate_assessment_criteria(self):
 		if self.assessment_criteria:
 			total_weightage = 0
@@ -18,3 +18,11 @@
 				total_weightage += criteria.weightage or 0
 			if total_weightage != 100:
 				frappe.throw(_("Total Weightage of all Assessment Criteria must be 100%"))
+
+	def get_topics(self):
+		try:
+			topic_list = self.get_all_children()
+			topic_data = [frappe.get_doc("Topic", topic.topic) for topic in topic_list]
+		except frappe.DoesNotExistError:
+			return None
+		return topic_data
\ No newline at end of file
diff --git a/erpnext/education/doctype/course/test_course.py b/erpnext/education/doctype/course/test_course.py
index b18f4a9..a24ba8a 100644
--- a/erpnext/education/doctype/course/test_course.py
+++ b/erpnext/education/doctype/course/test_course.py
@@ -2,6 +2,7 @@
 # Copyright (c) 2015, Frappe Technologies and Contributors
 # See license.txt
 from __future__ import unicode_literals
+from erpnext.education.doctype.topic.test_topic import make_topic
 
 import frappe
 import unittest
@@ -9,4 +10,35 @@
 # test_records = frappe.get_test_records('Course')
 
 class TestCourse(unittest.TestCase):
-	pass
+	def setUp(self):
+		make_course_and_linked_topic("_Test Course 1", ["_Test Topic 1", "_Test Topic 2"])
+
+	def test_get_topics(self):
+		course = frappe.get_doc("Course", "_Test Course 1")
+		topics = course.get_topics()
+		self.assertEqual(topics[0].name, "_Test Topic 1")
+		self.assertEqual(topics[1].name, "_Test Topic 2")
+		frappe.db.rollback()
+
+def make_course(name):
+	try:
+		course = frappe.get_doc("Course", name)
+	except frappe.DoesNotExistError:
+		course = frappe.get_doc({
+			"doctype": "Course",
+			"course_name": name,
+			"course_code": name
+		}).insert()
+	return course.name
+
+def make_course_and_linked_topic(course_name, topic_name_list):
+	try:
+		course = frappe.get_doc("Course", course_name)
+	except frappe.DoesNotExistError:
+		make_course(course_name)
+		course = frappe.get_doc("Course", course_name)
+	topic_list = [make_topic(topic_name) for topic_name in topic_name_list]
+	for topic in topic_list:
+		course.append("topics", {"topic": topic})
+	course.save()
+	return course
diff --git a/erpnext/education/doctype/course_activity/__init__.py b/erpnext/education/doctype/course_activity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/course_activity/__init__.py
diff --git a/erpnext/education/doctype/course_activity/course_activity.js b/erpnext/education/doctype/course_activity/course_activity.js
new file mode 100644
index 0000000..5115fc4
--- /dev/null
+++ b/erpnext/education/doctype/course_activity/course_activity.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Course Activity', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/course_activity/course_activity.json b/erpnext/education/doctype/course_activity/course_activity.json
new file mode 100644
index 0000000..99ae9ae
--- /dev/null
+++ b/erpnext/education/doctype/course_activity/course_activity.json
@@ -0,0 +1,301 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "format:EDU-CA-{YYYY}-{#####}",
+ "beta": 1,
+ "creation": "2018-10-01 17:35:54.391413",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "enrollment",
+   "fieldtype": "Link",
+   "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": "Enrollment",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Course Enrollment",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "enrollment.course",
+   "fieldname": "course",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Course",
+   "length": 0,
+   "no_copy": 0,
+   "options": "",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 1,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "enrollment.student",
+   "fieldname": "student",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Student",
+   "length": 0,
+   "no_copy": 0,
+   "options": "",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 1,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "content_type",
+   "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": "Content Type",
+   "length": 0,
+   "no_copy": 0,
+   "options": "\nArticle\nVideo",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "content",
+   "fieldtype": "Dynamic Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Content",
+   "length": 0,
+   "no_copy": 0,
+   "options": "content_type",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "activity_date",
+   "fieldtype": "Datetime",
+   "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": "Activity Date",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-12-06 11:53:08.006123",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course Activity",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 1,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_activity/course_activity.py b/erpnext/education/doctype/course_activity/course_activity.py
new file mode 100644
index 0000000..054b192
--- /dev/null
+++ b/erpnext/education/doctype/course_activity/course_activity.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.model.document import Document
+
+class CourseActivity(Document):
+	def validate(self):
+		self.check_if_enrolled()
+
+
+	def check_if_enrolled(self):
+		if frappe.db.exists("Course Enrollment", self.enrollment):
+			return True
+		else:
+			frappe.throw(_("Course Enrollment {0} does not exists".format(self.enrollment)))
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_activity/test_course_activity.js b/erpnext/education/doctype/course_activity/test_course_activity.js
new file mode 100644
index 0000000..c89c89e
--- /dev/null
+++ b/erpnext/education/doctype/course_activity/test_course_activity.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: Course Activity", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Course Activity
+		() => frappe.tests.make('Course Activity', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/course_activity/test_course_activity.py b/erpnext/education/doctype/course_activity/test_course_activity.py
new file mode 100644
index 0000000..5269a6b
--- /dev/null
+++ b/erpnext/education/doctype/course_activity/test_course_activity.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestCourseActivity(unittest.TestCase):
+	pass
+
+def make_course_activity(enrollment, content_type, content):
+	activity = frappe.get_all("Course Activity", filters={'enrollment': enrollment, 'content_type': content_type, 'content': content})
+	try:
+		activity = frappe.get_doc("Course Activity", activity[0]['name'])
+	except (IndexError, frappe.DoesNotExistError):
+		activity = frappe.get_doc({
+			"doctype": "Course Activity",
+			"enrollment": enrollment,
+			"content_type": content_type,
+			"content": content,
+			"activity_date": frappe.utils.datetime.datetime.now()
+		}).insert()
+	return activity
diff --git a/erpnext/education/doctype/course_content/__init__.py b/erpnext/education/doctype/course_content/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/course_content/__init__.py
diff --git a/erpnext/education/doctype/course_content/course_content.js b/erpnext/education/doctype/course_content/course_content.js
new file mode 100644
index 0000000..b9faf99
--- /dev/null
+++ b/erpnext/education/doctype/course_content/course_content.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Course Content', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/course_content/course_content.json b/erpnext/education/doctype/course_content/course_content.json
new file mode 100644
index 0000000..378e560
--- /dev/null
+++ b/erpnext/education/doctype/course_content/course_content.json
@@ -0,0 +1,142 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2018-10-01 13:04:09.313771", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_from": "", 
+   "fieldname": "content_type", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Content Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "\nArticle\nVideo\nQuiz", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "column_break_2", 
+   "fieldtype": "Column Break", 
+   "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": "", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "content", 
+   "fieldtype": "Dynamic Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Content", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "content_type", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2018-10-17 07:36:04.029818", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Course Content", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_content/course_content.py b/erpnext/education/doctype/course_content/course_content.py
new file mode 100644
index 0000000..0d2f85a
--- /dev/null
+++ b/erpnext/education/doctype/course_content/course_content.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class CourseContent(Document):
+	pass
diff --git a/erpnext/education/doctype/course_content/test_course_content.js b/erpnext/education/doctype/course_content/test_course_content.js
new file mode 100644
index 0000000..786e67e
--- /dev/null
+++ b/erpnext/education/doctype/course_content/test_course_content.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: Course Content", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Course Content
+		() => frappe.tests.make('Course Content', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/course_content/test_course_content.py b/erpnext/education/doctype/course_content/test_course_content.py
new file mode 100644
index 0000000..9be4b1f
--- /dev/null
+++ b/erpnext/education/doctype/course_content/test_course_content.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestCourseContent(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/course_enrollment/__init__.py b/erpnext/education/doctype/course_enrollment/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/__init__.py
diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.js b/erpnext/education/doctype/course_enrollment/course_enrollment.js
new file mode 100644
index 0000000..b5d3cc5
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/course_enrollment.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Course Enrollment', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.json b/erpnext/education/doctype/course_enrollment/course_enrollment.json
new file mode 100644
index 0000000..6286ec1
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/course_enrollment.json
@@ -0,0 +1,233 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "format:EDU-CE-{YYYY}-{#####}",
+ "beta": 1,
+ "creation": "2018-10-15 15:35:39.375161",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "program_enrollment",
+   "fieldtype": "Link",
+   "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": "Program Enrollment",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Program Enrollment",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "student",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 1,
+   "label": "Student",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Student",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "course",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Course",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Course",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "enrollment_date",
+   "fieldtype": "Date",
+   "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": "Enrollment Date",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-11-25 18:59:01.742377",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course Enrollment",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.py b/erpnext/education/doctype/course_enrollment/course_enrollment.py
new file mode 100644
index 0000000..9508636
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/course_enrollment.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.model.document import Document
+from functools import reduce
+
+class CourseEnrollment(Document):
+	def get_progress(self, student):
+		"""
+		Returns Progress of given student for a particular course enrollment
+
+			:param self: Course Enrollment Object
+			:param student: Student Object
+		"""
+		course = frappe.get_doc('Course', self.course)
+		topics = course.get_topics()
+		progress = []
+		for topic in topics:
+			progress.append(student.get_topic_progress(self.name, topic))
+		return reduce(lambda x,y: x+y, progress) # Flatten out the List
+
+	def validate_duplication(self):
+		enrollment = frappe.get_all("Course Enrollment", filters={
+			"student": self.student,
+			"course": self.course,
+			"program_enrollment": self.program_enrollment
+		})
+		if enrollment:
+			frappe.throw(_("Student is already enrolled."))
+
+	def add_quiz_activity(self, quiz_name, quiz_response,answers, score, status):
+		result = {k: ('Correct' if v else 'Wrong') for k,v in answers.items()}
+		result_data = []
+		for key in answers:
+			item = {}
+			item['question'] = key
+			item['quiz_result'] = result[key]
+			try:
+				if isinstance(quiz_response[key], list):
+					item['selected_option'] = ', '.join(frappe.get_value('Options', res, 'option') for res in quiz_response[key])
+				else:
+					item['selected_option'] = frappe.get_value('Options', quiz_response[key], 'option')
+			except KeyError:
+				item['selected_option'] = "Unattempted"
+			result_data.append(item)
+
+		quiz_activity = frappe.get_doc({
+			"doctype": "Quiz Activity",
+			"enrollment": self.name,
+			"quiz": quiz_name,
+			"activity_date": frappe.utils.datetime.datetime.now(),
+			"result": result_data,
+			"score": score,
+			"status": status
+			}).insert()
+
+	def add_activity(self, content_type, content):
+		if check_activity_exists(self.name, content_type, content):
+			pass
+		else:
+			activity = frappe.get_doc({
+				"doctype": "Course Activity",
+				"enrollment": self.name,
+				"content_type": content_type,
+				"content": content,
+				"activity_date": frappe.utils.datetime.datetime.now()
+				})
+			activity.insert()
+
+def check_activity_exists(enrollment, content_type, content):
+	activity = frappe.get_all("Course Activity", filters={'enrollment': enrollment, 'content_type': content_type, 'content': content})
+	return bool(activity)
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_enrollment/test_course_enrollment.js b/erpnext/education/doctype/course_enrollment/test_course_enrollment.js
new file mode 100644
index 0000000..216cc30
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/test_course_enrollment.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: Course Enrollment", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Course Enrollment
+		() => frappe.tests.make('Course Enrollment', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/course_enrollment/test_course_enrollment.py b/erpnext/education/doctype/course_enrollment/test_course_enrollment.py
new file mode 100644
index 0000000..5ecace2
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/test_course_enrollment.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+
+from erpnext.education.doctype.student.test_student import create_student
+from erpnext.education.doctype.student.test_student import get_student
+from erpnext.education.doctype.program.test_program import setup_program
+from erpnext.education.doctype.course_activity.test_course_activity import make_course_activity
+
+class TestCourseEnrollment(unittest.TestCase):
+	def setUp(self):
+		setup_program()
+		student = create_student({"first_name": "_Test First", "last_name": "_Test Last", "email": "_test_student_1@example.com"})
+		program_enrollment = student.enroll_in_program("_Test Program")
+		course_enrollment = student.enroll_in_course("_Test Course 1", program_enrollment.name)
+		make_course_activity(course_enrollment.name, "Article", "_Test Article 1-1")
+
+	def test_get_progress(self):
+		student = get_student("_test_student_1@example.com")
+		program_enrollment_name = frappe.get_list("Program Enrollment", filters={"student": student.name, "Program": "_Test Program"})[0].name
+		course_enrollment_name = frappe.get_list("Course Enrollment", filters={"student": student.name, "course": "_Test Course 1", "program_enrollment": program_enrollment_name})[0].name
+		course_enrollment = frappe.get_doc("Course Enrollment", course_enrollment_name)
+		progress = course_enrollment.get_progress(student)
+		finished = {'content': '_Test Article 1-1', 'content_type': 'Article', 'is_complete': True}
+		self.assertTrue(finished in progress)
+		frappe.db.rollback()
+
+
+
diff --git a/erpnext/education/doctype/course_topic/__init__.py b/erpnext/education/doctype/course_topic/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/course_topic/__init__.py
diff --git a/erpnext/education/doctype/course_topic/course_topic.js b/erpnext/education/doctype/course_topic/course_topic.js
new file mode 100644
index 0000000..7d03ba3
--- /dev/null
+++ b/erpnext/education/doctype/course_topic/course_topic.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Course Topic', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/course_topic/course_topic.json b/erpnext/education/doctype/course_topic/course_topic.json
new file mode 100644
index 0000000..3fcddc1
--- /dev/null
+++ b/erpnext/education/doctype/course_topic/course_topic.json
@@ -0,0 +1,109 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-12-12 11:51:25.952740",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "topic",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Topic",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Topic",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "topic.topic_name",
+   "fieldname": "topic_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Topic Name",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2018-12-12 13:01:58.960425",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course Topic",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_topic/course_topic.py b/erpnext/education/doctype/course_topic/course_topic.py
new file mode 100644
index 0000000..2364f17
--- /dev/null
+++ b/erpnext/education/doctype/course_topic/course_topic.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class CourseTopic(Document):
+	pass
diff --git a/erpnext/education/doctype/course_topic/test_course_topic.js b/erpnext/education/doctype/course_topic/test_course_topic.js
new file mode 100644
index 0000000..d8d154f
--- /dev/null
+++ b/erpnext/education/doctype/course_topic/test_course_topic.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: Course Topic", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Course Topic
+		() => frappe.tests.make('Course Topic', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/course_topic/test_course_topic.py b/erpnext/education/doctype/course_topic/test_course_topic.py
new file mode 100644
index 0000000..7ce46d2
--- /dev/null
+++ b/erpnext/education/doctype/course_topic/test_course_topic.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestCourseTopic(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/education_settings/education_settings.json b/erpnext/education/doctype/education_settings/education_settings.json
index c1eaa11..3be4988 100644
--- a/erpnext/education/doctype/education_settings/education_settings.json
+++ b/erpnext/education/doctype/education_settings/education_settings.json
@@ -1,359 +1,492 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-04-05 13:33:04.519313", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2017-04-05 13:33:04.519313",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "current_academic_year", 
-   "fieldtype": "Link", 
-   "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": "Current Academic Year", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Academic Year", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "current_academic_year",
+   "fieldtype": "Link",
+   "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": "Current Academic Year",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Academic Year",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "current_academic_term", 
-   "fieldtype": "Link", 
-   "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": "Current Academic Term", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Academic Term", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "current_academic_term",
+   "fieldtype": "Link",
+   "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": "Current Academic Term",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Academic Term",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "attendance_freeze_date", 
-   "fieldtype": "Date", 
-   "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 Freeze Date", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "attendance_freeze_date",
+   "fieldtype": "Date",
+   "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 Freeze Date",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_4", 
-   "fieldtype": "Column Break", 
-   "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, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break",
+   "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,
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "For Batch based Student Group, the Student Batch will be validated for every Student from the Program Enrollment.", 
-   "fieldname": "validate_batch", 
-   "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": "Validate Batch for Students in Student Group", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "description": "For Batch based Student Group, the Student Batch will be validated for every Student from the Program Enrollment.",
+   "fieldname": "validate_batch",
+   "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": "Validate Batch for Students in Student Group",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "For Course based Student Group, the Course will be validated for every Student from the enrolled Courses in Program Enrollment.", 
-   "fieldname": "validate_course", 
-   "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": "Validate Enrolled Course for Students in Student Group", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "description": "For Course based Student Group, the Course will be validated for every Student from the enrolled Courses in Program Enrollment.",
+   "fieldname": "validate_course",
+   "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": "Validate Enrolled Course for Students in Student Group",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "description": "If enabled, field Academic Term will be Mandatory in Program Enrollment Tool.", 
-   "fieldname": "academic_term_reqd", 
-   "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": "Make Academic Term Mandatory", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "0",
+   "description": "If enabled, field Academic Term will be Mandatory in Program Enrollment Tool.",
+   "fieldname": "academic_term_reqd",
+   "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": "Make Academic Term Mandatory",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_7", 
-   "fieldtype": "Section Break", 
-   "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, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "section_break_7",
+   "fieldtype": "Section Break",
+   "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,
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Full Name", 
-   "fieldname": "instructor_created_by", 
-   "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": "Instructor Records to be created by", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Full Name\nNaming Series\nEmployee Number", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "Full Name",
+   "fieldname": "instructor_created_by",
+   "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": "Instructor Records to be created by",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Full Name\nNaming Series\nEmployee Number",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "web_academy_settings_section",
+   "fieldtype": "Section Break",
+   "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": "LMS Settings",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "portal_title",
+   "fieldtype": "Data",
+   "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": "Portal Title",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "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": "Description",
+   "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,
+   "translatable": 0,
    "unique": 0
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 1, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-07-26 04:43:35.406690", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Education Settings", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 1,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-12-11 15:49:15.045116",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Education Settings",
+ "name_case": "",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 0,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 0,
+   "role": "System Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Education Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 0,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 0,
+   "role": "Education Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 0,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 0,
+   "role": "Guest",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "restrict_to_domain": "Education",
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/options/__init__.py b/erpnext/education/doctype/options/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/options/__init__.py
diff --git a/erpnext/education/doctype/options/options.json b/erpnext/education/doctype/options/options.json
new file mode 100644
index 0000000..59deab7
--- /dev/null
+++ b/erpnext/education/doctype/options/options.json
@@ -0,0 +1,107 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2018-10-15 14:05:28.601274", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "option", 
+   "fieldtype": "Small Text", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Option", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "is_correct", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Is Correct", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2018-10-15 14:16:18.303156", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Options", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/options/options.py b/erpnext/education/doctype/options/options.py
new file mode 100644
index 0000000..a11d77a
--- /dev/null
+++ b/erpnext/education/doctype/options/options.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class Options(Document):
+	pass
diff --git a/erpnext/education/doctype/program/program.js b/erpnext/education/doctype/program/program.js
index 5146a19..98263b5 100644
--- a/erpnext/education/doctype/program/program.js
+++ b/erpnext/education/doctype/program/program.js
@@ -4,40 +4,5 @@
 cur_frm.add_fetch('fee_structure', 'total_amount', 'amount');
 
 frappe.ui.form.on("Program", "refresh", function(frm) {
-	if(!frm.doc.__islocal) {
-		frm.add_custom_button(__("Student Applicant"), function() {
-			frappe.route_options = {
-				program: frm.doc.name
-			}
-			frappe.set_route("List", "Student Applicant");
-		});
-		
-		frm.add_custom_button(__("Program Enrollment"), function() {
-			frappe.route_options = {
-				program: frm.doc.name
-			}
-			frappe.set_route("List", "Program Enrollment");
-		});
-		
-		frm.add_custom_button(__("Student Group"), function() {
-			frappe.route_options = {
-				program: frm.doc.name
-			}
-			frappe.set_route("List", "Student Group");
-		});
-		
-		frm.add_custom_button(__("Fee Structure"), function() {
-			frappe.route_options = {
-				program: frm.doc.name
-			}
-			frappe.set_route("List", "Fee Structure");
-		});
-		
-		frm.add_custom_button(__("Fees"), function() {
-			frappe.route_options = {
-				program: frm.doc.name
-			}
-			frappe.set_route("List", "Fees");
-		});
-	}
+	
 });
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/program.json b/erpnext/education/doctype/program/program.json
index 05e35a2..cb8d778 100644
--- a/erpnext/education/doctype/program/program.json
+++ b/erpnext/education/doctype/program/program.json
@@ -1,277 +1,627 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:program_code", 
- "beta": 0, 
- "creation": "2015-09-07 12:54:03.609282", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 0, 
- "engine": "InnoDB", 
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:program_code",
+ "beta": 0,
+ "creation": "2015-09-07 12:54:03.609282",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 0,
+ "engine": "InnoDB",
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "program_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Program Name", 
-   "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": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "program_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Program Name",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "department", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 1, 
-   "label": "Department", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Department", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Department",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Department",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "fieldtype": "Column Break", 
-   "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, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break",
+   "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,
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "program_code", 
-   "fieldtype": "Data", 
-   "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": "Program Code", 
-   "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": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "program_code",
+   "fieldtype": "Data",
+   "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": "Program Code",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 1
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "program_abbreviation",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Program Abbreviation",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "program_abbreviation", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Program Abbreviation", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "",
+   "fetch_if_empty": 0,
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "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": "Portal Settings",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_5", 
-   "fieldtype": "Section Break", 
-   "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": "Course", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "courses",
+   "fieldtype": "Table",
+   "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": "Courses",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Program Course",
+   "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,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "courses", 
-   "fieldtype": "Table", 
-   "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": "Courses", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Program Course", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "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": "Description",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "intro_video",
+   "fieldtype": "Data",
+   "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": "Intro Video",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "hero_image",
+   "fieldtype": "Attach Image",
+   "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": "Hero Image",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "0",
+   "fetch_if_empty": 0,
+   "fieldname": "is_published",
+   "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": "Is Published",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "0",
+   "fetch_if_empty": 0,
+   "fieldname": "is_featured",
+   "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": "Is Featured",
+   "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,
+   "translatable": 0,
    "unique": 0
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "menu_index": 0, 
- "modified": "2017-11-10 18:56:18.413911", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Program", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "menu_index": 0,
+ "modified": "2019-03-18 15:26:56.737903",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Program",
+ "name_case": "",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Academics User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Guest",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Student",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "search_fields": "program_name", 
- "show_name_in_global_search": 1, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "restrict_to_domain": "Education",
+ "route": "",
+ "search_fields": "program_name",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/program.py b/erpnext/education/doctype/program/program.py
index f626880..dbeda40 100644
--- a/erpnext/education/doctype/program/program.py
+++ b/erpnext/education/doctype/program/program.py
@@ -7,4 +7,8 @@
 from frappe.model.document import Document
 
 class Program(Document):
-	pass
\ No newline at end of file
+
+	def get_course_list(self):
+		program_course_list = self.get_all_children()
+		course_list = [frappe.get_doc("Course", program_course.course) for program_course in program_course_list]
+		return course_list
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/program_dashboard.py b/erpnext/education/doctype/program/program_dashboard.py
new file mode 100644
index 0000000..cb8f742
--- /dev/null
+++ b/erpnext/education/doctype/program/program_dashboard.py
@@ -0,0 +1,20 @@
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'program',
+		'transactions': [
+			{
+				'label': _('Admission and Enrollment'),
+				'items': ['Student Applicant', 'Program Enrollment']
+			},
+			{
+				'label': _('Student Activity'),
+				'items': ['Student Group' ]
+			},
+			{
+				'label': _('Fee'),
+				'items': ['Fees','Fee Structure']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/test_program.py b/erpnext/education/doctype/program/test_program.py
index a4accda..3bcca3a 100644
--- a/erpnext/education/doctype/program/test_program.py
+++ b/erpnext/education/doctype/program/test_program.py
@@ -2,11 +2,85 @@
 # Copyright (c) 2015, Frappe Technologies and Contributors
 # See license.txt
 from __future__ import unicode_literals
+from erpnext.education.doctype.course.test_course import make_course
+from erpnext.education.doctype.topic.test_topic import make_topic_and_linked_content
+from erpnext.education.doctype.course.test_course import make_course_and_linked_topic
 
 import frappe
 import unittest
 
-# test_records = frappe.get_test_records('Program')
+test_data = {
+	"program_name": "_Test Program",
+	"description": "_Test Program",
+	"course": [{
+		"course_name": "_Test Course 1",
+		"topic": [{
+				"topic_name": "_Test Topic 1-1",
+				"content": [{
+					"type": "Article",
+					"name": "_Test Article 1-1"
+				}, {
+					"type": "Article",
+					"name": "_Test Article 1-2"
+				}]
+			},
+			{
+				"topic_name": "_Test Topic 1-2",
+				"content": [{
+					"type": "Article",
+					"name": "_Test Article 1-3"
+				}, {
+					"type": "Article",
+					"name": "_Test Article 1-4"
+				}]
+			}
+		]
+	}]
+}
 
 class TestProgram(unittest.TestCase):
-	pass
+	def setUp(self):
+		make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"])
+
+	def test_get_course_list(self):
+		program = frappe.get_doc("Program", "_Test Program 1")
+		course = program.get_course_list()
+		self.assertEqual(course[0].name, "_Test Course 1")
+		self.assertEqual(course[1].name, "_Test Course 2")
+		frappe.db.rollback()
+
+def make_program(name):
+	program = frappe.get_doc({
+		"doctype": "Program",
+		"program_name": name,
+		"program_code": name,
+		"description": "_test description",
+		"is_published": True,
+		"is_featured": True,
+	}).insert()
+	return program.name
+
+def make_program_and_linked_courses(program_name, course_name_list):
+	try:
+		program = frappe.get_doc("Program", program_name)
+	except frappe.DoesNotExistError:
+		make_program(program_name)
+		program = frappe.get_doc("Program", program_name)
+	course_list = [make_course(course_name) for course_name in course_name_list]
+	for course in course_list:
+		program.append("courses", {"course": course})
+	program.save()
+	return program
+
+def setup_program():
+	topic_list = [course['topic'] for course in test_data['course']]
+	for topic in topic_list[0]:
+		make_topic_and_linked_content(topic['topic_name'], topic['content'])
+
+	all_courses_list = [{'course': course['course_name'], 'topic': [topic['topic_name'] for topic in course['topic']]} for course in test_data['course']] # returns [{'course': 'Applied Math', 'topic': ['Trignometry', 'Geometry']}]
+	for course in all_courses_list:
+		make_course_and_linked_topic(course['course'], course['topic'])
+
+	course_list = [course['course_name'] for course in test_data['course']]
+	program = make_program_and_linked_courses(test_data['program_name'], course_list)
+	return program
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/test_records.json b/erpnext/education/doctype/program/test_records.json
index e5eda70..7901db3 100644
--- a/erpnext/education/doctype/program/test_records.json
+++ b/erpnext/education/doctype/program/test_records.json
@@ -1,12 +1,14 @@
 [
 	{
-		"program_name": "_Test Program",
+		"program_name": "_Test Program 1",
 		"program_code": "_TP1",
+		"description": "Test Description",
 		"program_abbreviation": "TP1"
 	},
 	{
 		"program_name": "_Test Program 2",
 		"program_code": "_TP2",
+		"description": "Test Description",
 		"program_abbreviation": "TP2"
 	}
-]
+]
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.json b/erpnext/education/doctype/program_enrollment/program_enrollment.json
index 5f4621f..1d8a434 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.json
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 0, 
@@ -714,7 +715,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-08-21 16:15:35.014952", 
+ "modified": "2018-11-07 21:13:06.502279", 
  "modified_by": "Administrator", 
  "module": "Education", 
  "name": "Program Enrollment", 
@@ -739,6 +740,25 @@
    "share": 1, 
    "submit": 1, 
    "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 0, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "LMS User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 1, 
+   "write": 1
   }
  ], 
  "quick_entry": 0, 
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index 320a58a..22cca86 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -8,6 +8,7 @@
 from frappe.model.document import Document
 from frappe.desk.reportview import get_match_cond, get_filters_cond
 from frappe.utils import comma_and
+import erpnext.www.lms as lms
 
 class ProgramEnrollment(Document):
 	def validate(self):
@@ -16,11 +17,12 @@
 			self.student_name = frappe.db.get_value("Student", self.student, "title")
 		if not self.courses:
 			self.extend("courses", self.get_courses())
-	
+
 	def on_submit(self):
 		self.update_student_joining_date()
 		self.make_fee_records()
-	
+		self.create_course_enrollments()
+
 	def validate_duplication(self):
 		enrollment = frappe.get_all("Program Enrollment", filters={
 			"student": self.student,
@@ -31,11 +33,11 @@
 		})
 		if enrollment:
 			frappe.throw(_("Student is already enrolled."))
-	
+
 	def update_student_joining_date(self):
 		date = frappe.db.sql("select min(enrollment_date) from `tabProgram Enrollment` where student= %s", self.student)
 		frappe.db.set_value("Student", self.student, "joining_date", date)
-		
+
 	def make_fee_records(self):
 		from erpnext.education.api import get_fee_components
 		fee_list = []
@@ -54,7 +56,7 @@
 					"program_enrollment": self.name,
 					"components": fee_components
 				})
-				
+
 				fees.save()
 				fees.submit()
 				fee_list.append(fees.name)
@@ -66,6 +68,56 @@
 	def get_courses(self):
 		return frappe.db.sql('''select course, course_name from `tabProgram Course` where parent = %s and required = 1''', (self.program), as_dict=1)
 
+	def create_course_enrollments(self):
+		student = frappe.get_doc("Student", self.student)
+		program = frappe.get_doc("Program", self.program)
+		course_list = [course.course for course in program.get_all_children()]
+		for course_name in course_list:
+			student.enroll_in_course(course_name=course_name, program_enrollment=self.name)
+
+	def get_all_course_enrollments(self):
+		course_enrollment_names = frappe.get_list("Course Enrollment", filters={'program_enrollment': self.name})
+		return [frappe.get_doc('Course Enrollment', course_enrollment.name) for course_enrollment in course_enrollment_names]
+
+	def get_quiz_progress(self):
+		student = frappe.get_doc("Student", self.student)
+		quiz_progress = frappe._dict()
+		progress_list = []
+		for course_enrollment in self.get_all_course_enrollments():
+			course_progress = course_enrollment.get_progress(student)
+			for progress_item in course_progress:
+				if progress_item['content_type'] == "Quiz":
+					progress_item['course'] = course_enrollment.course
+					progress_list.append(progress_item)
+		if not progress_list:
+			return None
+		quiz_progress.quiz_attempt = progress_list
+		quiz_progress.name = self.program
+		quiz_progress.program = self.program
+		return quiz_progress
+
+	def get_program_progress(self):
+		import math
+		program = frappe.get_doc("Program", self.program)
+		program_progress = {}
+		progress = []
+		for course in program.get_all_children():
+			course_progress = lms.get_student_course_details(course.course, self.program)
+			is_complete = False
+			if course_progress['flag'] == "Completed":
+				is_complete = True
+			progress.append({'course_name': course.course_name, 'name': course.course, 'is_complete': is_complete})
+
+		program_progress['progress'] = progress
+		program_progress['name'] = self.program
+		program_progress['program'] = frappe.get_value("Program", self.program, 'program_name')
+
+		try:
+			program_progress['percentage'] = math.ceil((sum([item['is_complete'] for item in progress] * 100)/len(progress)))
+		except ZeroDivisionError:
+			program_progress['percentage'] = 0
+
+		return program_progress
 
 @frappe.whitelist()
 def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
@@ -102,11 +154,11 @@
 
 	return frappe.db.sql("""select
 			name, title from tabStudent
-		where 
+		where
 			name not in (%s)
-		and 
+		and
 			`%s` LIKE %s
-		order by 
+		order by
 			idx desc, name
 		limit %s, %s"""%(
 			", ".join(['%s']*len(students)), searchfield, "%s", "%s", "%s"),
diff --git a/erpnext/education/doctype/program_enrollment/test_program_enrollment.py b/erpnext/education/doctype/program_enrollment/test_program_enrollment.py
index c26e899..c6cbee1 100644
--- a/erpnext/education/doctype/program_enrollment/test_program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/test_program_enrollment.py
@@ -6,7 +6,21 @@
 import frappe
 import unittest
 
-# test_records = frappe.get_test_records('Program Enrollment')
+from erpnext.education.doctype.student.test_student import create_student
+from erpnext.education.doctype.student.test_student import get_student
+from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
+from erpnext.education.doctype.course_activity.test_course_activity import make_course_activity
 
 class TestProgramEnrollment(unittest.TestCase):
-	pass
+
+	def setUp(self):
+		create_student({"first_name": "_Test Name", "last_name": "_Test Last Name", "email": "_test_student@example.com"})
+		make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"])
+
+	def test_create_course_enrollments(self):
+		student = get_student("_test_student@example.com")
+		enrollment = student.enroll_in_program("_Test Program 1")
+		course_enrollments = student.get_all_course_enrollments()
+		self.assertTrue("_Test Course 1" in course_enrollments.keys())
+		self.assertTrue("_Test Course 2" in course_enrollments.keys())
+		frappe.db.rollback()
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py
index db23ac7..9f8f9f4 100644
--- a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py
+++ b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py
@@ -48,7 +48,7 @@
 			return students
 		else:
 			frappe.throw(_("No students Found"))
-			
+
 	def enroll_students(self):
 		total = len(self.students)
 		for i, stud in enumerate(self.students):
diff --git a/erpnext/education/doctype/question/__init__.py b/erpnext/education/doctype/question/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/question/__init__.py
diff --git a/erpnext/education/doctype/question/question.js b/erpnext/education/doctype/question/question.js
new file mode 100644
index 0000000..01b3091
--- /dev/null
+++ b/erpnext/education/doctype/question/question.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Question', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/question/question.json b/erpnext/education/doctype/question/question.json
new file mode 100644
index 0000000..14a9f3c
--- /dev/null
+++ b/erpnext/education/doctype/question/question.json
@@ -0,0 +1,167 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 1, 
+ "allow_rename": 0, 
+ "autoname": "format:QUESTION-{#####}", 
+ "beta": 0, 
+ "creation": "2018-10-01 15:58:00.696815", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "question", 
+   "fieldtype": "Small Text", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Question", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "description": "", 
+   "fetch_if_empty": 0, 
+   "fieldname": "options", 
+   "fieldtype": "Table", 
+   "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": "Options", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Options", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2019-04-22 14:02:08.140652", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Question", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Academics User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Instructor", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 0, 
+   "delete": 0, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "LMS User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 0
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 0, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/question/question.py b/erpnext/education/doctype/question/question.py
new file mode 100644
index 0000000..8cd2398
--- /dev/null
+++ b/erpnext/education/doctype/question/question.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.model.document import Document
+
+class Question(Document):
+
+	def validate(self):
+		self.check_at_least_one_option()
+		self.check_minimum_one_correct_answer()
+
+	def check_at_least_one_option(self):
+		if len(self.options) <= 1:
+			frappe.throw(_("A question must have more than one options"))
+		else:
+			pass
+
+	def check_minimum_one_correct_answer(self):
+		correct_options = [option.is_correct for option in self.options]
+		if bool(sum(correct_options)):
+			pass
+		else:
+			frappe.throw(_("A qustion must have at least one correct options"))
+
+	def get_answer(self):
+		options = self.options
+		answers = [item.name for item in options if item.is_correct == True]
+		if len(answers) == 0:
+			frappe.throw("No correct answer is set for {0}".format(self.name))
+			return None
+		elif len(answers) == 1:
+			return answers[0]
+		else:
+			return answers
\ No newline at end of file
diff --git a/erpnext/education/doctype/question/test_question.js b/erpnext/education/doctype/question/test_question.js
new file mode 100644
index 0000000..509939c
--- /dev/null
+++ b/erpnext/education/doctype/question/test_question.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: Question", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Question
+		() => frappe.tests.make('Question', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/question/test_question.py b/erpnext/education/doctype/question/test_question.py
new file mode 100644
index 0000000..552872e
--- /dev/null
+++ b/erpnext/education/doctype/question/test_question.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestQuestion(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/quiz/__init__.py b/erpnext/education/doctype/quiz/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/quiz/__init__.py
diff --git a/erpnext/education/doctype/quiz/quiz.js b/erpnext/education/doctype/quiz/quiz.js
new file mode 100644
index 0000000..122cf37
--- /dev/null
+++ b/erpnext/education/doctype/quiz/quiz.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quiz', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/quiz/quiz.json b/erpnext/education/doctype/quiz/quiz.json
new file mode 100644
index 0000000..f91bc0f
--- /dev/null
+++ b/erpnext/education/doctype/quiz/quiz.json
@@ -0,0 +1,299 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:title",
+ "beta": 0,
+ "creation": "2018-10-17 05:52:50.149904",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "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": "Title",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 1
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "question",
+   "fieldtype": "Table",
+   "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": "Question",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Quiz Question",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "quiz_configuration_section",
+   "fieldtype": "Section Break",
+   "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": "Quiz Configuration",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "passing_score",
+   "fieldtype": "Float",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Passing Score",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "1",
+   "description": "Enter 0 to waive limit",
+   "fieldname": "max_attempts",
+   "fieldtype": "Int",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Max Attempts",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "Last Highest Score",
+   "fieldname": "grading_basis",
+   "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": "Grading Basis",
+   "length": 0,
+   "no_copy": 0,
+   "options": "\nLast Attempt\nLast Highest Score",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-11-25 19:07:36.190116",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Quiz",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz/quiz.py b/erpnext/education/doctype/quiz/quiz.py
new file mode 100644
index 0000000..6da50a6
--- /dev/null
+++ b/erpnext/education/doctype/quiz/quiz.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class Quiz(Document):
+
+	def validate_quiz_attempts(self, enrollment, quiz_name):
+		if self.max_attempts > 0:
+			try:
+				if len(frappe.get_all("Quiz Activity", {'enrollment': enrollment.name, 'quiz': quiz_name})) >= self.max_attempts:
+					frappe.throw('Maximum attempts reached!')
+			except Exception as e:
+				pass
+
+
+	def evaluate(self, response_dict, quiz_name):
+		# self.validate_quiz_attempts(enrollment, quiz_name)
+		questions = [frappe.get_doc('Question', question.question_link) for question in self.question]
+		answers = {q.name:q.get_answer() for q in questions}
+		correct_answers = {}
+		for key in answers:
+			try:
+				if isinstance(response_dict[key], list):
+					result = compare_list_elementwise(response_dict[key], answers[key])
+				else:
+					result = (response_dict[key] == answers[key])
+			except:
+				result = False
+			correct_answers[key] = result
+		score = (sum(correct_answers.values()) * 100 ) / len(answers)
+		if score >= self.passing_score:
+			status = "Pass"
+		else:
+			status = "Fail"
+		return correct_answers, score, status
+
+
+	def get_questions(self):
+		quiz_question = self.get_all_children()
+		if quiz_question:
+			questions = [frappe.get_doc('Question', question.question_link).as_dict() for question in quiz_question]
+			for question in questions:
+				correct_options = [option.is_correct for option in question.options]
+				if sum(correct_options) > 1:
+					question['type'] = "MultipleChoice"
+				else:
+					question['type'] = "SingleChoice"
+			return questions
+		else:
+			return None
+
+def compare_list_elementwise(*args):
+	try:
+		if all(len(args[0]) == len(_arg) for _arg in args[1:]):
+			return all(all([element in (item) for element in args[0]]) for item in args[1:])
+		else:
+			return False
+	except TypeError:
+		frappe.throw("Compare List function takes on list arguments")
+
diff --git a/erpnext/education/doctype/quiz/test_quiz.js b/erpnext/education/doctype/quiz/test_quiz.js
new file mode 100644
index 0000000..147d139
--- /dev/null
+++ b/erpnext/education/doctype/quiz/test_quiz.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: Quiz", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Quiz
+		() => frappe.tests.make('Quiz', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/quiz/test_quiz.py b/erpnext/education/doctype/quiz/test_quiz.py
new file mode 100644
index 0000000..344fd54
--- /dev/null
+++ b/erpnext/education/doctype/quiz/test_quiz.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestQuiz(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/quiz_activity/__init__.py b/erpnext/education/doctype/quiz_activity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/quiz_activity/__init__.py
diff --git a/erpnext/education/doctype/quiz_activity/quiz_activity.js b/erpnext/education/doctype/quiz_activity/quiz_activity.js
new file mode 100644
index 0000000..f6ba12c
--- /dev/null
+++ b/erpnext/education/doctype/quiz_activity/quiz_activity.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quiz Activity', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/quiz_activity/quiz_activity.json b/erpnext/education/doctype/quiz_activity/quiz_activity.json
new file mode 100644
index 0000000..e78db42
--- /dev/null
+++ b/erpnext/education/doctype/quiz_activity/quiz_activity.json
@@ -0,0 +1,490 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "format:EDU-QA-{YYYY}-{#####}",
+ "beta": 1,
+ "creation": "2018-10-15 15:48:40.482821",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "enrollment",
+   "fieldtype": "Link",
+   "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": "Enrollment",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Course Enrollment",
+   "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": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "enrollment.student",
+   "fieldname": "student",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Student",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Student",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 1,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "enrollment.course",
+   "fieldname": "course",
+   "fieldtype": "Link",
+   "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": "Course",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Course",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 1,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "quiz",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Quiz",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Quiz",
+   "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": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "status",
+   "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": "Status",
+   "length": 0,
+   "no_copy": 0,
+   "options": "\nPass\nFail",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 1,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "result",
+   "fieldtype": "Table",
+   "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": "Result",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Quiz Result",
+   "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": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "activity_date",
+   "fieldtype": "Data",
+   "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": "Activity Date",
+   "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": 1,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "score",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Score",
+   "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": 1,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-11-25 19:05:52.434437",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Quiz Activity",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz_activity/quiz_activity.py b/erpnext/education/doctype/quiz_activity/quiz_activity.py
new file mode 100644
index 0000000..24c7175
--- /dev/null
+++ b/erpnext/education/doctype/quiz_activity/quiz_activity.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class QuizActivity(Document):
+	pass
diff --git a/erpnext/education/doctype/quiz_activity/test_quiz_activity.js b/erpnext/education/doctype/quiz_activity/test_quiz_activity.js
new file mode 100644
index 0000000..94b5ab7
--- /dev/null
+++ b/erpnext/education/doctype/quiz_activity/test_quiz_activity.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: Quiz Activity", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Quiz Activity
+		() => frappe.tests.make('Quiz Activity', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/quiz_activity/test_quiz_activity.py b/erpnext/education/doctype/quiz_activity/test_quiz_activity.py
new file mode 100644
index 0000000..fb0425d
--- /dev/null
+++ b/erpnext/education/doctype/quiz_activity/test_quiz_activity.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestQuizActivity(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/quiz_question/__init__.py b/erpnext/education/doctype/quiz_question/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/quiz_question/__init__.py
diff --git a/erpnext/education/doctype/quiz_question/quiz_question.json b/erpnext/education/doctype/quiz_question/quiz_question.json
new file mode 100644
index 0000000..3857c5c
--- /dev/null
+++ b/erpnext/education/doctype/quiz_question/quiz_question.json
@@ -0,0 +1,110 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2018-10-17 06:13:00.098883", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "question_link", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Question Link", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Question", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_from": "question_link.question", 
+   "fieldname": "question", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Question", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2018-10-18 15:35:12.195250", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Quiz Question", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz_question/quiz_question.py b/erpnext/education/doctype/quiz_question/quiz_question.py
new file mode 100644
index 0000000..317e75b
--- /dev/null
+++ b/erpnext/education/doctype/quiz_question/quiz_question.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class QuizQuestion(Document):
+	pass
diff --git a/erpnext/education/doctype/quiz_result/__init__.py b/erpnext/education/doctype/quiz_result/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/quiz_result/__init__.py
diff --git a/erpnext/education/doctype/quiz_result/quiz_result.js b/erpnext/education/doctype/quiz_result/quiz_result.js
new file mode 100644
index 0000000..a018749
--- /dev/null
+++ b/erpnext/education/doctype/quiz_result/quiz_result.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quiz Result', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/quiz_result/quiz_result.json b/erpnext/education/doctype/quiz_result/quiz_result.json
new file mode 100644
index 0000000..86505ac
--- /dev/null
+++ b/erpnext/education/doctype/quiz_result/quiz_result.json
@@ -0,0 +1,145 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2018-10-15 15:52:25.766374", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "question", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Question", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Question", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 1, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "selected_option", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Selected Option", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 1, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "quiz_result", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Result", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "\nCorrect\nWrong", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 1, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2019-03-27 17:58:54.388848", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Quiz Result", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz_result/quiz_result.py b/erpnext/education/doctype/quiz_result/quiz_result.py
new file mode 100644
index 0000000..a4fd9f0
--- /dev/null
+++ b/erpnext/education/doctype/quiz_result/quiz_result.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class QuizResult(Document):
+	pass
diff --git a/erpnext/education/doctype/quiz_result/test_quiz_result.js b/erpnext/education/doctype/quiz_result/test_quiz_result.js
new file mode 100644
index 0000000..43f53a1
--- /dev/null
+++ b/erpnext/education/doctype/quiz_result/test_quiz_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: Quiz Result", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Quiz Result
+		() => frappe.tests.make('Quiz Result', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/quiz_result/test_quiz_result.py b/erpnext/education/doctype/quiz_result/test_quiz_result.py
new file mode 100644
index 0000000..86ee52d
--- /dev/null
+++ b/erpnext/education/doctype/quiz_result/test_quiz_result.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestQuizResult(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/student/student.json b/erpnext/education/doctype/student/student.json
index af6c8b1..bee915e 100644
--- a/erpnext/education/doctype/student/student.json
+++ b/erpnext/education/doctype/student/student.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
@@ -20,6 +21,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_1", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -52,6 +54,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "default": "1", 
+   "fetch_if_empty": 0, 
    "fieldname": "enabled", 
    "fieldtype": "Check", 
    "hidden": 0, 
@@ -84,6 +87,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_3", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -115,6 +119,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "first_name", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -147,6 +152,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "middle_name", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -179,6 +185,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "last_name", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -211,6 +218,41 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "user", 
+   "fieldtype": "Link", 
+   "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": "User ID", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "User", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "column_break_4", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -243,6 +285,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "default": "", 
+   "fetch_if_empty": 0, 
    "fieldname": "naming_series", 
    "fieldtype": "Select", 
    "hidden": 0, 
@@ -276,6 +319,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "student_email_id", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -295,7 +339,7 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 0, 
+   "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
    "translatable": 0, 
@@ -308,6 +352,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "student_mobile_number", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -342,6 +387,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "default": "Today", 
+   "fetch_if_empty": 0, 
    "fieldname": "joining_date", 
    "fieldtype": "Date", 
    "hidden": 0, 
@@ -374,6 +420,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "image", 
    "fieldtype": "Attach Image", 
    "hidden": 1, 
@@ -408,6 +455,7 @@
    "collapsible": 0, 
    "collapsible_depends_on": "", 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_7", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -440,6 +488,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "date_of_birth", 
    "fieldtype": "Date", 
    "hidden": 0, 
@@ -472,6 +521,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "blood_group", 
    "fieldtype": "Select", 
    "hidden": 0, 
@@ -505,6 +555,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "column_break_3", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -536,6 +587,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "gender", 
    "fieldtype": "Select", 
    "hidden": 0, 
@@ -569,6 +621,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "nationality", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -602,6 +655,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "student_applicant", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -635,6 +689,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_22", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -667,6 +722,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "address_line_1", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -699,6 +755,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "address_line_2", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -731,6 +788,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "pincode", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -763,6 +821,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "column_break_20", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -794,6 +853,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "city", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -826,6 +886,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "state", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -858,6 +919,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_18", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -890,6 +952,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "guardians", 
    "fieldtype": "Table", 
    "hidden": 0, 
@@ -923,6 +986,7 @@
    "bold": 0, 
    "collapsible": 1, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_20", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -956,6 +1020,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "siblings", 
    "fieldtype": "Table", 
    "hidden": 0, 
@@ -989,6 +1054,7 @@
    "bold": 0, 
    "collapsible": 1, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "exit", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -1021,6 +1087,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "date_of_leaving", 
    "fieldtype": "Date", 
    "hidden": 0, 
@@ -1053,6 +1120,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "leaving_certificate_number", 
    "fieldtype": "Data", 
    "hidden": 0, 
@@ -1085,6 +1153,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "column_break_31", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -1116,6 +1185,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "reason_for_leaving", 
    "fieldtype": "Text", 
    "hidden": 0, 
@@ -1149,6 +1219,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "default": "", 
+   "fetch_if_empty": 0, 
    "fieldname": "title", 
    "fieldtype": "Data", 
    "hidden": 1, 
@@ -1176,18 +1247,16 @@
   }
  ], 
  "has_web_view": 0, 
- "hide_heading": 0, 
  "hide_toolbar": 0, 
  "idx": 0, 
  "image_field": "image", 
- "image_view": 0, 
  "in_create": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-08-21 14:44:35.278833", 
+ "modified": "2019-04-10 17:46:26.893020", 
  "modified_by": "Administrator", 
  "module": "Education", 
  "name": "Student", 
@@ -1231,11 +1300,48 @@
    "share": 1, 
    "submit": 0, 
    "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 0, 
+   "delete": 0, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Student", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 0
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 0, 
+   "delete": 0, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "LMS User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 0
   }
  ], 
  "quick_entry": 0, 
  "read_only": 0, 
- "read_only_onload": 0, 
  "restrict_to_domain": "Education", 
  "show_name_in_global_search": 1, 
  "sort_field": "modified", 
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index 53bf6f7..cf8407c 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -7,7 +7,7 @@
 from frappe.model.document import Document
 from frappe import _
 from frappe.desk.form.linked_with import get_linked_doctypes
-
+from erpnext.education.utils import check_content_completion, check_quiz_completion
 class Student(Document):
 	def validate(self):
 		self.title = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name]))
@@ -39,11 +39,99 @@
 		if student:
 			frappe.throw(_("Student {0} exist against student applicant {1}").format(student[0][0], self.student_applicant))
 
+	def after_insert(self):
+		self.create_student_user()
+
+	def create_student_user(self):
+		"""Create a website user for student creation if not already exists"""
+		if not frappe.db.exists("User", self.student_email_id):
+			student_user = frappe.get_doc({
+				'doctype':'User',
+				'first_name': self.first_name,
+				'last_name': self.last_name,
+				'email': self.student_email_id,
+				'gender': self.gender,
+				'send_welcome_email': 1,
+				'user_type': 'Website User'
+				})
+			student_user.add_roles("Student", "LMS User")
+			student_user.save()
+			update_password_link = student_user.reset_password()
+
 	def update_applicant_status(self):
 		"""Updates Student Applicant status to Admitted"""
 		if self.student_applicant:
 			frappe.db.set_value("Student Applicant", self.student_applicant, "application_status", "Admitted")
 
+	def get_all_course_enrollments(self):
+		"""Returns a list of course enrollments linked with the current student"""
+		course_enrollments = frappe.get_all("Course Enrollment", filters={"student": self.name}, fields=['course', 'name'])
+		if not course_enrollments:
+			return None
+		else:
+			enrollments = {item['course']:item['name'] for item in course_enrollments}
+			return enrollments
+
+	def get_program_enrollments(self):
+		"""Returns a list of course enrollments linked with the current student"""
+		program_enrollments = frappe.get_all("Program Enrollment", filters={"student": self.name}, fields=['program'])
+		if not program_enrollments:
+			return None
+		else:
+			enrollments = [item['program'] for item in program_enrollments]
+			return enrollments
+
+	def get_topic_progress(self, course_enrollment_name, topic):
+		"""
+		Get Progress Dictionary of a student for a particular topic
+			:param self: Student Object
+			:param course_enrollment_name: Name of the Course Enrollment
+			:param topic: Topic DocType Object
+		"""
+		contents = topic.get_contents()
+		progress = []
+		for content in contents:
+			if content.doctype in ('Article', 'Video'):
+				status = check_content_completion(content.name, content.doctype, course_enrollment_name)
+				progress.append({'content': content.name, 'content_type': content.doctype, 'is_complete': status})
+			elif content.doctype == 'Quiz':
+				status, score, result = check_quiz_completion(content, course_enrollment_name)
+				progress.append({'content': content.name, 'content_type': content.doctype, 'is_complete': status, 'score': score, 'result': result})
+		return progress
+
+	def enroll_in_program(self, program_name):
+		try:
+			enrollment = frappe.get_doc({
+					"doctype": "Program Enrollment",
+					"student": self.name,
+					"academic_year": frappe.get_last_doc("Academic Year").name,
+					"program": program_name,
+					"enrollment_date": frappe.utils.datetime.datetime.now()
+				})
+			enrollment.save(ignore_permissions=True)
+		except frappe.exceptions.ValidationError:
+			enrollment_name = frappe.get_list("Program Enrollment", filters={"student": self.name, "Program": program_name})[0].name
+			return frappe.get_doc("Program Enrollment", enrollment_name)
+		else:
+			enrollment.submit()
+			return enrollment
+
+	def enroll_in_course(self, course_name, program_enrollment, enrollment_date=frappe.utils.datetime.datetime.now()):
+		try:
+			enrollment = frappe.get_doc({
+					"doctype": "Course Enrollment",
+					"student": self.name,
+					"course": course_name,
+					"program_enrollment": program_enrollment,
+					"enrollment_date": enrollment_date
+				})
+			enrollment.save(ignore_permissions=True)
+		except frappe.exceptions.ValidationError:
+			enrollment_name = frappe.get_list("Course Enrollment", filters={"student": self.name, "course": course_name, "program_enrollment": program_enrollment})[0].name
+			return frappe.get_doc("Program Enrollment", enrollment_name)
+		else:
+			return enrollment
+
 def get_timeline_data(doctype, name):
 	'''Return timeline for attendance'''
 	return dict(frappe.db.sql('''select unix_timestamp(`date`), count(*)
diff --git a/erpnext/education/doctype/student/student_dashboard.py b/erpnext/education/doctype/student/student_dashboard.py
index d86f4f2..0cbd17b 100644
--- a/erpnext/education/doctype/student/student_dashboard.py
+++ b/erpnext/education/doctype/student/student_dashboard.py
@@ -9,7 +9,7 @@
 		'transactions': [
 			{
 				'label': _('Admission'),
-				'items': ['Program Enrollment']
+				'items': ['Program Enrollment', 'Course Enrollment']
 			},
 			{
 				'label': _('Student Activity'),
@@ -20,6 +20,10 @@
 				'items': ['Assessment Result']
 			},
 			{
+				'label': _('Student LMS Activity'),
+				'items': ['Course Activity', 'Quiz Activity' ]
+			},
+			{
 				'label': _('Attendance'),
 				'items': ['Student Attendance', 'Student Leave Application']
 			},
diff --git a/erpnext/education/doctype/student/test_records.json b/erpnext/education/doctype/student/test_records.json
index 6acc4b6..8ad3afa 100644
--- a/erpnext/education/doctype/student/test_records.json
+++ b/erpnext/education/doctype/student/test_records.json
@@ -6,6 +6,7 @@
 		"program": "TC101",
 		"date_of_birth": "2000-01-01",
 		"gender": "Male",
+		"student_email_id": "_test_student@example.com",
 		"blood_group": "A+"
 
 	},
@@ -16,6 +17,7 @@
 		"program": "TC101",
 		"date_of_birth": "2000-01-01",
 		"gender": "Male",
+		"student_email_id": "_test_student_1@example.com",
 		"blood_group": "A+"
 
 	},
@@ -25,27 +27,8 @@
 		"last_name": "Name 2",
 		"program": "TC101",
 		"date_of_birth": "2000-01-01",
-		"gender": "Male",
-		"blood_group": "A+"
-
-	},
-	{
-		"first_name": "_Test",
-		"middle_name": "Student",
-		"last_name": "Name 3",
-		"program": "TC101",
-		"date_of_birth": "2000-01-01",
-		"gender": "Male",
-		"blood_group": "A+"
-
-	},
-	{
-		"first_name": "_Test",
-		"middle_name": "Student",
-		"last_name": "Name 4",
-		"program": "TC101",
-		"date_of_birth": "2000-01-01",
-		"gender": "Male",
+		"gender": "Female",
+		"student_email_id": "_test_student_2@example.com",
 		"blood_group": "A+"
 
 	}
diff --git a/erpnext/education/doctype/student/test_student.py b/erpnext/education/doctype/student/test_student.py
index cc6537f..8610edb 100644
--- a/erpnext/education/doctype/student/test_student.py
+++ b/erpnext/education/doctype/student/test_student.py
@@ -2,11 +2,60 @@
 # Copyright (c) 2015, Frappe Technologies and Contributors
 # See license.txt
 from __future__ import unicode_literals
+from frappe.test_runner import make_test_records
+from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
+from erpnext.education.doctype.course.test_course import make_course
 
 import frappe
 import unittest
 
-# test_records = frappe.get_test_records('Student')
-
+test_records = frappe.get_test_records('Student')
 class TestStudent(unittest.TestCase):
-	pass
+	def setUp(self):
+		create_student({"first_name": "_Test Name", "last_name": "_Test Last Name", "email": "_test_student@example.com"})
+		make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"])
+
+	def test_create_student_user(self):
+		self.assertTrue(bool(frappe.db.exists("User", "_test_student@example.com")))
+		frappe.db.rollback()
+
+	def test_enroll_in_program(self):
+		student = get_student("_test_student@example.com")
+		enrollment = student.enroll_in_program("_Test Program 1")
+		test_enrollment = frappe.get_all("Program Enrollment", filters={"student": student.name, "Program": "_Test Program 1"})
+		self.assertTrue(len(test_enrollment))
+		self.assertEqual(test_enrollment[0]['name'], enrollment.name)
+		frappe.db.rollback()
+
+	def test_get_program_enrollments(self):
+		student = get_student("_test_student@example.com")
+		enrollment = student.enroll_in_program("_Test Program 1")
+		program_enrollments = student.get_program_enrollments()
+		self.assertTrue("_Test Program 1" in program_enrollments)
+		frappe.db.rollback()
+
+	def test_get_all_course_enrollments(self):
+		student = get_student("_test_student@example.com")
+		enrollment = student.enroll_in_program("_Test Program 1")
+		course_enrollments = student.get_all_course_enrollments()
+		self.assertTrue("_Test Course 1" in course_enrollments.keys())
+		self.assertTrue("_Test Course 2" in course_enrollments.keys())
+		frappe.db.rollback()
+
+def create_student(student_dict):
+	student = get_student(student_dict['email'])
+	if not student:
+		student = frappe.get_doc({
+			"doctype": "Student",
+			"first_name": student_dict['first_name'],
+			"last_name": student_dict['last_name'],
+			"student_email_id": student_dict['email']
+		}).insert()
+	return student
+
+def get_student(email):
+	try:
+		student_id = frappe.get_all("Student", {"student_email_id": email}, ["name"])[0].name
+		return frappe.get_doc("Student", student_id)
+	except IndexError:
+		return None
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_applicant/student_applicant.json b/erpnext/education/doctype/student_applicant/student_applicant.json
index 297821f..71134e0 100644
--- a/erpnext/education/doctype/student_applicant/student_applicant.json
+++ b/erpnext/education/doctype/student_applicant/student_applicant.json
@@ -150,6 +150,39 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "default": "0", 
+   "fieldname": "lms_only", 
+   "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": "LMS Only", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "paid", 
    "fieldtype": "Check", 
    "hidden": 0, 
@@ -627,7 +660,7 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 0, 
+   "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
    "translatable": 0, 
@@ -1160,7 +1193,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-08-21 14:44:30.146264", 
+ "modified": "2018-10-05 13:15:59.283862", 
  "modified_by": "Administrator", 
  "module": "Education", 
  "name": "Student Applicant", 
diff --git a/erpnext/education/doctype/topic/__init__.py b/erpnext/education/doctype/topic/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/topic/__init__.py
diff --git a/erpnext/education/doctype/topic/test_topic.js b/erpnext/education/doctype/topic/test_topic.js
new file mode 100644
index 0000000..4460b79
--- /dev/null
+++ b/erpnext/education/doctype/topic/test_topic.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: Topic", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Topic
+		() => frappe.tests.make('Topic', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/topic/test_topic.py b/erpnext/education/doctype/topic/test_topic.py
new file mode 100644
index 0000000..d03db1c
--- /dev/null
+++ b/erpnext/education/doctype/topic/test_topic.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestTopic(unittest.TestCase):
+	def setUp(self):
+		make_topic_and_linked_content("_Test Topic 1", [{"type":"Article", "name": "_Test Article 1"}])
+
+	def test_get_contents(self):
+		topic = frappe.get_doc("Topic", "_Test Topic 1")
+		contents = topic.get_contents()
+		self.assertEqual(contents[0].doctype, "Article")
+		self.assertEqual(contents[0].name, "_Test Article 1")
+		frappe.db.rollback()
+
+def make_topic(name):
+	try:
+		topic = frappe.get_doc("Topic", name)
+	except frappe.DoesNotExistError:
+		topic = frappe.get_doc({
+			"doctype": "Topic",
+			"topic_name": name,
+			"topic_code": name,
+		}).insert()
+	return topic.name
+
+def make_topic_and_linked_content(topic_name, content_dict_list):
+	try:
+		topic = frappe.get_doc("Topic", topic_name)
+	except frappe.DoesNotExistError:
+		make_topic(topic_name)
+		topic = frappe.get_doc("Topic", topic_name)
+	content_list = [make_content(content['type'], content['name']) for content in content_dict_list]
+	for content in content_list:
+		topic.append("topic_content", {"content": content.title, "content_type": content.doctype})
+	topic.save()
+	return topic
+
+
+def make_content(type, name):
+	try:
+		content = frappe.get_doc(type, name)
+	except frappe.DoesNotExistError:
+		content = frappe.get_doc({"doctype": type, "title": name}).insert()
+	return content
diff --git a/erpnext/education/doctype/topic/topic.js b/erpnext/education/doctype/topic/topic.js
new file mode 100644
index 0000000..695c174
--- /dev/null
+++ b/erpnext/education/doctype/topic/topic.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Topic', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/topic/topic.json b/erpnext/education/doctype/topic/topic.json
new file mode 100644
index 0000000..f47b10d
--- /dev/null
+++ b/erpnext/education/doctype/topic/topic.json
@@ -0,0 +1,297 @@
+{
+ "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "field:topic_code", 
+ "beta": 0, 
+ "creation": "2018-12-12 11:37:39.917760", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "topic_name", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Name", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "column_break_2", 
+   "fieldtype": "Column Break", 
+   "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, 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "topic_code", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Code", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 1
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "section_break_4", 
+   "fieldtype": "Section Break", 
+   "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, 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "topic_content", 
+   "fieldtype": "Table", 
+   "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": "Topic Content", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Topic Content", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fetch_if_empty": 0, 
+   "fieldname": "hero_image", 
+   "fieldtype": "Attach Image", 
+   "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": "Hero Image", 
+   "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, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "menu_index": 0, 
+ "modified": "2019-04-09 11:35:34.137040", 
+ "modified_by": "Administrator", 
+ "module": "Education", 
+ "name": "Topic", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Administrator", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Instructor", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/topic/topic.py b/erpnext/education/doctype/topic/topic.py
new file mode 100644
index 0000000..339fc7d
--- /dev/null
+++ b/erpnext/education/doctype/topic/topic.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class Topic(Document):
+	def get_contents(self):
+		try:
+			topic_content_list = self.get_all_children()
+			content_data = [frappe.get_doc(topic_content.content_type, topic_content.content) for topic_content in topic_content_list]
+		except Exception as e:
+			frappe.log_error(frappe.get_traceback())
+			return None
+		return content_data
\ No newline at end of file
diff --git a/erpnext/education/doctype/topic_content/__init__.py b/erpnext/education/doctype/topic_content/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/topic_content/__init__.py
diff --git a/erpnext/education/doctype/topic_content/test_topic_content.js b/erpnext/education/doctype/topic_content/test_topic_content.js
new file mode 100644
index 0000000..bf9a62d
--- /dev/null
+++ b/erpnext/education/doctype/topic_content/test_topic_content.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: Topic Content", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Topic Content
+		() => frappe.tests.make('Topic Content', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/topic_content/test_topic_content.py b/erpnext/education/doctype/topic_content/test_topic_content.py
new file mode 100644
index 0000000..cf304f6
--- /dev/null
+++ b/erpnext/education/doctype/topic_content/test_topic_content.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestTopicContent(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/topic_content/topic_content.js b/erpnext/education/doctype/topic_content/topic_content.js
new file mode 100644
index 0000000..9cda0ca
--- /dev/null
+++ b/erpnext/education/doctype/topic_content/topic_content.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Topic Content', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/topic_content/topic_content.json b/erpnext/education/doctype/topic_content/topic_content.json
new file mode 100644
index 0000000..5220788
--- /dev/null
+++ b/erpnext/education/doctype/topic_content/topic_content.json
@@ -0,0 +1,140 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-12-12 11:42:57.987434",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "content_type",
+   "fieldtype": "Select",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Content Type",
+   "length": 0,
+   "no_copy": 0,
+   "options": "\nArticle\nVideo\nQuiz",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break",
+   "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,
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "content",
+   "fieldtype": "Dynamic Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Content",
+   "length": 0,
+   "no_copy": 0,
+   "options": "content_type",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2018-12-12 11:46:46.112018",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Topic Content",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/topic_content/topic_content.py b/erpnext/education/doctype/topic_content/topic_content.py
new file mode 100644
index 0000000..9b2c90b
--- /dev/null
+++ b/erpnext/education/doctype/topic_content/topic_content.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class TopicContent(Document):
+	pass
diff --git a/erpnext/education/doctype/video/__init__.py b/erpnext/education/doctype/video/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/education/doctype/video/__init__.py
diff --git a/erpnext/education/doctype/video/test_video.js b/erpnext/education/doctype/video/test_video.js
new file mode 100644
index 0000000..a82a221
--- /dev/null
+++ b/erpnext/education/doctype/video/test_video.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: Video", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Video
+		() => frappe.tests.make('Video', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/education/doctype/video/test_video.py b/erpnext/education/doctype/video/test_video.py
new file mode 100644
index 0000000..ecb09a2
--- /dev/null
+++ b/erpnext/education/doctype/video/test_video.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestVideo(unittest.TestCase):
+	pass
diff --git a/erpnext/education/doctype/video/video.js b/erpnext/education/doctype/video/video.js
new file mode 100644
index 0000000..c35c19b
--- /dev/null
+++ b/erpnext/education/doctype/video/video.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Video', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/education/doctype/video/video.json b/erpnext/education/doctype/video/video.json
new file mode 100644
index 0000000..cc8f718
--- /dev/null
+++ b/erpnext/education/doctype/video/video.json
@@ -0,0 +1,262 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "field:title",
+ "beta": 0,
+ "creation": "2018-10-17 05:47:13.087395",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "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": "Title",
+   "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,
+   "translatable": 0,
+   "unique": 1
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "description",
+   "fieldtype": "Text Editor",
+   "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": "Description",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "duration",
+   "fieldtype": "Data",
+   "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": "Duration",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "url",
+   "fieldtype": "Data",
+   "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": "URL",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "publish_date",
+   "fieldtype": "Date",
+   "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": "Publish Date",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-11-25 19:07:17.134288",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Video",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "LMS User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 0
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/video/video.py b/erpnext/education/doctype/video/video.py
new file mode 100644
index 0000000..b19f812
--- /dev/null
+++ b/erpnext/education/doctype/video/video.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class Video(Document):
+
+
+	def get_video(self):
+		pass
diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py
index 1b93c9d..bf766ad 100644
--- a/erpnext/education/utils.py
+++ b/erpnext/education/utils.py
@@ -2,7 +2,7 @@
 # Copyright (c) 2015, Frappe Technologies and contributors
 # For lice
 
-from __future__ import unicode_literals
+from __future__ import unicode_literals, division
 import frappe
 from frappe import _
 
@@ -10,19 +10,19 @@
 
 def validate_overlap_for(doc, doctype, fieldname, value=None):
 	"""Checks overlap for specified field.
-	
-	:param fieldname: Checks Overlap for this field 
+
+	:param fieldname: Checks Overlap for this field
 	"""
-	
+
 	existing = get_overlap_for(doc, doctype, fieldname, value)
 	if existing:
 		frappe.throw(_("This {0} conflicts with {1} for {2} {3}").format(doc.doctype, existing.name,
 			doc.meta.get_label(fieldname) if not value else fieldname , value or doc.get(fieldname)), OverlapError)
-	
+
 def get_overlap_for(doc, doctype, fieldname, value=None):
 	"""Returns overlaping document for specified field.
-	
-	:param fieldname: Checks Overlap for this field 
+
+	:param fieldname: Checks Overlap for this field
 	"""
 
 	existing = frappe.db.sql("""select name, from_time, to_time from `tab{0}`
@@ -42,7 +42,8 @@
 		}, as_dict=True)
 
 	return existing[0] if existing else None
-	
+
+
 def validate_duplicate_student(students):
 	unique_students= []
 	for stud in students:
@@ -51,3 +52,93 @@
 				.format(stud.student, stud.student_name, unique_students.index(stud.student)+1, stud.idx))
 		else:
 			unique_students.append(stud.student)
+
+		return None
+
+# LMS Utils
+def get_current_student():
+	"""
+	Returns student user name, example EDU-STU-2018-00001 (Based on the naming series).
+	Takes email from from frappe.session.user
+	"""
+	email = frappe.session.user
+	if email in ('Administrator', 'Guest'):
+		return None
+	try:
+		student_id = frappe.get_all("Student", {"student_email_id": email}, ["name"])[0].name
+		return frappe.get_doc("Student", student_id)
+	except (IndexError, frappe.DoesNotExistError):
+		return None
+
+def check_super_access():
+	current_user = frappe.get_doc('User', frappe.session.user)
+	roles = set([role.role for role in current_user.roles])
+	return bool(roles & {'Administrator', 'Instructor', 'Education Manager', 'System Manager', 'Academic User'})
+
+def get_program_enrollment(program_name):
+	"""
+	Function to get program enrollments for a particular student for a program
+	"""
+	student = get_current_student()
+	if not student:
+		return None
+	else:
+		enrollment = frappe.get_all("Program Enrollment", filters={'student':student.name, 'program': program_name})
+		if enrollment:
+			return enrollment[0].name
+		else:
+			return None
+
+def get_program_and_enrollment_status(program_name):
+	program = frappe.get_doc('Program', program_name)
+	is_enrolled = bool(get_program_enrollment(program_name)) or check_super_access()
+	return {'program': program, 'is_enrolled': is_enrolled}
+
+def get_course_enrollment(course_name):
+	student = get_current_student()
+	if not student:
+		return None
+	enrollment_name = frappe.get_all("Course Enrollment", filters={'student': student.name, 'course':course_name})
+	try:
+		name = enrollment_name[0].name
+		enrollment = frappe.get_doc("Course Enrollment", name)
+		return enrollment
+	except:
+		return None
+
+def create_student_from_current_user():
+	user = frappe.get_doc("User", frappe.session.user)
+	student = frappe.get_doc({
+		"doctype": "Student",
+		"first_name": user.first_name,
+		"last_name": user.last_name,
+		"student_email_id": user.email,
+		"user": frappe.session.user
+		})
+	student.save(ignore_permissions=True)
+	return student
+
+def enroll_in_course(course_name, program_name):
+	student = get_current_student()
+	return student.enroll_in_course(course_name=course_name, program_enrollment=get_program_enrollment(program_name))
+
+def check_content_completion(content_name, content_type, enrollment_name):
+	activity = frappe.get_all("Course Activity", filters={'enrollment': enrollment_name, 'content_type': content_type, 'content': content_name})
+	if activity:
+		return True
+	else:
+		return False
+
+def check_quiz_completion(quiz, enrollment_name):
+	attempts = frappe.get_all("Quiz Activity", filters={'enrollment': enrollment_name, 'quiz': quiz.name}, fields=["name", "activity_date", "score", "status"])
+	status = False if quiz.max_attempts == 0 else bool(len(attempts) == quiz.max_attempts)
+	score = None
+	result = None
+	if attempts:
+		if quiz.grading_basis == 'Last Highest Score':
+			attempts = sorted(attempts, key = lambda i: int(i.score), reverse=True)
+		score = attempts[0]['score']
+		result = attempts[0]['status']
+		if result == 'Pass':
+			status = True
+	return status, score, result
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 608e8b2..ecc9611 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -11,6 +11,7 @@
 app_license = "GNU General Public License (v3)"
 source_link = "https://github.com/frappe/erpnext"
 
+
 develop_version = '12.x.x-develop'
 
 error_report_email = "support@erpnext.com"
@@ -168,6 +169,10 @@
 	{'role': 'Student', 'doctype':'Student', 'email_field': 'student_email_id'},
 ]
 
+role_home_page = {
+	"LMS User": "/lms"
+}
+
 has_website_permission = {
 	"Sales Order": "erpnext.controllers.website_list_for_contact.has_website_permission",
 	"Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission",
diff --git a/erpnext/hr/doctype/designation/designation.json b/erpnext/hr/doctype/designation/designation.json
index 1d4a3cf..4c3888b 100644
--- a/erpnext/hr/doctype/designation/designation.json
+++ b/erpnext/hr/doctype/designation/designation.json
@@ -1,119 +1,194 @@
 {
- "allow_copy": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:designation_name", 
- "beta": 0, 
- "creation": "2013-01-10 16:34:13", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 0, 
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:designation_name",
+ "beta": 0,
+ "creation": "2013-01-10 16:34:13",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 0,
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "designation_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Designation", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "designation_name", 
-   "oldfieldtype": "Data", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "designation_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Designation",
+   "length": 0,
+   "no_copy": 0,
+   "oldfieldname": "designation_name",
+   "oldfieldtype": "Data",
+   "permlevel": 0,
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Text", 
-   "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": "Description", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "description",
+   "fieldtype": "Text",
+   "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": "Description",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "required_skills_section",
+   "fieldtype": "Section Break",
+   "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": "Required Skills",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "skills",
+   "fieldtype": "Table",
+   "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": "Skills",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Designation Skill",
+   "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,
+   "translatable": 0,
    "unique": 0
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "icon": "fa fa-bookmark", 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2017-02-17 16:53:43.895882", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Designation", 
- "owner": "Administrator", 
+ ],
+ "has_web_view": 0,
+ "hide_toolbar": 0,
+ "icon": "fa fa-bookmark",
+ "idx": 1,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "menu_index": 0,
+ "modified": "2019-04-16 10:02:23.277734",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Designation",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 0,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 1, 
- "sort_order": "ASC", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "show_name_in_global_search": 1,
+ "sort_order": "ASC",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/designation_skill/__init__.py b/erpnext/hr/doctype/designation_skill/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/designation_skill/__init__.py
diff --git a/erpnext/hr/doctype/designation_skill/designation_skill.json b/erpnext/hr/doctype/designation_skill/designation_skill.json
new file mode 100644
index 0000000..30e23d0
--- /dev/null
+++ b/erpnext/hr/doctype/designation_skill/designation_skill.json
@@ -0,0 +1,74 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2019-04-16 10:01:05.259881",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "skill",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Skill",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Skill",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-04-16 13:42:10.760449",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Designation Skill",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/designation_skill/designation_skill.py b/erpnext/hr/doctype/designation_skill/designation_skill.py
new file mode 100644
index 0000000..c37d21f
--- /dev/null
+++ b/erpnext/hr/doctype/designation_skill/designation_skill.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class DesignationSkill(Document):
+	pass
diff --git a/erpnext/hr/doctype/employee_skill/__init__.py b/erpnext/hr/doctype/employee_skill/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill/__init__.py
diff --git a/erpnext/hr/doctype/employee_skill/employee_skill.json b/erpnext/hr/doctype/employee_skill/employee_skill.json
new file mode 100644
index 0000000..4b1419e
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill/employee_skill.json
@@ -0,0 +1,141 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2019-04-16 09:57:52.751635",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "skill",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Skill",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Skill",
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "proficiency",
+   "fieldtype": "Rating",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Proficiency",
+   "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": 1,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "Today",
+   "fetch_if_empty": 0,
+   "fieldname": "evaluation_date",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Evaluation Date",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-04-16 14:13:17.111035",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Skill",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_skill/employee_skill.py b/erpnext/hr/doctype/employee_skill/employee_skill.py
new file mode 100644
index 0000000..ac05fba
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill/employee_skill.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class EmployeeSkill(Document):
+	pass
diff --git a/erpnext/hr/doctype/employee_skill_map/__init__.py b/erpnext/hr/doctype/employee_skill_map/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill_map/__init__.py
diff --git a/erpnext/hr/doctype/employee_skill_map/employee_skill_map.js b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.js
new file mode 100644
index 0000000..b82b18d
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.js
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Employee Skill Map', {
+	// refresh: function(frm) {
+
+	// }
+	designation: (frm) => {
+		frm.set_value('employee_skills', null);
+		if (frm.doc.designation) {
+			frappe.db.get_doc('Designation', frm.doc.designation).then((designation) => {
+				designation.skills.forEach(designation_skill => {
+					let row = frappe.model.add_child(frm.doc, 'Employee Skill', 'employee_skills');
+					row.skill = designation_skill.skill;
+					row.proficiency = 1;
+				});
+				refresh_field('employee_skills');
+			});
+		}
+	}
+});
diff --git a/erpnext/hr/doctype/employee_skill_map/employee_skill_map.json b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.json
new file mode 100644
index 0000000..624145f
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.json
@@ -0,0 +1,298 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:employee",
+ "beta": 0,
+ "creation": "2019-04-16 10:07:48.303426",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 0,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "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": "Employee",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Employee",
+   "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,
+   "translatable": 0,
+   "unique": 1
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "employee.employee_name",
+   "fetch_if_empty": 0,
+   "fieldname": "employee_name",
+   "fieldtype": "Read Only",
+   "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": "Employee Name",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "employee.designation",
+   "fetch_if_empty": 0,
+   "fieldname": "designation",
+   "fieldtype": "Read Only",
+   "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": "Designation",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "skills_section",
+   "fieldtype": "Section Break",
+   "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": "Skills",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "employee_skills",
+   "fieldtype": "Table",
+   "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": "Employee Skills",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Employee Skill",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "trainings_section",
+   "fieldtype": "Section Break",
+   "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": "Trainings",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "trainings",
+   "fieldtype": "Table",
+   "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": "Trainings",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Employee Training",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2019-04-16 16:16:40.058429",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Skill Map",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "employee_name",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py
new file mode 100644
index 0000000..073f02f
--- /dev/null
+++ b/erpnext/hr/doctype/employee_skill_map/employee_skill_map.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class EmployeeSkillMap(Document):
+	pass
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
index 865e821..899b869 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
@@ -20,6 +21,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "employee", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -54,6 +56,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "fetch_from": "employee.company", 
+   "fetch_if_empty": 0, 
    "fieldname": "company", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -87,6 +90,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "column_break_2", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -118,6 +122,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "payroll_period", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -151,6 +156,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "total_exemption_amount", 
    "fieldtype": "Currency", 
    "hidden": 0, 
@@ -184,6 +190,7 @@
    "collapsible": 0, 
    "columns": 0, 
    "fetch_from": "employee.department", 
+   "fetch_if_empty": 0, 
    "fieldname": "department", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -217,6 +224,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "amended_from", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -249,6 +257,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "section_break_8", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -280,6 +289,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fetch_if_empty": 0, 
    "fieldname": "declarations", 
    "fieldtype": "Table", 
    "hidden": 0, 
@@ -300,7 +310,7 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "translatable": 0, 
@@ -317,7 +327,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-08-21 16:15:49.363307", 
+ "modified": "2019-04-23 15:50:48.693555", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Employee Tax Exemption Declaration", 
diff --git a/erpnext/hr/doctype/employee_training/__init__.py b/erpnext/hr/doctype/employee_training/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/employee_training/__init__.py
diff --git a/erpnext/hr/doctype/employee_training/employee_training.json b/erpnext/hr/doctype/employee_training/employee_training.json
new file mode 100644
index 0000000..0e0dc15
--- /dev/null
+++ b/erpnext/hr/doctype/employee_training/employee_training.json
@@ -0,0 +1,108 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2019-04-16 16:15:50.931545",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "training",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Training",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Training Event",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "training.end_time",
+   "fetch_if_empty": 0,
+   "fieldname": "training_date",
+   "fieldtype": "Date",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Training Date",
+   "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,
+   "translatable": 0,
+   "unique": 0
+  }
+ ],
+ "has_web_view": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2019-04-22 12:48:56.925419",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Training",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_training/employee_training.py b/erpnext/hr/doctype/employee_training/employee_training.py
new file mode 100644
index 0000000..810796d
--- /dev/null
+++ b/erpnext/hr/doctype/employee_training/employee_training.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class EmployeeTraining(Document):
+	pass
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 9e13cb6..1b487a6 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -167,7 +167,7 @@
 			if d.amount_based_on_formula:
 				formula = d.formula.strip() if d.formula else None
 				if formula:
-					amount = frappe.safe_eval(formula, self.whitelisted_globals, data)
+					amount = rounded(frappe.safe_eval(formula, self.whitelisted_globals, data))
 			if amount:
 				data[d.abbr] = amount
 
@@ -602,12 +602,11 @@
 			annual_earning = taxable_earning["taxable_earning"] * period_factor
 			exemption_amount = 0
 			if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee,
-			"payroll_period": payroll_period.name, "docstatus": 1}):
+					"payroll_period": payroll_period.name, "docstatus": 1}):
 				exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration",
 					{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
 					"total_exemption_amount")
 			annual_taxable_earning = annual_earning - exemption_amount
-
 		if self.deduct_tax_for_unclaimed_employee_benefits or self.deduct_tax_for_unsubmitted_tax_exemption_proof:
 			tax_detail = self.get_tax_paid_in_period(payroll_period, tax_component)
 			if tax_detail:
@@ -739,22 +738,24 @@
 		# less paid taxes
 		if args.get("pro_rata_tax_paid"):
 			tax_amount -= args.get("pro_rata_tax_paid")
+		tax_amount = rounded(tax_amount)
 		struct_row = self.get_salary_slip_row(args.get("tax_component"))
 		return [struct_row, tax_amount, benefit_tax, additional_tax]
 
-	def calculate_tax_by_tax_slab(self, payroll_period, annual_earning):
+	def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning):
 		payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
 		data = self.get_data_for_eval()
+		data.update({"annual_taxable_earning": annual_taxable_earning})
 		taxable_amount = 0
 		for slab in payroll_period_obj.taxable_salary_slabs:
 			if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
 				continue
-			if not slab.to_amount and annual_earning > slab.from_amount:
-				taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01
+			if not slab.to_amount and annual_taxable_earning > slab.from_amount:
+				taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
 				continue
-			if annual_earning > slab.from_amount and annual_earning < slab.to_amount:
-				taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01
-			elif annual_earning > slab.from_amount and annual_earning > slab.to_amount:
+			if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount:
+				taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
+			elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount:
 				taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01
 		return taxable_amount
 
@@ -773,13 +774,21 @@
 
 	def get_period_factor(self, period_start, period_end, start_date=None, end_date=None):
 		# TODO if both deduct checked update the factor to make tax consistent
+		joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"])
+		if getdate(joining_date) > getdate(period_start):
+			period_start = joining_date
+		if relieving_date and getdate(relieving_date) < getdate(period_end):
+			period_end = relieving_date
+
 		payroll_days = date_diff(period_end, period_start) + 1
 		if start_date and end_date:
 			salary_days = date_diff(end_date, start_date) + 1
 			return flt(payroll_days)/flt(salary_days)
+
 		# if period configured for a year and monthly frequency return 12 to make tax calc consistent
 		if 360 <= payroll_days <= 370 and self.payroll_frequency == "Monthly":
 			return 12
+
 		salary_days = date_diff(self.end_date, self.start_date) + 1
 		return flt(payroll_days)/flt(salary_days)
 
diff --git a/erpnext/hr/doctype/skill/__init__.py b/erpnext/hr/doctype/skill/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/skill/__init__.py
diff --git a/erpnext/hr/doctype/skill/skill.js b/erpnext/hr/doctype/skill/skill.js
new file mode 100644
index 0000000..a939ff0
--- /dev/null
+++ b/erpnext/hr/doctype/skill/skill.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Skill', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/hr/doctype/skill/skill.json b/erpnext/hr/doctype/skill/skill.json
new file mode 100644
index 0000000..5182973
--- /dev/null
+++ b/erpnext/hr/doctype/skill/skill.json
@@ -0,0 +1,113 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:skill_name",
+ "beta": 0,
+ "creation": "2019-04-16 09:54:39.486915",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 0,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "skill_name",
+   "fieldtype": "Data",
+   "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": "Skill Name",
+   "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,
+   "translatable": 0,
+   "unique": 1
+  }
+ ],
+ "has_web_view": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2019-04-16 09:55:00.536328",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Skill",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/skill/skill.py b/erpnext/hr/doctype/skill/skill.py
new file mode 100644
index 0000000..8d24212
--- /dev/null
+++ b/erpnext/hr/doctype/skill/skill.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class Skill(Document):
+	pass
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
index f02212c..43e6fe5 100644
--- a/erpnext/portal/product_configurator/utils.py
+++ b/erpnext/portal/product_configurator/utils.py
@@ -173,7 +173,6 @@
 		valid_attribute_values = valid_options.get(attr.attribute, [])
 		ordered_values = ordered_attribute_value_map.get(attr.attribute, [])
 		attr['values'] = [v for v in ordered_values if v in valid_attribute_values]
-		attr['values'] = valid_attribute_values
 
 	return attributes
 
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index 60e72da..45de6eb 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -54,5 +54,8 @@
         "stock/dashboard/item_dashboard.html",
         "stock/dashboard/item_dashboard_list.html",
         "stock/dashboard/item_dashboard.js"
+    ],
+    "js/lms.min.js": [
+        "public/js/education/lms/lms.js"
     ]
 }
diff --git a/erpnext/public/js/education/lms/call.js b/erpnext/public/js/education/lms/call.js
new file mode 100644
index 0000000..e35acbd
--- /dev/null
+++ b/erpnext/public/js/education/lms/call.js
@@ -0,0 +1,15 @@
+frappe.ready(() => {
+	frappe.provide('lms');
+
+	lms.call = (method, args) => {
+		const method_path = 'erpnext.www.lms.' + method;
+		return new Promise((resolve, reject) => {
+			return frappe.call({
+				method: method_path,
+				args,
+			})
+			.then(r => resolve(r.message))
+			.fail(reject);
+		});
+	};
+});
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Article.vue b/erpnext/public/js/education/lms/components/Article.vue
new file mode 100644
index 0000000..eab1424
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Article.vue
@@ -0,0 +1,44 @@
+<template>
+<div>
+    <ContentTitle :title="contentData.title" :author="contentData.author" :publishDate="contentData.publish_date">
+        <slot></slot>
+    </ContentTitle>
+    <section class="article-content-section">
+        <div>
+            <div class="content" v-html="contentData.content"></div>
+            <div class="text-right">
+            </div>
+            <div class="mt-3 text-right">
+                <a class="text-muted" href="/report"><i class="octicon octicon-issue-opened" title="Report"></i> Report a
+                    Mistake</a>
+            </div>
+        </div>
+    </section>
+</div>
+</template>
+<script>
+import ContentTitle from './ContentTitle.vue'
+export default {
+	props: ['content', 'type'],
+	name: 'Article',
+	data() {
+    	return {
+    		contentData: ''
+    	}
+    },
+    mounted() {
+    	this.getContent().then(data => this.contentData = data);
+    },
+    methods: {
+        getContent() {
+            return lms.call('get_content', {
+                content_type: this.type,
+                content: this.content
+            })
+        }
+    },
+    components: {
+        ContentTitle
+    }
+};
+</script>
diff --git a/erpnext/public/js/education/lms/components/Breadcrumb.vue b/erpnext/public/js/education/lms/components/Breadcrumb.vue
new file mode 100644
index 0000000..e7c0fc3
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Breadcrumb.vue
@@ -0,0 +1,49 @@
+<template>
+	<div>
+		<span v-for="(route, index) in routeData">
+			<router-link :to="route.route">{{ route.label }}</router-link><span> / </span>
+		</span>
+	</div>
+</template>
+<script type="text/javascript">
+	export default {
+		name: "Breadcrumb",
+		data() {
+			return {
+				routeName: this.$route.name,
+				routeParams: this.$route.params,
+				routeData: [{
+					label: "All Programs",
+					route: "/List/Program"
+				}]
+			}
+		},
+		mounted() {
+			this.buildBreadcrumb()
+		},
+		methods: {
+			buildBreadcrumb() {
+				if(this.routeName == 'program') {
+					return
+				}
+				if(this.routeName == 'course') {
+					let routeObject = {
+						label: this.routeParams.program_name,
+						route: `/Program/${this.routeParams.program_name}`
+					}
+					this.routeData.push(routeObject)
+				}
+				if(this.routeName == 'content') {
+					this.routeData.push({
+						label: this.routeParams.program_name,
+						route: `/Program/${this.routeParams.program_name}`
+					})
+					this.routeData.push({
+						label: this.routeParams.course_name,
+						route: `/Program/${this.routeParams.program_name}/${this.routeParams.course_name}`
+					})
+				}
+			}
+		}
+	};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Button.vue b/erpnext/public/js/education/lms/components/Button.vue
new file mode 100644
index 0000000..4d8df4b
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Button.vue
@@ -0,0 +1,25 @@
+<template>
+	<button :class="classList" v-on="$listeners" v-bind="$attrs" @click="goToRoute">
+		<slot></slot>
+	</button>
+</template>
+<script>
+export default {
+	name: 'AButton',
+	props: ['type', 'size', 'route'],
+	computed: {
+		classList() {
+			return [
+				'btn',
+				'btn-' + this.type,
+				'btn-' + this.size
+			]
+		}
+	},
+	methods: {
+		goToRoute() {
+			this.$router.push(this.route);
+		}
+	}
+}
+</script>
diff --git a/erpnext/public/js/education/lms/components/CardList.vue b/erpnext/public/js/education/lms/components/CardList.vue
new file mode 100644
index 0000000..298627f
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/CardList.vue
@@ -0,0 +1,28 @@
+<template>
+	<section class="featured-products-section" :class='sectionType'>
+	<h5 class='featured-heading' v-html="title"></h5>
+	<div class="featured-products row">
+		<!-- <p class='lead text-center' v-html="description"></p> -->
+		<slot name="card-list-slot"></slot>
+	</div>
+	<div class='mt-4 text-center'>
+		<slot name="list-bottom"></slot>
+	</div>
+</section>
+</template>
+<script>
+export default {
+    props:['title', 'description', 'sectionType'],
+    name: "CardList",
+};
+</script>
+<style scoped>
+
+.featured-heading {
+    text-transform: uppercase;
+    letter-spacing: 0.5px;
+    font-size: 12px;
+    font-weight: 500;
+}
+
+</style>
diff --git a/erpnext/public/js/education/lms/components/ContentNavigation.vue b/erpnext/public/js/education/lms/components/ContentNavigation.vue
new file mode 100644
index 0000000..a07c0f8
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/ContentNavigation.vue
@@ -0,0 +1,40 @@
+<template>
+	<div class="nav-buttons">
+		<button class='btn btn-outline-secondary' @click="$router.go(-1)">Back</button>
+		<button v-if="nextContent" class='btn btn-primary' @click="goNext()">Next</button>
+		<button v-else class='btn btn-primary' @click="finish()">Finish Topic</button>
+	</div>
+</template>
+
+<script>
+export default {
+	props: ['nextContent', 'nextContentType'],
+	name: 'ContentNavigation',
+	methods: {
+		addActivity() {
+			if(this.$route.params.type != "Quiz"){
+				console.log("Adding Activity")
+				lms.call("add_activity",
+					{
+						course: this.$route.params.course_name,
+						content_type: this.$route.params.type,
+						content: this.$route.params.content,
+					}
+				)
+			}
+		},
+		goNext() {
+			this.addActivity()
+			this.$router.push({ name: 'content', params: { course: this.$route.params.course_name, type:this.nextContentType, content:this.nextContent }})
+		},
+		finish() {
+			this.addActivity()
+			this.$router.push({ name: 'course', params: { program_name: this.$route.params.program_name, course_name: this.$route.params.course_name}})
+			lms.trigger('course-completed', course_name);
+		}
+	}
+};
+</script>
+
+<style lang="css" scoped>
+</style>
diff --git a/erpnext/public/js/education/lms/components/ContentTitle.vue b/erpnext/public/js/education/lms/components/ContentTitle.vue
new file mode 100644
index 0000000..a488ab8
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/ContentTitle.vue
@@ -0,0 +1,29 @@
+<template>
+    <section class='article-top-section video-section-bg'>
+        <div>
+            <div class="row">
+                <div class="col-md-8">
+                    <h2>{{ title }}</h2>
+                    <span v-if="typeof author !== 'undefined' || author !== null" class="text-muted">
+                        <span v-if="publishDate">Published on {{ publishDate }}</span>
+                        <span v-if="author">— {{ author }}</span>
+                    </span>
+                </div>
+                <div class="col-md-4 text-right">
+                    <slot></slot>
+                </div>
+            </div>
+            <hr>
+        </div>
+    </section>
+</template>
+
+<script>
+export default {
+    props: ['title', 'publishDate', 'author'],
+    name: 'ContentTitle',
+};
+</script>
+
+<style lang="css" scoped>
+</style>
diff --git a/erpnext/public/js/education/lms/components/CourseCard.vue b/erpnext/public/js/education/lms/components/CourseCard.vue
new file mode 100644
index 0000000..223654f
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/CourseCard.vue
@@ -0,0 +1,92 @@
+<template>
+    <div class="mt-3 col-md-4 col-sm-12">
+        <div class="card h-100">
+            <div class="card-hero-img" v-if="course.hero_image" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>
+            <div v-else class="card-image-wrapper">
+                <div class="image-body">{{ course.course_name }}</div>
+            </div>
+            <div class='card-body'>
+                <h5 class="card-title">{{ course.course_name }}</h5>
+                <span class="course-list text-muted" id="getting-started">
+                    Topics
+                    <ul class="mb-0 mt-1" style="padding-left: 1.5em;">
+                        <li v-for="topic in course.topics" :key="topic.name">
+                            <div>{{ topic.topic_name }}</div>
+                        </li>
+                    </ul>
+                </span>
+            </div>
+            <div class='p-3' style="display: flex; justify-content: space-between;">
+                <div>
+                    <span v-if="complete"><i class="mr-2 text-success fa fa-check-circle" aria-hidden="true"></i>Course Complete</span>
+                </div>
+                <div class='text-right'>
+                    <a-button
+                        :type="'primary'"
+                        size="sm"
+                        :route="courseRoute"
+                    >
+                        {{ buttonName }}
+                    </a-button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import AButton from './Button.vue';
+
+export default {
+    props: ['course', 'program_name'],
+    name: "CourseCard",
+    components: {
+        AButton
+    },
+    data() {
+        return {
+            courseDetails: {},
+        }
+    },
+    mounted() {
+        if(lms.store.checkLogin()) this.getCourseDetails().then(data => this.courseDetails = data)
+    },
+    computed: {
+        courseRoute() {
+            return `${this.program_name}/${this.course.name}`
+        },
+        complete() {
+            if(lms.store.checkProgramEnrollment(this.program_name)){
+                if (this.courseDetails.flag === "Completed" ) {
+                    return true
+                }
+                else {
+                    return false
+                }
+            }
+            else {
+                return false
+            }
+        },
+        isLogin() {
+            return lms.store.checkLogin()
+        },
+        buttonName() {
+            if(lms.store.checkProgramEnrollment(this.program_name)){
+                return "Start Course"
+            }
+            else {
+                return "Explore"
+            }
+        }
+    },
+    methods: {
+        getCourseDetails() {
+			return lms.call('get_student_course_details', {
+                    course_name: this.course.name,
+                    program_name: this.program_name
+				})
+        },
+    }
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Navbar.vue b/erpnext/public/js/education/lms/components/Navbar.vue
new file mode 100644
index 0000000..f3f3ce4
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Navbar.vue
@@ -0,0 +1,85 @@
+<template>
+<nav class="navbar navbar-light bg-white navbar-expand-lg sticky-top shadow-sm">
+    <div class="container">
+        <a class="navbar-brand" href="/lms">
+            <span>{{ portal.title }}</span>
+        </a>
+        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+            <span class="navbar-toggler-icon"></span>
+        </button>
+
+        <div class="collapse navbar-collapse" id="navbarSupportedContent">
+            <ul class="navbar-nav mr-auto">
+
+                <li class="nav-item">
+                    <a class="nav-link" href="lms#/List/Program">
+                        All Programs
+                    </a>
+                </li>
+
+                <li class="nav-item">
+                    <a class="nav-link" href="/lms#/Profile">
+                        Profile
+                    </a>
+                </li>
+            </ul>
+            <ul class="navbar-nav ml-auto">
+                <!-- post login tools -->
+                <li v-if="isLogin" class="nav-item dropdown logged-in" id="website-post-login" data-label="website-post-login">
+                    <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+                        <span class="user-image-wrapper">
+                            <span class="avatar avatar-small" :title="fullName">
+                                    <span class="avatar-frame" :style="avatarStyle" :title="fullName"></span>
+                            </span>
+                        </span>
+                        <span class="full-name">{{ fullName }}</span>
+                        <b class="caret"></b>
+                    </a>
+                    <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                        <a class="dropdown-item" href="/me" rel="nofollow"> My Account </a>
+                        <a class="dropdown-item" href="/?cmd=web_logout" rel="nofollow"> Logout </a>
+                    </ul>
+                </li>
+
+                <li v-else class="nav-item">
+                    <a class="nav-link btn-login-area" href="/login">Login</a>
+                </li>
+            </ul>
+        </div>
+    </div>
+</nav>
+</template>
+<script>
+export default {
+    name: "Home",
+    data() {
+    	return{
+            portal: {},
+            avatar: frappe.user_image,
+            fullName: frappe.full_name,
+            isLogin: frappe.is_user_logged_in()
+    	}
+    },
+	mounted() {
+        this.getPortalDetails().then(data => this.portal = data);
+    },
+    methods: {
+        getPortalDetails() {
+            return lms.call("get_portal_details")
+        }
+    },
+    computed: {
+		avatarStyle() {
+			return `background-image: url("${this.avatar}")`
+        },
+        // isLogin() {
+        //     return frappe.is_user_logged_in()
+        // },
+	}
+};
+</script>
+<style scoped>
+a {
+	text-decoration: none;
+}
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/ProfileInfo.vue b/erpnext/public/js/education/lms/components/ProfileInfo.vue
new file mode 100644
index 0000000..6f3e8f1
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/ProfileInfo.vue
@@ -0,0 +1,85 @@
+<template>
+<section>
+		<div class="py-5">
+			<div class="row">
+				<div class="col-sm-12">
+					<div>
+						<h3>{{ fullName }}</h3>
+						<ul>
+							<li class="row">
+								<div class="col-md-3 col-sm-4 pr-0 text-muted">Email:</div>
+								<div class="col-md-9 col-sm-8">{{ email }}</div>
+							</li>
+							<li v-if="joiningDate" class="row">
+								<div class="col-md-3 col-sm-4 pr-0 text-muted">Date of Joining:</div>
+								<div class="col-md-9 col-sm-8">{{ joiningDate }}</div>
+							</li>
+							<li class="row">
+								<div class="col-md-3 col-sm-4 pr-0 text-muted">Programs Enrolled:</div>
+								<div class="col-md-9 col-sm-8">
+									<ul v-if="enrolledPrograms">
+										<li v-for="program in enrolledPrograms" :key="program">{{ program }}</li>
+									</ul>
+									<span v-else>None</span>
+								</div>
+							</li>
+						</ul>
+					</div>
+					<a href="/update-profile" class="edit-button text-muted">Edit Profile</a>
+				</div>
+			</div>
+			<div ></div>
+		</div>
+	</section>
+</template>
+<script>
+
+export default {
+	props: ['enrolledPrograms'],
+	name: "ProfileInfo",
+	data() {
+		return {
+			avatar: frappe.user_image,
+			fullName: frappe.full_name,
+			abbr: frappe.get_abbr(frappe.get_cookie("full_name")),
+			email: frappe.session.user,
+			joiningDate: ''
+		}
+	},
+	mounted(){
+		this.getJoiningDate().then(data => {
+			if(data) {
+				this.joiningDate = lms.moment(String(data)).format('D MMMM YYYY')
+			}
+		})
+	},
+	computed: {
+		avatarStyle() {
+			return `background-image: url("${this.avatar}")`
+		},
+	},
+	methods: {
+		getJoiningDate() {
+			return lms.call("get_joining_date")
+		}
+	}
+};
+</script>
+<style scoped>
+	.edit-button {
+		position: absolute;
+		top: 0;
+		right: 0;
+	}
+
+	.standard-image {
+		font-size: 72px;
+		border-radius: 6px;
+	}
+
+	ul {
+		list-style-type: none;
+		padding: 0;
+		margin: 0
+	}
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/ProgramCard.vue b/erpnext/public/js/education/lms/components/ProgramCard.vue
new file mode 100644
index 0000000..26d3882
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/ProgramCard.vue
@@ -0,0 +1,82 @@
+<template>
+<div class='mt-3 col-md-4 col-sm-12'>
+    <div class="card h-100">
+        <router-link :to="'/Program/' + program.name">
+            <div class="card-hero-img" v-if="program.hero_image" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>
+            <div v-else class="card-image-wrapper text-center">
+                <div class="image-body">{{ program.program_name }}</div>
+            </div>
+            <div class='card-body'>
+                <h5 class='card-title'>{{ program.program_name }}</h5>
+                <div class="text-muted">{{ program.description.substring(0,200) }}...</div>
+            </div>
+        </router-link>
+        <div class='text-right p-3'>
+            <button v-if="program.intro_video" class='btn btn-light btn-sm' data-toggle="modal" data-target="#videoModal">Watch Intro</button>
+            <a-button v-if="enrolled" type="dark" size="sm" :route="programPageRoute">
+                {{ buttonName }}
+            </a-button>
+            <button v-else-if="isLogin" class='btn btn-dark btn-sm' @click="enroll()">{{ enrollButton }}</button>
+            <a v-else class='btn btn-secondary btn-sm' href="/login#signup">Sign Up</a>
+        </div>
+        <VideoModal v-if="program.intro_video" :title="program.program_name" :video="program.intro_video"/>
+    </div>
+</div>
+</template>
+<script>
+import AButton from './Button.vue';
+import VideoModal from './VideoModal.vue';
+export default {
+    props: ['program', 'enrolled'],
+    name: "ProgramCard",
+    data() {
+    	return {
+            isLogin: frappe.is_user_logged_in(),
+            enrollButton: 'Enroll Now',
+            programRoute: { name: 'program', params: { program_name: this.program.name }},
+            image: "'" + this.program.hero_image + "'"
+    	};
+    },
+    methods: {
+        enroll() {
+            this.enrollButton = 'Enrolling...'
+            lms.call('enroll_in_program', {
+                program_name: this.program.name,
+            }).then(data => {
+                lms.store.updateEnrolledPrograms()
+                this.$router.push(this.programRoute)
+            })
+        }
+    },
+    computed: {
+        buttonName() {
+            if(this.enrolled){
+                return "Start Program"
+            }
+            else {
+                return "Enroll"
+            }
+        },
+        programPageRoute() {
+            return this.programRoute
+        },
+        isEnrolled() {
+            return lms.store.enrolledPrograms.includes(this.program.name)
+        }
+    },
+    components: {
+        AButton,
+        VideoModal
+    }
+};
+</script>
+
+<style lang="css" scoped>
+    a {
+        text-decoration: none;
+        color: black;
+    }
+    a.btn-secondary {
+        color: white !important;
+    }
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/ProgressCard.vue b/erpnext/public/js/education/lms/components/ProgressCard.vue
new file mode 100644
index 0000000..77fb6ef
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/ProgressCard.vue
@@ -0,0 +1,89 @@
+<template>
+    <div class='mt-3 col-md-4 col-sm-12'>
+        <div class="card h-100">
+            <div class='card-body'>
+                <router-link :to="'/Program/' + programData.name">
+                    <h5 class='card-title'>{{ programData.program }}</h5>
+                </router-link>
+                <span class="course-list text-muted" id="getting-started">
+                    Courses
+                    <ul class="mb-0 mt-1 list-unstyled" style="padding-left: 1.5em;">
+                        <li v-for="item in programData.progress" :key="item.name">
+                            <span v-if="item.is_complete"><i class="text-success fa fa-check-circle" aria-hidden="true"></i></span>
+                            <span v-else><i class="text-secondary fa fa-circle-o" aria-hidden="true"></i></span>
+                            {{ item.course_name }}
+                        </li>
+                    </ul>
+                </span>
+            </div>
+            <div class='p-3' style="display: flex; justify-content: space-between;">
+                <div></div>
+                <div class='text-right'>
+                    <a-button
+                        :type="buttonType"
+                        size="sm btn-block"
+                        :route="programRoute"
+                    >
+                        {{ buttonName }}
+                    </a-button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import AButton from './Button.vue';
+export default {
+    props: ['program'],
+    name: "ProgressCard",
+    data() {
+    	return {
+            programData: {}
+    	};
+    },
+    mounted() {
+        this.getProgramProgress().then(data => this.programData = data)
+    },
+    methods: {
+       getProgramProgress() {
+			return lms.call('get_program_progress', {
+                    program_name: this.program
+				})
+        },
+    },
+    computed: {
+        programRoute() {
+            return {name: 'program', params: {program_name: this.program}}
+        },
+        buttonType() {
+            if (this.programData.percentage == 100 ){
+                return "success"
+            }
+            else if (this.programData.percentage == "0" ) {
+                return "secondary"
+            }
+            else {
+                return "info"
+            }
+        },
+        buttonName() {
+            if (this.programData.percentage == 100 ){
+                return "Program Complete"
+            }
+            else {
+                return `${this.programData.percentage}% Completed`
+            }
+        }
+    },
+    components: {
+        AButton
+    },
+};
+</script>
+<style scoped>
+
+	a {
+		text-decoration: none;
+		color: black;
+	}
+</style>
diff --git a/erpnext/public/js/education/lms/components/Quiz.vue b/erpnext/public/js/education/lms/components/Quiz.vue
new file mode 100644
index 0000000..0a6199a
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Quiz.vue
@@ -0,0 +1,119 @@
+<template>
+	<section class="quiz-section">
+    <div>
+        <div class="row">
+            <div class="col-md-8">
+                <h2>{{ content }}</h2>
+            </div>
+        </div>
+        <div class="content">
+            <hr>
+            <div id="quiz" :name="content">
+                <div id="quiz-body">
+					<component v-for="question in quizData" :key="question.name" v-bind:is="question.type" :question="question" @updateResponse="updateResponse" :isDisabled="isDisabled"></component>
+                </div>
+                <div class="mt-3">
+                    <div>
+                        <div v-if="isDisabled || submitted" id="post-quiz-actions" class="row">
+                            <div class="col-md-8 text-left">
+                                <span v-html="message"></span>
+                            </div>
+                            <div class="col-md-4 text-right">
+                                <slot></slot>
+                            </div>
+                        </div>
+                        <div v-else id="quiz-actions" class="text-right">
+                            <button class='btn btn-outline-secondary' type="reset" :disabled="isDisabled">Reset</button>
+                            <button class='btn btn-primary' @click="submitQuiz" type="button" :disabled="isDisabled">Submit</button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="mt-3 text-right">
+            <a class="text-muted" href="/report"><i class="octicon octicon-issue-opened" title="Report"></i> Report a
+                Mistake</a>
+        </div>
+    </div>
+</section>
+</template>
+
+<script>
+import QuizSingleChoice from "./Quiz/QuizSingleChoice.vue"
+import QuizMultipleChoice from "./Quiz/QuizMultipleChoice.vue"
+
+export default {
+	props: ['content', 'type'],
+	name: 'Quiz',
+	data() {
+    	return {
+    		quizData: '',
+    		quizResponse: {},
+            score: '',
+            submitted: false,
+            isDisabled: false,
+            quizStatus: {},
+    	}
+    },
+    mounted() {
+    	this.getQuizWithoutAnswers().then(data => {
+    		this.quizData = data.quizData
+            this.quizStatus = data.status
+            this.isDisabled = data.status.is_complete
+    	});
+    },
+    components: {
+    	'SingleChoice': QuizSingleChoice,
+        'MultipleChoice': QuizMultipleChoice
+    },
+    methods: {
+        getQuizWithoutAnswers() {
+            return lms.call("get_quiz_without_answers",
+                {
+                    quiz_name: this.content,
+                    course_name: this.$route.params.course_name
+                }
+    	    )
+        },
+		updateResponse(res) {
+            this.quizResponse[res.question] = res.option
+		},
+		submitQuiz() {
+			lms.call("evaluate_quiz",
+				{
+					quiz_response: this.quizResponse,
+                    quiz_name: this.content,
+                    course: this.$route.params.course_name
+				}
+            ).then(data => {
+                this.score = data
+                this.submitted = true
+                this.quizResponse = null
+			});
+		}
+	},
+    computed: {
+      currentComponent: function() {
+        if(this.quizData.type === "MultipleChoice") {
+            return 'QuizMultipleChoice'
+        }
+        else {
+            return 'QuizSingleChoice'
+        }
+      },
+      message: function() {
+        if(this.submitted) {
+            return '<h3>Your Score: <span id="result">'+ this.score +'</span></h3>'
+        }
+        let message = '<h4>You have exhausted all attempts for this quiz.</h4>'
+        if(this.quizStatus.result == 'Pass') {
+            message = "<h4>You have successfully completed this quiz.</h4>Score: " + this.quizStatus.score
+        }
+        return message
+      }
+    },
+};
+</script>
+
+<style lang="css" scoped>
+</style>
diff --git a/erpnext/public/js/education/lms/components/Quiz/QuizMultipleChoice.vue b/erpnext/public/js/education/lms/components/Quiz/QuizMultipleChoice.vue
new file mode 100644
index 0000000..338b1ac
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Quiz/QuizMultipleChoice.vue
@@ -0,0 +1,34 @@
+<template>
+	<div class="question mt-4">
+    <h5>{{ question.question }}</h5>
+    <div class="options ml-2">
+        <div v-for="option in question.options" :key="option.name" class="form-check pb-1">
+            <input v-model="checked" class="form-check-input" type="checkbox" :name="question.name" :id="option.name" :value="option.name" @change="emitResponse(question.name, option.name)" :disabled="isDisabled">
+            <label class="form-check-label" :for="option.name">
+                {{ option.option }}
+            </label>
+        </div>
+    </div>
+</div>
+</template>
+
+<script>
+export default {
+	props: ['question', 'isDisabled'],
+	name: 'QuizSingleChoice',
+    data() {
+        return {
+            checked: []
+        }
+    },
+	methods: {
+		emitResponse(q, o) {
+            console.log(this.checked)
+			this.$emit('updateResponse', {'question':q , 'option': this.checked, 'type': this.question.type})
+		}
+	}
+};
+</script>
+
+<style lang="css" scoped>
+</style>
diff --git a/erpnext/public/js/education/lms/components/Quiz/QuizSingleChoice.vue b/erpnext/public/js/education/lms/components/Quiz/QuizSingleChoice.vue
new file mode 100644
index 0000000..235cbce
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Quiz/QuizSingleChoice.vue
@@ -0,0 +1,28 @@
+<template>
+	<div class="question mt-4">
+    <h5>{{ question.question }}</h5>
+    <div class="options ml-2">
+        <div v-for="option in question.options" :key="option.name" class="form-check pb-1">
+            <input class="form-check-input" type="radio" :name="question.name" :id="option.name" :value="option.name" @change="emitResponse(question.name, option.name)" :disabled="isDisabled">
+            <label class="form-check-label" :for="option.name">
+                {{ option.option }}
+            </label>
+        </div>
+    </div>
+</div>
+</template>
+
+<script>
+export default {
+	props: ['question', 'isDisabled'],
+	name: 'QuizSingleChoice',
+	methods: {
+		emitResponse(q, o) {
+			this.$emit('updateResponse', {'question':q , 'option': o, 'type': this.question.type})
+		}
+	}
+};
+</script>
+
+<style lang="css" scoped>
+</style>
diff --git a/erpnext/public/js/education/lms/components/ScoreCard.vue b/erpnext/public/js/education/lms/components/ScoreCard.vue
new file mode 100644
index 0000000..1cf53ef
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/ScoreCard.vue
@@ -0,0 +1,60 @@
+<template>
+    <div v-if="quizData" class='mt-3 col-md-4 col-sm-12'>
+        <div class="card h-100">
+            <div class='card-body'>
+                <h5 class='card-title'>{{ quizData.program }}</h5>
+                <div v-for="attempt in quizData.quiz_attempt" :key="attempt.content" class="course-list" id="getting-started">
+                    <div>
+                        {{ attempt.content }}
+                        <ul v-if="attempt.is_complete">
+                            <li><span class="text-muted">Score: </span>{{ attempt.score }}</li>
+                            <li><span class="text-muted">Status: </span>{{attempt.result }}</li>
+                        </ul>
+                        <span v-else>- Unattempted</span>
+                    </div>
+                </div>
+            </div>
+            <div class='p-3' style="display: flex; justify-content: space-between;">
+                <div></div>
+                <div class='text-right'>
+                    <a-button
+                            :type="'primary'"
+                            size="sm btn-block"
+                            :route="programRoute"
+                        >
+                            Go To Program
+                        </a-button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import AButton from './Button.vue';
+export default {
+    props: ['program'],
+    name: "ScoreCard",
+    data() {
+    	return {
+            quizData: {}
+    	};
+    },
+    mounted() {
+        this.getQuizProgress().then(data => this.quizData = data)
+    },
+    methods: {
+       getQuizProgress() {
+			return lms.call('get_quiz_progress_of_program', {
+                    program_name: this.program
+				})
+        },
+        programRoute() {
+            return {name: 'program', params: {program_name: this.program}}
+        },
+    },
+    components: {
+        AButton
+    },
+};
+</script>
+
diff --git a/erpnext/public/js/education/lms/components/TopSection.vue b/erpnext/public/js/education/lms/components/TopSection.vue
new file mode 100644
index 0000000..c27d003
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/TopSection.vue
@@ -0,0 +1,27 @@
+<template>
+<div class="hero">
+	<h1 class="text-center" v-html="title"></h1>
+	<p class='text-center' v-html="description"></p>
+	<p class="text-center padding">
+		<slot></slot>
+	</p>
+</div>
+</template>
+<script>
+
+export default {
+	props: ['title', 'description'],
+    name: "TopSection",
+};
+</script>
+<style scoped>
+	.hero {
+		padding-top: 50px;
+		padding-bottom: 100px;
+	}
+
+	.hero h1 {
+		font-size: 40px;
+		font-weight: 200;
+	}
+</style>
diff --git a/erpnext/public/js/education/lms/components/TopSectionButton.vue b/erpnext/public/js/education/lms/components/TopSectionButton.vue
new file mode 100644
index 0000000..0fa49d4
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/TopSectionButton.vue
@@ -0,0 +1,49 @@
+<template>
+    <button v-if="isLoggedIn" class='btn btn-primary btn-md' @click="primaryAction()">{{ buttonName }}</button>
+	<a v-else class='btn btn-primary btn-md' href="/login#signup">{{ buttonName }}</a>
+</template>
+<script>
+export default {
+    name: "TopSectionButton",
+    data() {
+        return {
+            buttonName: '',
+            isLoggedIn: lms.store.checkLogin(),
+            nextContent: '',
+            nextContentType: '',
+            nextCourse: '',
+            link: '',
+        }
+    },
+    mounted() {
+        this.computeButtons()
+    },
+    methods: {
+        computeButtons(){
+            if(this.isLoggedIn){
+                    this.buttonName = 'Explore Programs'
+            }
+            else{
+                this.buttonName = 'Sign Up'
+            }
+        },
+        primaryAction() {
+            if(this.$route.name == 'home'){
+                this.$router.push('List/Program');
+            }
+            else if(this.$route.name == 'program' && lms.store.enrolledPrograms.includes(this.$route.params.program_name)){
+                this.$router.push({ name: 'content', params: { program_name: this.$route.params.program_name, course: this.nextCourse, type: this.nextContentType, content: this.nextContent}})
+            }
+            else {
+                lms.call("enroll_in_program",
+                    {
+                        program_name: this.$route.params.program_name,
+                        student_email_id: frappe.session.user
+                    }
+                )
+                lms.store.updateEnrolledPrograms()
+            }
+        },
+    }
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/TopicCard.vue b/erpnext/public/js/education/lms/components/TopicCard.vue
new file mode 100644
index 0000000..3e930df
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/TopicCard.vue
@@ -0,0 +1,112 @@
+
+<template>
+    <div class="mt-3 col-md-4 col-sm-12">
+        <div class="card h-100">
+            <div class="card-hero-img" v-if="topic.hero_image" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>
+            <div v-else class="card-image-wrapper">
+                <div class="image-body">{{ topic.topic_name }}</div>
+            </div>
+            <div class='card-body'>
+                <h5 class="card-title">{{ topic.topic_name }}</h5>
+                <span class="course-list text-muted" id="getting-started">
+                    Content
+                    <ul class="mb-0 mt-1" style="padding-left: 1.5em;">
+                        <li v-for="content in topic.topic_content" :key="content.name">
+                            <router-link v-if="isLogin" tag="a" :class="'text-muted'" :to="{name: 'content', params:{program_name: program_name, topic:topic.name, course_name: course_name, type:content.content_type, content: content.content} }">
+                                {{ content.content }}
+                            </router-link>
+                            <div v-else><span style="padding-right: 0.4em"></span>{{ content.content }}</div>
+                        </li>
+                    </ul>
+                </span>
+            </div>
+            <div v-if="isLogin" class='p-3' style="display: flex; justify-content: space-between;">
+                <div>
+                    <span v-if="complete"><i class="mr-2 text-success fa fa-check-circle" aria-hidden="true"></i>Course Complete</span>
+                </div>
+                <div class='text-right'>
+                    <a-button
+                    :type="'primary'"
+                    size="sm"
+                    :route="firstContentRoute"
+                >
+                    {{ buttonName }}
+                </a-button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import AButton from './Button.vue';
+
+export default {
+    props: ['topic', 'course_name', 'program_name'],
+    name: "TopicCard",
+    data() {
+        return {
+            topicDetails: {}
+        }
+    },
+    mounted() {
+        if(lms.store.checkLogin()) this.gettopicDetails().then(data => this.topicDetails = data)
+    },
+    components: {
+        AButton
+    },
+    computed: {
+        firstContentRoute() {
+            if(lms.store.checkLogin()){
+                return `/Program/${this.program_name}/${this.course_name}/${this.topic.name}/${this.topicDetails.content_type}/${this.topicDetails.content}`
+            }
+            else {
+                return {}
+            }
+        },
+        complete() {
+            if(lms.store.checkProgramEnrollment(this.program_name)){
+                if (this.topicDetails.flag === "Completed" ) {
+                    return true
+                }
+                else {
+                    return false
+                }
+            }
+            else {
+                return false
+            }
+        },
+        isLogin() {
+            // return lms.store.checkProgramEnrollment(this.program_name)
+            return lms.store.checkLogin()
+        },
+        buttonName() {
+            if(lms.store.checkProgramEnrollment(this.program_name)){
+                if (this.topicDetails.flag == 'Continue'){
+                    return 'Continue'
+                }
+                else {
+                    return 'Start Topic'
+                }
+            }
+            else {
+                return "Explore"
+            }
+        }
+    },
+    methods: {
+        iconClass(content_type) {
+            if(content_type == 'Video') return 'fa fa-play'
+            if(content_type == 'Article') return 'fa fa-file-text-o'
+            if(content_type == 'Quiz') return 'fa fa-question-circle-o'
+        },
+        gettopicDetails() {
+			return lms.call('get_student_topic_details', {
+                    topic_name: this.topic.name,
+                    course_name: this.course_name,
+				})
+        },
+    }
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/Video.vue b/erpnext/public/js/education/lms/components/Video.vue
new file mode 100644
index 0000000..27f922f
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/Video.vue
@@ -0,0 +1,64 @@
+<template>
+<div>
+    <section class='mt-2'>
+    <div>
+        <div class="mt-3 row">
+            <div class="col-md-8">
+                <h2>{{ contentData.name }}</h2>
+                <span class="text-muted">
+                    <i class="octicon octicon-clock" title="Duration"></i> {{ contentData.duration }} Mins
+                    &mdash; Published on {{ contentData.publish_date }}.
+                </span>
+            </div>
+            <div class="col-md-4 text-right">
+                <slot></slot>
+            </div>
+        </div>
+        <youtube-player :url="contentData.url" class="mt-3"/>
+        <hr>
+    </div>
+</section>
+<section class="video-description-section">
+    <div>
+        <div class="content" v-html="contentData.description">
+        </div>
+        <div class="text-right hidden">
+            <a class='btn btn-outline-secondary' href="/classrooms/module">Previous</a>
+            <a class='btn btn-primary' href="/classrooms/module">Next</a>
+        </div>
+        <div class="mt-3 text-right">
+            <a class="text-muted" href="/report"><i class="octicon octicon-issue-opened" title="Report"></i> Report a
+                Mistake</a>
+        </div>
+    </div>
+</section>
+</div>
+</template>
+<script>
+import YoutubePlayer from './YoutubePlayer.vue'
+
+export default {
+	props: ['content', 'type'],
+	name: 'Video',
+	data() {
+    	return {
+            contentData: '',
+    	}
+    },
+    components: {
+        YoutubePlayer
+    },
+    mounted() {
+        this.getContent()
+            .then(data => this.contentData = data)
+    },
+    methods: {
+        getContent() {
+            return lms.call('get_content', {
+                content_type: this.type,
+                content: this.content
+            })
+        }
+    }
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/VideoModal.vue b/erpnext/public/js/education/lms/components/VideoModal.vue
new file mode 100644
index 0000000..71227ad
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/VideoModal.vue
@@ -0,0 +1,35 @@
+<template>
+	<div class="modal" id="videoModal" tabindex="-1" role="dialog">
+		<div class="modal-dialog" role="document">
+			<div class="modal-content">
+			<div class="modal-header">
+				<h5 class="modal-title">{{ title }}</h5>
+				<button type="button" class="close" data-dismiss="modal" aria-label="Close">
+				<span id="close_modal" aria-hidden="true" @click="stopVideo()">&times;</span>
+				</button>
+			</div>
+			<div class="modal-body">
+				<youtube-player :url="video"/>
+			</div>
+			</div>
+		</div>
+	</div>
+</template>
+<script type="text/javascript">
+import YoutubePlayer from './YoutubePlayer.vue'
+
+export default {
+	name: 'VideoModal',
+	props: ['title', 'video'],
+	components: {
+		YoutubePlayer
+	},
+	methods: {
+		stopVideo() {
+			$('.yvideo').each(function() {
+  				this.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*')
+			});
+		}
+	}
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/components/YoutubePlayer.vue b/erpnext/public/js/education/lms/components/YoutubePlayer.vue
new file mode 100644
index 0000000..9377b57
--- /dev/null
+++ b/erpnext/public/js/education/lms/components/YoutubePlayer.vue
@@ -0,0 +1,36 @@
+<template>
+	<div class="embed-responsive embed-responsive-16by9">
+        <iframe class="embed-responsive-item yvideo" :src="'https://www.youtube.com/embed/' + videoID + '?version=3&enablejsapi=1'" allowfullscreen></iframe>
+    </div>
+</template>
+<script type="text/javascript">
+	export default {
+		name: 'YoutubePlayer',
+		props: ['url'],
+		data() {
+			return {
+				videoID: ''
+			}
+		},
+		watch: {
+			url() {
+				this.videoID = this.getVideoID(this.url)
+			}
+		},
+		methods: {
+			getVideoID(link) {
+				if (!Array.prototype.last){
+					Array.prototype.last = function(){
+						return this[this.length - 1];
+					};
+				};
+				if (link.includes('v=')){
+					return link.split('v=')[1].split('&')[0]
+				}
+				else if (link.includes('youtu.be')) {
+					return link.split('/').last().split('?')[0]
+				}
+		    }
+		}
+	};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/lms.js b/erpnext/public/js/education/lms/lms.js
new file mode 100644
index 0000000..4665b14
--- /dev/null
+++ b/erpnext/public/js/education/lms/lms.js
@@ -0,0 +1,81 @@
+import Vue from 'vue/dist/vue.js';
+import VueRouter from 'vue-router/dist/vue-router.js';
+import moment from 'moment/min/moment.min.js';
+
+import lmsRoot from "./lmsRoot.vue";
+import routes from './routes';
+import './call';
+
+Vue.use(VueRouter);
+
+var store = {
+	enrolledPrograms: [],
+	enrolledCourses: []
+};
+
+// let profile_page = `<a class="dropdown-item" href="/lms#/Profile" rel="nofollow"> LMS Profile </a>`
+// document.querySelector('#website-post-login > ul').innerHTML += profile_page
+
+frappe.ready(() => {
+	frappe.provide('lms');
+
+	lms.moment = moment;
+
+	lms.store = new Vue({
+		data: store,
+		methods: {
+			updateEnrolledPrograms() {
+				if(this.checkLogin()) {
+					lms.call("get_program_enrollments").then(data => {
+						this.enrolledPrograms = data;
+					});
+				}
+			},
+			updateEnrolledCourses() {
+				if(this.checkLogin()) {
+					lms.call("get_all_course_enrollments").then(data => {
+						this.enrolledCourses = data;
+					});
+				}
+			},
+			checkLogin() {
+				return frappe.is_user_logged_in();
+			},
+			updateState() {
+				this.checkLogin();
+				this.updateEnrolledPrograms();
+				this.updateEnrolledCourses();
+			},
+			checkProgramEnrollment(programName) {
+				if(this.checkLogin()){
+					if(this.enrolledPrograms) {
+						if(this.enrolledPrograms.includes(programName)) {
+							return true;
+						}
+						else {
+							return false;
+						}
+					}
+					else {
+						return false;
+					}
+				}
+				else {
+					return false;
+				}
+			}
+		}
+	});
+	lms.view = new Vue({
+		el: "#lms-app",
+		router: new VueRouter({ routes }),
+		template: "<lms-root/>",
+		components: { lmsRoot },
+		mounted() {
+			lms.store.updateState();
+		}
+	});
+	lms.view.$router.afterEach((to, from) => {
+		window.scrollTo(0,0);
+	});
+});
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/lmsRoot.vue b/erpnext/public/js/education/lms/lmsRoot.vue
new file mode 100644
index 0000000..d359265
--- /dev/null
+++ b/erpnext/public/js/education/lms/lmsRoot.vue
@@ -0,0 +1,45 @@
+<template>
+	<div id="lms-root">
+		<navbar></navbar>
+		<main class="container my-5">
+			<div class="page_content">
+				<router-view :key="$route.fullPath"></router-view>
+			</div>
+		</main>
+	</div>
+</template>
+<script>
+import Navbar from "./components/Navbar.vue"
+export default {
+	name: "lmsRoot",
+	components: {
+		Navbar
+	}
+};
+</script>
+<style>
+	div.card-hero-img {
+        height: 220px;
+        background-size: cover;
+        background-repeat: no-repeat;
+        background-position: center;
+        background-color: rgb(250, 251, 252);
+    }
+
+    .card-image-wrapper {
+        display: flex;
+        overflow: hidden;
+        height: 220px;
+        background-color: rgb(250, 251, 252);
+        justify-content: center;
+    }
+
+    .image-body {
+        align-self: center;
+        color: #d1d8dd;
+        font-size: 24px;
+        font-weight: 600;
+        line-height: 1;
+        padding: 20px;
+    }
+</style>
diff --git a/erpnext/public/js/education/lms/pages/ContentPage.vue b/erpnext/public/js/education/lms/pages/ContentPage.vue
new file mode 100644
index 0000000..542e937
--- /dev/null
+++ b/erpnext/public/js/education/lms/pages/ContentPage.vue
@@ -0,0 +1,87 @@
+<template>
+	<div>
+		<breadcrumb/>
+		<component v-bind:is="currentComponent" :content="content" :type="type">
+			<ContentNavigation :nextContent="nextContent" :nextContentType="nextContentType"/>
+		</component>
+	</div>
+</template>
+<script>
+import Article from "../components/Article.vue"
+import Quiz from "../components/Quiz.vue"
+import Video from "../components/Video.vue"
+import ContentNavigation from "../components/ContentNavigation.vue"
+import Breadcrumb from "../components/Breadcrumb.vue"
+
+export default {
+	props:['program_name', 'course_name', 'topic', 'type', 'content'],
+	name: "ContentPage",
+	data() {
+		return{
+			nextContent: '',
+			nextContentType: '',
+		}
+	},
+	computed: {
+	  currentComponent: function() {
+	  	if(this.type === "Article") {
+	  		return 'Article'
+	  	}
+	  	else if(this.type === "Quiz") {
+	  		return 'Quiz'
+	  	}
+	  	else if(this.type === "Video") {
+	  		return 'Video'
+	  	}
+	  },
+	},
+	mounted() {
+	  	this.getNextContent().then(data => {
+	  		this.nextContent = data.content,
+	  		this.nextContentType = data.content_type
+	  	});
+	},
+	methods: {
+		getNextContent(){
+			return lms.call("get_next_content",
+				{
+					current_content: this.content,
+					current_content_type: this.type,
+					topic: this.topic,
+			  	}
+			);
+		}
+	},
+	components: {
+		Article,
+		Video,
+		Quiz,
+		ContentNavigation,
+		Breadcrumb
+	}
+};
+</script>
+
+<style>
+.footer-message {
+	display: none;
+}
+
+.video-description-section {
+	padding-top: 0em !important;
+}
+
+.article-top-section {
+	padding-top: 0.5em !important;
+	padding-bottom: 0rem !important;
+}
+
+.article-content-section {
+	padding-top: 0em !important;
+}
+
+.quiz-section {
+	padding-top: 0.5em !important;
+	padding-bottom: 0rem !important;
+}
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/CoursePage.vue b/erpnext/public/js/education/lms/pages/CoursePage.vue
new file mode 100644
index 0000000..9aaf8a9
--- /dev/null
+++ b/erpnext/public/js/education/lms/pages/CoursePage.vue
@@ -0,0 +1,49 @@
+<template>
+<div>
+	<breadcrumb></breadcrumb>
+	<TopSection v-bind:title="course.course_name" v-bind:description="course.description">
+    </TopSection>
+	<CardList :title="'Topics'" :description="''" :sectionType="'section-padding section-bg'">
+        <TopicCard slot="card-list-slot" v-for="topic in topicData" :topic="topic" :course_name="course_name" :program_name="program_name" :key="topic.name"/>
+    </CardList>
+</div>
+</template>
+<script>
+import TopSection from "../components/TopSection.vue"
+import CardList from "../components/CardList.vue"
+import TopicCard from "../components/TopicCard.vue"
+import Breadcrumb from "../components/Breadcrumb.vue"
+
+export default {
+	props: ['program_name','course_name'],
+    name: "CoursePage",
+    components: {
+		TopSection,
+		CardList,
+		TopicCard,
+		Breadcrumb
+	},
+	data() {
+		return {
+			course: {},
+			topicData: [],
+		}
+	},
+	mounted() {
+		this.getCourseDetails().then(data => this.course = data);
+		this.getTopics().then(data => this.topicData = data);
+	},
+	methods: {
+		getCourseDetails() {
+			return lms.call('get_course_details', {
+				course_name: this.course_name
+			});
+		},
+		getTopics() {
+			return lms.call('get_topics', {
+				course_name: this.course_name
+			})
+		}
+	}
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/Home.vue b/erpnext/public/js/education/lms/pages/Home.vue
new file mode 100644
index 0000000..5690086
--- /dev/null
+++ b/erpnext/public/js/education/lms/pages/Home.vue
@@ -0,0 +1,48 @@
+<template>
+<div>
+	<TopSection :title="portal.title" :description="portal.description">
+        <TopSectionButton/>
+    </TopSection>
+	<CardList :title="'Featured Programs'" :description="'Master ERPNext'" :sectionType="'section-padding section-bg'">
+        <ProgramCard slot="card-list-slot" v-for="item in featuredPrograms" :key="item.program.name" :program="item.program" :enrolled="item.is_enrolled"/>
+        <AButton slot="list-bottom" :type="'primary'" :size="'md'" :route="'List/Program'">View All</AButton>
+    </CardList>
+</div>
+</template>
+<script>
+import Button from '../components/Button.vue';
+import TopSection from "../components/TopSection.vue"
+import CardList from "../components/CardList.vue"
+import ProgramCard from "../components/ProgramCard.vue"
+import TopSectionButton from "../components/TopSectionButton.vue"
+
+export default {
+    name: "Home",
+    data() {
+    	return{
+    		portal: {},
+            featuredPrograms: {},
+            // enrolledPrograms: new Set()
+    	}
+    },
+    components: {
+        AButton: Button,
+		TopSection,
+        CardList,
+        ProgramCard,
+        TopSectionButton
+    },
+	mounted() {
+        this.getPortalDetails().then(data => this.portal = data);
+        this.getFeaturedPrograms().then(data => this.featuredPrograms = data);
+    },
+    methods: {
+        getPortalDetails() {
+            return lms.call("get_portal_details")
+        },
+        getFeaturedPrograms() {
+            return lms.call("get_featured_programs")
+        }
+    }
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/ListPage.vue b/erpnext/public/js/education/lms/pages/ListPage.vue
new file mode 100644
index 0000000..0768191
--- /dev/null
+++ b/erpnext/public/js/education/lms/pages/ListPage.vue
@@ -0,0 +1,53 @@
+<template>
+	<div>
+		<TopSection :title="'Programs at ' + portal.title" :description="portal.description">
+        	<AButton v-if="isLogin" :type="'primary'" :size="'lg'" :route="{ name: 'signup'}">Sign Up</AButton>
+    	</TopSection>
+		<CardList :title="'All Programs'" :description="''" :sectionType="'section-padding section-bg'">
+			<ProgramCard slot="card-list-slot" v-for="item in masterData" :key="item.program.name" :program="item.program" :enrolled="item.is_enrolled"/>
+		</CardList>
+	</div>
+</template>
+<script>
+import ProgramCard from '../components/ProgramCard.vue';
+import CourseCard from "../components/CourseCard.vue"
+import Button from '../components/Button.vue';
+import TopSection from "../components/TopSection.vue"
+import CardList from "../components/CardList.vue"
+
+
+export default {
+	props: ['master'],
+    name: "ListPage",
+    components: {
+        AButton: Button,
+		CourseCard,
+		ProgramCard,
+		CardList,
+		TopSection		
+	},
+	data() {
+		return {
+			portal: {},
+			masterData: {}
+		}
+	},
+	mounted() {
+        this.getPortalDetails().then(data => this.portal = data);
+        this.getMaster().then(data => this.masterData = data);
+    },
+    methods: {
+        getPortalDetails() {
+            return lms.call("get_portal_details")
+        },
+        getMaster() {
+            return lms.call("get_all_programs")
+        }
+	},
+	computed: {
+		isLogin() {
+			return !lms.store.checkLogin()
+		}
+	}
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/ProfilePage.vue b/erpnext/public/js/education/lms/pages/ProfilePage.vue
new file mode 100644
index 0000000..c926463
--- /dev/null
+++ b/erpnext/public/js/education/lms/pages/ProfilePage.vue
@@ -0,0 +1,50 @@
+<template>
+<div>
+	<ProfileInfo :enrolledPrograms="enrolledPrograms"></ProfileInfo>
+	<div v-if="enrolledPrograms">
+		<CardList :title="'Your Progress'" :description="''" :sectionType="'section-padding section-bg'">
+	        <ProgressCard slot="card-list-slot" v-for="program in enrolledPrograms" :program="program" :key="program"/>
+	    </CardList>
+		<CardList :title="'Quiz Attempts'" :description="''" :sectionType="'section-padding section'">
+	        <ScoreCard slot="card-list-slot" v-for="program in enrolledPrograms" :program="program" :key="program"/>
+	    </CardList>
+	</div>
+	<div v-else>
+		You haven't enrolled in any programs yet.
+	</div>
+
+</div>
+</template>
+<script>
+import Button from '../components/Button.vue';
+import TopSection from "../components/TopSection.vue"
+import CardList from "../components/CardList.vue"
+import ProgressCard from "../components/ProgressCard.vue"
+import ProfileInfo from "../components/ProfileInfo.vue"
+import ScoreCard from "../components/ScoreCard.vue"
+
+export default {
+    name: "ProfilePage",
+    components: {
+        AButton: Button,
+		TopSection,
+		CardList,
+		ProfileInfo,
+		ProgressCard,
+		ScoreCard
+	},
+	data() {
+		return {
+			enrolledPrograms: {},
+		}
+	},
+	mounted() {
+        this.getEnrolledPrograms().then(data => this.enrolledPrograms = data);
+    },
+    methods: {
+        getEnrolledPrograms() {
+            return lms.call("get_program_enrollments")
+        }
+    }
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/pages/ProgramPage.vue b/erpnext/public/js/education/lms/pages/ProgramPage.vue
new file mode 100644
index 0000000..2a13661
--- /dev/null
+++ b/erpnext/public/js/education/lms/pages/ProgramPage.vue
@@ -0,0 +1,49 @@
+<template>
+<div>
+	<breadcrumb></breadcrumb>
+	<TopSection v-bind:title="program.program_name" v-bind:description="program.description">
+    </TopSection>
+	<CardList :title="'Courses'" :description="''" :sectionType="'section-padding'">
+        <CourseCard slot="card-list-slot" v-for="course in courseData" :course="course" :program_name="program_name" :key="course.name"/>
+    </CardList>
+</div>
+</template>
+<script>
+import TopSection from "../components/TopSection.vue"
+import CardList from "../components/CardList.vue"
+import CourseCard from "../components/CourseCard.vue"
+import Breadcrumb from "../components/Breadcrumb.vue"
+
+export default {
+	props: ['program_name'],
+    name: "ProgramPage",
+    components: {
+		TopSection,
+		CardList,
+		CourseCard,
+		Breadcrumb
+	},
+	data() {
+		return {
+			program: {},
+			courseData: [],
+		}
+	},
+	mounted() {
+		this.getProgramDetails().then(data => this.program = data);
+		this.getCourses().then(data => this.courseData = data);
+	},
+	methods: {
+		getProgramDetails() {
+			return lms.call('get_program', {
+				program_name: this.program_name
+			});
+		},
+		getCourses() {
+			return lms.call('get_courses', {
+				program_name: this.program_name
+			})
+		}
+	}
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/lms/routes.js b/erpnext/public/js/education/lms/routes.js
new file mode 100644
index 0000000..483f222
--- /dev/null
+++ b/erpnext/public/js/education/lms/routes.js
@@ -0,0 +1,92 @@
+import Home from "./pages/Home.vue";
+import ProgramPage from "./pages/ProgramPage.vue";
+import CoursePage from "./pages/CoursePage.vue";
+import ContentPage from "./pages/ContentPage.vue";
+import ListPage from "./pages/ListPage.vue";
+import ProfilePage from "./pages/ProfilePage.vue";
+
+const routes = [{
+	name: 'home',
+	path: '',
+	component: Home
+},
+{
+	name: 'program',
+	path: '/Program/:program_name',
+	component: ProgramPage,
+	props: true
+},
+{
+	name: 'course',
+	path: '/Program/:program_name/:course_name/',
+	component: CoursePage,
+	props: true,
+},
+{
+	name: 'content',
+	path: '/Program/:program_name/:course_name/:topic/:type/:content',
+	component: ContentPage,
+	props: true,
+	beforeRouteUpdate (to, from, next) {
+		if (lms.store.checkProgramEnrollment(to.params.program_name)) {
+			next();
+		} else {
+			next({
+				name: 'program',
+				params: {
+					program_name: to.params.program_name
+				}
+			});
+		}
+	}
+},
+{
+	name: 'list',
+	path: '/List/:master',
+	component: ListPage,
+	props: true
+},
+{
+	name: 'signup',
+	path: '/Signup',
+	beforeEnter(to, from, next) {
+		window.location = window.location.origin.toString() + '/login#signup';
+	},
+	component: Home,
+	props: true
+},
+{
+	name: 'login',
+	path: '/Login',
+	beforeEnter(to, from, next) {
+		window.location = window.location.origin.toString() + '/login#login';
+	},
+	component: Home,
+	props: true
+},
+{
+	name: 'logout',
+	path: '/Logout',
+	beforeEnter(to, from, next) {
+		window.location = window.location.origin.toString() + '/?cmd=web_logout';
+	},
+	component: Home,
+	props: true
+},
+{
+	name: 'profile',
+	path: '/Profile',
+	component: ProfilePage,
+	props: true,
+	beforeEnter: (to, from, next) => {
+		if (!lms.store.checkLogin()) {
+			next({
+				name: 'home'
+			});
+		} else {
+			next();
+		}
+	}
+}];
+
+export default routes;
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index cd69dd4..b8c4604 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -412,7 +412,6 @@
 @frappe.whitelist()
 def make_sales_invoice(source_name, target_doc=None):
 	doc = frappe.get_doc('Delivery Note', source_name)
-	sales_orders = [d.against_sales_order for d in doc.items]
 	returned_qty_map = get_returned_qty_map(source_name)
 	invoiced_qty_map = get_invoiced_qty_map(source_name)
 
@@ -452,7 +451,7 @@
 				returned_qty = 0
 		return pending_qty, returned_qty
 
-	doc = get_mapped_doc("Delivery Note", source_name, 	{
+	doc = get_mapped_doc("Delivery Note", source_name, {
 		"Delivery Note": {
 			"doctype": "Sales Invoice",
 			"validation": {
@@ -470,7 +469,7 @@
 				"cost_center": "cost_center"
 			},
 			"postprocess": update_item,
-			"filter": lambda d: get_pending_qty(d)[0]<=0
+			"filter": lambda d: get_pending_qty(d)[0] <= 0 if not doc.get("is_return") else get_pending_qty(d)[0] > 0
 		},
 		"Sales Taxes and Charges": {
 			"doctype": "Sales Taxes and Charges",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 71cf1da..6953279 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -457,7 +457,7 @@
 				"asset": "asset",
 			},
 			"postprocess": update_item,
-			"filter": lambda d: get_pending_qty(d)[0]<=0
+			"filter": lambda d: get_pending_qty(d)[0] <= 0 if not doc.get("is_return") else get_pending_qty(d)[0] > 0
 		},
 		"Purchase Taxes and Charges": {
 			"doctype": "Purchase Taxes and Charges",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index da2d09f..a6af4bd 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -35,7 +35,7 @@
 
 class StockEntry(StockController):
 	def get_feed(self):
-		return _("From {0} to {1}").format(self.from_warehouse, self.to_warehouse)
+		return self.stock_entry_type
 
 	def onload(self):
 		for item in self.get("items"):
diff --git a/erpnext/stock/report/inactive_items/__init__.py b/erpnext/stock/report/inactive_items/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/report/inactive_items/__init__.py
diff --git a/erpnext/stock/report/inactive_items/inactive_items.js b/erpnext/stock/report/inactive_items/inactive_items.js
new file mode 100644
index 0000000..39dfd5c
--- /dev/null
+++ b/erpnext/stock/report/inactive_items/inactive_items.js
@@ -0,0 +1,34 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Inactive Items"] = {
+	"filters": [
+		{
+			fieldname: "item",
+			label: __("Item"),
+			fieldtype: "Link",
+			options: "Item"
+		},
+		{
+			fieldname: "item_group",
+			label: __("Item Group"),
+			fieldtype: "Link",
+			options: "Item Group"
+		},
+		{
+			fieldname: "based_on",
+			label: __("Based On"),
+			fieldtype: "Select",
+			options: "Sales Order\nSales Invoice",
+			default: "Sales Order"
+		},
+		{
+			fieldname: "days",
+			label: __("Days Since Last order"),
+			fieldtype: "Select",
+			options: [30, 60, 90],
+			default: 30
+		},
+	]
+}
diff --git a/erpnext/stock/report/inactive_items/inactive_items.json b/erpnext/stock/report/inactive_items/inactive_items.json
new file mode 100644
index 0000000..b9eb05e
--- /dev/null
+++ b/erpnext/stock/report/inactive_items/inactive_items.json
@@ -0,0 +1,31 @@
+{
+ "add_total_row": 0, 
+ "creation": "2019-04-16 16:05:00.647308", 
+ "disable_prepared_report": 0, 
+ "disabled": 0, 
+ "docstatus": 0, 
+ "doctype": "Report", 
+ "idx": 0, 
+ "is_standard": "Yes", 
+ "letter_head": "Test Letter Head 1", 
+ "modified": "2019-04-16 16:06:33.630043", 
+ "modified_by": "Administrator", 
+ "module": "Stock", 
+ "name": "Inactive Items", 
+ "owner": "Administrator", 
+ "prepared_report": 0, 
+ "ref_doctype": "Sales Invoice", 
+ "report_name": "Inactive Items", 
+ "report_type": "Script Report", 
+ "roles": [
+  {
+   "role": "Accounts User"
+  }, 
+  {
+   "role": "Accounts Manager"
+  }, 
+  {
+   "role": "Auditor"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/stock/report/inactive_items/inactive_items.py b/erpnext/stock/report/inactive_items/inactive_items.py
new file mode 100644
index 0000000..8d87912
--- /dev/null
+++ b/erpnext/stock/report/inactive_items/inactive_items.py
@@ -0,0 +1,148 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import getdate, add_days, today, cint
+from frappe import _
+
+def execute(filters=None):
+
+	columns = get_columns()
+	data = get_data(filters)
+	return columns, data
+
+def get_columns():
+
+	columns = [
+		{
+			"fieldname": "territory",
+			"fieldtype": "Link",
+			"label": _("Territory"),
+			"options": "Territory",
+			"width": 100
+		},
+		{
+			"fieldname": "item_group",
+			"fieldtype": "Link",
+			"label": _("Item Group"),
+			"options": "Item Group",
+			"width": 150
+		},
+		{
+			"fieldname": "item_name",
+			"fieldtype": "Link",
+			"options": "Item",
+			"label": "Item",
+			"width": 150
+		},
+		{
+			"fieldname": "item_name",
+			"fieldtype": "Data",
+			"label": _("Item Name"),
+			"width": 150
+		},
+
+		{
+			"fieldname": "customer",
+			"fieldtype": "Link",
+			"label": _("Customer"),
+			"options": "Customer",
+			"width": 100
+		},
+		{
+			"fieldname": "last_order_date",
+			"fieldtype": "Date",
+			"label": _("Last Order Date"),
+			"width": 100
+		},
+		{
+			"fieldname": "qty",
+			"fieldtype": "Float",
+			"label": _("Quantity"),
+			"width": 100
+		},
+		{
+			"fieldname": "days_since_last_order",
+			"fieldtype": "Int",
+			"label": _("Days Since Last Order"),
+			"width": 100
+		},
+	]
+
+	return columns
+
+
+def get_data(filters):
+
+	data = []
+	items = get_items(filters)
+	sales_invoice_data = get_sales_details(filters)
+
+	for item in items:
+		if sales_invoice_data.get(item.name):
+			item_obj = sales_invoice_data[item.name]
+			if item_obj.days_since_last_order > cint(filters['days']):
+				row = {
+					"territory": item_obj.territory,
+					"item_group": item_obj.item_group,
+					"item": item_obj.name,
+					"item_name": item_obj.item_name,
+					"customer": item_obj.customer,
+					"last_order_date": item_obj.last_order_date,
+					"qty": item_obj.qty,
+					"days_since_last_order": item_obj.days_since_last_order
+				}
+				data.append(row)
+		else:
+			row = {
+				"item_group": item.item_group,
+				"item": item.name,
+				"item_name": item.item_name
+			}
+			data.append(row)
+
+	return data
+
+
+def get_sales_details(filters):
+
+	data = []
+	item_details_map = {}
+
+	date_field = "s.transaction_date" if filters["based_on"] == "Sales Order" else "s.posting_date"
+
+	sales_data = frappe.db.sql("""
+		select s.territory, s.customer, si.item_group, si.item_name, si.qty, {date_field} as last_order_date,
+		DATEDIFF(CURDATE(), {date_field}) as days_since_last_order
+		from `tab{doctype}` s, `tab{doctype} Item` si
+		where s.name = si.parent and s.docstatus = 1
+		group by si.name order by days_since_last_order """ #nosec
+		.format(date_field = date_field, doctype = filters['based_on']), as_dict=1)
+
+	for d in sales_data:
+		item_details_map.setdefault(d.item_name, d)
+
+	return item_details_map
+
+def get_items(filters):
+
+	filters_dict = {
+		"disabled": 0,
+		"is_stock_item": 1
+	}
+
+	if filters.get("item_group"):
+		filters_dict.update({
+			"item_group": filters["item_group"]
+		})
+
+	if filters.get("item"):
+		filters_dict.update({
+			"name": filters["item"]
+		})
+
+	items = frappe.get_all("Item", fields=["name", "item_group", "item_name"], filters=filters_dict, order_by="name")
+
+	return items
+
diff --git a/erpnext/www/lms.html b/erpnext/www/lms.html
new file mode 100644
index 0000000..1796194
--- /dev/null
+++ b/erpnext/www/lms.html
@@ -0,0 +1,10 @@
+{% extends "templates/web.html" %}
+
+{% block title %}{{ heading or "LMS"}}{% endblock %}
+
+{% block navbar %}{% endblock %}
+
+{% block content %}
+<div id="lms-app"></div>
+<script type="text/javascript" src="/assets/js/lms.min.js"></script>
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/lms.py b/erpnext/www/lms.py
new file mode 100644
index 0000000..7561d73
--- /dev/null
+++ b/erpnext/www/lms.py
@@ -0,0 +1,242 @@
+from __future__ import unicode_literals
+import erpnext.education.utils as utils
+import frappe
+from frappe import _
+
+# LMS Utils to Update State for Vue Store
+@frappe.whitelist()
+def get_program_enrollments():
+	student = utils.get_current_student()
+	if student == None:
+		return None
+	return student.get_program_enrollments()
+
+@frappe.whitelist()
+def get_all_course_enrollments():
+	student = utils.get_current_student()
+	if student == None:
+		return None
+	return student.get_all_course_enrollments()
+
+# Vue Client Functions
+@frappe.whitelist(allow_guest=True)
+def get_portal_details():
+	"""
+	Returns portal details from Education Settings Doctype. This contains the Title and Description for LMS amoung other things.
+	"""
+	from erpnext import get_default_company
+
+	settings = frappe.get_doc("Education Settings")
+	title = settings.portal_title or get_default_company()
+	description = settings.description
+	return dict(title=title, description=description)
+
+@frappe.whitelist(allow_guest=True)
+def get_featured_programs():
+	featured_program_names = frappe.get_all("Program", filters={"is_published": True, "is_featured": True})
+	if featured_program_names:
+		featured_list = [utils.get_program_and_enrollment_status(program['name']) for program in featured_program_names]
+		return featured_list
+	else:
+		return get_all_programs()[:2]
+
+@frappe.whitelist(allow_guest=True)
+def get_all_programs():
+	program_names = frappe.get_all("Program", filters={"is_published": True})
+	if program_names:
+		program_list = [utils.get_program_and_enrollment_status(program['name']) for program in program_names]
+		return program_list
+
+@frappe.whitelist(allow_guest=True)
+def get_program(program_name):
+	try:
+		return frappe.get_doc('Program', program_name)
+	except frappe.DoesNotExistError:
+		frappe.throw(_("Program {0} does not exist.".format(program_name)))
+
+# Functions to get program & course details
+@frappe.whitelist(allow_guest=True)
+def get_courses(program_name):
+	program = frappe.get_doc('Program', program_name)
+	courses = program.get_course_list()
+	return courses
+
+@frappe.whitelist()
+def get_next_content(current_content, current_content_type, topic):
+	if frappe.session.user == "Guest":
+		return None
+	topic = frappe.get_doc("Topic", topic)
+	content_list = [{'content_type':item.doctype, 'content':item.name} for item in topic.get_contents()]
+	current_index = content_list.index({'content': current_content, 'content_type': current_content_type})
+	try:
+		return content_list[current_index + 1]
+	except IndexError:
+		return None
+
+def get_quiz_with_answers(quiz_name):
+	try:
+		quiz = frappe.get_doc("Quiz", quiz_name).get_questions()
+		quiz_output = [{'name':question.name, 'question':question.question, 'options':[{'name': option.name, 'option':option.option, 'is_correct':option.is_correct} for option in question.options]} for question in quiz]
+		return quiz_output
+	except:
+		frappe.throw("Quiz {0} does not exist".format(quiz_name))
+		return None
+
+@frappe.whitelist()
+def get_quiz_without_answers(quiz_name, course_name):
+	try:
+		quiz = frappe.get_doc("Quiz", quiz_name)
+		questions = quiz.get_questions()
+	except:
+		frappe.throw("Quiz {0} does not exist".format(quiz_name))
+		return None
+
+	if utils.check_super_access():
+		quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions]
+		return { 'quizData': quiz_output, 'status': None}
+
+	enrollment = utils.get_course_enrollment(course_name).name
+	quiz_progress = {}
+	quiz_progress['is_complete'], quiz_progress['score'], quiz_progress['result']  = utils.check_quiz_completion(quiz, enrollment)
+	quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions]
+	return { 'quizData': quiz_output, 'status': quiz_progress}
+
+@frappe.whitelist()
+def evaluate_quiz(course, quiz_response, quiz_name):
+	"""LMS Function: Evaluates a simple multiple choice quiz.
+	:param course: name of the course
+	:param quiz_response: contains user selected choices for a quiz in the form of a string formatted as a dictionary. The function uses `json.loads()` to convert it to a python dictionary.
+	:param quiz_name: Name of the quiz attempted
+	"""
+	import json
+	quiz_response = json.loads(quiz_response)
+	quiz = frappe.get_doc("Quiz", quiz_name)
+	answers, score, status = quiz.evaluate(quiz_response, quiz_name)
+	print(answers)
+
+	course_enrollment = utils.get_course_enrollment(course)
+	if course_enrollment:
+		course_enrollment.add_quiz_activity(quiz_name, quiz_response, answers, score, status)
+
+	return score
+
+@frappe.whitelist()
+def enroll_in_program(program_name):
+	student = utils.get_current_student()
+	if not student:
+		student = utils.create_student_from_current_user()
+	program_enrollment = student.enroll_in_program(program_name)
+	return program_name
+
+# Academdy Activity
+@frappe.whitelist()
+def add_activity(course, content_type, content):
+	if not utils.get_current_student():
+		return
+	enrollment = utils.get_course_enrollment(course)
+	enrollment.add_activity(content_type, content)
+
+@frappe.whitelist()
+def get_student_course_details(course_name, program_name):
+	"""
+	Return the porgress of a course in a program as well as the content to continue from.
+		:param course_name:
+		:param program_name:
+	"""
+	student = utils.get_current_student()
+	if not student:
+		return {'flag':'Start Course' }
+
+	course_enrollment = utils.get_course_enrollment(course_name)
+	program_enrollment = utils.get_program_enrollment(program_name)
+
+	if not program_enrollment:
+		return None
+
+	if not course_enrollment:
+		course_enrollment = utils.enroll_in_course(course_name, program_name)
+
+	progress = course_enrollment.get_progress(student)
+	count = sum([activity['is_complete'] for activity in progress])
+	if count == 0:
+		return {'flag':'Start Course'}
+	elif count == len(progress):
+		return {'flag':'Completed'}
+	elif count < len(progress):
+		next_item = next(item for item in progress if item['is_complete']==False)
+		return {'flag':'Continue'}
+
+@frappe.whitelist()
+def get_student_topic_details(topic_name, course_name):
+	"""
+	Return the porgress of a course in a program as well as the content to continue from.
+		:param topic_name:
+		:param course_name:
+	"""
+	topic = frappe.get_doc("Topic", topic_name)
+	student = utils.get_current_student()
+	if not student:
+		topic_content = topic.get_all_children()
+		if topic_content:
+			return {'flag':'Start Course', 'content_type': topic_content[0].content_type, 'content': topic_content[0].content}
+		else:
+			return None
+	course_enrollment = utils.get_course_enrollment(course_name)
+	progress = student.get_topic_progress(course_enrollment.name, topic)
+	if not progress:
+		return { 'flag':'Start Topic', 'content_type': None, 'content': None }
+	count = sum([activity['is_complete'] for activity in progress])
+	if count == 0:
+		return {'flag':'Start Topic', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']}
+	elif count == len(progress):
+		return {'flag':'Completed', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']}
+	elif count < len(progress):
+		next_item = next(item for item in progress if item['is_complete']==False)
+		return {'flag':'Continue', 'content_type': next_item['content_type'], 'content': next_item['content']}
+
+@frappe.whitelist()
+def get_program_progress(program_name):
+	program_enrollment = frappe.get_doc("Program Enrollment", utils.get_program_enrollment(program_name))
+	if not program_enrollment:
+		return None
+	else:
+		return program_enrollment.get_program_progress()
+
+@frappe.whitelist()
+def get_joining_date():
+	student = utils.get_current_student()
+	if student:
+		return student.joining_date
+
+@frappe.whitelist()
+def get_quiz_progress_of_program(program_name):
+	program_enrollment = frappe.get_doc("Program Enrollment", utils.get_program_enrollment(program_name))
+	if not program_enrollment:
+		return None
+	else:
+		return program_enrollment.get_quiz_progress()
+
+
+@frappe.whitelist(allow_guest=True)
+def get_course_details(course_name):
+	try:
+		course = frappe.get_doc('Course', course_name)
+		return course
+	except:
+		return None
+
+# Functions to get program & course details
+@frappe.whitelist(allow_guest=True)
+def get_topics(course_name):
+	try:
+		course = frappe.get_doc('Course', course_name)
+		return course.get_topics()
+	except frappe.DoesNotExistError:
+		frappe.throw(_("Course {0} does not exist.".format(course_name)))
+
+@frappe.whitelist()
+def get_content(content_type, content):
+	try:
+		return frappe.get_doc(content_type, content)
+	except frappe.DoesNotExistError:
+		frappe.throw(_("{0} {1} does not exist.".format(content_type, content)))
\ No newline at end of file
diff --git a/erpnext/www/test_lms.py b/erpnext/www/test_lms.py
new file mode 100644
index 0000000..e63f4c9
--- /dev/null
+++ b/erpnext/www/test_lms.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies and Contributors
+# See license.txt
+from __future__ import unicode_literals
+from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
+
+import frappe
+import unittest
+
+class TestLms(unittest.TestCase):
+    pass
\ No newline at end of file