def export_as_csv(modeladmin: admin.ModelAdmin, request: HttpRequest, queryset: QuerySet) -> HttpResponse: semester = Semester.get_current_semester() records = Record.objects.filter( student__in=queryset, group__course__semester=semester, status=1).select_related( 'student', 'student__user', 'group', 'group__course') opts = modeladmin.model._meta response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename=%s.csv' % str(opts).replace('.', '_') writer = csv.writer(response) for record in records: writer.writerow([record.student.matricula, record.student.user.first_name, record.student.user.last_name, record.group.course.name, record.group.get_type_display(), record.group.get_terms_as_string()]) return response
def prepare_data_for_create_poll(request, group_id=0): data = pop_template_from_session(request) if group_id > 0: group = Group.objects.get(pk=group_id) data['group'] = group.pk data['type'] = group.type data['course_id'] = group.course.pk data['semester'] = group.course.semester.pk data['groups'] = Group.objects.filter( type=group.type, course=group.course).order_by('teacher') if data['semester']: data['courses'] = get_courses_for_user(request, data['semester']) else: semester_id = Semester.get_current_semester() data['semester'] = semester_id data['courses'] = get_courses_for_user(request, semester_id) data['studies_types'] = Program.objects.all() data['semesters'] = Semester.objects.all() data['sections'] = Section.objects.filter(deleted=False) data['types'] = GROUP_TYPE_CHOICES return data
def get_polls_for_semester(semester=None): if not semester: semester = Semester.get_current_semester() return Poll.objects.filter(semester=semester, deleted=False).select_related( 'group', 'group__course', 'group__teacher', 'group__teacher__user')
def get_groups_without_poll(): semester = Semester.get_current_semester() polls = Poll.objects.filter(semester=semester, group__isnull=False, deleted=False).order_by('pk') polls = [p.group_id for p in polls] groups = Group.objects.filter(course__semester=semester).order_by('pk') return [g for g in groups if g.pk not in polls]
def count_current_semester_polls_without_keys(): from apps.grade.ticket_create.models.public_key import PublicKey semester = Semester.get_current_semester() polls_with_keys = PublicKey.objects.all().values('poll') return Poll.objects.filter( semester=semester, deleted=False).exclude(pk__in=polls_with_keys).count()
def handle(self, *args, **kwargs): semester_id = kwargs["semester"] created, skipped = 0, 0 if semester_id: semester = Semester.objects.get(id=semester_id) else: semester = Semester.get_current_semester() self.stdout.write(f"Selected semester: `{semester}` with id {semester.id}") # Check whether poll exists for a selected semester self.stdout.write(f"\n{HEADER}Semester polls") semester_poll = Poll.objects.filter(semester=semester).count() > 0 if semester_poll: self.stdout.write(f"{MARGIN}Poll for a selected semester already exists") skipped += 1 else: new_poll = Poll(group=None, course=None, semester=semester) new_poll.save() self.stdout.write( f"{CREATED}Poll for a selected semester does not exist, creating" ) created += 1 # Check whether poll exists for courses held in a selected semester self.stdout.write(f"\n{HEADER}Course/group polls") courses = CourseInstance.objects.filter(semester=semester) for course in courses: course_poll = Poll.objects.filter(course=course).count() > 0 if not course.has_exam or course_poll: self.stdout.write(f"{MARGIN}{course}") skipped += 1 else: new_poll = Poll(group=None, course=course, semester=None) new_poll.save() self.stdout.write(f"{CREATED}{course}") created += 1 groups = Group.objects.filter(course=course) for group in groups: group_poll = Poll.objects.filter(group=group).count() > 0 if group_poll: self.stdout.write(f"{MARGIN}{MARGIN}{group}") skipped += 1 else: new_poll = Poll(group=group, course=None, semester=None) new_poll.save() self.stdout.write(f"{CREATED}{MARGIN}{group}") created += 1 self.stdout.write(f"\n{HEADER}Summary") self.stdout.write(f"{MARGIN}Created: {created}, skipped: {skipped}")
def changelist_view(self, request, extra_context=None): if 'course__semester__id__exact' not in request.GET: q = request.GET.copy() semester = Semester.get_current_semester() q['course__semester__id__exact'] = semester.id request.GET = q request.META['QUERY_STRING'] = request.GET.urlencode() return super(GroupAdmin, self).changelist_view(request, extra_context=extra_context)
def make_template_variables(request): """ parse POST for template datas @author mjablonski @param request @return dictionary - templates option """ var = {} if request.POST.get('title', '') == '': raise NoTitleException type = int(request.POST.get('type', 0)) if not type: type = None studies_type = int(request.POST.get('studies-type', -1)) if studies_type > -1: studies_type = Program.objects.get(pk=studies_type) else: studies_type = None course = int(request.POST.get('course', 0)) if course > 0: course = CourseInstance.objects.get(pk=course) elif not course: course = None else: course = -1 group = int(request.POST.get('group', 0)) if group > 0: group = Group.objects.filter(pk=group) else: group = None semester = int(request.POST.get('semester', 0)) if semester > 0: semester = Semester.objects.get(pk=semester) else: semester = Semester.get_current_semester() var['type'] = type var['studies_type'] = studies_type var['course'] = course var['title'] = request.POST.get('title', '') var['semester'] = semester var['description'] = request.POST.get('description', '') var['groups_without'] = request.POST.get('poll-only-without', 'off') var['group'] = group var['exam'] = request.POST.get('exam', False) return var
def session(request, semester=None): from apps.enrollment.courses.models.semester import Semester exams_filter = ExamFilter(request.GET, queryset=Term.get_exams()) if semester: semester = Semester.get_by_id(semester) else: semester = Semester.get_current_semester() return TemplateResponse(request, 'schedule/session.html', { "semester": semester, "exams": exams_filter.qs })
def get_all_polls_for_student(student: Student, semester: Semester = None) -> List: """Checks the eligibility of a student and returns a list of polls. :param student: a valid instance of `Student` class. :param semester: if no semester is given, assumes a current one. :returns: a list of all available polls for a given student. """ if not student.is_active: return [] current_semester = semester if current_semester is None: current_semester = Semester.get_current_semester() if current_semester is None: return [] if not current_semester.is_grade_active: return [] polls = [] poll_for_semester = Poll.objects.filter( semester=current_semester).first() if poll_for_semester: polls.append(poll_for_semester) # Retrieves only the groups that the Student is enrolled in records = records_models.Record.objects.filter( student=student, status=records_models.RecordStatus.ENROLLED, group__course__semester=current_semester, ).select_related('group') for record in records: group = record.group course = group.course semester = course.semester if semester == current_semester: if course.has_exam: poll_for_course = Poll.objects.get(course=course) if poll_for_course and poll_for_course not in polls: polls.append(poll_for_course) poll_for_group = Poll.objects.get(group=group) if poll_for_group: polls.append(poll_for_group) return polls
def tickets_generate(request): """Renders tickets_generate page and lists Polls student is entitled to.""" semester = Semester.get_current_semester() is_grade_active = semester.is_grade_active if not is_grade_active: messages.error( request, "Ocena zajęć jest w tej chwili zamknięta; nie można pobrać biletów" ) return redirect('grade-main') polls = get_grouped_polls(request.user.student) data = { 'polls': polls, 'is_grade_active': is_grade_active, } return render(request, 'ticket_create/tickets_generate.html', data)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) classrooms = Classroom.objects.filter(can_reserve=True) by_floor = defaultdict(list) floor_names = dict(floors) for r in classrooms: by_floor[floor_names[r.floor]].append((r.pk, r.number)) self.fields['rooms'].choices = by_floor.items() semester = Semester.get_current_semester() next_sem = Semester.objects.get_next() weeks = [(week[0], f"{week[0]} - {week[1]}") for week in semester.get_all_weeks()] if semester != next_sem: weeks.insert(0, ('nextsem', f"Generuj z planu zajęć dla semestru '{next_sem}'")) weeks.insert(0, ('currsem', f"Generuj z planu zajęć dla semestru '{semester}'")) self.fields['week'].widget.choices = weeks
def generate_keys_for_polls(semester=None): from apps.enrollment.courses.models.semester import Semester if not semester: semester = Semester.get_current_semester() poll_list = Poll.get_polls_without_keys(semester) pub_list = [] priv_list = [] i = 1 for el in poll_list: (pub, priv) = generate_rsa_key() pub_list.append(pub) priv_list.append(priv) i = i + 1 save_public_keys(list(zip(poll_list, pub_list))) save_private_keys(list(zip(poll_list, priv_list))) print(i - 1) return
def __init__(self, user, data=None, **kwargs): if data: data = deepcopy(data) if 'type' not in data: data['type'] = Event.TYPE_GENERIC super(EventForm, self).__init__(data, **kwargs) if not self.instance.pk: self.instance.author = user if BaseUser.is_employee(user): self.fields['type'].choices = Event.TYPES_FOR_TEACHER else: self.fields['type'].choices = Event.TYPES_FOR_STUDENT if not BaseUser.is_employee(user): self.fields['course'].queryset = CourseInstance.objects.none() else: semester = Semester.get_current_semester() previous_semester = Semester.get_semester(datetime.now().date() - timedelta(days=30)) queryset = CourseInstance.objects.filter(semester__in=[semester, previous_semester]). \ select_related('semester'). \ order_by('semester') if not user.has_perm('schedule.manage_events'): queryset = CourseInstance.objects.filter( groups__type='1', groups__teacher=user.employee, semester__in=[semester, previous_semester]) self.fields['course'].queryset = queryset self.fields['title'].widget.attrs.update({'class': 'form-control'}) self.fields['type'].widget.attrs.update({'class': 'form-control'}) self.fields['course'].widget.attrs.update({'class': 'form-control'}) self.fields['description'].widget.attrs.update( {'class': 'form-control'}) self.fields['visible'].widget.attrs.update({ 'checked': '', 'class': 'custom-control-input' })
def get_all_polls_for_semester(user, semester: Semester = None) -> List['Poll']: """Returns all polls that user may see the submissions for. The polls will be annotated with submission counts. """ current_semester = semester if current_semester is None: current_semester = Semester.get_current_semester() is_superuser = user.is_superuser is_employee = user.employee if not is_superuser and not is_employee: return Poll.objects.none() poll_for_semester = Poll.objects.filter(semester=current_semester) if is_superuser: polls_for_courses = Poll.objects.filter( course__semester=current_semester) polls_for_groups = Poll.objects.filter( group__course__semester=current_semester) elif is_employee: polls_for_courses = Poll.objects.filter( course__semester=current_semester, course__owner=user.employee, ) | Poll.objects.filter(group__course__semester=current_semester, group__course__owner=user.employee) polls_for_groups = Poll.objects.filter( group__course__semester=current_semester, group__teacher=user.employee, ) qs = poll_for_semester | polls_for_courses | polls_for_groups sub_count_ann = models.Count( 'submission', filter=models.Q(submission__submitted=True)) return list(qs.annotate(number_of_submissions=sub_count_ann))
def this_semester(self): return self.filter(semester=Semester.get_current_semester())
def sign_tickets(request): """Signs the tickets sent by a student and returns list of signatures. The student must request to sign all the tickets he is entitled to. The signing may only be performed once in a semester. Request must be a dict of objects: { "signing_requests": [ # An object for every poll. { # Id of the poll. "id": 123, # A blinded ticket. "ticket": 12345..., }, ] } Returns: A list of signed tickets, each being a dict like below. { # Id of the poll. 'id': 123, # The ticket from the request signed using a private key # corresponding to the poll. 'signature': 1234... } Errors: 400 BadRequest: When JSON request could not be parsed. 403 Forbidden: When the student tries to sign a ticket for a poll he is not entitled to, fails to request a ticket he is entitled to, or has already been signing this semester. """ try: signing_requests_dict = json.loads(request.body.decode('utf-8')) except json.decoder.JSONDecodeError: return HttpResponseBadRequest("Couldn't parse JSON") signing_requests = signing_requests_dict['signing_requests'] semester = Semester.get_current_semester() student_polls = { poll.pk for poll in Poll.get_all_polls_for_student(request.user.student, semester) } request_polls = {int(req['id']) for req in signing_requests} if request_polls - student_polls: return HttpResponseForbidden( f"Student nie jest upoważniony do tych ankiet: {request_polls - student_polls}." ) if student_polls - request_polls: return HttpResponseForbidden( f"Student powinien również wygenerować bilety dla tych " "ankiet: {student_polls - request_polls}.") if len(request_polls) != len(signing_requests): return HttpResponseForbidden( f"Próbowano podpisać wiele biletów do jednej ankiety.") # Now we made sure that student_polls == request_polls # We obtain a lock on RSA keys. keys = RSAKeys.objects.filter(poll__in=request_polls).select_for_update() keys_by_poll = {key.poll_id: key for key in keys} _, created = StudentGraded.objects.get_or_create( student=request.user.student, semester=semester) if not created: return HttpResponseForbidden( f"Student już podpisywał bilety w tym semestrze.") response = [] for signing_request in signing_requests: key = keys_by_poll[int(signing_request['id'])] signed_ticket = key.sign_ticket(signing_request['ticket']) signing_response = { 'id': signing_request['id'], 'signature': str(signed_ticket), } response.append(signing_response) return JsonResponse(response, safe=False)
def __init__(self, data=None, *args, **kwargs): if not data: semester = Semester.get_current_semester() data = {'event__course__semester': semester.id} super(ExamFilter, self).__init__(data, *args, **kwargs)
def check_grade_status() -> bool: """Checks whether any of the semesters has grade enabled.""" current_semester = Semester.get_current_semester() return current_semester.is_grade_active
def get_all_polls_for_group(group, semester=None): if not semester: semester = Semester.get_current_semester() return Poll.objects.filter(semester=semester, group=group, deleted=False)
def handle(self, *args, **options): semester = Semester.get_current_semester() freedays = Freeday.objects.filter(Q(day__gte=semester.lectures_beginning), Q(day__lte=semester.lectures_ending))\ .values_list('day', flat=True) changed = ChangedDay.objects.filter( Q(day__gte=semester.lectures_beginning), Q(day__lte=semester.lectures_ending)).values_list( 'day', 'weekday') days = {0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: []} day = semester.lectures_beginning s4 = Classroom.objects.get(number='4') s5 = Classroom.objects.get(number='5') s25 = Classroom.objects.get(number='25') s141 = Classroom.objects.get(number='141') s139 = Classroom.objects.get(number='139') s140 = Classroom.objects.get(number='140') s103 = Classroom.objects.get(number='103') s104 = Classroom.objects.get(number='104') s105 = Classroom.objects.get(number='105') s108 = Classroom.objects.get(number='108') s110 = Classroom.objects.get(number='110') s119 = Classroom.objects.get(number='119') s237 = Classroom.objects.get(number='237') s310 = Classroom.objects.get(number='310') while day <= semester.lectures_ending: if day in freedays: day = day + datetime.timedelta(days=1) continue weekday = day.weekday() for d in changed: if d[0] == day: weekday = int(d[1]) - 1 break days[weekday].append(day) day = day + datetime.timedelta(days=1) def create_event(title, visible=True): ev = Event() ev.title = title ev.type = '4' ev.visible = visible ev.status = '1' ev.author_id = 1 ev.save() return ev def create_term(event, day, start, end, room, minutes_start=0, minutes_end=0): newTerm = Term() newTerm.event = event newTerm.day = day newTerm.start = datetime.time(hour=start, minute=minutes_start) newTerm.end = datetime.time(hour=end, minute=minutes_end) newTerm.room = room newTerm.save() for d in days[4]: # piatek ev = create_event('Kolokwia') create_term(ev, d, 14, 16, s25) ev = create_event('Jezyk Angielski') create_term(ev, d, 12, 15, s4) ev = create_event('INSTYTUT DZIENNIKARSTWA') create_term(ev, d, 15, 20, s141) create_term(ev, d, 15, 20, s140) create_term(ev, d, 15, 20, s139) create_term(ev, d, 15, 20, s103) create_term(ev, d, 15, 20, s104) create_term(ev, d, 15, 20, s4) create_term(ev, d, 15, 20, s5) ev = create_event('SEMINARIUM ZJP') create_term(ev, d, 13, 15, s105) for d in days[5]: # sobota ev = create_event('INSTYTUT DZIENNIKARSTWA') create_term(ev, d, 9, 18, s141) create_term(ev, d, 9, 18, s140) create_term(ev, d, 9, 18, s139) create_term(ev, d, 9, 18, s103) create_term(ev, d, 9, 18, s104) create_term(ev, d, 9, 18, s5) create_term(ev, d, 9, 18, s4) for d in days[6]: # niedziela ev = create_event('INSTYTUT DZIENNIKARSTWA') create_term(ev, d, 9, 18, s141) create_term(ev, d, 9, 18, s140) create_term(ev, d, 9, 18, s139) create_term(ev, d, 9, 18, s103) create_term(ev, d, 9, 18, s104) create_term(ev, d, 9, 18, s5) create_term(ev, d, 9, 18, s4) for d in days[0]: # poniedzialke ev = create_event('Jezyk Angielski') create_term(ev, d, 8, 12, s4) ev = create_event('INSTYTUT MATEMATYCZNY') create_term(ev, d, 10, 12, s104) for d in days[1]: # wtorek ev = create_event('JUG') create_term(ev, d, 18, 21, s25, minutes_start=30) ev = create_event('SEMINARIUM ZMN') create_term(ev, d, 14, 16, s104) create_term(ev, d, 14, 16, s237) ev = create_event('INSTYTUT DZIENNIKARSTWA') create_term(ev, d, 12, 14, s4) ev = create_event('JUG') create_term(ev, d, 18, 21, s25, 30) ev = create_event('Grupa .NET') create_term(ev, d, 18, 20, s119) for d in days[2]: # sroda ev = create_event('SEMINARIUM PGK') create_term(ev, d, 12, 14, s105) ev = create_event('INSTYTUT DZIENNIKARSTWA') create_term(ev, d, 10, 12, s4) for d in days[3]: # czwartek ev = create_event('SEMINARIUM PIO') create_term(ev, d, 16, 18, s237) ev = create_event('SEMINARIUM ZZOIA') create_term(ev, d, 12, 14, s119) ev = create_event('SEMINARIUM INSTYTUTOWE') create_term(ev, d, 14, 16, s119) ev = create_event('INSTYTUT DZIENNIKARSTWA') create_term(ev, d, 8, 10, s4) create_term(ev, d, 12, 14, s4) create_term(ev, d, 16, 20, s5)
def get(self, request, semester_id=None, poll_id=None, submission_id=None): """Controls the main logic of passing the data to the template responsible for presenting the results of the poll. :param semester_id: if given, fetches polls from requested semester. :param poll_id: if given, displays summary for a given poll. :param submission_id: if given, displays detailed submission view. """ is_grade_active = check_grade_status() if semester_id is None: semester_id = Semester.get_current_semester().id current_semester = Semester.get_current_semester() selected_semester = Semester.objects.filter(pk=semester_id).get() available_polls = Poll.get_all_polls_for_semester( user=request.user, semester=selected_semester) current_poll = Poll.objects.filter(id=poll_id).first() if poll_id is not None: submissions = Submission.objects.filter( poll=poll_id, submitted=True).order_by('modified') if current_poll not in available_polls: # User does not have permission to view details about # the selected poll messages.error( request, "Nie masz uprawnień do wyświetlenia tej ankiety.") return redirect('grade-poll-results', semester_id=semester_id) else: submissions = [] semesters = Semester.objects.all() if request.user.is_superuser or request.user.employee: return render( request, self.template_name, { 'is_grade_active': is_grade_active, 'polls': group(entries=available_polls, sort=True), 'results': self.__get_processed_results(submissions), 'results_iterator': itertools.count(), 'semesters': semesters, 'current_semester': current_semester, 'current_poll_id': poll_id, 'current_poll': current_poll, 'selected_semester': selected_semester, 'submissions_count': self.__get_counter_for_categories(available_polls), 'iterator': itertools.count(), }, ) messages.error(request, "Nie masz uprawnień do wyświetlania wyników oceny.") return redirect('grade-main')
def display_report(request, form, report_type: 'Literal["table", "doors"]'): class ListEvent(NamedTuple): date: Optional[datetime.datetime] weekday: int # Monday is 1, Sunday is 7 like in # https://docs.python.org/3/library/datetime.html#datetime.date.isoweekday. begin: datetime.time end: datetime.time room: Classroom title: str type: str author: str rooms = set(Classroom.objects.filter(id__in=form.cleaned_data['rooms'])) events: List[ListEvent] = [] # Every event will regardless of its origin be translated into a ListEvent. beg_date = form.cleaned_data.get('beg_date', None) end_date = form.cleaned_data.get('end_date', None) semester = None if form.cleaned_data.get('week', None) == 'currsem': semester = Semester.get_current_semester() elif form.cleaned_data.get('week', None) == 'nextsem': semester = Semester.objects.get_next() if semester: terms = CourseTerm.objects.filter( group__course__semester=semester, classrooms__in=rooms).distinct().select_related( 'group__course', 'group__teacher', 'group__teacher__user').prefetch_related('classrooms') for term in terms: for r in set(term.classrooms.all()) & rooms: events.append( ListEvent(date=None, weekday=int(term.dayOfWeek), begin=term.start_time, end=term.end_time, room=r, title=term.group.course.name, type=term.group.human_readable_type(), author=term.group.teacher.get_full_name())) terms = SpecialReservation.objects.filter( semester=semester, classroom__in=rooms).select_related('classroom') for term in terms: events.append( ListEvent(date=None, weekday=int(term.dayOfWeek), begin=term.start_time, end=term.end_time, room=term.classroom, title=term.title, type="", author="")) elif 'week' in form.cleaned_data: beg_date = datetime.datetime.strptime(form.cleaned_data['week'], "%Y-%m-%d") end_date = beg_date + datetime.timedelta(days=6) if beg_date and end_date: terms = Term.objects.filter( day__gte=beg_date, day__lte=end_date, room__in=rooms, event__status=Event.STATUS_ACCEPTED).select_related( 'room', 'event', 'event__group', 'event__author') for term in terms: events.append( ListEvent(date=term.day, weekday=term.day.isoweekday(), begin=term.start, end=term.end, room=term.room, title=term.event.title or str(term.event.course) or "", type=term.event.group.human_readable_type() if term.event.group else term.event.get_type_display(), author=term.event.author.get_full_name())) if report_type == 'table': events = sorted(events, key=operator.attrgetter('room.id', 'date', 'begin')) else: events = sorted(events, key=operator.attrgetter('room.id', 'weekday', 'begin')) terms_by_room = groupby(events, operator.attrgetter('room.number')) terms_by_room = sorted([(int(k), list(g)) for k, g in terms_by_room]) return render( request, f'schedule/reports/report_{report_type}.html', { 'events': terms_by_room, 'semester': semester, 'beg_date': beg_date, 'end_date': end_date, })