def post(self, request, *args, **kwargs): year = kwargs.get('year') semester = kwargs.get('semester') year, semester = parse_year_semester(year=year, semester=semester) people = self.get_people(semester=semester, year=year) if not request.user.has_perm('profiles.add_duespayment') or not request.user.has_perm('profiles.delete_duespayment') or not request.user.has_perm('profiles.change_duespayment'): raise PermissionDenied to_be_saved = [] for person in people: paid = request.POST.get('pk_{}-paid'.format(person.pk), False) current_dues_payments = person.dues_payments.filter(semester=semester, year=year) if current_dues_payments and paid is False: current_dues_payments.delete() elif not current_dues_payments and paid == 'on': to_be_saved.append(DuesPayment(person=person, semester=semester, year=year)) if to_be_saved: DuesPayment.objects.bulk_create(to_be_saved) return redirect('profiles:roster', semester=semester, year=year)
def tours_status(self, semester=None, year=None): """ Returns dictionary of form: { 'status': 'complete'|'incomplete'|'projected', 'num_required': int, 'num_remaining': int, 'num_to_sign_up': int, 'num_extra': int, 'date_projected': date|None, 'complete': [], 'late': [], 'missed': [], 'upcoming': [], 'tours': [], } """ year, semester = core_utils.parse_year_semester(year, semester) now_obj = core_utils.now() semester_tours = self.tours.filter(counts_for_requirements=True).semester(semester=semester, year=year).order_by('time') complete = semester_tours.filter(missed=False, time__lte=now_obj) late = semester_tours.filter(late=True, missed=False, time__lte=now_obj) missed = semester_tours.filter(missed=True, time__lte=now_obj) past = semester_tours.filter(time__lt=now_obj) upcoming = semester_tours.filter(time__gte=now_obj) num_required = self.tours_required_num(semester=semester, year=year) num_remaining = num_required - complete.count() num_extra = abs(min(num_remaining, 0)) num_remaining = max(num_remaining, 0) num_to_sign_up = max(num_remaining - upcoming.count(), 0) # calculate status if num_remaining <= 0: status = 'complete' elif num_remaining <= upcoming.count(): status = 'projected' else: status = 'incomplete' if status == 'projected': completion_obj = upcoming[num_remaining - 1] date_projected = completion_obj.time else: date_projected = None return { 'status': status, 'num_required': num_required, 'num_remaining': num_remaining, 'num_to_sign_up': num_to_sign_up, 'num_extra': num_extra, 'date_projected': date_projected, 'complete': complete, 'late': late, 'missed': missed, 'past': past, 'upcoming': upcoming, 'tours': semester_tours, }
def semester(self, semester=None, year=None): """ Includes only members who are inactive for the given semester and year """ year, semester = core_utils.parse_year_semester(year=year, semester=semester) start, end = core_utils.semester_bounds(semester=semester, year=year) return self.filter(time__gte=start, time__lte=end)
def get(self, request, *args, **kwargs): semester = kwargs.get('semester') year = kwargs.get('year') year, semester = parse_year_semester(year=year, semester=semester) people = Person.objects.current_members(semester=semester, year=year) output = '\n'.join(person.as_vcard() for person in people) response = HttpResponse(output, content_type="text/x-vCard") response['Content-Disposition'] = 'attachment; filename=cks_members_{}_{}.vcf'.format(semester, year) return response
def requirements(self, semester=None, year=None): """ Get requirements for a given semester. """ year, semester = core_utils.parse_year_semester(year, semester) tours_required = self.tours_required_num(semester, year) shifts_required = self.shifts_required_num(semester, year) dues_required = core_utils.dues_required(semester=semester, year=year) return tours_required, shifts_required, dues_required
def dues_status(self, semester=None, year=None): year, semester = core_utils.parse_year_semester(year, semester) dues_required = core_utils.dues_required(semester=semester, year=year) if dues_required: if self.dues_payments.filter(year=year, semester=semester): return 'complete' else: return 'incomplete' else: return 'not_required'
def get(self, request, *args, **kwargs): year = kwargs.get('year') semester = kwargs.get('semester') year, semester = parse_year_semester(year, semester) prev_semester = delta_semester(semester=semester, year=year, delta=-1, as_dict=True) next_semester = delta_semester(semester=semester, year=year, delta=1, as_dict=True) collect_dues = dues_required(semester=semester, year=year) person = request.user.person if not person.is_active(semester=next_semester['semester'], year=next_semester['year']): next_semester = None if not person.is_active(semester=prev_semester['semester'], year=prev_semester['year']): prev_semester = None person.cached_status = { 'tours_status': person.tours_status(year=year, semester=semester), 'shifts_status': person.shifts_status(year=year, semester=semester), 'dues_status': person.dues_status(year=year, semester=semester), } # determine status tours_status = person.cached_status['tours_status']['status'] shifts_status = person.cached_status['shifts_status']['status'] dues_status = person.cached_status['dues_status'] statuses = (tours_status, shifts_status, dues_status) if tours_status == 'incomplete' or shifts_status == 'incomplete' or dues_status == 'incomplete': status = 'incomplete' elif all([x in ('complete', 'projected', 'not_required') for x in statuses]) and any([x == 'projected' for x in statuses]): status = 'projected' else: status = 'complete' status_names = { 'incomplete': 'Requirements Incomplete', 'projected': 'Projected to Complete', 'complete': 'Requirements Complete', } context = { 'person': person, 'status_class': status, 'status': status_names[status], 'tours': person.tours.semester(year=year, semester=semester).order_by('time'), 'shifts': person.shifts.semester(year=year, semester=semester).order_by('time'), 'next_semester': next_semester, 'prev_semester': prev_semester, 'collect_dues': collect_dues, } return render(request, 'public/profile.html', context)
def shifts_required_num(self, semester=None, year=None): year, semester = core_utils.parse_year_semester(year, semester) # start with default shifts_required = core_utils.get_default_num_shifts(semester=semester, year=year) # check for override try: overridden_reqs = self.overridden_requirements.get(semester=semester, year=year) shifts_required = overridden_reqs.shifts_required except OverrideRequirement.DoesNotExist: pass # get number of missed shifts num_missed = self.shifts.semester(semester=semester, year=year).filter(missed=True).count() num_extra = num_missed * core_utils.get_setting('Missed Shift Penalty') return shifts_required + num_extra
def get(self, request, *args, **kwargs): year = kwargs.get('year') semester = kwargs.get('semester') year, semester = parse_year_semester(year=year, semester=semester) prev_semester = delta_semester(semester=semester, year=year, delta=-1, as_dict=True) next_semester = delta_semester(semester=semester, year=year, delta=1, as_dict=True) collect_dues = dues_required(semester=semester, year=year) people = self.get_people(semester=semester, year=year) is_current_semester = semester == current_semester() and year == now().year # cache requirements status results so that we don't have to keep hitting the db for person in people: dues_status = person.dues_status(semester=semester, year=year) person.cached_status = { 'tours_status': person.tours_status(semester=semester, year=year), 'shifts_status': person.shifts_status(semester=semester, year=year), 'dues_status': dues_status, 'active': person.is_active(semester=semester, year=year) } # dues payments if collect_dues: paid = dues_status == 'complete' person.dues_payment_form = DuesPaymentForm(initial={'pk': person.pk, 'paid': paid}, prefix='pk_{}'.format(person.pk)) context = { 'semester': semester, 'year': year, 'people': people, 'prev_semester': prev_semester, 'next_semester': next_semester, 'collect_dues': collect_dues, 'is_current_semester': is_current_semester, } return render(request, 'profiles/roster.html', context)
def get(self, request, *args, **kwargs): year = kwargs.get('year') semester = kwargs.get('semester') year, semester = parse_year_semester(year, semester) prev_semester = delta_semester(semester=semester, year=year, delta=-1, as_dict=True) next_semester = delta_semester(semester=semester, year=year, delta=1, as_dict=True) collect_dues = dues_required(semester=semester, year=year) person = request.user.person if not person.is_active(semester=next_semester['semester'], year=next_semester['year']): next_semester = None if not person.is_active(semester=prev_semester['semester'], year=prev_semester['year']): prev_semester = None person.cached_status = { 'tours_status': person.tours_status(year=year, semester=semester), 'shifts_status': person.shifts_status(year=year, semester=semester), 'dues_status': person.dues_status(year=year, semester=semester), } # determine status tours_status = person.cached_status['tours_status']['status'] shifts_status = person.cached_status['shifts_status']['status'] dues_status = person.cached_status['dues_status'] statuses = (tours_status, shifts_status, dues_status) if tours_status == 'incomplete' or shifts_status == 'incomplete' or dues_status == 'incomplete': status = 'incomplete' elif all( [x in ('complete', 'projected', 'not_required') for x in statuses]) and any([x == 'projected' for x in statuses]): status = 'projected' else: status = 'complete' status_names = { 'incomplete': 'Requirements Incomplete', 'projected': 'Projected to Complete', 'complete': 'Requirements Complete', } context = { 'person': person, 'status_class': status, 'status': status_names[status], 'tours': person.tours.semester(year=year, semester=semester).order_by('time'), 'shifts': person.shifts.semester(year=year, semester=semester).order_by('time'), 'next_semester': next_semester, 'prev_semester': prev_semester, 'collect_dues': collect_dues, } return render(request, 'public/profile.html', context)