mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-10-31 06:49:52 +01:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			29b01ebb13
			...
			630633bab4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 630633bab4 | ||
|  | 8d7d7cd645 | ||
|  | e53575d31d | ||
|  | 412ff4e067 | 
| @@ -399,6 +399,8 @@ class Pool(models.Model): | ||||
|                 passage.observer = tds[line[3]].participation | ||||
|                 await passage.asave() | ||||
|  | ||||
|         await sync_to_async(self.associated_pool.update_spreadsheet)() | ||||
|  | ||||
|         return self.associated_pool | ||||
|  | ||||
|     def __str__(self): | ||||
|   | ||||
| @@ -192,24 +192,6 @@ class PoolForm(forms.ModelForm): | ||||
|         } | ||||
|  | ||||
|  | ||||
| class PoolTeamsForm(forms.ModelForm): | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.fields["participations"].queryset = self.instance.tournament.participations.all() | ||||
|  | ||||
|     class Meta: | ||||
|         model = Pool | ||||
|         fields = ('participations',) | ||||
|         widgets = { | ||||
|             "participations": forms.SelectMultiple(attrs={ | ||||
|                 'class': 'selectpicker', | ||||
|                 'data-live-search': 'true', | ||||
|                 'data-live-search-normalize': 'true', | ||||
|                 'data-width': 'fit', | ||||
|             }), | ||||
|         } | ||||
|  | ||||
|  | ||||
| class AddJuryForm(forms.ModelForm): | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|   | ||||
| @@ -453,15 +453,23 @@ class Tournament(models.Model): | ||||
|             tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation) | ||||
|             tweak1 = tweak1_qs.get() if tweak1_qs.exists() else None | ||||
|  | ||||
|             line.append(f"=SIERREUR('Poule {pool1.short_name}'!$D{pool1.juries.count() + 10 + passage1.position}; 0)") | ||||
|             line.append(tweak1.diff if tweak1 else 0) | ||||
|  | ||||
|             if self.pools.filter(round=2, participations=participation).exists(): | ||||
|                 pool2 = self.pools.get(round=2, participations=participation) | ||||
|                 passage2 = pool2.passages.get(defender=participation) | ||||
|                 tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation) | ||||
|                 tweak2 = tweak2_qs.get() if tweak2_qs.exists() else None | ||||
|  | ||||
|             line.append(f"=SIERREUR('Poule {pool1.short_name}'!$D{pool1.juries.count() + 10 + passage1.position}; 0)") | ||||
|             line.append(tweak1.diff if tweak1 else 0) | ||||
|             line.append(f"=SIERREUR('Poule {pool2.short_name}'!$D{pool2.juries.count() + 10 + passage2.position}; 0)") | ||||
|                 line.append( | ||||
|                     f"=SIERREUR('Poule {pool2.short_name}'!$D{pool2.juries.count() + 10 + passage2.position}; 0)") | ||||
|                 line.append(tweak2.diff if tweak2 else 0) | ||||
|             else: | ||||
|                 # User has no second pool yet | ||||
|                 line.append(0) | ||||
|                 line.append(0) | ||||
|  | ||||
|             line.append(f"=$B{i + 2} + $C{i + 2} + $D{i + 2} + E{i + 2}") | ||||
|             line.append(f"=RANG($F{i + 2}; $F$2:$F${participations.count() + 1})") | ||||
|  | ||||
| @@ -609,16 +617,19 @@ class Tournament(models.Model): | ||||
|             trigram = line[0][-4:-1] | ||||
|             participation = self.participations.get(team__trigram=trigram) | ||||
|             pool1 = self.pools.get(round=1, participations=participation) | ||||
|             pool2 = self.pools.get(round=2, participations=participation) | ||||
|             tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation) | ||||
|             tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation) | ||||
|             tweak1_nb, tweak2_nb = int(line[2]), int(line[4]) | ||||
|             tweak1_nb = int(line[2]) | ||||
|             if not tweak1_nb: | ||||
|                 tweak1_qs.delete() | ||||
|             else: | ||||
|                 tweak1_qs.update_or_create(defaults={'diff': tweak1_nb}, | ||||
|                                            create_defaults={'diff': tweak1_nb, 'pool': pool1, | ||||
|                                                             'participation': participation}) | ||||
|  | ||||
|             if self.pools.filter(round=2, participations=participation).exists(): | ||||
|                 pool2 = self.pools.get(round=2, participations=participation) | ||||
|                 tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation) | ||||
|                 tweak2_nb = int(line[4]) | ||||
|                 if not tweak2_nb: | ||||
|                     tweak2_qs.delete() | ||||
|                 else: | ||||
| @@ -1299,11 +1310,6 @@ class Pool(models.Model): | ||||
|                 note.set_all(*note_line) | ||||
|                 note.save() | ||||
|  | ||||
|     def save(self, force_insert=False, force_update=False, using=None, update_fields=None): | ||||
|         if os.getenv('GOOGLE_PRIVATE_KEY_ID', None):  # Google Sheets support is enabled | ||||
|             self.update_juries_lines_spreadsheet() | ||||
|         super().save(force_insert, force_update, using, update_fields) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return _("Pool of day {round} for tournament {tournament} with teams {teams}")\ | ||||
|             .format(round=self.round, | ||||
|   | ||||
| @@ -125,9 +125,7 @@ | ||||
|         </div> | ||||
|         {% if user.registration.is_volunteer %} | ||||
|             <div class="card-footer text-center"> | ||||
|                 <button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#addPassageModal">{% trans "Add passage" %}</button> | ||||
|                 <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updatePoolModal">{% trans "Update" %}</button> | ||||
|                 <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updateTeamsModal">{% trans "Update teams" %}</button> | ||||
|             </div> | ||||
|         {% endif %} | ||||
|     </div> | ||||
| @@ -138,21 +136,11 @@ | ||||
|  | ||||
|     {% render_table passages %} | ||||
|  | ||||
|     {% trans "Add passage" as modal_title %} | ||||
|     {% trans "Add" as modal_button %} | ||||
|     {% url "participation:passage_create" pk=pool.pk as modal_action %} | ||||
|     {% include "base_modal.html" with modal_id="addPassage" modal_button_type="success" %} | ||||
|  | ||||
|     {% trans "Update pool" as modal_title %} | ||||
|     {% trans "Update" as modal_button %} | ||||
|     {% url "participation:pool_update" pk=pool.pk as modal_action %} | ||||
|     {% include "base_modal.html" with modal_id="updatePool" %} | ||||
|  | ||||
|     {% trans "Update teams" as modal_title %} | ||||
|     {% trans "Update" as modal_button %} | ||||
|     {% url "participation:pool_update_teams" pk=pool.pk as modal_action %} | ||||
|     {% include "base_modal.html" with modal_id="updateTeams" %} | ||||
|  | ||||
|     {% trans "Upload notes" as modal_title %} | ||||
|     {% trans "Upload" as modal_button %} | ||||
|     {% url "participation:pool_upload_notes" pk=pool.pk as modal_action %} | ||||
| @@ -163,8 +151,6 @@ | ||||
|     <script> | ||||
|         document.addEventListener('DOMContentLoaded', () => { | ||||
|             initModal("updatePool", "{% url "participation:pool_update" pk=pool.pk %}") | ||||
|             initModal("updateTeams", "{% url "participation:pool_update_teams" pk=pool.pk %}") | ||||
|             initModal("addPassage", "{% url "participation:passage_create" pk=pool.pk %}") | ||||
|             initModal("uploadNotes", "{% url "participation:pool_upload_notes" pk=pool.pk %}") | ||||
|         }) | ||||
|     </script> | ||||
|   | ||||
| @@ -5,9 +5,9 @@ from django.urls import path | ||||
| from django.views.generic import TemplateView | ||||
|  | ||||
| from .views import CreateTeamView, FinalNotationSheetTemplateView, JoinTeamView, MyParticipationDetailView, \ | ||||
|     MyTeamDetailView, NotationSheetsArchiveView, NoteUpdateView, ParticipationDetailView, PassageCreateView, \ | ||||
|     MyTeamDetailView, NotationSheetsArchiveView, NoteUpdateView, ParticipationDetailView, \ | ||||
|     PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \ | ||||
|     PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateTeamsView, PoolUpdateView, PoolUploadNotesView, \ | ||||
|     PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \ | ||||
|     ScaleNotationSheetTemplateView, SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \ | ||||
|     TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \ | ||||
|     TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \ | ||||
| @@ -60,13 +60,11 @@ urlpatterns = [ | ||||
|     path("pools/<int:pk>/notation/scale/", ScaleNotationSheetTemplateView.as_view(), name="pool_scale_note_sheet"), | ||||
|     path("pools/<int:pk>/notation/final/", FinalNotationSheetTemplateView.as_view(), name="pool_final_note_sheet"), | ||||
|     path("pools/<int:pool_id>/notation/sheets/", NotationSheetsArchiveView.as_view(), name="pool_notation_sheets"), | ||||
|     path("pools/<int:pk>/update-teams/", PoolUpdateTeamsView.as_view(), name="pool_update_teams"), | ||||
|     path("pools/<int:pk>/jury/", PoolJuryView.as_view(), name="pool_jury"), | ||||
|     path("pools/<int:pk>/jury/remove/<int:jury_id>/", PoolRemoveJuryView.as_view(), name="pool_remove_jury"), | ||||
|     path("pools/<int:pk>/jury/preside/<int:jury_id>/", PoolPresideJuryView.as_view(), name="pool_preside"), | ||||
|     path("pools/<int:pk>/upload-notes/", PoolUploadNotesView.as_view(), name="pool_upload_notes"), | ||||
|     path("pools/<int:pk>/upload-notes/template/", PoolNotesTemplateView.as_view(), name="pool_notes_template"), | ||||
|     path("pools/passages/add/<int:pk>/", PassageCreateView.as_view(), name="passage_create"), | ||||
|     path("pools/passages/<int:pk>/", PassageDetailView.as_view(), name="passage_detail"), | ||||
|     path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"), | ||||
|     path("pools/passages/<int:pk>/solution/", SynthesisUploadView.as_view(), name="upload_synthesis"), | ||||
|   | ||||
| @@ -40,7 +40,7 @@ from tfjm.lists import get_sympa_client | ||||
| from tfjm.views import AdminMixin, VolunteerMixin | ||||
|  | ||||
| from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \ | ||||
|     PoolForm, PoolTeamsForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \ | ||||
|     PoolForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \ | ||||
|     UploadNotesForm, ValidateParticipationForm | ||||
| from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak | ||||
| from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable | ||||
| @@ -880,19 +880,12 @@ class PoolUpdateView(VolunteerMixin, UpdateView): | ||||
|             return super().dispatch(request, *args, **kwargs) | ||||
|         return self.handle_no_permission() | ||||
|  | ||||
|  | ||||
| class PoolUpdateTeamsView(VolunteerMixin, UpdateView): | ||||
|     model = Pool | ||||
|     form_class = PoolTeamsForm | ||||
|  | ||||
|     def dispatch(self, request, *args, **kwargs): | ||||
|         if not request.user.is_authenticated: | ||||
|             return self.handle_no_permission() | ||||
|         if request.user.registration.is_admin or request.user.registration.is_volunteer \ | ||||
|                 and (self.get_object().tournament in request.user.registration.organized_tournaments.all() | ||||
|                      or request.user.registration in self.get_object().juries.all()): | ||||
|             return super().dispatch(request, *args, **kwargs) | ||||
|         return self.handle_no_permission() | ||||
|     def form_valid(self, form): | ||||
|         ret = super().form_valid(form) | ||||
|         # Update Google Sheets juries lines | ||||
|         if os.getenv('GOOGLE_PRIVATE_KEY_ID', None): | ||||
|             self.object.update_juries_lines_spreadsheet() | ||||
|         return ret | ||||
|  | ||||
|  | ||||
| class SolutionsDownloadView(VolunteerMixin, View): | ||||
| @@ -1075,6 +1068,10 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView): | ||||
|         self.object.juries.add(reg) | ||||
|         self.object.save() | ||||
|  | ||||
|         # Update Google Sheets juries lines | ||||
|         if os.getenv('GOOGLE_PRIVATE_KEY_ID', None): | ||||
|             self.object.update_juries_lines_spreadsheet() | ||||
|  | ||||
|         # Add notification | ||||
|         messages.success(self.request, _("The jury {name} has been successfully added!") | ||||
|                          .format(name=f"{user.first_name} {user.last_name}")) | ||||
| @@ -1870,35 +1867,6 @@ class NotationSheetsArchiveView(VolunteerMixin, DetailView): | ||||
|         return response | ||||
|  | ||||
|  | ||||
| class PassageCreateView(VolunteerMixin, CreateView): | ||||
|     model = Passage | ||||
|     form_class = PassageForm | ||||
|  | ||||
|     def dispatch(self, request, *args, **kwargs): | ||||
|         if not request.user.is_authenticated: | ||||
|             return self.handle_no_permission() | ||||
|  | ||||
|         qs = Pool.objects.filter(pk=self.kwargs["pk"]) | ||||
|         if not qs.exists(): | ||||
|             raise Http404 | ||||
|         self.pool = qs.get() | ||||
|  | ||||
|         if request.user.registration.is_admin or request.user.registration.is_volunteer \ | ||||
|                 and (self.pool.tournament in request.user.registration.organized_tournaments.all() | ||||
|                      or request.user.registration in self.pool.juries.all()): | ||||
|             return super().dispatch(request, *args, **kwargs) | ||||
|  | ||||
|         return self.handle_no_permission() | ||||
|  | ||||
|     def get_form(self, form_class=None): | ||||
|         form = super().get_form(form_class) | ||||
|         form.instance.pool = self.pool | ||||
|         form.fields["defender"].queryset = self.pool.participations.all() | ||||
|         form.fields["opponent"].queryset = self.pool.participations.all() | ||||
|         form.fields["reporter"].queryset = self.pool.participations.all() | ||||
|         return form | ||||
|  | ||||
|  | ||||
| class PassageDetailView(LoginRequiredMixin, DetailView): | ||||
|     model = Passage | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user