diff --git a/erpnext/config/education.py b/erpnext/config/education.py index e4e77f36d6..5a05a258b2 100644 --- a/erpnext/config/education.py +++ b/erpnext/config/education.py @@ -135,6 +135,10 @@ def get_data(): "name": "Assessment Plan Status", "doctype": "Assessment Plan" }, + { + "type": "doctype", + "name": "Student Report Generation Tool" + } ] }, { diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py index a830e5bdc0..841c2e88c4 100644 --- a/erpnext/education/doctype/student/student.py +++ b/erpnext/education/doctype/student/student.py @@ -22,14 +22,16 @@ class Student(Document): def update_student_name_in_linked_doctype(self): linked_doctypes = get_linked_doctypes("Student") for d in linked_doctypes: - if "student_name" in [f.fieldname for f in frappe.get_meta(d).fields]: - frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s""" - .format(d, linked_doctypes[d]["fieldname"]),(self.title, self.name)) + meta = frappe.get_meta(d) + if not meta.issingle: + if "student_name" in [f.fieldname for f in meta.fields]: + frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s""" + .format(d, linked_doctypes[d]["fieldname"]),(self.title, self.name)) - if "child_doctype" in linked_doctypes[d].keys() and "student_name" in \ - [f.fieldname for f in frappe.get_meta(linked_doctypes[d]["child_doctype"]).fields]: - frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s""" - .format(linked_doctypes[d]["child_doctype"], linked_doctypes[d]["fieldname"]),(self.title, self.name)) + if "child_doctype" in linked_doctypes[d].keys() and "student_name" in \ + [f.fieldname for f in frappe.get_meta(linked_doctypes[d]["child_doctype"]).fields]: + frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s""" + .format(linked_doctypes[d]["child_doctype"], linked_doctypes[d]["fieldname"]),(self.title, self.name)) def check_unique(self): """Validates if the Student Applicant is Unique""" diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html index e5a7682082..72772b7b32 100644 --- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html +++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html @@ -1,82 +1,371 @@ -
-

{{ _("Student Report Card") }}

-
- {{ _("Student: ") }} {{ frappe.db.get_value("Student", doc.students[0], "title") }}
- {{ _("Program: ") }} {{ doc.program }}
- {{ _("Assessment Group: ") }} {{ doc.assessment_group }} -
+ + +
+ +
+ + {% if letterhead and add_letterhead %} +
{{ letterhead }}
+ {% endif %} + +
+ +
+
+
+
+ +
+
+ {{ doc.students[0] }} +
+
+ +
+
+ +
+
+ {{ doc.student_name }} +
+
+ +
+
+ +
+
+ {{ doc.program }} +
+
+ +
+
+ +
+
+ {{ doc.student_batch }} +
+
+
+ +
+
+
+ +
+
+ {{ doc.academic_year }} +
+
+ + {% if doc.academic_term %} +
+
+ +
+
+ {{ doc.academic_term }} +
+
+ {% endif %} + +
+
+ +
+
+ {{ doc.assessment_group }} +
+
+
+
+ + +{% if doc.show_marks | int %} + {% set result_data = 'score' %} +{% else %} + {% set result_data = 'grade' %} +{% endif %} + {% for course in courses %} -
-
- Course: {{ course }} ({{ frappe.db.get_value("Course", course, "course_name") }}) + +
+
+ +
+ + + + + + {% for assessment_group in assessment_groups %} + + {% endfor %} + + + + + {% for criteria in course_criteria[course] %} + + + {% for assessment_group in assessment_groups %} + {% if (assessment_result.get(course) and assessment_result.get(course).get(assessment_group) and assessment_result.get(course).get(assessment_group).get(criteria)) %} + + {% else %} + + {% endif %} + {% endfor %} + + {% endfor %} + + +
+
+
+ +
+
+ {{ course }} ({{ frappe.db.get_value("Course", course, "course_name") }}) +
+
+
{{ _("Assessment Criteria") }} {{ assessment_group }}
{{ criteria }} + {{ assessment_result.get(course).get(assessment_group).get(criteria).get(result_data) }} + {% if result_data == 'score' %} + ({{ assessment_result.get(course).get(assessment_group).get(criteria).get('maximum_score') }}) + {% endif %} +
+
- - - - - {% for assessment_group in assessment_groups %} - - {% endfor %} - - - - {% for criteria in course_criteria[course] %} - - - {% for assessment_group in assessment_groups %} - {% if (assessment_result.get(course) and assessment_result.get(course).get(assessment_group) and assessment_result.get(course).get(assessment_group).get(criteria)) %} - - {% else %} - - {% endif %} - {% endfor %} - - {% endfor %} - -
Assessment Criteria {{ assessment_group }}
{{ criteria }} {{ assessment_result.get(course).get(assessment_group).get(criteria).get("grade") }}
+
+ {% endfor %} -
-

{{ _("Attendance")}}


-
- Present {{ doc.present_days }} out of {{ doc.max_days }} +
+ +
+
+

