diff --git a/erpnext/config/schools.py b/erpnext/config/schools.py index f9696d0b46..1d33d4d096 100644 --- a/erpnext/config/schools.py +++ b/erpnext/config/schools.py @@ -68,7 +68,7 @@ def get_data(): }, { "type": "doctype", - "name": "Student Batch Attendance Tool" + "name": "Student Attendance Tool" }, { "type": "report", diff --git a/erpnext/public/build.json b/erpnext/public/build.json index ac1c7c3205..30b09000fd 100644 --- a/erpnext/public/build.json +++ b/erpnext/public/build.json @@ -1,37 +1,38 @@ { - "css/erpnext.css": [ - "public/css/erpnext.css" - ], - "js/erpnext-web.min.js": [ - "public/js/website_utils.js", - "public/js/shopping_cart.js" - ], - "js/erpnext.min.js": [ - "public/js/conf.js", - "public/js/utils.js", - "public/js/queries.js", - "public/js/sms_manager.js", - "public/js/utils/party.js", - "public/js/templates/address_list.html", - "public/js/templates/contact_list.html", - "public/js/controllers/stock_controller.js", - "public/js/payment/payments.js", - "public/js/controllers/taxes_and_totals.js", - "public/js/controllers/transaction.js", - "public/js/pos/pos.html", - "public/js/pos/pos_bill_item.html", - "public/js/pos/pos_item.html", - "public/js/pos/pos_tax_row.html", - "public/js/pos/pos_invoice_list.html", - "public/js/payment/pos_payment.html", - "public/js/payment/payment_details.html", - "public/js/templates/item_selector.html", - "public/js/utils/item_selector.js", - "public/js/help_links.js" - ], - "js/item-dashboard.min.js": [ - "stock/dashboard/item_dashboard.html", - "stock/dashboard/item_dashboard_list.html", - "stock/dashboard/item_dashboard.js" - ] -} + "css/erpnext.css": [ + "public/css/erpnext.css" + ], + "js/erpnext-web.min.js": [ + "public/js/website_utils.js", + "public/js/shopping_cart.js" + ], + "js/erpnext.min.js": [ + "public/js/conf.js", + "public/js/utils.js", + "public/js/queries.js", + "public/js/sms_manager.js", + "public/js/utils/party.js", + "public/js/templates/address_list.html", + "public/js/templates/contact_list.html", + "public/js/controllers/stock_controller.js", + "public/js/payment/payments.js", + "public/js/controllers/taxes_and_totals.js", + "public/js/controllers/transaction.js", + "public/js/pos/pos.html", + "public/js/pos/pos_bill_item.html", + "public/js/pos/pos_item.html", + "public/js/pos/pos_tax_row.html", + "public/js/pos/pos_invoice_list.html", + "public/js/payment/pos_payment.html", + "public/js/payment/payment_details.html", + "public/js/templates/item_selector.html", + "public/js/utils/item_selector.js", + "public/js/help_links.js", + "public/js/schools/student_button.html" + ], + "js/item-dashboard.min.js": [ + "stock/dashboard/item_dashboard.html", + "stock/dashboard/item_dashboard_list.html", + "stock/dashboard/item_dashboard.js" + ] +} \ No newline at end of file diff --git a/erpnext/public/js/schools/student_button.html b/erpnext/public/js/schools/student_button.html new file mode 100644 index 0000000000..dabaf2660e --- /dev/null +++ b/erpnext/public/js/schools/student_button.html @@ -0,0 +1,20 @@ +
+
+ +
+
\ No newline at end of file diff --git a/erpnext/schools/api.py b/erpnext/schools/api.py index 7cb02a3793..bf09351ff5 100644 --- a/erpnext/schools/api.py +++ b/erpnext/schools/api.py @@ -52,8 +52,10 @@ def mark_attendance(students_present, students_absent, course_schedule=None, stu :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"], "Present", course_schedule, student_batch, date) diff --git a/erpnext/schools/doctype/course_schedule/course_schedule.js b/erpnext/schools/doctype/course_schedule/course_schedule.js index 04a8cdedf2..12e852215a 100644 --- a/erpnext/schools/doctype/course_schedule/course_schedule.js +++ b/erpnext/schools/doctype/course_schedule/course_schedule.js @@ -1,134 +1,15 @@ frappe.provide("schools") frappe.ui.form.on("Course Schedule", { - onload: function(frm) { - if (frm.doc.from_datetime && frm.doc.to_datetime) { - var from_datetime = moment(frm.doc.from_datetime); - var to_datetime = moment(frm.doc.to_datetime); - frm.doc.schedule_date = from_datetime.format(moment.defaultFormat); - frm.doc.from_time = from_datetime.format("HH:mm:ss"); - frm.doc.to_time = to_datetime.format("HH:mm:ss"); - } - }, - refresh: function(frm) { - if (!frm.doc.__islocal && frm.doc.student_group) { - frappe.call({ - method: "erpnext.schools.api.check_attendance_records_exist", - args: { - "course_schedule": frm.doc.name - }, - callback: function(r) { - if (r.message) { - hide_field('attendance'); - frm.events.view_attendance(frm) - } else { - frappe.call({ - method: "erpnext.schools.api.get_student_group_students", - args: { - "student_group": frm.doc.student_group - }, - callback: function(r) { - if (r.message) { - frm.events.get_students(frm, r.message) - } - } - }); - } + if (!frm.doc.__islocal) { + frm.add_custom_button(__("Attendance"), function() { + frappe.route_options = { + based_on: "Course Schedule", + course_schedule: frm.doc.name } + frappe.set_route("Form", "Student Attendance Tool"); }); - } else { - hide_field('attendance'); } - }, - - view_attendance: function(frm) { - hide_field('attendance'); - frm.add_custom_button(__("View attendance"), function() { - frappe.route_options = { - course_schedule: frm.doc.name - } - frappe.set_route("List", "Student Attendance"); - }); - }, - - get_students: function(frm, students) { - if (!frm.students_area) { - frm.students_area = $('
') - .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 = $('

\ - \ - \ -

').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, - "course_schedule": frm.doc.name - }, - callback: function(r) { - frm.events.view_attendance(frm) - } - }); - }); - - - $.each(students, function(i, m) { - $(repl('
\ -
\ - \ -
', { student: m.student_name })).appendTo(me.wrapper); - }); - } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/erpnext/schools/doctype/course_schedule/course_schedule.json b/erpnext/schools/doctype/course_schedule/course_schedule.json index 122285e980..450d7cfad2 100644 --- a/erpnext/schools/doctype/course_schedule/course_schedule.json +++ b/erpnext/schools/doctype/course_schedule/course_schedule.json @@ -382,62 +382,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "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": 1, - "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, @@ -478,7 +422,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-12-01 12:59:25.086606", + "modified": "2016-12-09 17:00:02.822788", "modified_by": "Administrator", "module": "Schools", "name": "Course Schedule", diff --git a/erpnext/schools/doctype/student_attendance/student_attendance.py b/erpnext/schools/doctype/student_attendance/student_attendance.py index 45b3014579..e2d01b56bd 100644 --- a/erpnext/schools/doctype/student_attendance/student_attendance.py +++ b/erpnext/schools/doctype/student_attendance/student_attendance.py @@ -31,9 +31,9 @@ class StudentAttendance(Document): (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 docstatus=1 and \ + student= %s and student_batch= %s and date= %s and name != %s and docstatus=1 and \ (course_schedule is Null or course_schedule='')""", - (self.student, self.date, self.name)) + (self.student, self.student_batch, self.date, self.name)) if attendance_records: frappe.throw(_("Attendance Record {0} exists against Student {1}") diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/__init__.py b/erpnext/schools/doctype/student_attendance_tool/__init__.py similarity index 100% rename from erpnext/schools/doctype/student_batch_attendance_tool/__init__.py rename to erpnext/schools/doctype/student_attendance_tool/__init__.py diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.js b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js similarity index 52% rename from erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.js rename to erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js index 2dc6a85d4a..7dd9dda259 100644 --- a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.js +++ b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js @@ -2,40 +2,35 @@ // For license information, please see license.txt frappe.provide("schools") -frappe.ui.form.on('Student Batch Attendance Tool', { +frappe.ui.form.on('Student Attendance Tool', { refresh: function(frm) { frm.disable_save(); - hide_field('attendance'); + }, + + based_on: function(frm) { + if (frm.doc.based_on == "Student Batch") { + frm.set_value("course_schedule", ""); + } else { + frm.set_value("student_batch", ""); + } }, student_batch: function(frm) { - if (frm.doc.student_batch && frm.doc.date) { + if ((frm.doc.student_batch && frm.doc.date) || frm.doc.course_schedule) { + var method = "erpnext.schools.doctype.student_attendance_tool.student_attendance_tool.get_student_attendance_records"; + frappe.call({ - method: "erpnext.schools.api.check_attendance_records_exist", + method: method, args: { - "student_batch": frm.doc.student_batch, - "date": frm.doc.date + based_on: frm.doc.based_on, + student_batch: frm.doc.student_batch, + date: frm.doc.date, + course_schedule: frm.doc.course_schedule }, 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) - } - } - }); - } + frm.events.get_students(frm, r.message); } - }); + }) } }, @@ -43,6 +38,10 @@ frappe.ui.form.on('Student Batch Attendance Tool', { frm.trigger("student_batch"); }, + course_schedule: function(frm) { + frm.trigger("student_batch"); + }, + get_students: function(frm, students) { if (!frm.students_area) { frm.students_area = $('
') @@ -72,7 +71,7 @@ schools.StudentsEditor = Class.extend({ .html(__('Check all')) .on("click", function() { $(me.wrapper).find('input[type="checkbox"]').each(function(i, check) { - if (!$(check).is(":checked")) { + if (!$(check).prop("disabled")) { check.checked = true; } }); @@ -82,55 +81,70 @@ schools.StudentsEditor = Class.extend({ .html(__('Uncheck all')) .on("click", function() { $(me.wrapper).find('input[type="checkbox"]').each(function(i, check) { - if ($(check).is(":checked")) { + if (!$(check).prop("disabled")) { check.checked = false; } }); }); - var get_student = function(idx) { + var get_present_student = function(student) { return students.filter(function(s) { return s.idx === idx; - })[0] + }) + } + var get_absent_student = function(idx) { + return students.filter(function(s) { + return s.idx === idx; + }) } 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) { - var idx = $(check).data().idx; - if ($(check).is(":checked")) { - students_present.push(get_student(idx)); - } else { - students_absent.push(get_student(idx)); - } + var studs = []; + $(me.wrapper.find('input[type="checkbox"]')).each(function(i, check) { + var $check = $(check); + studs.push({ + student: $check.data().student, + student_name: $check.data().studentName, + idx: $check.data().idx, + disabled: $check.prop("disabled"), + checked: $check.is(":checked") + }); }); + + var students_present = studs.filter(function(stud) { + return !stud.disabled && stud.checked; + }); + + var students_absent = studs.filter(function(stud) { + return !stud.disabled && !stud.checked; + }); + frappe.call({ method: "erpnext.schools.api.mark_attendance", args: { "students_present": students_present, "students_absent": students_absent, "student_batch": frm.doc.student_batch, + "course_schedule": frm.doc.course_schedule, "date": frm.doc.date }, callback: function(r) { - hide_field('attendance'); + frm.trigger("student_batch"); } }); }); - - $.each(students, function(i, m) { - $(repl('
\ -
\ - \ -
', { - name: m.student_name, - idx: m.idx - })).appendTo(me.wrapper); + var htmls = students.map(function(student) { + return frappe.render_template("student_button", { + student: student.student, + student_name: student.student_name, + idx: student.idx, + status: student.status + }) }); + + $(htmls.join("")).appendTo(me.wrapper); } }); \ No newline at end of file diff --git a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.json b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.json similarity index 72% rename from erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.json rename to erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.json index defc886b1c..092af041a9 100644 --- a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.json +++ b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.json @@ -16,18 +16,19 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "student_batch", - "fieldtype": "Link", + "default": "", + "fieldname": "based_on", + "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Student Batch", + "label": "Based On", "length": 0, "no_copy": 0, - "options": "Student Batch", + "options": "Student Batch\nCourse Schedule", "permlevel": 0, "precision": "", "print_hide": 0, @@ -35,7 +36,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 @@ -72,6 +73,67 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "eval:doc.based_on ==\"Student Batch\"", + "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, + "depends_on": "eval:doc.based_on ==\"Course Schedule\"", + "fieldname": "course_schedule", + "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 Schedule", + "length": 0, + "no_copy": 0, + "options": "Course Schedule", + "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": "eval:doc.based_on ==\"Student Batch\"", "fieldname": "date", "fieldtype": "Date", "hidden": 0, @@ -100,7 +162,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "", + "depends_on": "eval: (doc.course_schedule \n|| (doc.student_batch && doc.date))", "fieldname": "attendance", "fieldtype": "Section Break", "hidden": 0, @@ -163,10 +225,10 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2016-12-01 12:58:31.822014", + "modified": "2016-12-09 17:36:28.739318", "modified_by": "Administrator", "module": "Schools", - "name": "Student Batch Attendance Tool", + "name": "Student Attendance Tool", "name_case": "", "owner": "Administrator", "permissions": [ diff --git a/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.py b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.py new file mode 100644 index 0000000000..30a692cf18 --- /dev/null +++ b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.py @@ -0,0 +1,40 @@ +# -*- 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 StudentAttendanceTool(Document): + pass + +@frappe.whitelist() +def get_student_attendance_records(based_on, date=None, student_batch=None, course_schedule=None): + student_list = [] + student_attendance_list = [] + + if based_on=="Course Schedule": + student_group = frappe.db.get_value("Course Schedule", course_schedule, "student_group") + if student_group: + student_list = frappe.get_list("Student Group Student", fields=["student", "student_name", "idx"] , \ + filters={"parent": student_group}, order_by= "idx") + else: + student_batch = frappe.db.get_value("Course Schedule", course_schedule, "student_batch") + if not student_list: + student_list = frappe.get_list("Student Batch Student", fields=["student", "student_name", "idx"] , filters={"parent": student_batch}, order_by= "idx") + + if course_schedule: + student_attendance_list= frappe.db.sql("""select student, status from `tabStudent Attendance` where \ + course_schedule= %s and docstatus=1""", (course_schedule), as_dict=1) + else: + student_attendance_list= frappe.db.sql("""select student, status from `tabStudent Attendance` where \ + student_batch= %s and date= %s and docstatus=1 and \ + (course_schedule is Null or course_schedule='')""", + (student_batch, date), as_dict=1) + + for attendance in student_attendance_list: + for student in student_list: + if student.student == attendance.student: + student.status = attendance.status + return student_list \ 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 deleted file mode 100644 index 49a5ae8a34..0000000000 --- a/erpnext/schools/doctype/student_batch_attendance_tool/student_batch_attendance_tool.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- 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