blob: 43d24383f900a060060c12e2308a6d683475187f [file] [log] [blame]
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +05301# -*- coding: utf-8 -*-
2# Copyright (c) 2015, Frappe Technologies and contributors
3# For license information, please see license.txt
4
5from __future__ import unicode_literals
6import frappe
7import json
8from frappe import _
9from frappe.model.mapper import get_mapped_doc
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +053010from frappe.utils import flt, cstr
Neil Trini Lasradofa2023d2017-02-13 19:26:16 +053011from frappe.email.doctype.email_group.email_group import add_subscribers
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053012
13@frappe.whitelist()
14def enroll_student(source_name):
15 """Creates a Student Record and returns a Program Enrollment.
16
17 :param source_name: Student Applicant.
18 """
Manas Solankiad2dc2c2017-03-15 17:45:02 +053019 frappe.publish_realtime('enroll_student_progress', {"progress": [1, 4]}, user=frappe.session.user)
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053020 student = get_mapped_doc("Student Applicant", source_name,
21 {"Student Applicant": {
22 "doctype": "Student",
23 "field_map": {
24 "name": "student_applicant"
25 }
Neil Trini Lasrado06724592016-08-22 12:57:09 +053026 }}, ignore_permissions=True)
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053027 student.save()
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053028 program_enrollment = frappe.new_doc("Program Enrollment")
29 program_enrollment.student = student.name
30 program_enrollment.student_name = student.title
31 program_enrollment.program = frappe.db.get_value("Student Applicant", source_name, "program")
Manas Solankiad2dc2c2017-03-15 17:45:02 +053032 frappe.publish_realtime('enroll_student_progress', {"progress": [4, 4]}, user=frappe.session.user)
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053033 return program_enrollment
34
35@frappe.whitelist()
Manas Solanki426b8a12017-05-09 15:32:52 +053036def check_attendance_records_exist(course_schedule=None, student_group=None, date=None):
37 """Check if Attendance Records are made against the specified Course Schedule or Student Group for given date.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053038
39 :param course_schedule: Course Schedule.
Manas Solanki426b8a12017-05-09 15:32:52 +053040 :param student_group: Student Group.
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053041 :param date: Date.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053042 """
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053043 if course_schedule:
44 return frappe.get_list("Student Attendance", filters={"course_schedule": course_schedule})
45 else:
Manas Solanki426b8a12017-05-09 15:32:52 +053046 return frappe.get_list("Student Attendance", filters={"student_group": student_group, "date": date})
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053047
48@frappe.whitelist()
Manas Solanki426b8a12017-05-09 15:32:52 +053049def mark_attendance(students_present, students_absent, course_schedule=None, student_group=None, date=None):
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053050 """Creates Multiple Attendance Records.
51
52 :param students_present: Students Present JSON.
53 :param students_absent: Students Absent JSON.
54 :param course_schedule: Course Schedule.
Manas Solanki426b8a12017-05-09 15:32:52 +053055 :param student_group: Student Group.
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053056 :param date: Date.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053057 """
Neil Trini Lasradoeccbf432016-12-09 17:38:59 +053058
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053059 present = json.loads(students_present)
60 absent = json.loads(students_absent)
Neil Trini Lasradoeccbf432016-12-09 17:38:59 +053061
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053062 for d in present:
Manas Solanki426b8a12017-05-09 15:32:52 +053063 make_attendance_records(d["student"], d["student_name"], "Present", course_schedule, student_group, date)
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053064
65 for d in absent:
Manas Solanki426b8a12017-05-09 15:32:52 +053066 make_attendance_records(d["student"], d["student_name"], "Absent", course_schedule, student_group, date)
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053067
Neil Trini Lasrado6841b312016-12-01 18:40:27 +053068 frappe.db.commit()
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053069 frappe.msgprint(_("Attendance has been marked successfully."))
70
Manas Solanki426b8a12017-05-09 15:32:52 +053071def make_attendance_records(student, student_name, status, course_schedule=None, student_group=None, date=None):
Manas Solankif869a672017-02-21 11:34:30 +053072 """Creates/Update Attendance Record.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053073
74 :param student: Student.
75 :param student_name: Student Name.
76 :param course_schedule: Course Schedule.
77 :param status: Status (Present/Absent)
78 """
Nabin Hait08847bd2017-02-22 13:05:46 +053079 student_attendance_list = frappe.get_list("Student Attendance", fields = ['name'], filters = {
Manas Solankif869a672017-02-21 11:34:30 +053080 "student": student,
81 "course_schedule": course_schedule,
Manas Solanki426b8a12017-05-09 15:32:52 +053082 "student_group": student_group,
Manas Solankif869a672017-02-21 11:34:30 +053083 "date": date
84 })
85
Nabin Hait08847bd2017-02-22 13:05:46 +053086 if student_attendance_list:
87 student_attendance = frappe.get_doc("Student Attendance", student_attendance_list[0])
Manas Solankif869a672017-02-21 11:34:30 +053088 else:
89 student_attendance = frappe.new_doc("Student Attendance")
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053090 student_attendance.student = student
91 student_attendance.student_name = student_name
92 student_attendance.course_schedule = course_schedule
Manas Solanki426b8a12017-05-09 15:32:52 +053093 student_attendance.student_group = student_group
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053094 student_attendance.date = date
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053095 student_attendance.status = status
Manas Solankif869a672017-02-21 11:34:30 +053096 student_attendance.save()
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053097
98@frappe.whitelist()
Neil Trini Lasradofa2023d2017-02-13 19:26:16 +053099def get_student_guardians(student):
100 """Returns List of Guardians of a Student.
101
102 :param student: Student.
103 """
104 guardians = frappe.get_list("Student Guardian", fields=["guardian"] ,
105 filters={"parent": student})
106 return guardians
107
108@frappe.whitelist()
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530109def get_student_group_students(student_group):
110 """Returns List of student, student_name in Student Group.
111
112 :param student_group: Student Group.
113 """
Neil Trini Lasrado16d40cf2017-01-20 19:16:39 +0530114 students = frappe.get_list("Student Group Student", fields=["student", "student_name"] ,
Manas Solanki426b8a12017-05-09 15:32:52 +0530115 filters={"parent": student_group, "active": 1}, order_by= "group_roll_number")
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530116 return students
117
118@frappe.whitelist()
119def get_fee_structure(program, academic_term=None):
120 """Returns Fee Structure.
121
122 :param program: Program.
123 :param academic_term: Academic Term.
124 """
125 fee_structure = frappe.db.get_values("Fee Structure", {"program": program,
126 "academic_term": academic_term}, 'name', as_dict=True)
127 return fee_structure[0].name if fee_structure else None
128
129@frappe.whitelist()
Neil Trini Lasradof02a0d42016-08-05 15:50:52 +0530130def get_fee_components(fee_structure):
131 """Returns Fee Components.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530132
133 :param fee_structure: Fee Structure.
134 """
135 if fee_structure:
Neil Trini Lasradof02a0d42016-08-05 15:50:52 +0530136 fs = frappe.get_list("Fee Component", fields=["fees_category", "amount"] , filters={"parent": fee_structure}, order_by= "idx")
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530137 return fs
138
139@frappe.whitelist()
Neil Trini Lasradoc20adb52016-09-05 16:55:54 +0530140def get_fee_schedule(program, student_category=None):
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530141 """Returns Fee Schedule.
142
143 :param program: Program.
Neil Trini Lasradoc20adb52016-09-05 16:55:54 +0530144 :param student_category: Student Category
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530145 """
146 fs = frappe.get_list("Program Fee", fields=["academic_term", "fee_structure", "due_date", "amount"] ,
Neil Trini Lasradoc20adb52016-09-05 16:55:54 +0530147 filters={"parent": program, "student_category": student_category }, order_by= "idx")
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530148 return fs
149
150@frappe.whitelist()
151def collect_fees(fees, amt):
152 paid_amount = flt(amt) + flt(frappe.db.get_value("Fees", fees, "paid_amount"))
153 total_amount = flt(frappe.db.get_value("Fees", fees, "total_amount"))
154 frappe.db.set_value("Fees", fees, "paid_amount", paid_amount)
155 frappe.db.set_value("Fees", fees, "outstanding_amount", (total_amount - paid_amount))
156 return paid_amount
157
158@frappe.whitelist()
159def get_course_schedule_events(start, end, filters=None):
160 """Returns events for Course Schedule Calendar view rendering.
161
162 :param start: Start date-time.
163 :param end: End date-time.
164 :param filters: Filters (JSON).
165 """
166 from frappe.desk.calendar import get_event_conditions
167 conditions = get_event_conditions("Course Schedule", filters)
168
169 data = frappe.db.sql("""select name, course,
170 timestamp(schedule_date, from_time) as from_datetime,
171 timestamp(schedule_date, to_time) as to_datetime,
172 room, student_group, 0 as 'allDay'
173 from `tabCourse Schedule`
174 where ( schedule_date between %(start)s and %(end)s )
175 {conditions}""".format(conditions=conditions), {
176 "start": start,
177 "end": end
178 }, as_dict=True, update={"allDay": 0})
179
180 return data
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530181
182@frappe.whitelist()
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530183def get_assessment_criteria(course):
184 """Returns Assessmemt Criteria and their Weightage from Course Master.
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530185
186 :param Course: Course
187 """
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530188 return frappe.get_list("Course Assessment Criteria", \
189 fields=["assessment_criteria", "weightage"], filters={"parent": course}, order_by= "idx")
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530190
191@frappe.whitelist()
Manas Solanki426b8a12017-05-09 15:32:52 +0530192def get_assessment_students(assessment_plan, student_group):
193
194 student_list = get_student_group_students(student_group)
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530195 for i, student in enumerate(student_list):
196 result = get_result(student.student, assessment_plan)
197 if result:
198 student_result = {}
199 for d in result.details:
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530200 student_result.update({d.assessment_criteria: cstr(d.score) + " ("+ d.grade + ")"})
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530201 student_result.update({"total_score": cstr(result.total_score) + " (" + result.grade + ")"})
202 student.update({'assessment_details': student_result})
203 else:
204 student.update({'assessment_details': None})
205 return student_list
206
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530207@frappe.whitelist()
Neil Trini Lasradoa56224c2017-01-04 17:00:43 +0530208def get_assessment_details(assessment_plan):
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530209 """Returns Assessment Criteria and Maximum Score from Assessment Plan Master.
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530210
Neil Trini Lasradoa56224c2017-01-04 17:00:43 +0530211 :param Assessment Plan: Assessment Plan
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530212 """
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530213 return frappe.get_list("Assessment Plan Criteria", \
214 fields=["assessment_criteria", "maximum_score"], filters={"parent": assessment_plan}, order_by= "idx")
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530215
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530216@frappe.whitelist()
217def get_result(student, assessment_plan):
218 """Returns Submitted Result of given student for specified Assessment Plan
219
220 :param Student: Student
221 :param Assessment Plan: Assessment Plan
222 """
223 results = frappe.get_all("Assessment Result", filters={"student": student, "assessment_plan": assessment_plan, "docstatus": 1})
224 if results:
225 return frappe.get_doc("Assessment Result", results[0])
226 else:
227 return None
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530228
229@frappe.whitelist()
230def get_grade(grading_scale, percentage):
231 """Returns Grade based on the Grading Scale and Score.
232
233 :param Grading Scale: Grading Scale
234 :param Percentage: Score Percentage Percentage
235 """
236 grading_scale_intervals = {}
Neil Trini Lasrado233ecfd2017-01-04 15:41:38 +0530237 for d in frappe.get_all("Grading Scale Interval", fields=["grade_code", "threshold"], filters={"parent": grading_scale}):
238 grading_scale_intervals.update({d.threshold:d.grade_code})
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530239 intervals = sorted(grading_scale_intervals.keys(), key=float, reverse=True)
240 for interval in intervals:
241 if flt(percentage) >= interval:
242 grade = grading_scale_intervals.get(interval)
243 break
244 else:
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530245 grade = ""
246 return grade
247
248@frappe.whitelist()
249def mark_assessment_result(student, assessment_plan, scores):
250 student_score = json.loads(scores)
251 details = []
252 for s in student_score.keys():
253 details.append({
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530254 "assessment_criteria": s,
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530255 "score": flt(student_score[s])
256 })
257 assessment_result = frappe.new_doc("Assessment Result")
258 assessment_result.update({
259 "student": student,
260 "student_name": frappe.db.get_value("Student", student, "title"),
261 "assessment_plan": assessment_plan,
262 "details": details
263 })
264 assessment_result.save()
265 assessment_result.submit()
Neil Trini Lasradofa2023d2017-02-13 19:26:16 +0530266 return assessment_result
267
268@frappe.whitelist()
269def update_email_group(doctype, name):
270 if not frappe.db.exists("Email Group", name):
271 email_group = frappe.new_doc("Email Group")
272 email_group.title = name
273 email_group.save()
274 email_list = []
275 students = []
Neil Trini Lasradofa2023d2017-02-13 19:26:16 +0530276 if doctype == "Student Group":
277 students = get_student_group_students(name)
278 for stud in students:
279 for guard in get_student_guardians(stud.student):
280 email = frappe.db.get_value("Guardian", guard.guardian, "email_address")
281 if email:
282 email_list.append(email)
Nabin Hait753c8de2017-02-22 11:53:13 +0530283 add_subscribers(name, email_list)