Merge pull request #6970 from komsel2228/develop

fix bugs uom and conversion factor on stock entry
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index d0fec44..b9846c8 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -2,7 +2,7 @@
 from __future__ import unicode_literals
 import frappe
 
-__version__ = '7.1.13'
+__version__ = '7.1.15'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 55b9b7e..9d891a5 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -69,11 +69,20 @@
 		from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
 		from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
 		unlink_ref_doc_from_payment_entries(self.doctype, self.name)
-		unlink_ref_doc_from_salary_slip(self.name)		
+		unlink_ref_doc_from_salary_slip(self.name)
 		self.make_gl_entries(1)
 		self.update_advance_paid()
 		self.update_expense_claim()
-		
+		self.unlink_advance_entry_reference()
+
+	def unlink_advance_entry_reference(self):
+		for d in self.get("accounts"):
+			if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
+				doc = frappe.get_doc(d.reference_type, d.reference_name)
+				doc.delink_advance_entries(self.name)
+				d.reference_type = ''
+				d.reference_name = ''
+				d.db_update()
 
 	def validate_party(self):
 		for d in self.get("accounts"):
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 6ecd8fa..ce0cb50 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -406,7 +406,10 @@
 
 		if(!frm.doc.paid_amount && frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
 			frm.set_value("paid_amount", frm.doc.received_amount);
-			frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
+
+			if(frm.doc.target_exchange_rate) {
+				frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
+			}
 			frm.set_value("base_paid_amount", frm.doc.base_received_amount);
 		}
 
@@ -426,7 +429,10 @@
 				(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
 			
 			frm.set_value("received_amount", frm.doc.paid_amount);
-			frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
+
+			if(frm.doc.source_exchange_rate) {
+				frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
+			}
 			frm.set_value("base_received_amount", frm.doc.base_paid_amount);
 		}
 		
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 7b9bf16..d4f8edb 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -60,7 +60,14 @@
 		self.setup_party_account_field()
 		self.make_gl_entries(cancel=1)
 		self.update_advance_paid()
-							
+		self.delink_advance_entry_references()
+	
+	def delink_advance_entry_references(self):
+		for reference in self.references:
+			if reference.reference_doctype in ("Sales Invoice", "Purchase Invoice"):
+				doc = frappe.get_doc(reference.reference_doctype, reference.reference_name)
+				doc.delink_advance_entries(self.name)
+
 	def set_missing_values(self):
 		if self.payment_type == "Internal Transfer":
 			for field in ("party", "party_balance", "total_allocated_amount", 
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index b4b8444..d8c9b04 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -437,6 +437,85 @@
 
 		self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no,
 			"warehouse"), pi.get("items")[0].rejected_warehouse)
+	
+	def test_outstanding_amount_after_advance_jv_cancelation(self):
+		from erpnext.accounts.doctype.journal_entry.test_journal_entry \
+			import test_records as jv_test_records
+
+		jv = frappe.copy_doc(jv_test_records[1])
+		jv.insert()
+		jv.submit()
+
+		pi = frappe.copy_doc(test_records[0])
+		pi.append("advances", {
+			"reference_type": "Journal Entry",
+			"reference_name": jv.name,
+			"reference_row": jv.get("accounts")[0].name,
+			"advance_amount": 400,
+			"allocated_amount": 300,
+			"remarks": jv.remark
+		})
+		pi.insert()
+		pi.submit()
+		pi.load_from_db()
+		
+		#check outstanding after advance allocation
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
+		
+		#added to avoid Document has been modified exception
+		jv = frappe.get_doc("Journal Entry", jv.name)
+		jv.cancel()
+		
+		pi.load_from_db()
+		#check outstanding after advance cancellation
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
+
+	def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
+		pe = frappe.get_doc({
+			"doctype": "Payment Entry",
+			"payment_type": "Pay",
+			"party_type": "Supplier",
+			"party": "_Test Supplier",
+			"company": "_Test Company",
+			"paid_from_account_currency": "INR",
+			"paid_to_account_currency": "INR",
+			"source_exchange_rate": 1,
+			"target_exchange_rate": 1,
+			"reference_no": "1",
+			"reference_date": nowdate(),
+			"received_amount": 300,
+			"paid_amount": 300,
+			"paid_from": "_Test Cash - _TC",
+			"paid_to": "_Test Payable - _TC"
+		})
+		pe.insert()
+		pe.submit()
+		
+		pi = frappe.copy_doc(test_records[0])
+		pi.is_pos = 0
+		pi.append("advances", {
+			"doctype": "Purchase Invoice Advance",
+			"reference_type": "Payment Entry",
+			"reference_name": pe.name,
+			"advance_amount": 300,
+			"allocated_amount": 300,
+			"remarks": pe.remarks
+		})
+		pi.insert()
+		pi.submit()
+		
+		pi.load_from_db()
+
+		#check outstanding after advance allocation
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
+		
+		#added to avoid Document has been modified exception
+		pe = frappe.get_doc("Payment Entry", pe.name)
+		pe.cancel()
+		
+		pi.load_from_db()
+		#check outstanding after advance cancellation
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
 
 def unlink_payment_on_cancel_of_invoice(enable=1):
 	accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 0011dfe..511eeaa 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -980,6 +980,86 @@
 		pe.submit()
 
 		self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
+	
+	def test_outstanding_amount_after_advance_jv_cancelation(self):
+		from erpnext.accounts.doctype.journal_entry.test_journal_entry \
+			import test_records as jv_test_records
+
+		jv = frappe.copy_doc(jv_test_records[0])
+		jv.insert()
+		jv.submit()
+
+		si = frappe.copy_doc(test_records[0])
+		si.append("advances", {
+			"doctype": "Sales Invoice Advance",
+			"reference_type": "Journal Entry",
+			"reference_name": jv.name,
+			"reference_row": jv.get("accounts")[0].name,
+			"advance_amount": 400,
+			"allocated_amount": 300,
+			"remarks": jv.remark
+		})
+		si.insert()
+		si.submit()
+		si.load_from_db()
+
+		#check outstanding after advance allocation
+		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
+		
+		#added to avoid Document has been modified exception
+		jv = frappe.get_doc("Journal Entry", jv.name)
+		jv.cancel()
+		
+		si.load_from_db()
+		#check outstanding after advance cancellation
+		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
+	
+	def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
+		pe = frappe.get_doc({
+			"doctype": "Payment Entry",
+			"payment_type": "Receive",
+			"party_type": "Customer",
+			"party": "_Test Customer",
+			"company": "_Test Company",
+			"paid_from_account_currency": "INR",
+			"paid_to_account_currency": "INR",
+			"source_exchange_rate": 1,
+			"target_exchange_rate": 1,
+			"reference_no": "1",
+			"reference_date": nowdate(),
+			"received_amount": 300,
+			"paid_amount": 300,
+			"paid_from": "_Test Receivable - _TC",
+			"paid_to": "_Test Cash - _TC"
+		})
+		pe.insert()
+		pe.submit()
+		
+		si = frappe.copy_doc(test_records[0])
+		si.is_pos = 0
+		si.append("advances", {
+			"doctype": "Sales Invoice Advance",
+			"reference_type": "Payment Entry",
+			"reference_name": pe.name,
+			"advance_amount": 300,
+			"allocated_amount": 300,
+			"remarks": pe.remarks
+		})
+		si.insert()
+		si.submit()
+		
+		si.load_from_db()
+
+		#check outstanding after advance allocation
+		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
+		
+		#added to avoid Document has been modified exception
+		pe = frappe.get_doc("Payment Entry", pe.name)
+		pe.cancel()
+		
+		si.load_from_db()
+		#check outstanding after advance cancellation
+		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
 
 def create_sales_invoice(**args):
 	si = frappe.new_doc("Sales Invoice")
