blob: 623b1e0a0eaacc153e7ad15d16fc780a204a0766 [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()
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053036def check_attendance_records_exist(course_schedule=None, student_batch=None, date=None):
37 """Check if Attendance Records are made against the specified Course Schedule or Student Batch for given date.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053038
39 :param course_schedule: Course Schedule.
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053040 :param student_batch: Student Batch.
41 :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:
46 return frappe.get_list("Student Attendance", filters={"student_batch": student_batch, "date": date})
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053047
48@frappe.whitelist()
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053049def mark_attendance(students_present, students_absent, course_schedule=None, student_batch=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.
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053055 :param student_batch: Student Batch.
56 :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:
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053063 make_attendance_records(d["student"], d["student_name"], "Present", course_schedule, student_batch, date)
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +053064
65 for d in absent:
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053066 make_attendance_records(d["student"], d["student_name"], "Absent", course_schedule, student_batch, 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
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053071def make_attendance_records(student, student_name, status, course_schedule=None, student_batch=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,
82 "student_batch": student_batch,
83 "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
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +053093 student_attendance.student_batch = student_batch
94 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 Lasradod9bc5592016-11-17 15:35:54 +0530109def get_student_batch_students(student_batch):
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530110 """Returns List of student, student_name, idx in Student Batch.
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +0530111
112 :param student_batch: Student Batch.
113 """
Neil Trini Lasrado16d40cf2017-01-20 19:16:39 +0530114 students = frappe.get_list("Student Batch Student", fields=["student", "student_name", "idx"] ,
115 filters={"parent": student_batch, "active": 1}, order_by= "idx")
Neil Trini Lasradod9bc5592016-11-17 15:35:54 +0530116 return students
117
118@frappe.whitelist()
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530119def get_student_group_students(student_group):
120 """Returns List of student, student_name in Student Group.
121
122 :param student_group: Student Group.
123 """
Neil Trini Lasrado16d40cf2017-01-20 19:16:39 +0530124 students = frappe.get_list("Student Group Student", fields=["student", "student_name"] ,
125 filters={"parent": student_group, "active": 1}, order_by= "idx")
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530126 return students
127
128@frappe.whitelist()
129def get_fee_structure(program, academic_term=None):
130 """Returns Fee Structure.
131
132 :param program: Program.
133 :param academic_term: Academic Term.
134 """
135 fee_structure = frappe.db.get_values("Fee Structure", {"program": program,
136 "academic_term": academic_term}, 'name', as_dict=True)
137 return fee_structure[0].name if fee_structure else None
138
139@frappe.whitelist()
Neil Trini Lasradof02a0d42016-08-05 15:50:52 +0530140def get_fee_components(fee_structure):
141 """Returns Fee Components.
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530142
143 :param fee_structure: Fee Structure.
144 """
145 if fee_structure:
Neil Trini Lasradof02a0d42016-08-05 15:50:52 +0530146 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 +0530147 return fs
148
149@frappe.whitelist()
Neil Trini Lasradoc20adb52016-09-05 16:55:54 +0530150def get_fee_schedule(program, student_category=None):
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530151 """Returns Fee Schedule.
152
153 :param program: Program.
Neil Trini Lasradoc20adb52016-09-05 16:55:54 +0530154 :param student_category: Student Category
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530155 """
156 fs = frappe.get_list("Program Fee", fields=["academic_term", "fee_structure", "due_date", "amount"] ,
Neil Trini Lasradoc20adb52016-09-05 16:55:54 +0530157 filters={"parent": program, "student_category": student_category }, order_by= "idx")
Neil Trini Lasrado3f0a5812016-07-19 14:17:33 +0530158 return fs
159
160@frappe.whitelist()
161def collect_fees(fees, amt):
162 paid_amount = flt(amt) + flt(frappe.db.get_value("Fees", fees, "paid_amount"))
163 total_amount = flt(frappe.db.get_value("Fees", fees, "total_amount"))
164 frappe.db.set_value("Fees", fees, "paid_amount", paid_amount)
165 frappe.db.set_value("Fees", fees, "outstanding_amount", (total_amount - paid_amount))
166 return paid_amount
167
168@frappe.whitelist()
169def get_course_schedule_events(start, end, filters=None):
170 """Returns events for Course Schedule Calendar view rendering.
171
172 :param start: Start date-time.
173 :param end: End date-time.
174 :param filters: Filters (JSON).
175 """
176 from frappe.desk.calendar import get_event_conditions
177 conditions = get_event_conditions("Course Schedule", filters)
178
179 data = frappe.db.sql("""select name, course,
180 timestamp(schedule_date, from_time) as from_datetime,
181 timestamp(schedule_date, to_time) as to_datetime,
182 room, student_group, 0 as 'allDay'
183 from `tabCourse Schedule`
184 where ( schedule_date between %(start)s and %(end)s )
185 {conditions}""".format(conditions=conditions), {
186 "start": start,
187 "end": end
188 }, as_dict=True, update={"allDay": 0})
189
190 return data
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530191
192@frappe.whitelist()
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530193def get_assessment_criteria(course):
194 """Returns Assessmemt Criteria and their Weightage from Course Master.
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530195
196 :param Course: Course
197 """
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530198 return frappe.get_list("Course Assessment Criteria", \
199 fields=["assessment_criteria", "weightage"], filters={"parent": course}, order_by= "idx")
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530200
201@frappe.whitelist()
202def get_assessment_students(assessment_plan, student_group=None, student_batch=None):
203 student_list = []
204 if student_group:
205 student_list = get_student_group_students(student_group)
206 elif student_batch:
207 student_list = get_student_batch_students(student_batch)
208 for i, student in enumerate(student_list):
209 result = get_result(student.student, assessment_plan)
210 if result:
211 student_result = {}
212 for d in result.details:
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530213 student_result.update({d.assessment_criteria: cstr(d.score) + " ("+ d.grade + ")"})
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530214 student_result.update({"total_score": cstr(result.total_score) + " (" + result.grade + ")"})
215 student.update({'assessment_details': student_result})
216 else:
217 student.update({'assessment_details': None})
218 return student_list
219
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530220@frappe.whitelist()
Neil Trini Lasradoa56224c2017-01-04 17:00:43 +0530221def get_assessment_details(assessment_plan):
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530222 """Returns Assessment Criteria and Maximum Score from Assessment Plan Master.
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530223
Neil Trini Lasradoa56224c2017-01-04 17:00:43 +0530224 :param Assessment Plan: Assessment Plan
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530225 """
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530226 return frappe.get_list("Assessment Plan Criteria", \
227 fields=["assessment_criteria", "maximum_score"], filters={"parent": assessment_plan}, order_by= "idx")
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530228
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530229@frappe.whitelist()
230def get_result(student, assessment_plan):
231 """Returns Submitted Result of given student for specified Assessment Plan
232
233 :param Student: Student
234 :param Assessment Plan: Assessment Plan
235 """
236 results = frappe.get_all("Assessment Result", filters={"student": student, "assessment_plan": assessment_plan, "docstatus": 1})
237 if results:
238 return frappe.get_doc("Assessment Result", results[0])
239 else:
240 return None
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530241
242@frappe.whitelist()
243def get_grade(grading_scale, percentage):
244 """Returns Grade based on the Grading Scale and Score.
245
246 :param Grading Scale: Grading Scale
247 :param Percentage: Score Percentage Percentage
248 """
249 grading_scale_intervals = {}
Neil Trini Lasrado233ecfd2017-01-04 15:41:38 +0530250 for d in frappe.get_all("Grading Scale Interval", fields=["grade_code", "threshold"], filters={"parent": grading_scale}):
251 grading_scale_intervals.update({d.threshold:d.grade_code})
Neil Trini Lasrado06ed74d2016-12-14 17:49:47 +0530252 intervals = sorted(grading_scale_intervals.keys(), key=float, reverse=True)
253 for interval in intervals:
254 if flt(percentage) >= interval:
255 grade = grading_scale_intervals.get(interval)
256 break
257 else:
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530258 grade = ""
259 return grade
260
261@frappe.whitelist()
262def mark_assessment_result(student, assessment_plan, scores):
263 student_score = json.loads(scores)
264 details = []
265 for s in student_score.keys():
266 details.append({
Neil Trini Lasrado749516c2017-02-01 18:40:30 +0530267 "assessment_criteria": s,
Neil Trini Lasrado2a9e0f62017-01-09 18:25:43 +0530268 "score": flt(student_score[s])
269 })
270 assessment_result = frappe.new_doc("Assessment Result")
271 assessment_result.update({
272 "student": student,
273 "student_name": frappe.db.get_value("Student", student, "title"),
274 "assessment_plan": assessment_plan,
275 "details": details
276 })
277 assessment_result.save()
278 assessment_result.submit()
Neil Trini Lasradofa2023d2017-02-13 19:26:16 +0530279 return assessment_result
280
281@frappe.whitelist()
282def update_email_group(doctype, name):
283 if not frappe.db.exists("Email Group", name):
284 email_group = frappe.new_doc("Email Group")
285 email_group.title = name
286 email_group.save()
287 email_list = []
288 students = []
289 if doctype == "Student Batch":
290 students = get_student_batch_students(name)
291 if doctype == "Student Group":
292 students = get_student_group_students(name)
293 for stud in students:
294 for guard in get_student_guardians(stud.student):
295 email = frappe.db.get_value("Guardian", guard.guardian, "email_address")
296 if email:
297 email_list.append(email)
Nabin Hait753c8de2017-02-22 11:53:13 +0530298 add_subscribers(name, email_list)