def validate_course(self, value): """ Check whether the course is in the school of the user logged. Somewhere else we should check that the user logged has enough permissions to do anything with a course. :return: """ if utils.get_school_from_user(self.user) != value.school: raise ValidationError( _('The course {} is not taught in this School ({}).').format( value, utils.get_school_from_user(self.user))) return value
def __init__(self, user, *args, **kwargs): super(BaseFormWithTeacherCheck, self).__init__(user, *args, **kwargs) # Populate the teacher picker with the correct teachers self.fields['teacher'].queryset = Teacher.objects.filter(school__id=get_school_from_user(user).id) \ .order_by('last_name', 'first_name') self.fields['teacher'].label_from_instance = self.teacher_label
def clean_school(self): if get_school_from_user(self.user) != self.cleaned_data['school']: self.add_error( None, forms.ValidationError( _('The school selected is not a valid choice.'))) return self.cleaned_data['school']
def __init__(self, user, *args, **kwargs): super(BaseFormWithHourSlotCheck, self).__init__(user, *args, **kwargs) # Get the correct hours slots self.fields['hour_slot'].queryset = HourSlot.objects.filter( hour_slots_group__school__id=get_school_from_user(user).id) \ .order_by('day_of_week', 'starts_at')
def get_queryset(self): """ :return: only the years of courses of the user logged's school """ school = utils.get_school_from_user(self.request.user) if school: return Course.objects.filter(school=school).values('year').distinct()
def test_func(self): """ The teacher requested is in the same school as the user doing the request. Actually when the teacher doesn't exist it should return 404, now instead it returns 403. :return: """ teacher_pk = self.kwargs.get('teacher_pk') return Teacher.objects.filter(id=teacher_pk).exists() and \ Teacher.objects.get(id=teacher_pk).school == utils.get_school_from_user(self.request.user)
def test_func(self): assignments = self.request.POST.getlist('assignments[]') if not (utils.is_adminschool(self.request.user)): return False school = utils.get_school_from_user(self.request.user) # They should be in the same school of the admin and all of them should exist return Assignment.objects.filter( id__in=assignments, school=school).count() == len(assignments)
def test_func(self): """ Returns True only when the user logged is an admin, and it is substituting the assignment that are in the correct school :return: """ assign = self.kwargs.get('assignment_pk') if not (utils.is_adminschool(self.request.user) and Assignment.objects.filter(id=assign).exists() and Assignment.objects.get(id=assign).school == utils.get_school_from_user(self.request.user)): return False if not Assignment.objects.filter(id=assign, school=utils.get_school_from_user( self.request.user).id).exists(): return False return True
def validate_school(self, value): """ Check whether the school is the correct one for the admin user logged. :param value: :return: """ if utils.get_school_from_user(self.user) != value: raise ValidationError( _('The school {} is not a valid choice.').format(value)) return value
def get_data(self, request, *args, **kwargs): try: school_year = kwargs.get('school_year_pk') school = utils.get_school_from_user(self.request.user) except ValueError: return [] assignments = Assignment.objects.filter(school=school, school_year=school_year, substitution=True) \ .order_by('-date', 'hour_start', 'hour_end') \ .values('date', 'hour_start', 'hour_end', 'course__year', 'course__section', 'subject__name', 'room__name', 'bes', 'co_teaching', 'teacher__first_name', 'teacher__last_name', 'substituted_assignment__teacher__last_name', 'substituted_assignment__teacher__first_name', 'free_substitution') df = pd.DataFrame(assignments) df['substitution_teacher'] = df['teacher__last_name'] + " " + df[ 'teacher__first_name'] del df['teacher__last_name'] del df['teacher__first_name'] df['absent_teacher'] = df[ 'substituted_assignment__teacher__last_name'] + " " + df[ 'substituted_assignment__teacher__first_name'] del df['substituted_assignment__teacher__last_name'] del df['substituted_assignment__teacher__first_name'] # Set the hour format to hh:mm df['hour_start'] = df['hour_start'].apply( lambda x: x.strftime('%H:%M')) df['hour_end'] = df['hour_end'].apply(lambda x: x.strftime('%H:%M')) # Set the boolean formats df['free_substitution'] = df['free_substitution'].apply( lambda x: _('True') if x else _('False')) df['bes'] = df['bes'].apply(lambda x: _('True') if x else _('False')) df['co_teaching'] = df['co_teaching'].apply(lambda x: _('True') if x else _('False')) # Rename both the index and the columns with reasonable human-readable names. subst_labels = { 'date': _('Date'), 'course__year': _('Course year'), 'course__section': _('Course section'), 'substitution_teacher': _('Substitution teacher'), 'absent_teacher': _('Absent teacher'), 'free_substitution': _('Free substitution'), 'subject__name': _('Subject'), 'room__name': _('Room'), 'bes': _('B.E.S.'), 'co_teaching': _('Co-teaching') } subst_labels.update(labels) df.rename(columns=subst_labels, inplace=True) return df
def validate_room(self, value): """ Check whether the room is in the school of the user logged. Somewhere else we should check that the user logged has enough permissions to do anything with a room. :return: """ if utils.get_school_from_user(self.user) != value.school: raise ValidationError( _('The room {} cannot be used in this school ({}).'.format( value, value.school))) return value
def clean_hour_slot(self): """ We need to check whether the hour_slot belongs to the correct school :return: """ if self.cleaned_data['hour_slot'].school != get_school_from_user( self.user): self.add_error( None, forms.ValidationError( _('The current school has no such hour slot!'))) return self.cleaned_data['hour_slot']
def clean_hour_slots_group(self): """ Check whether the hour_slots_group is in the school of the user logged. Somewhere else we should check that the user logged has enough permissions to do anything with a subject. :return: """ if get_school_from_user( self.user) != self.cleaned_data['hour_slots_group'].school: self.add_error( None, forms.ValidationError( _('The HourSlotsGroup {} is not present in the school ({}).' .format(self.cleaned_data['hour_slots_group'], self.cleaned_data['hour_slots_group'].school)))) return self.cleaned_data['hour_slots_group']
def test_func(self): """ Returns True only when the user logged is an admin, and it is replicating the assignments that are in the correct school :return: """ assignments = self.request.POST.getlist('assignments[]') for assign in assignments: if not (utils.is_adminschool(self.request.user) and Assignment.objects.filter(id=assign).exists() and Assignment.objects.get(id=assign).school == utils.get_school_from_user(self.request.user)): return False return True
def clean_teacher(self): """ Check whether the teacher is in the school of the user logged. Somewhere else we should check that the user logged has enough permissions to do anything with a teacher. :return: """ if get_school_from_user( self.user) != self.cleaned_data['teacher'].school: self.add_error( None, forms.ValidationError( _('The teacher {} is not in the school ({}).'.format( self.cleaned_data['teacher'], self.cleaned_data['teacher'].school)))) return self.cleaned_data['teacher']
def clean_room(self): """ Check whether the room is in the school of the user logged. Somewhere else we should check that the user logged has enough permissions to do anything with a room. :return: """ if 'room' in self.cleaned_data and \ self.cleaned_data['room'] is not None and \ get_school_from_user(self.user) != self.cleaned_data['room'].school: self.add_error( None, forms.ValidationError( _('The room {} does not exist in the school ({}).'.format( self.cleaned_data['room'], self.cleaned_data['subject'].school)))) return self.cleaned_data['room']
def __init__(self, user, *args, **kwargs): """ Add hour_slot selection based on the current school, and ordered by week_day and starts_at :param user: the user logged, the school is retrieved by her. """ super(AbsenceBlockCreateForm, self).__init__(user, *args, **kwargs) # Get the correct hours slots in the MultipleChoiceField self.fields['hour_slots'] = forms.ModelMultipleChoiceField( queryset=HourSlot.objects.filter( school=get_school_from_user(self.user).id).order_by( 'hour_slots_group__name', 'day_of_week', 'starts_at'), help_text=_( "Do you want to assign multiple absence blocks?" " Use shift key and the mouse click to select multiple hour slots." ), label=_('Hour slots')) assign_html_style_to_visible_forms_fields(self)
def test_func(self): """ Returns True only when the user logged is an admin, it is substituting the assignments that are in the correct school and the teacher is in the same school too. :return: """ assign = self.kwargs.get('assignment_pk') teacher = self.kwargs.get('teacher_pk') school = utils.get_school_from_user(self.request.user) if not (utils.is_adminschool(self.request.user) and Assignment.objects.filter(id=assign).exists() and Assignment.objects.get(id=assign).school == school): return False if not Teacher.objects.filter(id=teacher, school=school.id).exists(): return False return True
def get_queryset(self, *args, **kwargs): """ Get all absence blocks for the given teacher, in the given time period. :param args: :param kwargs: :return: """ teacher_pk = self.kwargs.get('teacher_pk') school_year_pk = self.kwargs.get('school_year_pk') try: # Return the teacher, but only among the ones in the school of the currently logged in user teacher = Teacher.objects.get(id=teacher_pk, school=utils.get_school_from_user(self.request.user)) school_year = SchoolYear.objects.get(id=school_year_pk) except ObjectDoesNotExist: # If trying to retrieve an invalid object: return Assignment.objects.none() return AbsenceBlock.objects.filter(teacher=teacher, school_year=school_year)
def post(self, request, *args, **kwargs): # Insert the substitution assignment assign = self.kwargs.get('assignment_pk') teacher = self.kwargs.get('teacher_pk') school = utils.get_school_from_user(self.request.user) a = Assignment.objects.get(id=assign, school=school.id) teachers_list = utils.get_available_teachers(a, school) other_teachers = Teacher.objects.filter(school=school).exclude( id__in=teachers_list.values('id')) new_assign = Assignment(teacher=Teacher.objects.get(id=teacher), course=a.course, subject=a.subject, room=a.room, date=a.date, hour_start=a.hour_start, hour_end=a.hour_end, bes=a.bes, co_teaching=a.co_teaching, substitution=True, absent=False, substituted_assignment=a, free_substitution=False) if teachers_list.filter(id=teacher).exists(): # The substitution counts and it's a normal one a.absent = True elif other_teachers.filter(id=teacher).exists(): # The substitution does not count new_assign.free_substitution = True else: return HttpResponse(_("The teacher is not valid!"), 400) a.save() new_assign.save() return HttpResponse(status=200)
def get(self, request, *args, **kwargs): # Return all teachers for a certain school. # May need to add only teachers for which there is at least one hour_per_teacher_in_class instance in # the given school_year request.assignment_pk = self.kwargs.get('assignment_pk') school = utils.get_school_from_user(self.request.user) a = Assignment.objects.get(id=self.kwargs.get('assignment_pk'), school=school.id) teachers_list = utils.get_available_teachers(a, school) # Show all the other teachers (the ones that may be busy or have an absence block). other_teachers = Teacher.objects.filter(school=school) \ .exclude(id__in=teachers_list.values('id')) \ .exclude(id=a.teacher.id) # Exclude the teacher herself! data = dict(available_teachers=teachers_list, other_teachers=other_teachers) serializer = SubstitutionSerializer(data=data, context={'request': request}) serializer.is_valid() return JsonResponse(serializer.data)
def filter_queryset(self, request, queryset, view): school = get_school_from_user(request.user) return queryset.filter(school=school.id)
def filter_queryset(self, request, queryset, view): school = get_school_from_user(request.user) return queryset.filter(course__hour_slots_group__school=school.id)
def get_data(self, request, *args, **kwargs): """ """ try: school_year = kwargs.get('school_year_pk') monday_date = datetime.datetime.strptime(kwargs.get('monday_date'), '%Y-%m-%d').date() end_date = monday_date + datetime.timedelta(days=6) school = utils.get_school_from_user(self.request.user) except ValueError: return [] self.monday_date = monday_date hour_slots = HourSlot.objects.filter(school=school, school_year=school_year) hours_hour_slots = hour_slots.extra(select={ 'hour_start': 'starts_at', 'hour_end': 'ends_at' }).order_by('hour_start', 'hour_end').values('hour_start', 'hour_end').distinct() assignments = Assignment.objects.filter(school=school, course__school_year=school_year, date__gte=monday_date, date__lte=end_date). \ order_by('teacher__last_name', 'teacher__first_name') hours_assign = assignments.order_by('hour_start', 'hour_end').values( 'hour_start', 'hour_end').distinct() hours_list = [h for h in hours_hour_slots] for h in hours_assign: if h not in hours_list: hours_list.append(h) nr_teachers = assignments.values('teacher__id').distinct() queryset = [{} for i in nr_teachers] dow_with_hour_slots = [ d + "_" + str(i) for d in days_of_week for i in range(len(hours_list)) ] for i in queryset: i.update({j: '' for j in dow_with_hour_slots}) teacher_id, teacher_idx = None, -1 for assign in assignments: if teacher_id != assign.teacher.id: teacher_id = assign.teacher.id teacher_idx += 1 queryset[teacher_idx]['teacher'] = str(assign.teacher) hs = {'hour_start': assign.hour_start, 'hour_end': assign.hour_end} hs_idx = hours_list.index(hs) field = days_of_week[assign.date.weekday()] + "_" + str(hs_idx) queryset[teacher_idx][field] = "{} {}".format( str(assign.course.year), assign.course.section) df = pd.DataFrame(queryset) # Set the index for the df to teacher, so that we can drop the counter of rows. df.set_index(['teacher'], inplace=True) # Create subcolumns, so that the dow will be the super column of the hours df.columns = pd.MultiIndex.from_tuples( [c.split('_') for c in df.columns]) # Rename both the index and the columns with reasonable human-readable names. general_labels = {'teacher': _('Teacher')} general_labels.update(labels) for i in range(len(hours_list)): general_labels.update({str(i): str(i + 1)}) df.rename(columns=general_labels, inplace=True) return df
def get_data(self, request, *args, **kwargs): """ """ try: school_year = kwargs.get('school_year_pk') teacher_pk = kwargs.get('teacher_pk') # TODO: maybe it is better to get Monday date here, # rather than letting JS doing the job and giving it for granted? monday_date = datetime.datetime.strptime(kwargs.get('monday_date'), '%Y-%m-%d').date() end_date = monday_date + datetime.timedelta(days=6) school = utils.get_school_from_user(self.request.user) except ValueError: return [] self.teacher = Teacher.objects.get(pk=teacher_pk) self.monday_date = monday_date hour_slots = HourSlot.objects.filter(school=school, school_year=school_year) hours_hour_slots = hour_slots.extra(select={ 'hour_start': 'starts_at', 'hour_end': 'ends_at' }).order_by('hour_start', 'hour_end').values('hour_start', 'hour_end').distinct() assignments = Assignment.objects.filter( school=school, course__school_year=school_year, teacher=teacher_pk, date__gte=monday_date, date__lte=end_date) hours_assign = assignments.order_by('hour_start', 'hour_end').values( 'hour_start', 'hour_end').distinct() hours_list = [h for h in hours_hour_slots] for h in hours_assign: if h not in hours_list: hours_list.append(h) queryset = sorted(hours_list, key=lambda x: (x['hour_start'], x['hour_end'])) for i in queryset: i.update({j: '' for j in days_of_week}) for assign in assignments: for hour in queryset: if hour['hour_start'] == assign.hour_start and \ hour['hour_end'] == assign.hour_end: day_of_week = days_of_week[assign.date.weekday()] hour[day_of_week] = "{} - {} {}".format( str(assign.subject), str(assign.course.year), str(assign.course.section)) break df = pd.DataFrame(queryset) # Set the hour format to hh:mm df['hour_start'] = df['hour_start'].apply( lambda x: x.strftime('%H:%M')) df['hour_end'] = df['hour_end'].apply(lambda x: x.strftime('%H:%M')) # Set the index for the df to hour_start and hour_end, so that we can drop the counter of rows. df.set_index(['hour_start', 'hour_end'], inplace=True) # Rename both the index and the columns with reasonable human-readable names. df.rename(labels, inplace=True) df.index.rename( ["".join(labels['hour_start']), "".join(labels['hour_end'])], inplace=True) return df
def __init__(self, user, *args, **kwargs): super(BaseFormWithCourseCheck, self).__init__(user, *args, **kwargs) self.fields['course'].queryset = Course.objects.filter(hour_slots_group__school__id=get_school_from_user(user).id) \ .order_by('hour_slots_group__school_year', 'year', 'section')
def post(self, request, *args, **kwargs): """ Create multiple instances of the assignments of a week in a given time period :param request: :return: """ assignments = self.request.POST.getlist('assignments[]') without_substitutions = json.loads( self.request.POST.get('without_substitutions', 'false')) # States if we should remove the non-conflicting assignments already present in the target week remove_extra_ass = json.loads( self.request.POST.get('remove_extra_ass', 'false')) try: from_date = datetime.datetime.strptime(kwargs.get('from'), '%Y-%m-%d').date() to_date = datetime.datetime.strptime(kwargs.get('to'), '%Y-%m-%d').date() school_year_pk = kwargs.get('school_year_pk') course_pk = kwargs.get('course_pk') except ValueError: # Wrong format of date: yyyy-mm-dd return HttpResponse(_('Wrong format of date: yyyy-mm-dd'), 400) if from_date > to_date: # From date should be smaller than to_date return HttpResponse( _('The beginning of the period is greater then the end of the period' ), 400) try: # Check if there are conflicts assignments_qs = Assignment.objects.filter(id__in=assignments) if without_substitutions: # the user doesn't want to replicate substitutions assignments_qs = assignments_qs.exclude(substitution=True) # Get the possible conflicts for course, teachers and rooms. # If we don't want to automatically delete the extra lectures we should report them as course conflicts course_conflicts, teacher_conflicts, room_conflicts = self.get_course_teacher_room_conflict( assignments_qs, from_date, to_date, check_course_conflicts=not remove_extra_ass) if len(course_conflicts) > 0 or len(teacher_conflicts) > 0 or len( room_conflicts) > 0: # There are conflicts! return JsonResponse(AssignmentSerializer( (course_conflicts | teacher_conflicts | room_conflicts).distinct(), context={ 'request': request }, many=True).data, safe=False, status=400) # Delete the assignments of that course in the specified period of time school = utils.get_school_from_user(request.user) assign_to_del = Assignment.objects.none() if remove_extra_ass: assign_to_del = Assignment.objects.filter(school=school, course=course_pk, school_year=school_year_pk, date__gte=from_date, date__lte=to_date). \ exclude(id__in=assignments) # avoid removing replicating assignments assign_to_del.delete() # Replicate the assignments assignments_list = [] # Iterate only over non substitutions. # In case we want to replicate them, then both substituted and substitution is going to be created, for a in assignments_qs.exclude(substitution=True): d = from_date while d <= to_date: if d != a.date and d.weekday() == a.date.weekday() and not \ Holiday.objects.filter(school=a.school, school_year=a.school_year, date_end__gte=d, date_start__lte=d).exists() and not \ Stage.objects.filter(school=a.school, school_year=a.school_year, date_start__lte=d, date_end__gte=d, course=a.course): # Found the correct day of the week when to duplicate the assignment # First we create the "substituted" or normal hour new_a = Assignment( teacher=a.teacher, course=a.course, subject=a.subject, room=a.room, hour_start=a.hour_start, hour_end=a.hour_end, bes=a.bes, co_teaching=a.co_teaching, substitution=a.substitution, substituted_assignment=a.substituted_assignment, absent=(False if without_substitutions else a.absent), date=d) new_a_dict = model_to_dict(new_a, exclude=['id']) # Add the new assignment only if is not already present if not Assignment.objects.filter( **new_a_dict).exists(): assignments_list.append(new_a) if not without_substitutions and Assignment.objects.filter( substituted_assignment=a).exists(): # If we want to replicate even the substitutions, then do it: substitution_ass = Assignment.objects.filter( substituted_assignment=a).first() new_a_substitution = Assignment( teacher=substitution_ass.teacher, course=substitution_ass.course, subject=substitution_ass.subject, room=substitution_ass.room, hour_start=substitution_ass.hour_start, hour_end=substitution_ass.hour_end, bes=substitution_ass.bes, co_teaching=substitution_ass.co_teaching, substitution=True, substituted_assignment= new_a, # The newly created assignment. absent=substitution_ass.absent, date=d) new_a_substitution_dict = model_to_dict( new_a_substitution, exclude=['id']) # Add the new assignment only if is not already present if not Assignment.objects.filter( **new_a_substitution_dict).exists(): assignments_list.append(new_a_substitution) d += datetime.timedelta(days=1) # Create with one single query. Assignment.objects.bulk_create(assignments_list) return HttpResponse(status=201) except ObjectDoesNotExist: return HttpResponse( _("One of the Assignments specified doesn't exist"), 404)
def __init__(self, user, *args, **kwargs): super(BaseFormWithRoomCheck, self).__init__(user, *args, **kwargs) self.fields['room'].queryset = Room.objects.filter(school__id=get_school_from_user(user).id) \ .order_by('name')
def __init__(self, user, *args, **kwargs): super(BaseFormWithHourSlotsGroupCheck, self).__init__(user, *args, **kwargs) self.fields['hour_slots_group'].queryset = HourSlotsGroup.objects. \ filter(school__id=get_school_from_user(user).id).order_by('name')
def __init__(self, user, *args, **kwargs): super(BaseFormWithSchoolCheck, self).__init__(user, *args, **kwargs) # Populate with the correct schools self.fields['school'].queryset = School.objects.filter( id=get_school_from_user(user).id)