# -*- coding: utf-8 -*- from __future__ import division from __future__ import print_function from __future__ import unicode_literals import unicodecsv import uuid from datetime import timedelta from icalendar import Calendar, Event as Vevent from django.shortcuts import redirect, get_object_or_404, render from django.http import Http404, HttpResponse from django.contrib.auth.decorators import login_required from django.contrib.auth.views import login as django_login_view from django.contrib.auth.models import User from django.utils import timezone import django.utils.six as six from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, \ SurveyQuestionAnswer from gestioncof.models import Event, EventRegistration, EventOption, \ EventOptionChoice from gestioncof.models import EventCommentField, EventCommentValue, \ CalendarSubscription from gestioncof.shared import send_custom_mail from gestioncof.models import CofProfile, Clipper from gestioncof.decorators import buro_required, cof_required from gestioncof.forms import UserProfileForm, EventStatusFilterForm, \ SurveyForm, SurveyStatusFilterForm, RegistrationUserForm, \ RegistrationProfileForm, AdminEventForm, EventForm, CalendarForm from bda.models import Tirage, Spectacle @login_required def home(request): data = {"surveys": Survey.objects.filter(old=False).all(), "events": Event.objects.filter(old=False).all(), "open_surveys": Survey.objects.filter(survey_open=True, old=False).all(), "open_events": Event.objects.filter(registration_open=True, old=False).all(), "open_tirages": Tirage.objects.filter(active=True).all(), "now": timezone.now()} return render(request, "home.html", data) def login(request): if request.user.is_authenticated(): return redirect("gestioncof.views.home") context = {} if request.method == "GET" and 'next' in request.GET: context['next'] = request.GET['next'] return render(request, "login_switch.html", context) def login_ext(request): if request.method == "POST" and "username" in request.POST: try: user = User.objects.get(username=request.POST["username"]) if not user.has_usable_password() or user.password in ("", "!"): profile, created = CofProfile.objects.get_or_create(user=user) if profile.login_clipper: return render(request, "error.html", {"error_type": "use_clipper_login"}) else: return render(request, "error.html", {"error_type": "no_password"}) except User.DoesNotExist: pass context = {} if request.method == "GET" and 'next' in request.GET: context['next'] = request.GET['next'] if request.method == "POST" and 'next' in request.POST: context['next'] = request.POST['next'] return django_login_view(request, template_name='login.html', extra_context=context) @login_required def logout(request): try: profile = request.user.profile except CofProfile.DoesNotExist: profile, created = CofProfile.objects.get_or_create(user=request.user) if profile.login_clipper: return redirect("django_cas_ng.views.logout") else: return redirect("django.contrib.auth.views.logout") @login_required def survey(request, survey_id): survey = get_object_or_404(Survey, id=survey_id) if not survey.survey_open: raise Http404 success = False deleted = False if request.method == "POST": form = SurveyForm(request.POST, survey=survey) if request.POST.get('delete'): try: current_answer = SurveyAnswer.objects.get(user=request.user, survey=survey) current_answer.delete() current_answer = None except SurveyAnswer.DoesNotExist: current_answer = None form = SurveyForm(survey=survey) success = True deleted = True else: if form.is_valid(): all_answers = [] for question_id, answers_ids in form.answers(): question = get_object_or_404(SurveyQuestion, id=question_id, survey=survey) if type(answers_ids) != list: answers_ids = [answers_ids] if not question.multi_answers and len(answers_ids) > 1: raise Http404 for answer_id in answers_ids: if not answer_id: continue answer_id = int(answer_id) answer = SurveyQuestionAnswer.objects.get( id=answer_id, survey_question=question) all_answers.append(answer) try: current_answer = SurveyAnswer.objects.get( user=request.user, survey=survey) except SurveyAnswer.DoesNotExist: current_answer = SurveyAnswer(user=request.user, survey=survey) current_answer.save() current_answer.answers = all_answers current_answer.save() success = True else: try: current_answer = SurveyAnswer.objects.get(user=request.user, survey=survey) form = SurveyForm(survey=survey, current_answers=current_answer.answers) except SurveyAnswer.DoesNotExist: current_answer = None form = SurveyForm(survey=survey) return render(request, "survey.html", {"survey": survey, "form": form, "success": success, "deleted": deleted, "current_answer": current_answer}) def get_event_form_choices(event, form): all_choices = [] for option_id, choices_ids in form.choices(): option = get_object_or_404(EventOption, id=option_id, event=event) if type(choices_ids) != list: choices_ids = [choices_ids] if not option.multi_choices and len(choices_ids) > 1: raise Http404 for choice_id in choices_ids: if not choice_id: continue choice_id = int(choice_id) choice = EventOptionChoice.objects.get( id=choice_id, event_option=option) all_choices.append(choice) return all_choices def update_event_form_comments(event, form, registration): for commentfield_id, value in form.comments(): field = get_object_or_404(EventCommentField, id=commentfield_id, event=event) if value == field.default: continue (storage, _) = EventCommentValue.objects.get_or_create( commentfield=field, registration=registration) storage.content = value storage.save() @login_required def event(request, event_id): event = get_object_or_404(Event, id=event_id) if not event.registration_open: raise Http404 success = False if request.method == "POST": form = EventForm(request.POST, event=event) if form.is_valid(): all_choices = get_event_form_choices(event, form) (current_registration, _) = \ EventRegistration.objects.get_or_create(user=request.user, event=event) current_registration.options = all_choices current_registration.save() success = True else: try: current_registration = \ EventRegistration.objects.get(user=request.user, event=event) form = EventForm(event=event, current_choices=current_registration.options) except EventRegistration.DoesNotExist: form = EventForm(event=event) return render(request, "event.html", {"event": event, "form": form, "success": success}) def clean_post_for_status(initial): d = initial.copy() for k, v in d.items(): if k.startswith("id_"): del d[k] d[k[3:]] = v return d @buro_required def event_status(request, event_id): event = get_object_or_404(Event, id=event_id) registrations_query = EventRegistration.objects.filter(event=event) post_data = clean_post_for_status(request.POST) form = EventStatusFilterForm(post_data or None, event=event) if form.is_valid(): for option_id, choice_id, value in form.filters(): if option_id == "has_paid": if value == "yes": registrations_query = registrations_query.filter(paid=True) elif value == "no": registrations_query = registrations_query.filter( paid=False) continue choice = get_object_or_404(EventOptionChoice, id=choice_id, event_option__id=option_id) if value == "none": continue if value == "yes": registrations_query = registrations_query.filter( options__id__exact=choice.id) elif value == "no": registrations_query = registrations_query.exclude( options__id__exact=choice.id) user_choices = registrations_query.prefetch_related("user").all() options = EventOption.objects.filter(event=event).all() choices_count = {} for option in options: for choice in option.choices.all(): choices_count[choice.id] = 0 for user_choice in user_choices: for choice in user_choice.options.all(): choices_count[choice.id] += 1 return render(request, "event_status.html", {"event": event, "user_choices": user_choices, "options": options, "choices_count": choices_count, "form": form}) @buro_required def survey_status(request, survey_id): survey = get_object_or_404(Survey, id=survey_id) answers_query = SurveyAnswer.objects.filter(survey=survey) post_data = clean_post_for_status(request.POST) form = SurveyStatusFilterForm(post_data or None, survey=survey) if form.is_valid(): for question_id, answer_id, value in form.filters(): answer = get_object_or_404(SurveyQuestionAnswer, id=answer_id, survey_question__id=question_id) if value == "none": continue if value == "yes": answers_query = answers_query.filter( answers__id__exact=answer.id) elif value == "no": answers_query = answers_query.exclude( answers__id__exact=answer.id) user_answers = answers_query.prefetch_related("user").all() questions = SurveyQuestion.objects.filter(survey=survey).all() answers_count = {} for question in questions: for answer in question.answers.all(): answers_count[answer.id] = 0 for user_answer in user_answers: for answer in user_answer.answers.all(): answers_count[answer.id] += 1 return render(request, "survey_status.html", {"survey": survey, "user_answers": user_answers, "questions": questions, "answers_count": answers_count, "form": form}) @cof_required def profile(request): success = False if request.method == "POST": form = UserProfileForm(request.POST, instance=request.user.profile) if form.is_valid(): form.save() success = True else: form = UserProfileForm(instance=request.user.profile) return render(request, "profile.html", {"form": form, "success": success}) def registration_set_ro_fields(user_form, profile_form): user_form.fields['username'].widget.attrs['readonly'] = True profile_form.fields['login_clipper'].widget.attrs['readonly'] = True @buro_required def registration_form(request, login_clipper=None, username=None): member = None if login_clipper: clipper = get_object_or_404(Clipper, username=login_clipper) try: # check if the given user is already registered member = User.objects.filter(username=login_clipper).get() username = member.username login_clipper = None except User.DoesNotExist: # new user, but prefill user_form = RegistrationUserForm() profile_form = RegistrationProfileForm() user_form.fields['username'].initial = login_clipper user_form.fields['email'].initial = \ login_clipper + "@clipper.ens.fr" profile_form.fields['login_clipper'].initial = login_clipper if clipper.fullname: bits = clipper.fullname.split(" ") user_form.fields['first_name'].initial = bits[0] if len(bits) > 1: user_form.fields['last_name'].initial = " ".join(bits[1:]) registration_set_ro_fields(user_form, profile_form) if username: member = get_object_or_404(User, username=username) (profile, _) = CofProfile.objects.get_or_create(user=member) # already existing, prefill user_form = RegistrationUserForm(instance=member) profile_form = RegistrationProfileForm(instance=profile) registration_set_ro_fields(user_form, profile_form) elif not login_clipper: # new user user_form = RegistrationUserForm() profile_form = RegistrationProfileForm() return render(request, "registration_form.html", {"user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper}) @buro_required def registration_form2(request, login_clipper=None, username=None): events = Event.objects.filter(old=False).all() member = None if login_clipper: clipper = get_object_or_404(Clipper, username=login_clipper) try: # check if the given user is already registered member = User.objects.filter(username=login_clipper).get() username = member.username login_clipper = None except User.DoesNotExist: # new user, but prefill user_form = RegistrationUserForm() profile_form = RegistrationProfileForm() event_forms = [AdminEventForm(event=event) for event in events] user_form.fields['username'].initial = login_clipper user_form.fields['email'].initial = \ login_clipper + "@clipper.ens.fr" profile_form.fields['login_clipper'].initial = login_clipper if clipper.fullname: bits = clipper.fullname.split(" ") user_form.fields['first_name'].initial = bits[0] if len(bits) > 1: user_form.fields['last_name'].initial = " ".join(bits[1:]) registration_set_ro_fields(user_form, profile_form) if username: member = get_object_or_404(User, username=username) (profile, _) = CofProfile.objects.get_or_create(user=member) # already existing, prefill user_form = RegistrationUserForm(instance=member) profile_form = RegistrationProfileForm(instance=profile) registration_set_ro_fields(user_form, profile_form) event_forms = [] for event in events: try: current_registration = EventRegistration.objects.get( user=member, event=event) form = AdminEventForm( event=event, current_registration=current_registration, paid=current_registration.paid) except EventRegistration.DoesNotExist: form = AdminEventForm(event=event) event_forms.append(form) elif not login_clipper: # new user user_form = RegistrationUserForm() profile_form = RegistrationProfileForm() event_forms = [AdminEventForm(event=event) for event in events] return render(request, "registration_form.html", {"user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper, "event_forms": event_forms}) @buro_required def registration(request): if request.POST: request_dict = request.POST.copy() if "num" in request_dict: del request_dict["num"] success = False user_form = RegistrationUserForm(request_dict) profile_form = RegistrationProfileForm(request_dict) events = Event.objects.filter(old=False).all() event_forms = \ [AdminEventForm(request_dict, event=event) for event in events] user_form.is_valid() profile_form.is_valid() for event_form in event_forms: event_form.is_valid() member = None login_clipper = None if "user_exists" in request_dict and request_dict["user_exists"]: username = request_dict["username"] try: member = User.objects.filter(username=username).get() (profile, _) = CofProfile.objects.get_or_create(user=member) user_form = RegistrationUserForm(request_dict, instance=member) profile_form = RegistrationProfileForm(request_dict, instance=profile) except User.DoesNotExist: try: clipper = Clipper.objects.filter(username=username).get() login_clipper = clipper.username except Clipper.DoesNotExist: pass for form in event_forms: if not form.is_valid(): break if form.cleaned_data['status'] == 'no': continue all_choices = get_event_form_choices(form.event, form) if user_form.is_valid() and profile_form.is_valid() \ and not any([not form.is_valid() for form in event_forms]): member = user_form.save() (profile, _) = CofProfile.objects.get_or_create(user=member) was_cof = profile.is_cof request_dict["num"] = profile.num profile_form = RegistrationProfileForm(request_dict, instance=profile) profile_form.is_valid() profile_form.save() (profile, _) = CofProfile.objects.get_or_create(user=member) if profile.is_cof and not was_cof: send_custom_mail(member, "bienvenue") for form in event_forms: if form.cleaned_data['status'] == 'no': try: current_registration = EventRegistration.objects.get( user=member, event=form.event) current_registration.delete() except EventRegistration.DoesNotExist: pass continue all_choices = get_event_form_choices(form.event, form) (current_registration, created_reg) = \ EventRegistration.objects.get_or_create(user=member, event=form.event) update_event_form_comments(form.event, form, current_registration) current_registration.options = all_choices current_registration.paid = \ (form.cleaned_data['status'] == 'paid') current_registration.save() if form.event.title == "Mega 15" and created_reg: field = EventCommentField.objects.get(event=form.event, name="Commentaires") try: comments = EventCommentValue.objects.get( commentfield=field, registration=current_registration).content except EventCommentValue.DoesNotExist: comments = field.default send_custom_mail(member, "mega", {"remarques": comments}) success = True return render(request, "registration_post.html", {"success": success, "user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper, "event_forms": event_forms}) else: return render(request, "registration.html") @buro_required def export_members(request): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename=membres_cof.csv' writer = unicodecsv.writer(response) for profile in CofProfile.objects.filter(is_cof=True).all(): user = profile.user bits = [profile.num, user.username, user.first_name, user.last_name, user.email, profile.phone, profile.occupation, profile.departement, profile.type_cotiz] writer.writerow([six.text_type(bit) for bit in bits]) return response @buro_required def csv_export_mega(filename, qs): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename=' + filename writer = unicodecsv.writer(response) for reg in qs.all(): user = reg.user profile = user.profile comments = "---".join( [comment.content for comment in reg.comments.all()]) bits = [user.username, user.first_name, user.last_name, user.email, profile.phone, profile.num, profile.comments if profile.comments else "", comments] writer.writerow([six.text_type(bit) for bit in bits]) return response @buro_required def export_mega_remarksonly(request): filename = 'remarques_mega_2015.csv' response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename=' + filename writer = unicodecsv.writer(response) event = Event.objects.get(title="Mega 15") commentfield = event.commentfields.get(name="Commentaires") for val in commentfield.values.all(): reg = val.registration user = reg.user profile = user.profile bits = [user.username, user.first_name, user.last_name, user.email, profile.phone, profile.num, profile.comments, val.content] writer.writerow([six.text_type(bit) for bit in bits]) return response @buro_required def export_mega_bytype(request, type): types = {"orga-actif": "Orga élève", "orga-branleur": "Orga étudiant", "conscrit-eleve": "Conscrit élève", "conscrit-etudiant": "Conscrit étudiant"} if type not in types: raise Http404 event = Event.objects.get(title="Mega 15") type_option = event.options.get(name="Type") participant_type = type_option.choices.get(value=types[type]).id qs = EventRegistration.objects.filter(event=event).filter( options__id__exact=participant_type) return csv_export_mega(type + '_mega_2015.csv', qs) @buro_required def export_mega_orgas(request): event = Event.objects.get(title="Mega 15") type_option = event.options.get(name="Type") participant_type_a = type_option.choices.get(value="Conscrit étudiant").id participant_type_b = type_option.choices.get(value="Conscrit élève").id qs = EventRegistration.objects.filter(event=event).exclude( options__id__in=(participant_type_a, participant_type_b)) return csv_export_mega('orgas_mega_15.csv', qs) @buro_required def export_mega_participants(request): event = Event.objects.get(title="Mega 15") type_option = event.options.get(name="Type") participant_type_a = type_option.choices.get(value="Conscrit étudiant").id participant_type_b = type_option.choices.get(value="Conscrit élève").id qs = EventRegistration.objects.filter(event=event).filter( options__id__in=(participant_type_a, participant_type_b)) return csv_export_mega('participants_mega_15.csv', qs) @buro_required def export_mega(request): event = Event.objects.filter(title="Mega 15") qs = EventRegistration.objects.filter(event=event) \ .order_by("user__username") return csv_export_mega('all_mega_2015.csv', qs) @buro_required def utile_cof(request): return render(request, "utile_cof.html", {}) @buro_required def utile_bda(request): tirages = Tirage.objects.all() return render(request, "utile_bda.html", {'tirages': tirages}) @buro_required def liste_bdadiff(request): titre = "BdA diffusion" personnes = CofProfile.objects.filter(mailing_bda=True, is_cof=True).all() return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) @buro_required def liste_bdarevente(request): titre = "BdA revente" personnes = CofProfile.objects.filter(mailing_bda_revente=True, is_cof=True).all() return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) @buro_required def liste_diffcof(request): titre = "Diffusion COF" personnes = CofProfile.objects.filter(mailing_cof=True, is_cof=True).all() return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) @cof_required def calendar(request): try: instance = CalendarSubscription.objects.get(user=request.user) except CalendarSubscription.DoesNotExist: instance = None if request.method == 'POST': form = CalendarForm(request.POST, instance=instance) if form.is_valid(): subscription = form.save(commit=False) if instance is None: subscription.user = request.user subscription.token = uuid.uuid4() subscription.save() form.save_m2m() return render(request, "calendar_subscription.html", {'form': form, 'success': True, 'token': str(subscription.token)}) else: return render(request, "calendar_subscription.html", {'form': form, 'error': "Formulaire incorrect"}) else: return render(request, "calendar_subscription.html", {'form': CalendarForm(instance=instance), 'token': instance.token if instance else None}) def calendar_ics(request, token): subscription = get_object_or_404(CalendarSubscription, token=token) shows = subscription.other_shows.all() if subscription.subscribe_to_my_shows: shows |= Spectacle.objects.filter( attribues__participant__user=subscription.user, tirage__active=True) shows = shows.distinct() vcal = Calendar() for show in shows: vevent = Vevent() vevent.add('dtstart', show.date) vevent.add('dtend', show.date + timedelta(seconds=7200)) vevent.add('summary', show.title) vevent.add('location', show.location.name) vcal.add_component(vevent) if subscription.subscribe_to_events: for event in Event.objects.filter(old=False).all(): vevent = Vevent() vevent.add('dtstart', event.start_date) vevent.add('dtend', event.end_date) vevent.add('summary', event.title) vevent.add('location', event.location) vevent.add('description', event.description) vcal.add_component(vevent) response = HttpResponse(content=vcal.to_ical()) response['Content-Type'] = "text/calendar" return response