{{ _("Student Attendance")}}


+
+ Present {{ doc.attendance.get("Present") if doc.attendance.get("Present") != None else '0' }} days + out of {{ doc.attendance.get("Present") + doc.attendance.get("Absent") }} +
+
+ +
+

{{ _("Parents Teacher Meeting Attendance")}}


+
+ Present {{ doc.parents_attendance if doc.parents_attendance != None else '0' }} + out of {{ doc.parents_meeting if doc.parents_meeting != None else '0' }} +
+
-
-

{{ _("Parents Meeting Attendance")}}


-
- Present {{ doc.parents_attendance }} out of {{ doc.parents_meeting }} +{% if doc.assessment_terms %} +
+
+

{{ doc.assessment_terms }}

+
+
+{% endif %}
-
\ No newline at end of file diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js index 11aae17dfa..d5103ca2ad 100644 --- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js +++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.js @@ -22,11 +22,45 @@ frappe.ui.form.on('Student Report Generation Tool', { refresh: function(frm) { frm.disable_save(); frm.page.clear_indicator(); - frm.fields_dict.preview_report_card.$input.addClass("btn-primary"); + frm.page.set_primary_action(__('Print Report Card'), () => { + let url = "/api/method/erpnext.education.doctype.student_report_generation_tool.student_report_generation_tool.preview_report_card"; + open_url_post(url, frm.doc, true); + }); }, - preview_report_card: function(frm) { - let url = "/api/method/erpnext.education.doctype.student_report_generation_tool.student_report_generation_tool.preview_report_card"; - open_url_post(url, frm.doc); + student: function(frm) { + if (frm.doc.student) { + frappe.call({ + method:"erpnext.education.api.get_current_enrollment", + args: { + "student": frm.doc.student, + "academic_year": frm.doc.academic_year + }, + callback: function(r) { + if(r){ + $.each(r.message, function(i, d) { + if (frm.fields_dict.hasOwnProperty(i)) { + frm.set_value(i, d); + } + }); + } + } + }); + } + }, + + terms: function(frm) { + if(frm.doc.terms) { + return frappe.call({ + method: 'erpnext.setup.doctype.terms_and_conditions.terms_and_conditions.get_terms_and_conditions', + args: { + template_name: frm.doc.terms, + doc: frm.doc + }, + callback: function(r) { + frm.set_value("assessment_terms", r.message); + } + }); + } } }); diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json index 63f1a897fe..88c59c2bdb 100644 --- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json +++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.json @@ -18,19 +18,19 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "academic_year", + "fieldname": "student", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 1, + "in_list_view": 0, "in_standard_filter": 0, - "label": "Academic Year", + "label": "Student", "length": 0, "no_copy": 0, - "options": "Academic Year", + "options": "Student", "permlevel": 0, "precision": "", "print_hide": 0, @@ -49,8 +49,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "academic_term", - "fieldtype": "Link", + "fieldname": "student_name", + "fieldtype": "Read Only", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -58,10 +58,9 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Academic Term", + "label": "Student Name", "length": 0, "no_copy": 0, - "options": "Academic Term", "permlevel": 0, "precision": "", "print_hide": 0, @@ -80,7 +79,38 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "student", + "fieldname": "program", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Program", + "length": 0, + "no_copy": 0, + "options": "Program", + "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_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "student_batch", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -89,10 +119,101 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Student", + "label": "Batch", + "length": 0, + "no_copy": 0, + "options": "Student Batch Name", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "include_all_assessment", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Include All Assessment Group", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "show_marks", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Show Marks", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "add_letterhead", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Add letterhead", "length": 0, "no_copy": 0, - "options": "Student", "permlevel": 0, "precision": "", "print_hide": 0, @@ -171,7 +292,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "program", + "fieldname": "academic_year", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -180,10 +301,73 @@ "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, - "label": "Program", + "label": "Academic Year", "length": 0, "no_copy": 0, - "options": "Program", + "options": "Academic Year", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "academic_term", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Academic Term", + "length": 0, + "no_copy": 0, + "options": "Academic Term", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "add_letterhead", + "fieldname": "letter_head", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Letter Head", + "length": 0, + "no_copy": 0, + "options": "Letter Head", "permlevel": 0, "precision": "", "print_hide": 0, @@ -211,96 +395,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Attendance Print Section", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "max_days", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Institution Open (Days)", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "present_days", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Student Present (Days)", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_10", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, + "label": "Print Section", "length": 0, "no_copy": 0, "permlevel": 0, @@ -330,7 +425,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Total Parent's Meeting", + "label": "Total Parents Teacher Meeting", "length": 0, "no_copy": 0, "permlevel": 0, @@ -360,7 +455,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Parent Present", + "label": "Attended by Parents", "length": 0, "no_copy": 0, "options": "", @@ -382,8 +477,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "section_break_9", - "fieldtype": "Section Break", + "fieldname": "terms", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -391,8 +486,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, + "label": "Terms", "length": 0, "no_copy": 0, + "options": "Terms and Conditions", "permlevel": 0, "precision": "", "print_hide": 0, @@ -411,8 +508,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "preview_report_card", - "fieldtype": "Button", + "fieldname": "assessment_terms", + "fieldtype": "Text Editor", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -420,7 +517,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Print Report Card", + "label": "Assessment Terms", "length": 0, "no_copy": 0, "permlevel": 0, @@ -446,7 +543,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2018-03-16 01:56:31.095554", + "modified": "2018-03-20 17:57:53.936119", "modified_by": "Administrator", "module": "Education", "name": "Student Report Generation Tool", diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py index 60f0c8f918..7b2e00713a 100644 --- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py +++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py @@ -16,60 +16,76 @@ class StudentReportGenerationTool(Document): @frappe.whitelist() -def preview_report_card(program, assessment_group, academic_year, academic_term=None, student=None, student_group=None, - max_days=None, present_days=None, parents_meeting=None, parents_attendance=None): - doc = frappe._dict() +def preview_report_card(**kwargs): + doc = frappe._dict(**kwargs) + doc.students = [doc.student] + if not (doc.student_name and doc.student_batch): + program_enrollment = frappe.get_all("Program Enrollment", fields=["student_batch_name", "student_name"], + filters={"student": doc.student, "docstatus": ('!=', 2), "academic_year": doc.academic_year}) + if program_enrollment: + doc.batch = program_enrollment[0].student_batch_name + doc.student_name = program_enrollment[0].student_name - # doc.program = program - doc.assessment_group = assessment_group - doc.academic_year = academic_year - doc.max_days = max_days - doc.present_days = present_days - doc.parents_meeting = parents_meeting - doc.parents_attendance = parents_attendance - if academic_term: - doc.academic_term = academic_term - if student_group: - doc.student_group = student_group - if student: - doc.students = [student] - - if not doc.students and not doc.student_group: - frappe.throw("Please select the Student or Student Group") - - values = get_formatted_result(doc, get_course=True, get_all_assessment_groups=True) - student_details = values.get("student_details") - assessment_result = values.get("assessment_result").get(doc.students[0]) + # get the assessment result of the selected student + values = get_formatted_result(doc, get_course=True, get_all_assessment_groups=doc.include_all_assessment) + assessment_result = values.get("assessment_result").get(doc.student) courses = values.get("course_dict") course_criteria = get_courses_criteria(courses) - assessment_groups = get_child_assessment_groups(doc.assessment_group) - if program: - doc.program = program + # get the assessment group as per the user selection + if int(doc.include_all_assessment): + assessment_groups = get_child_assessment_groups(doc.assessment_group) + else: + assessment_groups = [doc.assessment_group] + + # get the attendance of the student for that peroid of time. + doc.attendance = get_attendance_count(doc.students[0], doc.academic_year, doc.academic_term) + template = "erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html" base_template_path = "frappe/www/printview.html" - + + from frappe.www.printview import get_letter_head + letterhead = get_letter_head(frappe._dict({"letter_head": doc.letterhead}), not doc.add_letterhead) + html = frappe.render_template(template, { "doc": doc, "assessment_result": assessment_result, "courses": courses, "assessment_groups": assessment_groups, - "course_criteria": course_criteria + "course_criteria": course_criteria, + "letterhead": letterhead.content, + "add_letterhead": int(doc.add_letterhead) if int(doc.add_letterhead) else 0 }) + final_template = frappe.render_template(base_template_path, {"body": html, "title": "Report Card"}) - final_template = frappe.render_template(base_template_path, { - "body": html, - "title": "Report Card" - }) - - frappe.response.filename = "Report Card.pdf" + frappe.response.filename = "Report Card " + doc.students[0] + ".pdf" frappe.response.filecontent = get_pdf(final_template) frappe.response.type = "download" + def get_courses_criteria(courses): course_criteria = frappe._dict() for course in courses: course_criteria[course] = [d.assessment_criteria for d in frappe.get_all("Course Assessment Criteria", fields=["assessment_criteria"], filters={"parent": course})] return course_criteria + + +def get_attendance_count(student, academic_year, academic_term=None): + if academic_year: + from_date, to_date = frappe.db.get_value("Academic Year", academic_year, ["year_start_date", "year_end_date"]) + elif academic_term: + from_date, to_date = frappe.db.get_value("Academic Term", academic_term, ["term_start_date", "term_end_date"]) + if from_date and to_date: + attendance = dict(frappe.db.sql('''select status, count(student) as no_of_days + from `tabStudent Attendance` where student = %s + and date between %s and %s group by status''', + (student, from_date, to_date))) + if "Absent" not in attendance.keys(): + attendance["Absent"] = 0 + if "Present" not in attendance.keys(): + attendance["Present"] = 0 + return attendance + else: + frappe.throw("Provide the academic year and set the starting and ending date.") \ No newline at end of file