mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-02-13 23:41:19 +00:00
Compare commits
3 Commits
53a55ee898
...
d05a8339fe
Author | SHA1 | Date | |
---|---|---|---|
|
d05a8339fe | ||
|
38dc00b2c9 | ||
|
4cd1e43564 |
@ -49,7 +49,7 @@ class Team(models.Model):
|
||||
return self.participants.filter(studentregistration__isnull=False)
|
||||
|
||||
@property
|
||||
def coachs(self):
|
||||
def coaches(self):
|
||||
return self.participants.filter(coachregistration__isnull=False)
|
||||
|
||||
@property
|
||||
|
@ -31,7 +31,7 @@ def update_mailing_list(instance: Team, **_):
|
||||
for student in instance.students.all():
|
||||
get_sympa_client().subscribe(student.user.email, f"equipe-{instance.trigram.lower()}", False,
|
||||
f"{student.user.first_name} {student.user.last_name}")
|
||||
for coach in instance.coachs.all():
|
||||
for coach in instance.coaches.all():
|
||||
get_sympa_client().subscribe(coach.user.email, f"equipe-{instance.trigram.lower()}", False,
|
||||
f"{coach.user.first_name} {coach.user.last_name}")
|
||||
|
||||
|
@ -22,9 +22,9 @@
|
||||
<dt class="col-sm-6 text-right">{% trans "Access code:" %}</dt>
|
||||
<dd class="col-sm-6">{{ team.access_code }}</dd>
|
||||
|
||||
<dt class="col-sm-6 text-right">{% trans "Coachs:" %}</dt>
|
||||
<dt class="col-sm-6 text-right">{% trans "Coaches:" %}</dt>
|
||||
<dd class="col-sm-6">
|
||||
{% for coach in team.coachs.all %}
|
||||
{% for coach in team.coaches.all %}
|
||||
<a href="{% url "registration:user_detail" pk=coach.user.pk %}">{{ coach }}</a>{% if not forloop.last %},{% endif %}
|
||||
{% empty %}
|
||||
{% trans "any" %}
|
||||
|
@ -173,11 +173,11 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
|
||||
context["validation_form"] = ValidateParticipationForm(self.request.POST or None)
|
||||
# A team is complete when there are at least 4 members plus a coache that have sent their authorizations,
|
||||
# their health sheet, they confirmed their email address and under-18 people sent their parental authorization.
|
||||
context["can_validate"] = team.students.count() >= 4 and team.coachs.exists() and \
|
||||
all(r.email_confirmed for r in team.students.all()) and \
|
||||
all(r.photo_authorization for r in team.participants.all()) and \
|
||||
all(r.health_sheet for r in team.participants.all()) and \
|
||||
all(r.parental_authorization for r in team.students.all() if r.under_18)
|
||||
context["can_validate"] = team.students.count() >= 4 and team.coaches.exists() and \
|
||||
all(r.email_confirmed for r in team.students.all()) and \
|
||||
all(r.photo_authorization for r in team.participants.all()) and \
|
||||
all(r.health_sheet for r in team.participants.all()) and \
|
||||
all(r.parental_authorization for r in team.students.all() if r.under_18)
|
||||
|
||||
return context
|
||||
|
||||
@ -240,8 +240,16 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
|
||||
mail_html = render_to_string("participation/mails/team_validated.html", mail_context)
|
||||
send_mail("[TFJM²] Équipe validée", mail_plain, None, [self.object.email], html_message=mail_html)
|
||||
|
||||
get_sympa_client().subscribe(self.object.email, "equipes", False, f"Equipe {self.object.name}")
|
||||
get_sympa_client().unsubscribe(self.object.email, "equipes-non-valides", False)
|
||||
if self.object.participation.tournament.price == 0:
|
||||
for registration in self.object.participants.all():
|
||||
registration.payment.type = "free"
|
||||
registration.payment.valid = True
|
||||
registration.payment.save()
|
||||
else:
|
||||
for coach in self.object.coaches.all():
|
||||
coach.payment.type = "free"
|
||||
coach.payment.valid = True
|
||||
coach.payment.save()
|
||||
elif "invalidate" in self.request.POST:
|
||||
self.object.participation.valid = None
|
||||
self.object.participation.save()
|
||||
@ -372,7 +380,7 @@ class TeamLeaveView(LoginRequiredMixin, TemplateView):
|
||||
Matrix.kick(f"#equipe-{team.trigram.lower()}:tfjm.org",
|
||||
f"@{request.user.registration.matrix_username}:tfjm.org",
|
||||
"Équipe quittée")
|
||||
if team.students.count() + team.coachs.count() == 0:
|
||||
if team.students.count() + team.coaches.count() == 0:
|
||||
team.delete()
|
||||
return redirect(reverse_lazy("index"))
|
||||
|
||||
|
@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.forms import FileInput
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import AdminRegistration, CoachRegistration, StudentRegistration, VolunteerRegistration
|
||||
from .models import AdminRegistration, CoachRegistration, Payment, StudentRegistration, VolunteerRegistration
|
||||
|
||||
|
||||
class SignupForm(UserCreationForm):
|
||||
@ -197,3 +197,34 @@ class AdminRegistrationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AdminRegistration
|
||||
fields = ('role', 'give_contact_to_animath', 'email_confirmed',)
|
||||
|
||||
|
||||
class PaymentForm(forms.ModelForm):
|
||||
"""
|
||||
Indicate payment information
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["valid"].widget.choices[0] = ('unknown', _("Pending"))
|
||||
|
||||
def clean_scholarship_file(self):
|
||||
if "scholarship_file" in self.files:
|
||||
file = self.files["scholarship_file"]
|
||||
if file.size > 2e6:
|
||||
raise ValidationError(_("The uploaded file size must be under 2 Mo."))
|
||||
if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]:
|
||||
raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file."))
|
||||
return self.cleaned_data["scholarship_file"]
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
|
||||
if "type" in cleaned_data and cleaned_data["type"] == "scholarship" \
|
||||
and "scholarship" not in cleaned_data and not self.instance.scholarship_file:
|
||||
self.add_error("scholarship_file", _("You must upload your scholarship attestation."))
|
||||
|
||||
return cleaned_data
|
||||
|
||||
class Meta:
|
||||
model = Payment
|
||||
fields = ('type', 'scholarship_file', 'additional_information', 'valid',)
|
||||
|
@ -17,7 +17,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.CharField(blank=True, choices=[('', 'No payment'), ('helloasso', 'Hello Asso'), ('scholarship', 'Scholarship'), ('bank_transfer', 'Bank transfer'), ('free', 'The tournament is free')], default='', max_length=16, verbose_name='type')),
|
||||
('scholarship_file', models.FileField(blank=True, default='', help_text='only if you have a scholarship.', unique=True, upload_to=registration.models.get_scholarship_filename, verbose_name='scholarship file')),
|
||||
('scholarship_file', models.FileField(blank=True, default='', help_text='only if you have a scholarship.', upload_to=registration.models.get_scholarship_filename, verbose_name='scholarship file')),
|
||||
('additional_information', models.TextField(blank=True, default='', help_text='To help us to find your payment.', verbose_name='additional information')),
|
||||
('valid', models.BooleanField(default=False, null=True, verbose_name='valid')),
|
||||
('registration', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='registration', to='registration.ParticipantRegistration', verbose_name='registration')),
|
||||
|
@ -320,7 +320,6 @@ class Payment(models.Model):
|
||||
verbose_name=_("scholarship file"),
|
||||
help_text=_("only if you have a scholarship."),
|
||||
upload_to=get_scholarship_filename,
|
||||
unique=True,
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
@ -338,6 +337,9 @@ class Payment(models.Model):
|
||||
default=False,
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse_lazy("registration:user_detail", args=(self.registration.user.id,))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("payment")
|
||||
verbose_name_plural = _("payments")
|
||||
|
14
apps/registration/templates/registration/payment_form.html
Normal file
14
apps/registration/templates/registration/payment_form.html
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% load crispy_forms_filters i18n %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<div id="form-content">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">{% trans "Update" %}</button>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
|
@ -53,7 +53,7 @@
|
||||
{% if user_object.registration.photo_authorization %}
|
||||
<a href="{{ user_object.registration.photo_authorization.url }}" data-turbolinks="false">{% trans "Download" %}</a>
|
||||
{% endif %}
|
||||
{% if user_object.pk == user.pk %}
|
||||
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
|
||||
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadPhotoAuthorizationModal">{% trans "Replace" %}</button>
|
||||
{% endif %}
|
||||
</dd>
|
||||
@ -63,7 +63,7 @@
|
||||
{% if user_object.registration.health_sheet %}
|
||||
<a href="{{ user_object.registration.health_sheet.url }}" data-turbolinks="false">{% trans "Download" %}</a>
|
||||
{% endif %}
|
||||
{% if user_object.pk == user.pk %}
|
||||
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
|
||||
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadHealthSheetModal">{% trans "Replace" %}</button>
|
||||
{% endif %}
|
||||
</dd>
|
||||
@ -76,7 +76,7 @@
|
||||
{% if user_object.registration.parental_authorization %}
|
||||
<a href="{{ user_object.registration.parental_authorization.url }}" data-turbolinks="false">{% trans "Download" %}</a>
|
||||
{% endif %}
|
||||
{% if user_object.pk == user.pk %}
|
||||
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
|
||||
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadParentalAuthorizationModal">{% trans "Replace" %}</button>
|
||||
{% endif %}
|
||||
</dd>
|
||||
@ -125,6 +125,11 @@
|
||||
{% else %}
|
||||
{{ user_object.registration.payment.get_type_display }}, {% trans "valid:" %} {{ user_object.registration.payment.valid|yesno:yesnodefault }}
|
||||
{% endif %}
|
||||
{% if user.registration.is_admin or user_object.registration.payment.valid is False %}
|
||||
<button class="btn-sm btn-secondary" data-toggle="modal" data-target="#updatePaymentModal">
|
||||
<i class="fas fa-money-bill-wave"></i> {% trans "Update payment" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</dd>
|
||||
</dl>
|
||||
@ -145,20 +150,34 @@
|
||||
{% url "registration:update_user" pk=user_object.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="updateUser" %}
|
||||
|
||||
{% trans "Upload photo authorization" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadPhotoAuthorization" modal_enctype="multipart/form-data" %}
|
||||
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
|
||||
{% trans "Upload photo authorization" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadPhotoAuthorization" modal_enctype="multipart/form-data" %}
|
||||
|
||||
{% trans "Upload health sheet" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadHealthSheet" modal_enctype="multipart/form-data" %}
|
||||
{% trans "Upload health sheet" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadHealthSheet" modal_enctype="multipart/form-data" %}
|
||||
|
||||
{% trans "Upload parental authorization" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadParentalAuthorization" modal_enctype="multipart/form-data" %}
|
||||
{% trans "Upload parental authorization" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadParentalAuthorization" modal_enctype="multipart/form-data" %}
|
||||
|
||||
{% trans "Upload parental authorization" as modal_title %}
|
||||
{% trans "Upload" as modal_button %}
|
||||
{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="uploadParentalAuthorization" modal_enctype="multipart/form-data" %}
|
||||
{% endif %}
|
||||
|
||||
{% if user_object.registration.team.participation.valid %}
|
||||
{% trans "Update payment" as modal_title %}
|
||||
{% trans "Update" as modal_button %}
|
||||
{% url "registration:update_payment" pk=user_object.registration.payment.pk as modal_action %}
|
||||
{% include "base_modal.html" with modal_id="updatePayment" modal_additional_class="modal-xl" modal_enctype="multipart/form-data" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrajavascript %}
|
||||
@ -169,21 +188,30 @@
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:update_user" pk=user_object.pk %} #form-content");
|
||||
});
|
||||
$('button[data-target="#uploadPhotoAuthorizationModal"]').click(function() {
|
||||
let modalBody = $("#uploadPhotoAuthorizationModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk %} #form-content");
|
||||
});
|
||||
$('button[data-target="#uploadHealthSheetModal"]').click(function() {
|
||||
let modalBody = $("#uploadHealthSheetModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk %} #form-content");
|
||||
});
|
||||
$('button[data-target="#uploadParentalAuthorizationModal"]').click(function() {
|
||||
let modalBody = $("#uploadParentalAuthorizationModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk %} #form-content");
|
||||
});
|
||||
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
|
||||
$('button[data-target="#uploadPhotoAuthorizationModal"]').click(function() {
|
||||
let modalBody = $("#uploadPhotoAuthorizationModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk %} #form-content");
|
||||
});
|
||||
$('button[data-target="#uploadHealthSheetModal"]').click(function() {
|
||||
let modalBody = $("#uploadHealthSheetModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk %} #form-content");
|
||||
});
|
||||
$('button[data-target="#uploadParentalAuthorizationModal"]').click(function() {
|
||||
let modalBody = $("#uploadParentalAuthorizationModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk %} #form-content");
|
||||
});
|
||||
{% endif %}
|
||||
{% if user_object.registration.team.participation.valid %}
|
||||
$('button[data-target="#updatePaymentModal"]').click(function() {
|
||||
let modalBody = $("#updatePaymentModal div.modal-body");
|
||||
if (!modalBody.html().trim())
|
||||
modalBody.load("{% url "registration:update_payment" pk=user_object.registration.payment.pk %} #form-content");
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from .views import AddOrganizerView, MyAccountDetailView, ResetAdminView, SignupView, UserDetailView,\
|
||||
UserImpersonateView, UserListView, UserResendValidationEmailView, UserUpdateView, UserUploadHealthSheetView, \
|
||||
UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, UserValidateView, \
|
||||
UserValidationEmailSentView
|
||||
from .views import AddOrganizerView, MyAccountDetailView, PaymentUpdateView, ResetAdminView, SignupView, \
|
||||
UserDetailView, UserImpersonateView, UserListView, UserResendValidationEmailView, UserUpdateView, \
|
||||
UserUploadHealthSheetView, UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, \
|
||||
UserValidateView, UserValidationEmailSentView
|
||||
|
||||
app_name = "registration"
|
||||
|
||||
@ -26,6 +26,7 @@ urlpatterns = [
|
||||
name="upload_user_health_sheet"),
|
||||
path("user/<int:pk>/upload-parental-authorization/", UserUploadParentalAuthorizationView.as_view(),
|
||||
name="upload_user_parental_authorization"),
|
||||
path("update-payment/<int:pk>/", PaymentUpdateView.as_view(), name="update_payment"),
|
||||
path("user/<int:pk>/impersonate/", UserImpersonateView.as_view(), name="user_impersonate"),
|
||||
path("user/list/", UserListView.as_view(), name="user_list"),
|
||||
path("reset-admin/", ResetAdminView.as_view(), name="reset_admin"),
|
||||
|
@ -15,8 +15,7 @@ from django.shortcuts import redirect, resolve_url
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
|
||||
from django_tables2 import SingleTableView
|
||||
@ -26,9 +25,9 @@ from tfjm.tokens import email_validation_token
|
||||
from tfjm.views import AdminMixin, UserMixin, VolunteerMixin
|
||||
|
||||
from .forms import AddOrganizerForm, AdminRegistrationForm, CoachRegistrationForm, HealthSheetForm, \
|
||||
ParentalAuthorizationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \
|
||||
ParentalAuthorizationForm, PaymentForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \
|
||||
VolunteerRegistrationForm
|
||||
from .models import ParticipantRegistration, Registration, StudentRegistration
|
||||
from .models import ParticipantRegistration, Payment, Registration, StudentRegistration
|
||||
from .tables import RegistrationTable
|
||||
|
||||
|
||||
@ -381,6 +380,31 @@ class UserUploadParentalAuthorizationView(UserMixin, UpdateView):
|
||||
return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
|
||||
|
||||
|
||||
class PaymentUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = Payment
|
||||
form_class = PaymentForm
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not self.request.user.is_authenticated or \
|
||||
not self.request.user.registration.is_admin \
|
||||
and (self.request.user != self.get_object().registration.user
|
||||
or self.get_object().valid is not False):
|
||||
return self.handle_no_permission()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
if not self.request.user.registration.is_admin:
|
||||
del form.fields["type"].widget.choices[-1]
|
||||
del form.fields["valid"]
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
if not self.request.user.registration.is_admin:
|
||||
form.instance.valid = None
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class PhotoAuthorizationView(LoginRequiredMixin, View):
|
||||
"""
|
||||
Display the sent photo authorization.
|
||||
|
@ -697,7 +697,7 @@ msgid "Access code:"
|
||||
msgstr "Code d'accès :"
|
||||
|
||||
#: apps/participation/templates/participation/team_detail.html:25
|
||||
msgid "Coachs:"
|
||||
msgid "Coaches:"
|
||||
msgstr "Encadrants :"
|
||||
|
||||
#: apps/participation/templates/participation/team_detail.html:34
|
||||
|
Loading…
x
Reference in New Issue
Block a user