def scholarship_c(request): """ Renders the Scholarship page listing all brother gpas """ brothers = Brother.objects.exclude(brother_status='2').order_by( 'last_name', 'first_name') plans = [] for brother in brothers: plan = ScholarshipReport.objects.filter(semester=get_semester(), brother__id=brother.id) if plan.exists(): plan = plan[0] else: plan = ScholarshipReport(brother=brother, semester=get_semester()) plan.save() plans.append(plan) brother_plans = zip(brothers, plans) context = { 'brother_plans': brother_plans, 'position': Position.objects.get(title=Position.PositionChoices.SCHOLARSHIP_CHAIR), } return render(request, "scholarship-chair/scholarship-chair.html", context)
def event_list(request): if not request.user.is_authenticated: # brother auth check messages.error(request, "Brother not logged in") return HttpResponseRedirect(reverse('dashboard:home')) """Renders all the semester events""" chapter_events = ChapterEvent.objects.filter( semester=get_semester()).order_by("date") recruitment_events = RecruitmentEvent.objects.filter( semester=get_semester()).order_by("date") service_events = ServiceEvent.objects.filter( semester=get_semester()).order_by("date") philanthropy_events = PhilanthropyEvent.objects.filter( semester=get_semester()).order_by("date") hs_events = HealthAndSafetyEvent.objects.filter( semester=get_semester()).order_by("date") context = { 'chapter_events': chapter_events, 'recruitment_events': recruitment_events, 'service_events': service_events, 'philanthropy_events': philanthropy_events, 'hs_events': hs_events, 'type': 'general' } return render(request, "general/event-list.html", context)
def service_c(request): """ Renders the service chair page with service submissions """ events = ServiceEvent.objects.filter(semester=get_semester()) submissions_pending = ServiceSubmission.objects.filter( semester=get_semester(), status='0').order_by("date") submissions_submitted = ServiceSubmission.objects.filter( semester=get_semester(), status='1').order_by("date") position = Position.objects.get( title=Position.PositionChoices.SERVICE_CHAIR) hours_pending = 0 for submission in submissions_pending: hours_pending += submission.hours for submission in submissions_submitted: hours_pending += submission.hours hours_approved = 0 submissions_approved = ServiceSubmission.objects.filter( semester=get_semester(), status='2') for submission in submissions_approved: hours_approved += submission.hours context = { 'events': events, 'hours_approved': hours_approved, 'hours_pending': hours_pending, 'submissions_pending': submissions_pending, 'submissions_submitted': submissions_submitted, 'position': position, } return render(request, 'service-chair/service-chair.html', context)
def detail_dates(request): semester_form = SelectSemester(request.GET or None) if semester_form.is_valid(): semester = semester_form.cleaned_data['semester'] else: semester = get_semester() thursday_dates = set([e.due_date for e in ThursdayDetail.objects.all()]) thursday_dates = [ ( e, reverse('dashboard:details_on_date', args=[str(e)]) ) for e in thursday_dates ] sunday_dates = set([e.due_date for e in SundayDetail.objects.all()]) sunday_dates = [ ( e, reverse('dashboard:details_on_date', args=[str(e)]) ) for e in sunday_dates ] context = { 'semester_form': semester_form, 'thursday_dates': thursday_dates, 'sunday_dates': sunday_dates, } return render(request, 'detail-manager/details-by-date.html', context)
def scholarship_c_gpa(request): """Renders Scholarship Gpa update page for the Scholarship Chair""" plans = ScholarshipReport.objects.filter( semester=get_semester()).order_by("brother__last_name") form_list = [] for plan in plans: new_form = GPAForm(request.POST or None, initial={ 'cum_GPA': plan.cumulative_gpa, 'past_GPA': plan.past_semester_gpa }, prefix=plan.id) form_list.append(new_form) form_plans = zip(form_list, plans) if request.method == 'POST': if forms_is_valid(form_list): for counter, form in enumerate(form_list): instance = form.clean() plan = plans[counter] plan.cumulative_gpa = instance['cum_GPA'] plan.past_semester_gpa = instance['past_GPA'] plan.save() return HttpResponseRedirect(reverse('dashboard:scholarship_c')) context = { 'form_plans': form_plans, } return render(request, 'scholarship-chair/scholarship-gpa.html', context)
def current_details_helper(request, brother): if not brother.does_house_details: context = { 'does_house_details': False, 'who': str(brother), } return render(request, 'house-management/list-details.html', context) context = {} last_sunday = SundayGroupDetail.objects.filter( group__brothers=brother, group__semester=get_semester() ).order_by('-due_date').first() if last_sunday: context['last_sunday'] = last_sunday context['last_sunday_link'] = last_sunday.finish_link() context['sunday_text'] = "\n\n\n".join( [d.full_text() for d in last_sunday.details.all()] ) last_thursday = ThursdayDetail.objects.filter( brother=brother ).order_by('-due_date').first() context['last_thursday'] = last_thursday context['last_thursday_link'] = last_thursday.finish_link() context['thursday_text'] = last_thursday.full_text() context['who'] = str(brother) context['does_house_details'] = True return render(request, 'house-management/list-details.html', context)
def attendance_csv(event_types, committee_name=None): """ Returns a request to the user to download a csv of the all active brothers' and candidates' attendance at events of the type passed in through the events_list parameter. Events are separated by type and brothers are separated between actives and candidates by an empty row. The first column is reserved for highlighting brothers with poor attendance. The next column lists all the actives and candidates. The first row is the label for which event type you're looking at. The next row has headers and event names and the one after has event dates. :param list[Event Class] event_types: A list of Event Types (classes) whose events should appear on the csv :param str committee_name: An optional parameter that is passed in when CommitteeMeetingEvent is passed in. The name of the committee whose CommitteeMeetingEvents should appear on the csv :returns: the request to download the csv :rtype: HttpResponse """ active_brothers = Brother.objects.filter(brother_status='1').order_by( 'last_name', 'first_name') candidates = Brother.objects.filter(brother_status='0').order_by( 'last_name', 'first_name') response = HttpResponse(content_type='text/csv') response[ 'Content-Disposition'] = 'attachment; filename="attendance-' + str( datetime.datetime.now().strftime('%d-%m-%y')) + '.csv" ' writer = csv.writer(response) for event_type in event_types: # pulls all events that are of event_type, if it's a CommitteeMeetingEvent, it only pulls Committee Meetings # from the chosen committee events = events_from_event_type(event_type, committee_name).order_by('date') if events.exists(): event_names_and_dates = events.values_list('name', 'date') accepted_excuses = Excuse.objects.filter( event__semester=get_semester(), status='1', event__in=events) # the first row of the tables will always be the label based on which type of event it is this info is # pulled from "get_human_readable_model_name" unless it's of type CommitteeMeetingEvent in which case the # label will be the committee display name rows = [label_row(event_type, committee_name)] # the second row has the names of each of the brothers, their brother status, and general attendance info # along with the names of the events. The first column is reserved to be blank rows += [informational_row(event_names_and_dates)] # the third row has the list of event_dates rows += [event_date_row(event_names_and_dates)] # the row between the brothers list and candidates list will be blank to separate/differentiate them for brother in list(active_brothers) + [''] + list(candidates): rows += [ brother_attendance_row(brother, events, accepted_excuses) ] rows += [['']] writer.writerows(rows) return response
def post_sunday(request): """Post Sunday Details, due on the date from the form""" date_form = SelectDate(request.POST or None) if request.method == 'POST': if date_form.is_valid(): groups = DetailGroup.objects.filter(semester=get_semester()) details = settings.SUNDAY_DETAILS g = [e for e in groups] groups = g random.shuffle(groups) random.shuffle(details) emails = [] for group in groups: if len(details) <= 0: break group_detail = SundayGroupDetail( group=group, due_date=date_form.cleaned_data['due_date'] ) group_detail.save() for _ in range(group.size()): if len(details) <= 0: break d = details.pop() det = SundayDetail( short_description=d['name'], long_description="\n".join(d['tasks']), due_date=date_form.cleaned_data['due_date'] ) det.save() group_detail.details.add(det) group_detail.save() emails.append( build_sunday_detail_email( group_detail, request.scheme + "://" + request.get_host() ) ) det_manager_email = Position.objects.get( title=Position.PositionChoices.DETAIL_MANAGER ).brothers.first().user.email for (subject, message, to) in emails: send_mail(subject, message, det_manager_email, to) context = { 'form': date_form, 'date': 'sunday', } return render(request, 'detail-manager/post-details.html', context)
def vphs(request): """ Renders the VPHS and the events they can create """ events = HealthAndSafetyEvent.objects.filter( semester=get_semester()).order_by("start_time").order_by("date") context = { 'position': Position.objects.get(title=Position.PositionChoices. VICE_PRESIDENT_OF_HEALTH_AND_SAFETY), 'events': events, } return render(request, 'vphs.html', context)
def home(request): """ Renders home page """ context = photo_context(Photo) recruitment_events = RecruitmentEvent.objects \ .filter(semester=get_semester()) \ .filter(date__gte=datetime.date.today()) \ .order_by("date") context.update({ 'recruitment_events': recruitment_events, }) return render(request, 'home.html', context)
def secretary(request): """ Renders the secretary page giving access to excuses and ChapterEvents """ excuses = Excuse.objects.filter(event__semester=get_semester(), status='0')\ .exclude(event__in=RecruitmentEvent.objects.all()).order_by("date_submitted", "event__date") events = ChapterEvent.objects.filter(semester=get_semester()).order_by("start_time").order_by("date") position = Position.objects.get(title=Position.PositionChoices.SECRETARY) brothers = [] if request.method == 'POST': mass_entry_form = BrotherMassEntryForm(request.POST) mass_entry_form.fields['brothers'].widget.attrs['readonly'] = False is_entry = False if "confirmation" in request.POST: create_mass_entry_brothers(request, mass_entry_form) return HttpResponseRedirect(reverse('dashboard:home')) elif "goback" in request.POST: is_entry = True # just want to go back to adding/editting data # however else we got here, we need to show the staged data else: brothers = staged_mass_entry_brothers(mass_entry_form) else: mass_entry_form = BrotherMassEntryForm() is_entry = True context = { 'excuses': excuses, 'events': events, 'mass_entry_form': mass_entry_form, 'is_entry': is_entry, # TODO change to have post stuff 'brothers': brothers, 'position': position, } return render(request, 'secretary/secretary.html', context)
def overall_attendance(event_type, committee_name=None): """ Returns information about all active brothers and their current attendance status at events of event_type :param event_type: The event_type to be queried :param str committee_name: An optional parameter that is passed in when CommitteeMeetingEvent is passed in. The name of the committee whose CommitteeMeetingEvents should be queried :returns: a list of tuples containing the Brother and then, respectively, the number of events excused, unexcused, attended or excused, and events eligible for them to attend :rtype: list[tuple(Brother, int, int, int, int)] """ brothers = Brother.objects.exclude(brother_status='2').order_by( 'last_name', 'first_name') events = events_from_event_type(event_type, committee_name) accepted_excuses = Excuse.objects.filter(event__semester=get_semester(), status='1', event__in=events) brother_attendance = [] # For each brother, appends a tuple to brother_attendance that contains the number of events excused, unexcused, # attended/excuse and events eligible for them to attend. The latter 2 are used to display the # attendance fraction for brother in brothers: events_eligible_list = events.filter(eligible_attendees=brother) events_eligible = events_eligible_list.count() events_attended = 0 events_excused = 0 events_unexcused = 0 for event in events_eligible_list: if event.attendees_brothers.filter(id=brother.id).exists(): events_attended += 1 elif accepted_excuses.filter(brother=brother, event=event).exists(): events_excused += 1 else: events_unexcused += 1 brother_attendance.append( (brother, events_excused, events_unexcused, events_attended + events_excused, events_eligible)) return brother_attendance
def recruitment_c_pnm(request, pnm_id): """ Renders PNM view for recruitment chair """ pnm = PotentialNewMember.objects.get(pk=pnm_id) events = RecruitmentEvent.objects.filter(semester=get_semester()).order_by("date").all() attended_events = [] for event in events: if event.attendees_pnms.filter(id=pnm_id).exists(): attended_events.append(event) context = { 'type': 'recruitment-chair-view', 'events': attended_events, 'pnm': pnm, } return render(request, 'potential-new-member.html', context)
def vice_president(request): """ Renders the Vice President page and all relevant information, primarily committee related """ committee_meetings = CommitteeMeetingEvent.objects.filter(semester=get_semester())\ .order_by("start_time").order_by("date") committees = Committee.objects.all() context = { 'position': Position.objects.get(title=Position.PositionChoices.VICE_PRESIDENT), 'committees': committees, 'committee_meetings': committee_meetings, } return render(request, 'vice-president/vice-president.html', context)
def select_groups(request): """Select brothers in detail groups (for this semester)""" form = SelectDetailGroups(request.POST or None, semester=get_semester()) position = Position.objects.get(title=Position.PositionChoices.DETAIL_MANAGER) if request.method == 'POST': if form.is_valid(): for gid, brothers in form.extract_groups(): group = DetailGroup.objects.get(pk=int(gid)) group.brothers = brothers group.save() context = { 'form': form, 'position': position, } return render(request, 'detail-manager/select-groups.html', context)
def delete_groups(request): """Delete detail groups. Can select a semester to delete form""" semester_form = SelectSemester(request.GET or None) if semester_form.is_valid(): semester = semester_form.cleaned_data['semester'] else: semester = get_semester() form = DeleteDetailGroup(request.POST or None, semester=semester) if request.method == 'POST': if form.is_valid(): for g in form.cleaned_data['groups']: g.delete() context = {'form': form, 'semester_form': semester_form} return render(request, 'detail-manager/delete-groups.html', context)
def recruitment_c(request): """ Renders Recruitment chair page with events for the current and following semester """ events = RecruitmentEvent.objects.filter(semester__year=get_year()).order_by("date") excuses = Excuse.objects.filter(event__semester=get_semester(), status='0', event__in=events).order_by("date_submitted", "event__date") current_season = get_season() semester_events = events.filter(semester__season=current_season) semester_events_next = events.exclude(semester__season=current_season) potential_new_members = PotentialNewMember.objects.all() committee_meetings, context = committee_meeting_panel(Position.PositionChoices.RECRUITMENT_CHAIR) context.update({ 'events': semester_events, 'events_future': semester_events_next, 'potential_new_members': potential_new_members, 'excuses': excuses, }) return render(request, 'recruitment-chair/recruitment-chair.html', context)
def all_details_helper(request, brother): if not brother.does_house_details: context = { 'does_house_details': False, 'who': str(brother), } return render(request, 'house-management/list-details.html', context) thursday_details = ThursdayDetail.objects.filter(brother=brother) sunday_group_details = SundayGroupDetail.objects.filter( group__brothers=brother, group__semester=get_semester() ) context = { 'thursday_details': thursday_details, 'sunday_group_details': sunday_group_details, 'does_house_details': True, 'who': str(brother), } return render(request, 'house-management/all-details.html', context)
def events_from_event_type(event_type, committee_name): """ returns the list of events of event_type that have already occurred, were this semester and are mandatory :param event_type: The event_type to be queried :param str committee_name: An optional parameter that is passed in when CommitteeMeetingEvent is passed in. The name of the committee whose CommitteeMeetingEvents should be queried :returns: the list of events that meet these criteria :rtype: Queryset(Event) """ events = event_type.objects.filter(semester=get_semester(), mandatory=True, date__lt=datetime.date.today()) # if the event_type is an Event, then this should actually return all Secretary managed events if (event_type is CommitteeMeetingEvent) and (committee_name is not None): events = events.filter(committee__committee=committee_name) return events
def brother_service_submission_add(request): """ Renders the Brother page for adding a service submission""" if not request.user.is_authenticated: # brother auth check messages.error(request, "Brother not logged in before adding service hours") return HttpResponseRedirect(reverse('dashboard:home')) form = ServiceSubmissionForm(request.POST or None) if request.method == 'POST': if form.is_valid(): instance = form.save(commit=False) semester = get_semester() brother = request.user.brother instance.brother = brother instance.semester = semester instance.save() return HttpResponseRedirect(reverse('dashboard:brother')) context = { 'title': 'Submit Service Hours', 'form': form, } return render(request, 'model-add.html', context)
def brother_view(request): """ Renders the brother page of current user showing all standard brother information """ if not request.user.is_authenticated: # brother auth check messages.error( request, "Brother needs to be logged in before viewing brother portal") return HttpResponseRedirect(reverse('dashboard:home')) brother = request.user.brother semester = get_semester() hs_events = HealthAndSafetyEvent.objects.filter( semester=semester, eligible_attendees=brother).order_by("date") chapter_events = ChapterEvent.objects.filter( semester=semester, eligible_attendees=brother).order_by("date") # creates lists of events that were pending and approved for the current brother excuses = Excuse.objects.filter( brother=brother, event__semester=semester).order_by("event__date") excuses_pending = excuses.filter(status='0').values_list('event', flat=True) excuses_approved = excuses.filter(status='1').values_list('event', flat=True) operational_committees = [] standing_committees = [] meetings = [] for committee in brother.committee_set.all(): if committee.in_standing(): standing_committees.append(committee) elif committee.in_operational(): operational_committees.append(committee) for meeting in committee.meetings.all(): meetings.append(meeting) # creates a list of tuples: (event, attendance type) chapter_attendance = create_attendance_list(chapter_events, excuses_pending, excuses_approved, brother) hs_attendance = create_attendance_list(hs_events, excuses_pending, excuses_approved, brother) current_season = get_season() recruitment_events = RecruitmentEvent.objects.filter( semester__season=current_season, semester__year=get_year(), eligible_attendees=brother).order_by("date") recruitment_events_next = RecruitmentEvent.objects.filter(semester__year=get_year(), eligible_attendees=brother)\ .exclude(semester__season=current_season).order_by("date") recruitment_attendance = create_attendance_list(recruitment_events, excuses_pending, excuses_approved, brother) pnms = PotentialNewMember.objects.filter( Q(primary_contact=brother) | Q(secondary_contact=brother) | Q(tertiary_contact=brother)).order_by("last_name", "first_name") service_events = ServiceEvent.objects.filter( semester=semester, eligible_attendees=brother).order_by("date") service_attendance = create_attendance_list(service_events, excuses_pending, excuses_approved, brother) # Service submissions submissions_pending = ServiceSubmission.objects.filter( brother=brother, semester=semester, status='0').order_by("date") submissions_submitted = ServiceSubmission.objects.filter( brother=brother, semester=semester, status='1').order_by("date") submissions_approved = ServiceSubmission.objects.filter( brother=brother, semester=semester, status='2').order_by("date") submissions_denied = ServiceSubmission.objects.filter( brother=brother, semester=semester, status='3').order_by("date") hours_pending = 0 for submission in submissions_pending: hours_pending += submission.hours for submission in submissions_submitted: hours_pending += submission.hours hours_approved = 0 for submission in submissions_approved: hours_approved += submission.hours philanthropy_events = PhilanthropyEvent.objects.filter(semester=semester, eligible_attendees=brother) \ .order_by("start_time").order_by("date") philanthropy_attendance = create_attendance_list(philanthropy_events, excuses_pending, excuses_approved, brother) mab = None if brother.brother_status == '0': mab = [ x.brother for x in brother.candidate_mab.filter(completed=False) ] elif brother.brother_status == '1': mab = [ x.candidate for x in brother.brother_mab.filter(completed=False) ] try: discord = OnlineMedia.objects.get(name='Discord') except ObjectDoesNotExist: discord = None if request.method == 'POST': pk = request.POST.get('id') if brother.brother_status == '0': mabro = brother.candidate_mab.get(brother=pk) mabro.completed = True mabro.save() elif brother.brother_status == '1': mabro = brother.brother_mab.get(candidate=pk) mabro.completed = True mabro.save() return HttpResponseRedirect(reverse('dashboard:brother')) context = { 'brother': brother, 'chapter_attendance': chapter_attendance, 'operational_committees': operational_committees, 'standing_committees': standing_committees, 'meetings': meetings, 'hs_attendance': hs_attendance, 'recruitment_events_next': recruitment_events_next, 'recruitment_attendance': recruitment_attendance, 'pnms': pnms, 'service_attendance': service_attendance, 'submissions_pending': submissions_pending, 'submissions_submitted': submissions_submitted, 'submissions_approved': submissions_approved, 'submissions_denied': submissions_denied, 'philanthropy_attendance': philanthropy_attendance, 'hours_approved': hours_approved, 'hours_pending': hours_pending, 'type': 'brother-view', 'notifies': notifies(brother), 'notified_by': notified_by(brother), 'mab': mab, 'discord': discord, } return render(request, "brother.html", context)
def marshal(request): """ Renders the marshal page listing all the candidates and relevant information to them """ candidates = Brother.objects.filter(brother_status='0').order_by( 'last_name', 'first_name') events = ChapterEvent.objects.filter(semester=get_semester()).exclude( date__gt=datetime.date.today()) excuses = Excuse.objects.filter(event__semester=get_semester(), status='1') events_excused_list = [] events_unexcused_list = [] randomized_list = request.session.pop('randomized_list', None) mab_form_list = [] for counter, candidate in enumerate(candidates): assigned_mab = MeetABrother.objects.filter( candidate=candidate).values_list('brother', flat=True) eligible_brothers = Brother.objects.filter(brother_status=1).exclude( pk__in=assigned_mab).order_by('last_name', 'first_name') form = MeetABrotherForm(request.POST or None, prefix=counter + 1, candidate=candidate.first_name + ' ' + candidate.last_name) mab_form_list.append(form) if randomized_list is not None or []: form.fields['assigned_brother1'].initial = randomized_list[ counter][0] form.fields['assigned_brother2'].initial = randomized_list[ counter][1] form.fields['randomize'].initial = randomized_list[counter][2] else: form.fields['randomize'].initial = True form.fields['assigned_brother1'].queryset = eligible_brothers form.fields['assigned_brother2'].queryset = eligible_brothers for candidate in candidates: events_excused = 0 events_unexcused = 0 if candidate.date_pledged: expected_events = events.exclude( date_pledged__lt=datetime.date.today()) else: expected_events = events for event in expected_events: if not event.attendees_brothers.filter(id=candidate.id).exists(): if excuses.filter(brother=candidate, event=event).exists(): events_excused += 1 else: events_unexcused += 1 events_excused_list.append(events_excused) events_unexcused_list.append(events_unexcused) candidate_attendance = zip(candidates, events_excused_list, events_unexcused_list) if request.method == 'POST': if 'submit' in request.POST: if forms_is_valid(mab_form_list): for counter, form in enumerate(mab_form_list): instance = form.clean() if instance['assigned_brother1']: mab1 = MeetABrother( candidate=candidates[counter], brother=instance['assigned_brother1']) mab1.save() if instance['assigned_brother2']: mab2 = MeetABrother( candidate=candidates[counter], brother=instance['assigned_brother2']) mab2.save() return HttpResponseRedirect( reverse('dashboard:meet_a_brother')) if 'randomize' in request.POST: if forms_is_valid(mab_form_list): randomized_list = [] random1 = [] random2 = [] for form in mab_form_list: instance = form.clean() if instance['randomize']: queryset1 = form.fields['assigned_brother1'].queryset queryset2 = queryset1 if queryset1.exists(): random1 = random.choices(queryset1, k=1)[0].pk queryset2 = queryset1.exclude(pk=random1) if queryset2.exists(): random2 = random.choices(queryset2, k=1)[0].pk randomized_list.append((random1, random2, True)) else: if instance['assigned_brother1']: random1 = instance['assigned_brother1'].pk else: random1 = [] if instance['assigned_brother2']: random2 = instance['assigned_brother2'].pk else: random2 = [] randomized_list.append( (random1, random2, instance['randomize'])) request.session['randomized_list'] = randomized_list return HttpResponseRedirect(reverse('dashboard:marshal')) context = { 'candidates': candidates, 'candidate_attendance': candidate_attendance, 'mab_form_list': mab_form_list, 'position': Position.objects.get(title=Position.PositionChoices.MARSHAL) } return render(request, 'marshal/marshal.html', context)