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 |                 passage.observer = tds[line[3]].participation | ||||||
|                 await passage.asave() |                 await passage.asave() | ||||||
|  |  | ||||||
|  |         await sync_to_async(self.associated_pool.update_spreadsheet)() | ||||||
|  |  | ||||||
|         return self.associated_pool |         return self.associated_pool | ||||||
|  |  | ||||||
|     def __str__(self): |     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): | class AddJuryForm(forms.ModelForm): | ||||||
|     def __init__(self, *args, **kwargs): |     def __init__(self, *args, **kwargs): | ||||||
|         super().__init__(*args, **kwargs) |         super().__init__(*args, **kwargs) | ||||||
|   | |||||||
| @@ -453,15 +453,23 @@ class Tournament(models.Model): | |||||||
|             tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation) |             tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation) | ||||||
|             tweak1 = tweak1_qs.get() if tweak1_qs.exists() else None |             tweak1 = tweak1_qs.get() if tweak1_qs.exists() else None | ||||||
|  |  | ||||||
|             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(f"=SIERREUR('Poule {pool1.short_name}'!$D{pool1.juries.count() + 10 + passage1.position}; 0)") | ||||||
|             line.append(tweak1.diff if tweak1 else 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(tweak2.diff if tweak2 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 {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"=$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})") |             line.append(f"=RANG($F{i + 2}; $F$2:$F${participations.count() + 1})") | ||||||
|  |  | ||||||
| @@ -609,21 +617,24 @@ class Tournament(models.Model): | |||||||
|             trigram = line[0][-4:-1] |             trigram = line[0][-4:-1] | ||||||
|             participation = self.participations.get(team__trigram=trigram) |             participation = self.participations.get(team__trigram=trigram) | ||||||
|             pool1 = self.pools.get(round=1, participations=participation) |             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) |             tweak1_qs = Tweak.objects.filter(pool=pool1, participation=participation) | ||||||
|             tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation) |             tweak1_nb = int(line[2]) | ||||||
|             tweak1_nb, tweak2_nb = int(line[2]), int(line[4]) |  | ||||||
|             if not tweak1_nb: |             if not tweak1_nb: | ||||||
|                 tweak1_qs.delete() |                 tweak1_qs.delete() | ||||||
|             else: |             else: | ||||||
|                 tweak1_qs.update_or_create(defaults={'diff': tweak1_nb}, |                 tweak1_qs.update_or_create(defaults={'diff': tweak1_nb}, | ||||||
|                                            create_defaults={'diff': tweak1_nb, 'pool': pool1, |                                            create_defaults={'diff': tweak1_nb, 'pool': pool1, | ||||||
|                                                             'participation': participation}) |                                                             'participation': participation}) | ||||||
|             if not tweak2_nb: |  | ||||||
|                 tweak2_qs.delete() |             if self.pools.filter(round=2, participations=participation).exists(): | ||||||
|             else: |                 pool2 = self.pools.get(round=2, participations=participation) | ||||||
|                 tweak2_qs.update_or_create(defaults={'diff': tweak2_nb}, |                 tweak2_qs = Tweak.objects.filter(pool=pool2, participation=participation) | ||||||
|                                            create_defaults={'diff': tweak2_nb, 'pool': pool2, |                 tweak2_nb = int(line[4]) | ||||||
|  |                 if not tweak2_nb: | ||||||
|  |                     tweak2_qs.delete() | ||||||
|  |                 else: | ||||||
|  |                     tweak2_qs.update_or_create(defaults={'diff': tweak2_nb}, | ||||||
|  |                                                create_defaults={'diff': tweak2_nb, 'pool': pool2, | ||||||
|                                                             'participation': participation}) |                                                             'participation': participation}) | ||||||
|  |  | ||||||
|     def get_absolute_url(self): |     def get_absolute_url(self): | ||||||
| @@ -1299,11 +1310,6 @@ class Pool(models.Model): | |||||||
|                 note.set_all(*note_line) |                 note.set_all(*note_line) | ||||||
|                 note.save() |                 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): |     def __str__(self): | ||||||
|         return _("Pool of day {round} for tournament {tournament} with teams {teams}")\ |         return _("Pool of day {round} for tournament {tournament} with teams {teams}")\ | ||||||
|             .format(round=self.round, |             .format(round=self.round, | ||||||
|   | |||||||
| @@ -125,9 +125,7 @@ | |||||||
|         </div> |         </div> | ||||||
|         {% if user.registration.is_volunteer %} |         {% if user.registration.is_volunteer %} | ||||||
|             <div class="card-footer text-center"> |             <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="#updatePoolModal">{% trans "Update" %}</button> | ||||||
|                 <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updateTeamsModal">{% trans "Update teams" %}</button> |  | ||||||
|             </div> |             </div> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|     </div> |     </div> | ||||||
| @@ -138,21 +136,11 @@ | |||||||
|  |  | ||||||
|     {% render_table passages %} |     {% 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 pool" as modal_title %} | ||||||
|     {% trans "Update" as modal_button %} |     {% trans "Update" as modal_button %} | ||||||
|     {% url "participation:pool_update" pk=pool.pk as modal_action %} |     {% url "participation:pool_update" pk=pool.pk as modal_action %} | ||||||
|     {% include "base_modal.html" with modal_id="updatePool" %} |     {% 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 notes" as modal_title %} | ||||||
|     {% trans "Upload" as modal_button %} |     {% trans "Upload" as modal_button %} | ||||||
|     {% url "participation:pool_upload_notes" pk=pool.pk as modal_action %} |     {% url "participation:pool_upload_notes" pk=pool.pk as modal_action %} | ||||||
| @@ -163,8 +151,6 @@ | |||||||
|     <script> |     <script> | ||||||
|         document.addEventListener('DOMContentLoaded', () => { |         document.addEventListener('DOMContentLoaded', () => { | ||||||
|             initModal("updatePool", "{% url "participation:pool_update" pk=pool.pk %}") |             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 %}") |             initModal("uploadNotes", "{% url "participation:pool_upload_notes" pk=pool.pk %}") | ||||||
|         }) |         }) | ||||||
|     </script> |     </script> | ||||||
|   | |||||||
| @@ -5,9 +5,9 @@ from django.urls import path | |||||||
| from django.views.generic import TemplateView | from django.views.generic import TemplateView | ||||||
|  |  | ||||||
| from .views import CreateTeamView, FinalNotationSheetTemplateView, JoinTeamView, MyParticipationDetailView, \ | from .views import CreateTeamView, FinalNotationSheetTemplateView, JoinTeamView, MyParticipationDetailView, \ | ||||||
|     MyTeamDetailView, NotationSheetsArchiveView, NoteUpdateView, ParticipationDetailView, PassageCreateView, \ |     MyTeamDetailView, NotationSheetsArchiveView, NoteUpdateView, ParticipationDetailView, \ | ||||||
|     PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \ |     PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \ | ||||||
|     PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateTeamsView, PoolUpdateView, PoolUploadNotesView, \ |     PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \ | ||||||
|     ScaleNotationSheetTemplateView, SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \ |     ScaleNotationSheetTemplateView, SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \ | ||||||
|     TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \ |     TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \ | ||||||
|     TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \ |     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/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: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: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/", 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/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>/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/", PoolUploadNotesView.as_view(), name="pool_upload_notes"), | ||||||
|     path("pools/<int:pk>/upload-notes/template/", PoolNotesTemplateView.as_view(), name="pool_notes_template"), |     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>/", PassageDetailView.as_view(), name="passage_detail"), | ||||||
|     path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"), |     path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"), | ||||||
|     path("pools/passages/<int:pk>/solution/", SynthesisUploadView.as_view(), name="upload_synthesis"), |     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 tfjm.views import AdminMixin, VolunteerMixin | ||||||
|  |  | ||||||
| from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \ | from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \ | ||||||
|     PoolForm, PoolTeamsForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \ |     PoolForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \ | ||||||
|     UploadNotesForm, ValidateParticipationForm |     UploadNotesForm, ValidateParticipationForm | ||||||
| from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak | from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament, Tweak | ||||||
| from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable | from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable | ||||||
| @@ -880,19 +880,12 @@ class PoolUpdateView(VolunteerMixin, UpdateView): | |||||||
|             return super().dispatch(request, *args, **kwargs) |             return super().dispatch(request, *args, **kwargs) | ||||||
|         return self.handle_no_permission() |         return self.handle_no_permission() | ||||||
|  |  | ||||||
|  |     def form_valid(self, form): | ||||||
| class PoolUpdateTeamsView(VolunteerMixin, UpdateView): |         ret = super().form_valid(form) | ||||||
|     model = Pool |         # Update Google Sheets juries lines | ||||||
|     form_class = PoolTeamsForm |         if os.getenv('GOOGLE_PRIVATE_KEY_ID', None): | ||||||
|  |             self.object.update_juries_lines_spreadsheet() | ||||||
|     def dispatch(self, request, *args, **kwargs): |         return ret | ||||||
|         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() |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class SolutionsDownloadView(VolunteerMixin, View): | class SolutionsDownloadView(VolunteerMixin, View): | ||||||
| @@ -1075,6 +1068,10 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView): | |||||||
|         self.object.juries.add(reg) |         self.object.juries.add(reg) | ||||||
|         self.object.save() |         self.object.save() | ||||||
|  |  | ||||||
|  |         # Update Google Sheets juries lines | ||||||
|  |         if os.getenv('GOOGLE_PRIVATE_KEY_ID', None): | ||||||
|  |             self.object.update_juries_lines_spreadsheet() | ||||||
|  |  | ||||||
|         # Add notification |         # Add notification | ||||||
|         messages.success(self.request, _("The jury {name} has been successfully added!") |         messages.success(self.request, _("The jury {name} has been successfully added!") | ||||||
|                          .format(name=f"{user.first_name} {user.last_name}")) |                          .format(name=f"{user.first_name} {user.last_name}")) | ||||||
| @@ -1870,35 +1867,6 @@ class NotationSheetsArchiveView(VolunteerMixin, DetailView): | |||||||
|         return response |         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): | class PassageDetailView(LoginRequiredMixin, DetailView): | ||||||
|     model = Passage |     model = Passage | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user