Added ability to mark attendance against a Student Batch
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/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_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