Esempio n. 1
0
  def form_valid(self, form):

    new_schedule = form.instance
    cur_schedule = Schedule.objects.get(id=new_schedule.id)

    new_set = new_schedule.trainees.all()
    current_set = cur_schedule.trainees.all()

    # If the trainee sets are identical, minor schedule update
    to_add = new_set.exclude(pk__in=current_set)
    to_delete = current_set.exclude(pk__in=new_set)

    if not to_add and not to_delete:
      return super(ScheduleAdminUpdate, self).form_valid(form)

    for t in to_delete:
      # trainee cannot be moved off of a schedule if there are rolls for events on that schedule
      t_events = t.rolls.order_by('event').distinct('event').values_list('event__id', flat=True)
      if cur_schedule.events.filter(id__in=t_events).exists():
        form._errors[NON_FIELD_ERRORS] = ErrorList([u'Trainee(s) cannot be removed from schedule. Split the schedule.'])
        return super(ScheduleAdminUpdate, self).form_invalid(form)

    for t in to_add:
      # trainee cannot be moved onto a schedule if there are rolls for events on a schedule that it will overlap
      sch_event_set = cur_schedule.events.values('event__id', 'event__start', 'event__end')
      tr_event_set = t.rolls.order_by('event').distinct('event').values('event__id', 'event__start', 'event__end')
      for i in tr_event_set:
        for j in sch_event_set:
          if EventUtils.time_overlap(i['event__start'], i['event__end'], j['event__start'], j['event__end']):
            form._errors[NON_FIELD_ERRORS] = ErrorList([u'Trainee(s) cannot be added to schedule. Split the schedule.'])
            return super(ScheduleAdminUpdate, self).form_invalid(form)

    return super(ScheduleAdminUpdate, self).form_valid(form)
Esempio n. 2
0
    def get_attendance_record(self, period=None):
        from leaveslips.models import GroupSlip
        c_term = Term.current_term()
        rolls = self.rolls.exclude(status='P').filter(
            date__gte=c_term.start, date__lte=c_term.end).order_by(
                'event', 'date').distinct('event',
                                          'date').prefetch_related('event')
        ind_slips = self.individualslips.filter(status__in=['A', 'S'])
        att_record = []  # list of non 'present' events
        excused_timeframes = []  # list of groupslip time ranges
        excused_rolls = []  # prevents duplicate rolls

        def attendance_record(att, start, end, event):
            return {
                'attendance': att,
                'start': start,
                'end': end,
                'event': event,
            }

        def reformat(slip):
            s = str(
                datetime.combine(slip['rolls__date'],
                                 slip['rolls__event__start'])).replace(
                                     ' ', 'T')
            e = str(
                datetime.combine(slip['rolls__date'],
                                 slip['rolls__event__end'])).replace(' ', 'T')
            return (s, e)

        group_slips = GroupSlip.objects.filter(trainees=self,
                                               status__in=['A', 'S'])

        rolls = rolls.order_by('event__id', 'date').distinct(
            'event__id', 'date')  # may not need to order

        if period is not None:
            # works without period, but makes calculate_summary really slow
            p = Period(c_term)
            start_date = p.start(period)
            end_date = p.end(period)
            startdt = datetime.combine(start_date, datetime.min.time())
            enddt = datetime.combine(end_date, datetime.max.time())
            rolls = rolls.filter(
                date__gte=start_date,
                date__lte=end_date)  # rolls for current period
            ind_slips = ind_slips.filter(
                rolls__in=[d['id'] for d in rolls.values('id')])
            group_slips = group_slips.filter(start__lte=enddt,
                                             end__gte=startdt)

        rolls = rolls.values('event__id', 'event__start', 'event__end',
                             'event__name', 'status', 'date')
        ind_slips = ind_slips.values('rolls__event__id', 'rolls__event__start',
                                     'rolls__event__end', 'rolls__date',
                                     'rolls__event__name', 'id')
        excused_timeframes = group_slips.values('start', 'end')

        # first, individual slips
        for slip in ind_slips:
            if slip['rolls__event__id'] is None:
                continue
            start, end = reformat(slip)
            att_record.append(
                attendance_record('E', start, end, slip['rolls__event__id']))
            excused_rolls.append(
                (slip['rolls__event__id'], slip['rolls__date']))

        for roll in rolls:
            excused = False
            for excused_roll in excused_rolls:
                if roll['event__id'] == excused_roll[0] and roll[
                        'date'] == excused_roll[
                            1]:  # Check if roll is excused using the roll's event and the roll's date
                    excused = True
                    break
            if excused is False:
                if roll['status'] == 'A':  # absent rolls
                    att_record.append(
                        attendance_record(
                            'A',
                            str(roll['date']) + 'T' +
                            str(roll['event__start']),
                            str(roll['date']) + 'T' + str(roll['event__end']),
                            roll['event__id']))
                else:  # tardy rolls
                    att_record.append(
                        attendance_record(
                            'T',
                            str(roll['date']) + 'T' +
                            str(roll['event__start']),
                            str(roll['date']) + 'T' + str(roll['event__end']),
                            roll['event__id']))
        # now, group slips
        for record in att_record:
            if record['event'] is None:
                continue
            if record['attendance'] != 'E':
                start_dt = parser.parse(record['start'])
                end_dt = parser.parse(record['end'])
                for tf in excused_timeframes:
                    if EventUtils.time_overlap(start_dt, end_dt, tf['start'],
                                               tf['end']):
                        record['attendance'] = 'E'
        return att_record