diff --git a/erpnext/config/schools.py b/erpnext/config/schools.py
index 6acf081..41a8e71 100644
--- a/erpnext/config/schools.py
+++ b/erpnext/config/schools.py
@@ -73,6 +73,10 @@
 				},
 				{
 					"type": "doctype",
+					"name": "Student Batch Attendance Tool"
+				},
+				{
+					"type": "doctype",
 					"name": "Scheduling Tool"
 				}
 			]
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 6da496b..98390ff 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -32,12 +32,13 @@
 
  # searches for active employees
 def employee_query(doctype, txt, searchfield, start, page_len, filters):
+	conditions = []
 	return frappe.db.sql("""select name, employee_name from `tabEmployee`
 		where status = 'Active'
 			and docstatus < 2
 			and ({key} like %(txt)s
 				or employee_name like %(txt)s)
-			{mcond}
+			{fcond} {mcond}
 		order by
 			if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
 			if(locate(%(_txt)s, employee_name), locate(%(_txt)s, employee_name), 99999),
@@ -45,6 +46,7 @@
 			name, employee_name
 		limit %(start)s, %(page_len)s""".format(**{
 			'key': searchfield,
+			'fcond': get_filters_cond(doctype, filters, conditions),
 			'mcond': get_match_cond(doctype)
 		}), {
 			'txt': "%%%s%%" % txt,
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 68e9155..60cd68c 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -164,14 +164,18 @@
 				frappe.throw(_("Maxiumm discount for Item {0} is {1}%").format(d.item_code, discount))
 
 	def validate_selling_price(self):
+		def throw_message(item_name, rate, ref_rate_field):
+			frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""")
+				.format(item_name, ref_rate_field, rate))
+
 		if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
 			return
 
 		for it in self.get("items"):
-			last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.name, ["last_purchase_rate", "is_stock_item"])
+			last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
 
 			if flt(it.base_rate) < flt(last_purchase_rate):
-				throw(it.name, last_purchase_rate, "last purchase rate")
+				throw_message(it.item_name, last_purchase_rate, "last purchase rate")
 
 			last_valuation_rate = frappe.db.sql("""
 				SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
@@ -182,9 +186,6 @@
 			if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate):
 				throw_message(it.name, last_valuation_rate, "valuation rate")
 
-		def throw_message(item_name, rate, ref_rate_field):
-			frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""")
-				.format(item_name, ref_rate_field, rate))
 
 	def get_item_list(self):
 		il = []
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index a51e2b5..c6a92ca 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -408,13 +408,13 @@
 	query = """select name, from_date, to_date, employee_name, half_day,
 		status, employee, docstatus
 		from `tabLeave Application` where
-		(from_date between %s and %s or to_date between %s and %s)
+		from_date <= %(end)s and to_date >= %(start)s <= to_date
 		and docstatus < 2
 		and status!="Rejected" """
 	if match_conditions:
 		query += " and " + match_conditions
 
-	for d in frappe.db.sql(query, (start, end, start, end), as_dict=True):
+	for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True):
 		e = {
 			"name": d.name,
 			"doctype": "Leave Application",
diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py
index 3554669..2077982 100644
--- a/erpnext/hr/doctype/process_payroll/process_payroll.py
+++ b/erpnext/hr/doctype/process_payroll/process_payroll.py
@@ -22,7 +22,7 @@
 
 		sal_struct = frappe.db.sql("""
 				select name from `tabSalary Structure`
-				where docstatus != 2 and company = %(company)s and
+				where docstatus != 2 and is_active = 'Yes' and company = %(company)s and
 				ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s""",
 				{"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
 		
@@ -51,8 +51,8 @@
 
 	def get_joining_releiving_condition(self):
 		cond = """
-			and ifnull(t1.date_of_joining, '0000-00-00') <= '%(from_date)s'
-			and ifnull(t1.relieving_date, '2199-12-31') >= '%(to_date)s'
+			and ifnull(t1.date_of_joining, '0000-00-00') <= '%(to_date)s'
+			and ifnull(t1.relieving_date, '2199-12-31') >= '%(from_date)s'
 		""" % {"from_date": self.from_date, "to_date": self.to_date}
 		return cond
 
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index 334e8a5..c5df2e6 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -28,7 +28,15 @@
 					type: "deduction"
 				}
 			}
-		})
+		});
+		frm.set_query("employee", "employees", function(doc) {
+			return {
+				query: "erpnext.controllers.queries.employee_query",
+				filters: {
+					company: doc.company
+				}
+			}
+		});
 	},
 	
 	refresh: function(frm) {
@@ -182,11 +190,3 @@
 		calculate_totals(frm.doc);
 	}
 })
-
-frappe.ui.form.on('Salary Structure Employee', {
-	onload: function(frm) {
-		frm.set_query("employee","employees", function(doc,cdt,cdn) {
-			return{ query: "erpnext.controllers.queries.employee_query" }
-		})
-	}
-});
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 3934935..7d0405b 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -523,9 +523,9 @@
 		planned_end_date, status
 		from `tabProduction Order`
 		where ((ifnull(planned_start_date, '0000-00-00')!= '0000-00-00') \
-				and (planned_start_date between %(start)s and %(end)s) \
-			or ((ifnull(planned_start_date, '0000-00-00')!= '0000-00-00') \
-				and planned_end_date between %(start)s and %(end)s)) {conditions}
+				and (planned_start_date <= %(end)s) \
+			and ((ifnull(planned_start_date, '0000-00-00')!= '0000-00-00') \
+				and planned_end_date >= %(start)s)) {conditions}
 		""".format(conditions=conditions), {
 			"start": start,
 			"end": end
diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json
index 8d844cd..d9f3082 100644
--- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json
+++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.json
@@ -816,7 +816,7 @@
  "issingle": 1, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2016-08-17 05:35:34.331954", 
+ "modified": "2016-11-16 05:35:34.331954", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Production Planning Tool", 
diff --git a/erpnext/patches/v7_1/update_missing_salary_component_type.py b/erpnext/patches/v7_1/update_missing_salary_component_type.py
index f0e3f6a..25624f5 100644
--- a/erpnext/patches/v7_1/update_missing_salary_component_type.py
+++ b/erpnext/patches/v7_1/update_missing_salary_component_type.py
@@ -9,6 +9,8 @@
 '''
 
 def execute():
+	frappe.reload_doc("accounts", "doctype", "salary_component_account")
+	
 	for s in frappe.db.sql('''select name, type, salary_component_abbr from `tabSalary Component` 
 			where ifnull(type, "")="" or ifnull(salary_component_abbr, "") = ""''', as_dict=1):
 			
@@ -43,4 +45,4 @@
 				
 			component.salary_component_abbr = abbr
 			
-		component.save()
\ No newline at end of file
+		component.save()
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index a9b48fc..0ae2f8b 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -133,9 +133,9 @@
 	data = frappe.db.sql("""select name, exp_start_date, exp_end_date,
 		subject, status, project from `tabTask`
 		where ((ifnull(exp_start_date, '0000-00-00')!= '0000-00-00') \
-				and (exp_start_date between %(start)s and %(end)s) \
-			or ((ifnull(exp_start_date, '0000-00-00')!= '0000-00-00') \
-				and exp_end_date between %(start)s and %(end)s))
+				and (exp_start_date <= %(end)s) \
+			or ((ifnull(exp_end_date, '0000-00-00')!= '0000-00-00') \
+				and exp_end_date >= %(start)s))
 		{conditions}""".format(conditions=conditions), {
 			"start": start,
 			"end": end
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index 02e5f18..6e26212 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -362,7 +362,7 @@
 		from `tabTimesheet Detail`, `tabTimesheet` 
 		where `tabTimesheet Detail`.parent = `tabTimesheet`.name 
 			and `tabTimesheet`.docstatus < 2 
-			and (from_time between %(start)s and %(end)s) {conditions} {match_cond}
+			and (from_time <= %(end)s and to_time >= %(start)s) {conditions} {match_cond}
 		""".format(conditions=conditions, match_cond = get_match_cond('Timesheet')), 
 		{
 			"start": start,
diff --git a/erpnext/projects/doctype/timesheet/timesheet_calendar.js b/erpnext/projects/doctype/timesheet/timesheet_calendar.js
index ad81de6..b22cd09 100644
--- a/erpnext/projects/doctype/timesheet/timesheet_calendar.js
+++ b/erpnext/projects/doctype/timesheet/timesheet_calendar.js
@@ -29,4 +29,4 @@
 		}
 	],
 	get_events_method: "erpnext.projects.doctype.timesheet.timesheet.get_events"
-}
\ No newline at end of file
+}
diff --git a/erpnext/schools/api.py b/erpnext/schools/api.py
index 6011158..dea8515 100644
--- a/erpnext/schools/api.py
+++ b/erpnext/schools/api.py
@@ -30,33 +30,40 @@
 	return program_enrollment
 
 @frappe.whitelist()
-def check_attendance_records_exist(course_schedule):
-	"""Check if Attendance Records are made against the specified Course Schedule.
+def check_attendance_records_exist(course_schedule=None, student_batch=None, date=None):
+	"""Check if Attendance Records are made against the specified Course Schedule or Student Batch for given date.
 
 	:param course_schedule: Course Schedule.
+	:param student_batch: Student Batch.
+	:param date: Date.
 	"""
-	return frappe.get_list("Student Attendance", filters={"course_schedule": course_schedule})
+	if course_schedule:
+		return frappe.get_list("Student Attendance", filters={"course_schedule": course_schedule})
+	else:
+		return frappe.get_list("Student Attendance", filters={"student_batch": student_batch, "date": date})
 
 @frappe.whitelist()
-def mark_attendance(students_present, students_absent, course_schedule):
+def mark_attendance(students_present, students_absent, course_schedule=None, student_batch=None, date=None):
 	"""Creates Multiple Attendance Records.
 
 	:param students_present: Students Present JSON.
 	:param students_absent: Students Absent JSON.
 	:param course_schedule: Course Schedule.
+	:param student_batch: Student Batch.
+	:param date: Date.
 	"""
 	present = json.loads(students_present)
 	absent = json.loads(students_absent)
 
 	for d in present:
-		make_attendance_records(d["student"], d["student_name"], course_schedule, "Present")
+		make_attendance_records(d["student"], d["student_name"], "Present", course_schedule, student_batch, date)
 
 	for d in absent:
-		make_attendance_records(d["student"], d["student_name"], course_schedule, "Absent")
+		make_attendance_records(d["student"], d["student_name"], "Absent", course_schedule, student_batch, date)
 
 	frappe.msgprint(_("Attendance has been marked successfully."))
 
-def make_attendance_records(student, student_name, course_schedule, status):
+def make_attendance_records(student, student_name, status, course_schedule=None, student_batch=None, date=None):
 	"""Creates Attendance Record.
 
 	:param student: Student.
@@ -68,11 +75,22 @@
 	student_attendance.student = student
 	student_attendance.student_name = student_name
 	student_attendance.course_schedule = course_schedule
+	student_attendance.student_batch = student_batch
+	student_attendance.date = date
 	student_attendance.status = status
 	student_attendance.submit()
 	frappe.db.commit()
 
 @frappe.whitelist()
+def get_student_batch_students(student_batch):
+	"""Returns List of student, student_name in Student Batch.
+
+	:param student_batch: Student Batch.
+	"""
+	students = frappe.get_list("Student Batch Student", fields=["student", "student_name"] , filters={"parent": student_batch}, order_by= "idx")
+	return students
+
+@frappe.whitelist()
 def get_student_group_students(student_group):
 	"""Returns List of student, student_name in Student Group.
 
diff --git a/erpnext/schools/doctype/assessment/assessment.json b/erpnext/schools/doctype/assessment/assessment.json
index 9f1349c..845f2f6 100644
--- a/erpnext/schools/doctype/assessment/assessment.json
+++ b/erpnext/schools/doctype/assessment/assessment.json
@@ -92,7 +92,36 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "student_batch", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Student Batch", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Batch", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -593,7 +622,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2016-11-07 05:47:47.529783", 
+ "modified": "2016-11-16 13:05:54.953750", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Assessment", 
diff --git a/erpnext/schools/doctype/assessment/assessment.py b/erpnext/schools/doctype/assessment/assessment.py
index de6a653..cb307cb 100644
--- a/erpnext/schools/doctype/assessment/assessment.py
+++ b/erpnext/schools/doctype/assessment/assessment.py
@@ -8,56 +8,66 @@
 from frappe import _
 
 class Assessment(Document):
-    def validate(self):
-        self.validate_overlap()
-    
-    def validate_overlap(self):
-        """Validates overlap for Student Group, Supervisor, Room"""
+	def validate(self):
+		self.validate_overlap()
+	
+	def validate_overlap(self):
+		"""Validates overlap for Student Group/Student Batch, Instructor, Room"""
+		
+		from erpnext.schools.utils import validate_overlap_for
 
-        from erpnext.schools.utils import validate_overlap_for
+		#Validate overlapping course schedules.
+		if self.student_batch:
+			validate_overlap_for(self, "Course Schedule", "student_batch")
 
-        validate_overlap_for(self, "Assessment", "student_group")
-        validate_overlap_for(self, "Course Schedule", "student_group" )
-        
-        if self.room:
-            validate_overlap_for(self, "Assessment", "room")
-            validate_overlap_for(self, "Course Schedule", "room")
+		if self.student_group:
+			validate_overlap_for(self, "Course Schedule", "student_group")
+		
+		validate_overlap_for(self, "Course Schedule", "instructor")
+		validate_overlap_for(self, "Course Schedule", "room")
 
-        if self.supervisor:
-            validate_overlap_for(self, "Assessment", "supervisor")
-            validate_overlap_for(self, "Course Schedule", "instructor", self.supervisor)
+		#validate overlapping assessment schedules.
+		if self.student_batch:
+			validate_overlap_for(self, "Assessment", "student_batch")
+		
+		if self.student_group:
+			validate_overlap_for(self, "Assessment", "student_group")
+		
+		validate_overlap_for(self, "Assessment", "room")
+		validate_overlap_for(self, "Assessment", "supervisor", self.instructor)
+
 
 def get_assessment_list(doctype, txt, filters, limit_start, limit_page_length=20):
-    user = frappe.session.user
-    student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
-    if student:
-        return frappe. db.sql('''select course, schedule_date, from_time, to_time, sgs.name from `tabAssessment` as assessment, 
-            `tabStudent Group Student` as sgs where assessment.student_group = sgs.parent and sgs.student = %s and assessment.docstatus=1
-            order by assessment.name asc limit {0} , {1}'''
-            .format(limit_start, limit_page_length), student, as_dict = True)
+	user = frappe.session.user
+	student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
+	if student:
+		return frappe. db.sql('''select course, schedule_date, from_time, to_time, sgs.name from `tabAssessment` as assessment, 
+			`tabStudent Group Student` as sgs where assessment.student_group = sgs.parent and sgs.student = %s and assessment.docstatus=1
+			order by assessment.name asc limit {0} , {1}'''
+			.format(limit_start, limit_page_length), student, as_dict = True)
 
 def get_list_context(context=None):
-    return {
-        "show_sidebar": True,
-        'no_breadcrumbs': True,
-        "title": _("Assessment Schedule"),
-        "get_list": get_assessment_list,
-        "row_template": "templates/includes/assessment/assessment_row.html"
-    }
+	return {
+		"show_sidebar": True,
+		'no_breadcrumbs': True,
+		"title": _("Assessment Schedule"),
+		"get_list": get_assessment_list,
+		"row_template": "templates/includes/assessment/assessment_row.html"
+	}
 
 @frappe.whitelist()
 def get_grade(grading_structure, result):
-    grade = frappe.db.sql("""select gi.from_score, gi.to_score, gi.grade_code, gi.grade_description 
-        from `tabGrading Structure` as gs, `tabGrade Interval` as gi 
-        where gs.name = gi.parent and gs.name = %(grading_structure)s and gi.from_score <= %(result)s 
-        and gi.to_score >= %(result)s""".format(), 
-        {
-            "grading_structure":grading_structure,
-            "result": result
-        },
-        as_dict=True)
-    
-    return grade[0].grade_code if grade else ""
+	grade = frappe.db.sql("""select gi.from_score, gi.to_score, gi.grade_code, gi.grade_description 
+		from `tabGrading Structure` as gs, `tabGrade Interval` as gi 
+		where gs.name = gi.parent and gs.name = %(grading_structure)s and gi.from_score <= %(result)s 
+		and gi.to_score >= %(result)s""".format(), 
+		{
+			"grading_structure":grading_structure,
+			"result": result
+		},
+		as_dict=True)
+   	 
+	return grade[0].grade_code if grade else ""
 
 def validate_grade(score, grade):
-    pass
\ No newline at end of file
+	pass
\ No newline at end of file
diff --git a/erpnext/schools/doctype/course_schedule/course_schedule.js b/erpnext/schools/doctype/course_schedule/course_schedule.js
index 2defbd5..ab34ae9 100644
--- a/erpnext/schools/doctype/course_schedule/course_schedule.js
+++ b/erpnext/schools/doctype/course_schedule/course_schedule.js
@@ -12,7 +12,7 @@
 	},
 	
 	refresh :function(frm) {
-		if(!frm.doc.__islocal) {
+		if(!frm.doc.__islocal && frm.doc.student_group) {
 			frappe.call({
 				method: "erpnext.schools.api.check_attendance_records_exist",
 				args: {
diff --git a/erpnext/schools/doctype/course_schedule/course_schedule.json b/erpnext/schools/doctype/course_schedule/course_schedule.json
index eda1ec7..4a4b2d3 100644
--- a/erpnext/schools/doctype/course_schedule/course_schedule.json
+++ b/erpnext/schools/doctype/course_schedule/course_schedule.json
@@ -2,7 +2,7 @@
  "allow_copy": 0, 
  "allow_import": 1, 
  "allow_rename": 0, 
- "autoname": "naming_series", 
+ "autoname": "naming_series:", 
  "beta": 0, 
  "creation": "2015-09-09 16:34:04.960369", 
  "custom": 0, 
@@ -17,6 +17,35 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "student_batch", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Student Batch", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Batch", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "student_group", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -36,7 +65,7 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -75,24 +104,23 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "default": "SH", 
-   "fieldname": "naming_series", 
-   "fieldtype": "Select", 
+   "fieldname": "instructor_name", 
+   "fieldtype": "Read Only", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Naming Series", 
+   "label": "Instructor Name", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "SH", 
+   "options": "instructor.Instructor_name", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 0, 
+   "read_only": 1, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -132,26 +160,27 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "course", 
-   "fieldtype": "Read Only", 
+   "default": "SH", 
+   "fieldname": "naming_series", 
+   "fieldtype": "Select", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Course", 
+   "label": "Naming Series", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "student_group.course", 
+   "options": "SH", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 1, 
+   "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -161,26 +190,26 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "instructor_name", 
-   "fieldtype": "Read Only", 
+   "fieldname": "course", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Instructor Name", 
+   "label": "Course", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "instructor.Instructor_name", 
+   "options": "Course", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 1, 
+   "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 0, 
+   "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -449,7 +478,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2016-11-07 05:51:34.493014", 
+ "modified": "2016-11-16 16:38:00.454295", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Course Schedule", 
diff --git a/erpnext/schools/doctype/course_schedule/course_schedule.py b/erpnext/schools/doctype/course_schedule/course_schedule.py
index 11f3894..ec30c62 100644
--- a/erpnext/schools/doctype/course_schedule/course_schedule.py
+++ b/erpnext/schools/doctype/course_schedule/course_schedule.py
@@ -4,34 +4,62 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe import _
 from frappe.model.document import Document
 
 class CourseSchedule(Document):
 	def validate(self):
 		self.instructor_name = frappe.db.get_value("Instructor", self.instructor, "instructor_name")
 		self.set_title()
+		self.validate_mandatory()
+		self.validate_course()
+		self.set_student_batch()
 		self.validate_date()
 		self.validate_overlap()
-		
+	
 	def set_title(self):
 		"""Set document Title"""
 		self.title = self.course + " by " + (self.instructor_name if self.instructor_name else self.instructor)
 
+	def validate_mandatory(self):
+		if not (self.student_batch or self.student_group):
+			frappe.throw(_("""Student Batch or Student Group is mandatory"""))
+	
+	def validate_course(self):
+		if self.student_group:
+			self.course= frappe.db.get_value("Student Group", self.student_group, "course")
+	
+	def set_student_batch(self):
+		if self.student_group:
+			self.student_batch = frappe.db.get_value("Student Group", self.student_group, "student_batch")
+	
 	def validate_date(self):
 		"""Validates if from_time is greater than to_time"""
 		if self.from_time > self.to_time:
-			frappe.throw("From Time cannot be greater than To Time.")
+			frappe.throw(_("From Time cannot be greater than To Time."))
 	
 	def validate_overlap(self):
-		"""Validates overlap for Student Group, Instructor, Room"""
+		"""Validates overlap for Student Group/Student Batch, Instructor, Room"""
 		
 		from erpnext.schools.utils import validate_overlap_for
 
-		validate_overlap_for(self, "Course Schedule", "student_group" )
+		#Validate overlapping course schedules.
+		if self.student_batch:
+			validate_overlap_for(self, "Course Schedule", "student_batch")
+
+		if self.student_group:
+			validate_overlap_for(self, "Course Schedule", "student_group")
+		
 		validate_overlap_for(self, "Course Schedule", "instructor")
 		validate_overlap_for(self, "Course Schedule", "room")
 
-		validate_overlap_for(self, "Assessment", "student_group")
+		#validate overlapping assessment schedules.
+		if self.student_batch:
+			validate_overlap_for(self, "Assessment", "student_batch")
+		
+		if self.student_group:
+			validate_overlap_for(self, "Assessment", "student_group")
+		
 		validate_overlap_for(self, "Assessment", "room")
 		validate_overlap_for(self, "Assessment", "supervisor", self.instructor)
 
diff --git a/erpnext/schools/doctype/scheduling_tool/scheduling_tool.js b/erpnext/schools/doctype/scheduling_tool/scheduling_tool.js
index 7109771..5011375 100644
--- a/erpnext/schools/doctype/scheduling_tool/scheduling_tool.js
+++ b/erpnext/schools/doctype/scheduling_tool/scheduling_tool.js
@@ -1,4 +1,5 @@
 cur_frm.add_fetch("student_group", "program", "program");
+cur_frm.add_fetch("student_group", "student_batch", "student_batch");
 cur_frm.add_fetch("student_group", "course", "course");
 cur_frm.add_fetch("student_group", "academic_year", "academic_year");
 cur_frm.add_fetch("student_group", "academic_term", "academic_term");
diff --git a/erpnext/schools/doctype/scheduling_tool/scheduling_tool.json b/erpnext/schools/doctype/scheduling_tool/scheduling_tool.json
index 41a7b94..cf2c1a3 100644
--- a/erpnext/schools/doctype/scheduling_tool/scheduling_tool.json
+++ b/erpnext/schools/doctype/scheduling_tool/scheduling_tool.json
@@ -9,11 +9,42 @@
  "doctype": "DocType", 
  "document_type": "Setup", 
  "editable_grid": 0, 
+ "engine": "InnoDB", 
  "fields": [
   {
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "student_batch", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Student Batch", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Batch", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "student_group", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -21,6 +52,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Student Group", 
    "length": 0, 
    "no_copy": 0, 
@@ -30,6 +62,36 @@
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_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_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": 0, 
+   "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 1, 
    "search_index": 0, 
@@ -40,6 +102,34 @@
    "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_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, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "academic_year", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -47,6 +137,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Academic Year", 
    "length": 0, 
    "no_copy": 0, 
@@ -56,6 +147,7 @@
    "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, 
@@ -66,6 +158,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "academic_term", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -73,6 +166,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Academic Term", 
    "length": 0, 
    "no_copy": 0, 
@@ -82,6 +176,7 @@
    "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, 
@@ -92,30 +187,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "column_break_3", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "program", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -123,6 +195,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Program", 
    "length": 0, 
    "no_copy": 0, 
@@ -132,6 +205,7 @@
    "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, 
@@ -142,32 +216,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "course", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 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, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "section_break_6", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -175,6 +224,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -182,6 +232,7 @@
    "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, 
@@ -192,6 +243,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "room", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -199,6 +251,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Room", 
    "length": 0, 
    "no_copy": 0, 
@@ -208,6 +261,7 @@
    "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, 
@@ -218,6 +272,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "column_break_9", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -225,6 +280,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -232,6 +288,7 @@
    "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, 
@@ -242,6 +299,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "instructor", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -249,6 +307,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Instructor", 
    "length": 0, 
    "no_copy": 0, 
@@ -258,6 +317,7 @@
    "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, 
@@ -268,6 +328,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "instructor_name", 
    "fieldtype": "Read Only", 
    "hidden": 0, 
@@ -275,6 +336,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Instructor Name", 
    "length": 0, 
    "no_copy": 0, 
@@ -284,6 +346,7 @@
    "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, 
@@ -294,6 +357,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "section_break_7", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -301,6 +365,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -308,6 +373,7 @@
    "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, 
@@ -318,6 +384,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "default": "", 
    "fieldname": "from_time", 
    "fieldtype": "Time", 
@@ -326,6 +393,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "From Time", 
    "length": 0, 
    "no_copy": 0, 
@@ -334,6 +402,7 @@
    "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, 
@@ -344,6 +413,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "default": "", 
    "fieldname": "course_start_date", 
    "fieldtype": "Date", 
@@ -352,6 +422,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Course Start Date", 
    "length": 0, 
    "no_copy": 0, 
@@ -361,6 +432,7 @@
    "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, 
@@ -371,6 +443,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "day", 
    "fieldtype": "Select", 
    "hidden": 0, 
@@ -378,6 +451,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Day", 
    "length": 0, 
    "no_copy": 0, 
@@ -387,6 +461,7 @@
    "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, 
@@ -397,6 +472,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "rechedule", 
    "fieldtype": "Check", 
    "hidden": 0, 
@@ -404,6 +480,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Rechedule", 
    "length": 0, 
    "no_copy": 0, 
@@ -412,6 +489,7 @@
    "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, 
@@ -422,6 +500,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "column_break_15", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -429,6 +508,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -436,6 +516,7 @@
    "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, 
@@ -446,6 +527,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "to_time", 
    "fieldtype": "Time", 
    "hidden": 0, 
@@ -453,6 +535,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "To TIme", 
    "length": 0, 
    "no_copy": 0, 
@@ -461,6 +544,7 @@
    "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, 
@@ -471,6 +555,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "default": "", 
    "fieldname": "course_end_date", 
    "fieldtype": "Date", 
@@ -479,6 +564,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
+   "in_standard_filter": 0, 
    "label": "Course End Date", 
    "length": 0, 
    "no_copy": 0, 
@@ -487,6 +573,7 @@
    "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, 
@@ -505,7 +592,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2016-07-25 01:24:48.220756", 
+ "modified": "2016-11-16 16:03:41.854229", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Scheduling Tool", 
@@ -522,6 +609,7 @@
    "export": 0, 
    "if_owner": 0, 
    "import": 0, 
+   "is_custom": 0, 
    "permlevel": 0, 
    "print": 0, 
    "read": 1, 
diff --git a/erpnext/schools/doctype/scheduling_tool/scheduling_tool.py b/erpnext/schools/doctype/scheduling_tool/scheduling_tool.py
index 4a62a74..b8ba578 100644
--- a/erpnext/schools/doctype/scheduling_tool/scheduling_tool.py
+++ b/erpnext/schools/doctype/scheduling_tool/scheduling_tool.py
@@ -22,7 +22,9 @@
 		self.validate_mandatory()
 		self.validate_date()
 		self.instructor_name= frappe.db.get_value("Instructor", self.instructor, "instructor_name")
-		self.course= frappe.db.get_value("Student Group", self.student_group, "course")
+		
+		if self.student_group:
+			self.course= frappe.db.get_value("Student Group", self.student_group, "course")
 		
 		if self.rechedule:
 			rescheduled, reschedule_errors = self.delete_course_schedule(rescheduled, reschedule_errors)
@@ -54,7 +56,11 @@
 			
 	def validate_mandatory(self):
 		"""Validates all mandatory fields"""
-		fields = ['student_group', 'room', 'instructor', 'from_time', 'to_time', 'course_start_date', 'course_end_date', 'day']
+		
+		if not (self.student_batch or self.student_group):
+			frappe.throw(_("""Student Batch or Student Group is mandatory"""))
+		
+		fields = ['course', 'room', 'instructor', 'from_time', 'to_time', 'course_start_date', 'course_end_date', 'day']
 		for d in  fields:
 			if not self.get(d):
 				frappe.throw(_("{0} is mandatory").format(self.meta.get_label(d)))	
@@ -68,6 +74,8 @@
 		"""Delete all course schedule within the Date range and specified filters"""
 		schedules = frappe.get_list("Course Schedule", fields=["name", "schedule_date"], filters = 
 			[["student_group", "=", self.student_group],
+			["student_batch", "=", self.student_batch],
+			["course", "=", self.course],
 			["schedule_date", ">=", self.course_start_date], 
 			["schedule_date", "<=", self.course_end_date]])
 		for d in schedules:
@@ -85,6 +93,7 @@
 		
 		course_schedule = frappe.new_doc("Course Schedule")
 		course_schedule.student_group = self.student_group
+		course_schedule.student_batch = self.student_batch
 		course_schedule.course = self.course
 		course_schedule.instructor = self.instructor
 		course_schedule.instructor_name = self.instructor_name
diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.json b/erpnext/schools/doctype/student_applicant/student_applicant.json
index 8fbf931..18a490a 100644
--- a/erpnext/schools/doctype/student_applicant/student_applicant.json
+++ b/erpnext/schools/doctype/student_applicant/student_applicant.json
@@ -988,7 +988,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2016-11-07 05:23:37.934779", 
+ "modified": "2016-11-17 10:26:13.225135", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Student Applicant", 
diff --git a/erpnext/schools/doctype/student_attendance/student_attendance.js b/erpnext/schools/doctype/student_attendance/student_attendance.js
index 5068208..6e79d52 100644
--- a/erpnext/schools/doctype/student_attendance/student_attendance.js
+++ b/erpnext/schools/doctype/student_attendance/student_attendance.js
@@ -1,6 +1,9 @@
 // Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
 // For license information, please see license.txt
 
+cur_frm.add_fetch("course_schedule", "schedule_date", "date");
+cur_frm.add_fetch("course_schedule", "student_batch", "student_batch");
+
 frappe.ui.form.on('Student Attendance', {
 	refresh: function(frm) {
 
diff --git a/erpnext/schools/doctype/student_attendance/student_attendance.json b/erpnext/schools/doctype/student_attendance/student_attendance.json
index 9caa9ae..70fcdf3 100644
--- a/erpnext/schools/doctype/student_attendance/student_attendance.json
+++ b/erpnext/schools/doctype/student_attendance/student_attendance.json
@@ -46,18 +46,18 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "student_name", 
-   "fieldtype": "Read Only", 
+   "fieldname": "course_schedule", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
-   "in_list_view": 0, 
+   "in_list_view": 1, 
    "in_standard_filter": 0, 
-   "label": "Student Name", 
+   "label": "Course Schedule", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "student.title", 
+   "options": "Course Schedule", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -75,6 +75,34 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "date", 
+   "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "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": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "column_break_3", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -102,18 +130,18 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "course_schedule", 
-   "fieldtype": "Link", 
+   "fieldname": "student_name", 
+   "fieldtype": "Read Only", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
-   "in_list_view": 1, 
+   "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Course Schedule", 
+   "label": "Student Name", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "Course Schedule", 
+   "options": "student.title", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -121,7 +149,36 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "student_batch", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Student Batch", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Batch", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -195,7 +252,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2016-11-07 05:29:02.601819", 
+ "modified": "2016-11-16 16:58:35.779867", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Student Attendance", 
diff --git a/erpnext/schools/doctype/student_attendance/student_attendance.py b/erpnext/schools/doctype/student_attendance/student_attendance.py
index 65dbd68..d9949b0 100644
--- a/erpnext/schools/doctype/student_attendance/student_attendance.py
+++ b/erpnext/schools/doctype/student_attendance/student_attendance.py
@@ -9,13 +9,31 @@
 
 class StudentAttendance(Document):
 	def validate(self):
+		self.validate_date()
+		self.validate_mandatory()
 		self.validate_duplication()
 		
+	def validate_date(self):
+		if self.course_schedule:
+			self.date = frappe.db.get_value("Course Schedule", self.course_schedule, "schedule_date")
+	
+	def validate_mandatory(self):
+		if not (self.student_batch or self.course_schedule):
+			frappe.throw(_("""Student Batch or Course Schedule is mandatory"""))
+	
 	def validate_duplication(self):
 		"""Check if the Attendance Record is Unique"""
-		attendance_records= frappe.db.sql("""select name from `tabStudent Attendance` where \
-			student= %s and course_schedule= %s and name != %s""",
-			(self.student, self.course_schedule, self.name))
+		
+		attendance_records=None
+		if self.course_schedule:
+			attendance_records= frappe.db.sql("""select name from `tabStudent Attendance` where \
+				student= %s and course_schedule= %s and name != %s and docstatus=1""",
+				(self.student, self.course_schedule, self.name))
+		else:
+			attendance_records= frappe.db.sql("""select name from `tabStudent Attendance` where \
+				student= %s and date= %s and name != %s and course_schedule='' and docstatus=1""",
+				(self.student, self.date, self.name))
+			
 		if attendance_records:
-			frappe.throw(_("Attendance Record {0} exists against Student {1} for Course Schedule {2}")
-				.format(attendance_records[0][0], self.student, self.course_schedule))
+			frappe.throw(_("Attendance Record {0} exists against Student {1}")
+				.format(attendance_records[0][0], self.student))
diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/__init__.py b/erpnext/schools/doctype/student_batch_attendance_tool/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/schools/doctype/student_batch_attendance_tool/__init__.py
diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.js b/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.js
new file mode 100644
index 0000000..a6d035a
--- /dev/null
+++ b/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.js
@@ -0,0 +1,128 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+frappe.provide("schools")
+
+frappe.ui.form.on('Student Batch Attendance Tool', {
+	refresh: function(frm) {
+		frm.disable_save();
+		hide_field('attendance');
+	},
+	
+	student_batch :function(frm) {
+		if(frm.doc.student_batch && frm.doc.date) {
+			frappe.call({
+				method: "erpnext.schools.api.check_attendance_records_exist",
+				args: {
+					"student_batch": frm.doc.student_batch,
+					"date": frm.doc.date
+				},
+				callback: function(r) {
+					if(r.message) {
+						frappe.msgprint("Attendance already marked.");
+						hide_field('attendance');
+					}
+					else {
+						frappe.call({
+							method: "erpnext.schools.api.get_student_batch_students",
+							args: {
+								"student_batch": frm.doc.student_batch
+							},
+							callback: function(r) {
+								if (r.message) {
+									unhide_field('attendance');
+									frm.events.get_students(frm, r.message)
+								}
+							}
+						});
+					}
+				}
+			});
+		}
+	},
+	
+	date: function(frm) {
+		frm.trigger("student_batch");
+	},
+	
+	get_students: function(frm, students) {
+		if(!frm.students_area) {
+		frm.students_area = $('<div>')
+			.appendTo(frm.fields_dict.students_html.wrapper);
+		}
+		frm.students_editor = new schools.StudentsEditor(frm, frm.students_area, students)
+	}
+});
+
+
+schools.StudentsEditor = Class.extend({
+	init: function(frm, wrapper, students) {
+		this.wrapper = wrapper;
+		this.frm = frm;
+		this.make(frm, students);
+	},
+	make: function(frm, students) {
+		var me = this;
+		
+		$(this.wrapper).empty();
+		var student_toolbar = $('<p>\
+			<button class="btn btn-default btn-add btn-xs" style="margin-right: 5px;"></button>\
+			<button class="btn btn-xs btn-default btn-remove" style="margin-right: 5px;"></button>\
+			<button class="btn btn-default btn-primary btn-mark-att btn-xs"></button></p>').appendTo($(this.wrapper));
+
+		student_toolbar.find(".btn-add")
+			.html(__('Check all'))
+			.on("click", function() {
+			$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
+				if(!$(check).is(":checked")) {
+					check.checked = true;
+				}
+			});
+		});
+
+		student_toolbar.find(".btn-remove")
+			.html(__('Uncheck all'))
+			.on("click", function() {
+			$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
+				if($(check).is(":checked")) {
+					check.checked = false;
+				}
+			});
+		});
+		
+		student_toolbar.find(".btn-mark-att")
+			.html(__('Mark Attendence'))
+			.on("click", function() {
+				var students_present = [];
+				var students_absent = [];
+				$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
+					if($(check).is(":checked")) {
+						students_present.push(students[i]);
+					}
+					else {
+						students_absent.push(students[i]);
+					}
+				});
+				frappe.call({
+					method: "erpnext.schools.api.mark_attendance",
+					args: {
+						"students_present": students_present,
+						"students_absent": students_absent,
+						"student_batch": frm.doc.student_batch,
+						"date": frm.doc.date
+					},
+					callback: function(r) {
+						hide_field('attendance');
+					}
+				});
+		});
+
+		
+		$.each(students, function(i, m) {
+			$(repl('<div class="col-sm-6">\
+				<div class="checkbox">\
+				<label><input type="checkbox" class="students-check" student="%(student)s">\
+				%(student)s</label>\
+			</div></div>', {student: m.student_name})).appendTo(me.wrapper);
+		});
+	}
+});
diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.json b/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.json
new file mode 100644
index 0000000..3361dcb
--- /dev/null
+++ b/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.json
@@ -0,0 +1,201 @@
+{
+ "allow_copy": 1, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2016-11-16 17:12:46.437539", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "student_batch", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Student Batch", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Batch", 
+   "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, 
+   "unique": 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_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, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "date", 
+   "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "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": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "depends_on": "", 
+   "fieldname": "attendance", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Attendance", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "students_html", 
+   "fieldtype": "HTML", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "in_standard_filter": 0, 
+   "label": "Students HTML", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "hide_heading": 1, 
+ "hide_toolbar": 1, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "in_dialog": 0, 
+ "is_submittable": 0, 
+ "issingle": 1, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2016-11-16 17:16:43.835693", 
+ "modified_by": "Administrator", 
+ "module": "Schools", 
+ "name": "Student Batch Attendance Tool", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 0, 
+   "email": 1, 
+   "export": 0, 
+   "if_owner": 0, 
+   "import": 0, 
+   "is_custom": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 0, 
+   "role": "Academics User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 0, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.py b/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.py
new file mode 100644
index 0000000..49a5ae8
--- /dev/null
+++ b/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, 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 StudentBatchAttendanceTool(Document):
+	pass
diff --git a/erpnext/templates/includes/order/order_macros.html b/erpnext/templates/includes/order/order_macros.html
index 70a1fd8..e77b8b4 100644
--- a/erpnext/templates/includes/order/order_macros.html
+++ b/erpnext/templates/includes/order/order_macros.html
@@ -4,7 +4,7 @@
     <div class="row item_name_and_description">
         <div class="col-xs-4 col-sm-2 order-image-col">
             <div class="order-image">
-                {{ product_image_square(d.image) }}
+                {{ product_image_square(d.thumbnail or d.image) }}
             </div>
         </div>
         <div class="col-xs-8 col-sm-10">
@@ -18,7 +18,7 @@
     <div class="row item_name_dropdown">
         <div class="col-xs-4 col-sm-4 order-image-col">
             <div class="order-image">
-             {{ product_image_square(d.image) }}
+             {{ product_image_square(d.thumbnail or d.image) }}
             </div>
         </div>
         <div class="col-xs-8 col-sm-8">
diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv
index cbec0e7..bd580f2 100644
--- a/erpnext/translations/fr.csv
+++ b/erpnext/translations/fr.csv
@@ -420,7 +420,7 @@
 DocType: Account,Cost of Goods Sold,Coût des marchandises vendues
 DocType: Purchase Invoice,Yearly,Annuel
 apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +226,Please enter Cost Center,S'il vous plaît entrer Centre de coûts
-DocType: Journal Entry Account,Sales Order,Bon de commande
+DocType: Journal Entry Account,Sales Order,Commande client
 apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py +68,Avg. Selling Rate,Moy. Taux de vente
 DocType: Assessment,Examiner Name,Nom de l&#39;examinateur
 apps/erpnext/erpnext/utilities/transaction_base.py +149,Quantity cannot be a fraction in row {0},La quantité ne peut pas être une fraction à la ligne {0}
@@ -722,7 +722,7 @@
 
 #### Description of Columns
 
-1. Calculation Type: 
+1. Calculation Type:
     - This can be on **Net Total** (that is the sum of basic amount).
     - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
     - **Actual** (as mentioned).
@@ -733,19 +733,19 @@
 6. Amount: Tax amount.
 7. Total: Cumulative total to this point.
 8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row).
-9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations de vente. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs dépenses / revenus comme le ""port"", ""assurance"", ""Manipulation"", etc. 
+9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations de vente. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs dépenses / revenus comme le ""port"", ""assurance"", ""Manipulation"", etc.
 
- #### Remarque 
+ #### Remarque
 
  Le taux d'imposition vous définir ici sera le taux d'imposition standard pour tous les articles ** **. Se il ya ** ** Articles qui ont des taux différents, ils doivent être ajoutés dans le ** Impôt de l'article ** ** table dans le Point ** maître.
 
- #### Description des colonnes 
+ #### Description des colonnes
 
- 1. Type de calcul: 
+ 1. Type de calcul:
  - Cela peut être le ** Net Total ** (ce est la somme de montant de base).
  - ** Sur Rang Précédent Total / Montant ** (pour les taxes ou frais cumulatifs). Si vous sélectionnez cette option, la taxe sera appliquée en pourcentage de la rangée précédente (dans la table d'impôt) montant ou totale.
  - ** ** Réelles (comme mentionné).
- 2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé 
+ 2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé
  3. Centre de Coût: Si la taxe / redevance est un revenu (comme le transport) ou dépenses qu'elle doit être réservé contre un centre de coûts.
  4. Description: Description de la taxe (qui sera imprimée sur les factures / guillemets).
  5. Taux: Le taux d'imposition.
@@ -941,7 +941,7 @@
 						Please enter a valid Invoice","Row {0}: Invoice {1} est invalide, il pourrait être annulé / n&#39;existe pas. \ S&#39;il vous plaît entrer une facture valide"
 apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +105,Row {0}: Payment against Sales/Purchase Order should always be marked as advance,Row {0}: Paiement contre Ventes / bon de commande doit toujours être marqué comme avance
 apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +16,Chemical,chimique
-apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades. 
+apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
                     Please check intervals {0} and {1} and try again",Les intervalles de code grade {0} chevauchements avec les intervalles de qualité pour les autres grades. S&#39;il vous plaît vérifier les intervalles {0} et {1} et essayez à nouveau
 apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py +694,All items have already been transferred for this Production Order.,Tous les éléments ont déjà été transférés pour cet ordre de production.
 DocType: Process Payroll,Select Payroll Year and Month,Sélectionnez paie Année et mois
@@ -2171,7 +2171,7 @@
 
 #### Description of Columns
 
-1. Calculation Type: 
+1. Calculation Type:
     - This can be on **Net Total** (that is the sum of basic amount).
     - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
     - **Actual** (as mentioned).
@@ -2183,19 +2183,19 @@
 7. Total: Cumulative total to this point.
 8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row).
 9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.
-10. Add or Deduct: Whether you want to add or deduct the tax.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations d'achat. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs de dépenses comme ""Expédition"", ""assurance"", ""Manipulation"", etc. 
+10. Add or Deduct: Whether you want to add or deduct the tax.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations d'achat. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs de dépenses comme ""Expédition"", ""assurance"", ""Manipulation"", etc.
 
- #### Remarque 
+ #### Remarque
 
  Le taux d'imposition que vous définissez ici sera le taux d'imposition standard pour tous les articles ** **. Se il ya ** ** Articles qui ont des taux différents, ils doivent être ajoutés dans le ** Impôt de l'article ** ** table dans le Point ** maître.
 
- #### Description des colonnes 
+ #### Description des colonnes
 
- 1. Type de calcul: 
+ 1. Type de calcul:
  - Cela peut être le ** Net Total ** (ce est la somme de montant de base).
  - ** Sur Rang Précédent Total / Montant ** (pour les taxes ou frais cumulatifs). Si vous sélectionnez cette option, la taxe sera appliquée en pourcentage de la rangée précédente (dans la table d'impôt) montant ou totale.
  - ** ** Réelles (comme mentionné).
- 2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé 
+ 2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé
  3. Centre de Coût: Si la taxe / redevance est un revenu (comme le transport) ou dépenses qu'elle doit être réservé contre un centre de coûts.
  4. Description: Description de la taxe (qui sera imprimée sur les factures / guillemets).
  5. Taux: Le taux d'imposition.
@@ -2389,7 +2389,7 @@
 1. Ways of addressing disputes, indemnity, liability, etc.
 1. Address and Contact of your Company.","Conditions d'utilisation standard qui peuvent être ajoutés aux ventes et achats.
 
- Exemples: 
+ Exemples:
 
  1. Validité de l'offre.
  1. Conditions de paiement (à l'avance, à crédit, une partie avance etc).
@@ -2398,7 +2398,7 @@
  1. Garantie cas échéant.
  1. Politique de retour.
  1. Conditions d'expédition, le cas échéant.
- 1. Façons de différends adressage, indemnisation, la responsabilité, etc. 
+ 1. Façons de différends adressage, indemnisation, la responsabilité, etc.
  1. Adresse et contact de votre société."
 DocType: Attendance,Leave Type,Type de Congé
 apps/erpnext/erpnext/controllers/stock_controller.py +173,Expense / Difference account ({0}) must be a 'Profit or Loss' account,Dépenses / compte de la différence ({0}) doit être un compte «de résultat»
@@ -3384,7 +3384,7 @@
 apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +15,Brokerage,courtage
 DocType: Address,Postal Code,Code Postal
 DocType: Production Order Operation,"in Minutes
-Updated via 'Time Log'","Mise à jour en quelques minutes 
+Updated via 'Time Log'","Mise à jour en quelques minutes
  via 'Log Time'"
 DocType: Customer,From Lead,Du prospect
 apps/erpnext/erpnext/config/manufacturing.py +13,Orders released for production.,Commandes validé pour la production.
@@ -3564,7 +3564,7 @@
 apps/erpnext/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +34,Bank Statement balance as per General Ledger,Solde du relevé bancaire que par General Ledger
 DocType: Job Applicant,Applicant Name,Nom du demandeur
 DocType: Authorization Rule,Customer / Item Name,Client / Nom d&#39;article
-DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. 
+DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**.
 
 The package **Item** will have ""Is Stock Item"" as ""No"" and ""Is Sales Item"" as ""Yes"".
 
@@ -3711,17 +3711,17 @@
 {% if phone %}Phone: {{ phone }}&lt;br&gt;{% endif -%}
 {% if fax %}Fax: {{ fax }}&lt;br&gt;{% endif -%}
 {% if email_id %}Email: {{ email_id }}&lt;br&gt;{% endif -%}
-</code></pre>","<H4> Modèle par défaut </ h4> 
- <p> <a Utilise href=""http://jinja.pocoo.org/docs/templates/""> Jinja Templating </a> et tous les champs d'adresse ( y compris les champs personnalisés le cas échéant) sera disponible </ p> 
- <pre> <code> {{address_line1}} & lt; br & gt; 
- {% si address_line2%} {{address_line2}} & lt; br & gt; { % endif -%} 
- {{ville}} & lt; br & gt; 
- {% si l'état%} {{}} Etat & lt; br & gt; {% endif -%} {% if 
- code PIN%} PIN: {{code PIN}} & lt; br & gt; {% endif -%} 
- {{pays}} & lt; br & gt; 
- {% si le téléphone%} Téléphone: {{téléphone}} & lt; br & gt; { % endif -%} 
- {% if télécopieur%} Fax: {{fax}} & lt; br & gt; {% endif -%} 
- {% si email_id%} Email: {{email_id}} & lt; br & gt ; {% endif -%} 
+</code></pre>","<H4> Modèle par défaut </ h4>
+ <p> <a Utilise href=""http://jinja.pocoo.org/docs/templates/""> Jinja Templating </a> et tous les champs d'adresse ( y compris les champs personnalisés le cas échéant) sera disponible </ p>
+ <pre> <code> {{address_line1}} & lt; br & gt;
+ {% si address_line2%} {{address_line2}} & lt; br & gt; { % endif -%}
+ {{ville}} & lt; br & gt;
+ {% si l'état%} {{}} Etat & lt; br & gt; {% endif -%} {% if
+ code PIN%} PIN: {{code PIN}} & lt; br & gt; {% endif -%}
+ {{pays}} & lt; br & gt;
+ {% si le téléphone%} Téléphone: {{téléphone}} & lt; br & gt; { % endif -%}
+ {% if télécopieur%} Fax: {{fax}} & lt; br & gt; {% endif -%}
+ {% si email_id%} Email: {{email_id}} & lt; br & gt ; {% endif -%}
  </ code> </ pre>"
 DocType: Salary Detail,Default Amount,Montant par défaut
 apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +93,Warehouse not found in the system,Entrepôt pas trouvé dans le système
@@ -3914,7 +3914,7 @@
 apps/erpnext/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +80,Year start date or end date is overlapping with {0}. To avoid please set company,Année de début ou de fin chevauche avec {0}. Pour éviter s'il vous plaît définir la société
 apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +157,Start date should be less than end date for Item {0},La date de début doit être inférieure à la date de fin de l'article {0}
 DocType: Item,"Example: ABCD.#####
-If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemple:. ABCD ##### 
+If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemple:. ABCD #####
  Si la série est réglé et n ° de série ne est pas mentionné dans les transactions, le numéro de série, puis automatique sera créé sur la base de cette série. Si vous voulez toujours de mentionner explicitement numéros de série pour ce produit. laissez ce champ vide."
 DocType: Upload Attendance,Upload Attendance,Chargez fréquentation
 apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.js +113,BOM and Manufacturing Quantity are required,BOM et fabrication Quantité sont nécessaires
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 3cc79ef..051334c 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -125,6 +125,20 @@
 			ret = None
 		
 		return ret
+	
+	def delink_advance_entries(self, linked_doc_name):
+		total_allocated_amount = 0
+		for adv in self.advances:
+			consider_for_total_advance = True
+			if adv.reference_name == linked_doc_name:
+				frappe.db.sql("""delete from `tab{0} Advance`
+					where name = %s""".format(self.doctype), adv.name)
+				consider_for_total_advance = False
+
+			if consider_for_total_advance:
+				total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount"))
+
+		frappe.db.set_value(self.doctype, self.name, "total_advance", total_allocated_amount, update_modified=False)
 
 def delete_events(ref_type, ref_name):
 	frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`