mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	Compare commits
	
		
			51 Commits
		
	
	
		
			survey_wei
			...
			f9d201ec0d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f9d201ec0d | ||
|  | 821efbf78b | ||
|  | a209e0d366 | ||
|  | ef485e0628 | ||
|  | 1481aa0635 | ||
|  | 867bf9fd25 | ||
|  | 47fda0ea36 | ||
|  | 623290827a | ||
|  | a87ce625f3 | ||
|  | 3559787fa7 | ||
|  | bd6ed27ae5 | ||
|  | 43dc676747 | ||
|  | caaeab6b0b | ||
|  | 54ba786884 | ||
|  | 80e109114f | ||
|  | 787005e60d | ||
|  | 414e103686 | ||
|  | 942d887c2e | ||
|  | a63c34fe37 | ||
|  | 2be6133458 | ||
|  | 7975fe47a6 | ||
|  | 476fbceeea | ||
|  | 8fbaa0bdc8 | ||
|  | a0de63effd | ||
|  | 09fb1d227e | ||
|  | 2e27d4f05c | ||
|  | 5d16dc4e7d | ||
|  | 3c34033bf5 | ||
|  | 131f508433 | ||
|  | 9162319734 | ||
|  | 5d2a8e9b79 | ||
|  | 33c94d0720 | ||
|  | 5040e8e8ea | ||
|  | c5697c4cb4 | ||
|  | e188c5a153 | ||
|  | 94e1fdc93a | ||
|  | d1ef367bab | ||
|  | 0fbb19c5fd | ||
|  | 21cbf2b21a | ||
|  | 361de9f8b4 | ||
|  | e2426bd6a6 | ||
|  | 7fea619a9f | ||
|  | 7b5eefcc0a | ||
|  | e4aa16986f | ||
|  | dd675b3676 | ||
|  | a5df98224f | ||
|  | 2cb9ac8735 | ||
|  | 35d4849a28 | ||
|  | 5a0fe7a6f0 | ||
|  | eda8460014 | ||
|  | 15c71ad31a | 
| @@ -7,21 +7,6 @@ stages: | ||||
| variables: | ||||
|   GIT_SUBMODULE_STRATEGY: recursive | ||||
|  | ||||
| # Debian Bullseye | ||||
| py39-django42: | ||||
|   stage: test | ||||
|   image: debian:bullseye | ||||
|   before_script: | ||||
|     - > | ||||
|         apt-get update && | ||||
|         apt-get install --no-install-recommends -y | ||||
|         python3-django python3-django-crispy-forms | ||||
|         python3-django-extensions python3-django-filters python3-django-polymorphic | ||||
|         python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil | ||||
|         python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache | ||||
|         python3-bs4 python3-setuptools tox texlive-xetex | ||||
|   script: tox -e py39-django42 | ||||
|  | ||||
| # Ubuntu 22.04 | ||||
| py310-django42: | ||||
|   stage: test | ||||
| @@ -54,8 +39,6 @@ py311-django42: | ||||
|         python3-bs4 python3-setuptools tox texlive-xetex | ||||
|   script: tox -e py311-django42 | ||||
|  | ||||
|  | ||||
|  | ||||
| linters: | ||||
|   stage: quality-assurance | ||||
|   image: debian:bookworm | ||||
|   | ||||
| @@ -265,12 +265,11 @@ class ActivityEntryView(LoginRequiredMixin, SingleTableMixin, TemplateView): | ||||
|         # Keep only users that have a note | ||||
|         note_qs = note_qs.filter(note__noteuser__isnull=False) | ||||
|  | ||||
|         # Keep only members | ||||
|         # Keep only valid members | ||||
|         note_qs = note_qs.filter( | ||||
|             note__noteuser__user__memberships__club=activity.attendees_club, | ||||
|             note__noteuser__user__memberships__date_start__lte=timezone.now(), | ||||
|             note__noteuser__user__memberships__date_end__gte=timezone.now(), | ||||
|         ) | ||||
|             note__noteuser__user__memberships__date_end__gte=timezone.now()).exclude(note__inactivity_reason='forced') | ||||
|  | ||||
|         # Filter with permission backend | ||||
|         note_qs = note_qs.filter(PermissionBackend.filter_queryset(self.request, Alias, "view")) | ||||
|   | ||||
| @@ -44,7 +44,8 @@ class ProfileForm(forms.ModelForm): | ||||
|     """ | ||||
|     A form for the extras field provided by the :model:`member.Profile` model. | ||||
|     """ | ||||
|     report_frequency = forms.IntegerField(required=False, initial=0, label=_("Report frequency")) | ||||
|     # Remove widget=forms.HiddenInput() if you want to use report frequency. | ||||
|     report_frequency = forms.IntegerField(required=False, initial=0, label=_("Report frequency"), widget=forms.HiddenInput()) | ||||
|  | ||||
|     last_report = forms.DateTimeField(required=False, disabled=True, label=_("Last report date")) | ||||
|  | ||||
| @@ -76,7 +77,8 @@ class ProfileForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = Profile | ||||
|         fields = '__all__' | ||||
|         exclude = ('user', 'email_confirmed', 'registration_valid', ) | ||||
|         # Remove ml_[asso]_registration from exclude if the concerned association uses nk20 to manage its mailing list. | ||||
|         exclude = ('user', 'email_confirmed', 'registration_valid', 'ml_sport_registration', ) | ||||
|  | ||||
|  | ||||
| class ImageForm(forms.Form): | ||||
|   | ||||
							
								
								
									
										18
									
								
								apps/member/migrations/0013_auto_20240807_1409.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								apps/member/migrations/0013_auto_20240807_1409.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| # Generated by Django 2.2.28 on 2024-08-07 12:09 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('member', '0012_club_add_registration_form'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='profile', | ||||
|             name='promotion', | ||||
|             field=models.PositiveSmallIntegerField(default=2024, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion'), | ||||
|         ), | ||||
|     ] | ||||
| @@ -42,12 +42,12 @@ class UserTable(tables.Table): | ||||
|     """ | ||||
|     alias = tables.Column() | ||||
|  | ||||
|     section = tables.Column(accessor='profile__section') | ||||
|     section = tables.Column(accessor='profile__section', orderable=False) | ||||
|  | ||||
|     # Override the column to let replace the URL | ||||
|     email = tables.EmailColumn(linkify=lambda record: "mailto:{}".format(record.email)) | ||||
|  | ||||
|     balance = tables.Column(accessor='note__balance', verbose_name=_("Balance")) | ||||
|     balance = tables.Column(accessor='note__balance', verbose_name=_("Balance"), orderable=False) | ||||
|  | ||||
|     def render_email(self, record, value): | ||||
|         # Replace the email by a dash if the user can't see the profile detail | ||||
|   | ||||
| @@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|         {{ title }} | ||||
|     </h3> | ||||
|     <div class="card-body"> | ||||
|         <input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note…"> | ||||
|         <input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note..."> | ||||
|         <div class="form-check"> | ||||
|             <label class="form-check-label" for="only_active"> | ||||
|                 <input type="checkbox" class="checkboxinput form-check-input" id="only_active" | ||||
|   | ||||
| @@ -260,11 +260,13 @@ class ButtonTable(tables.Table): | ||||
|         text=_('edit'), | ||||
|         accessor='pk', | ||||
|         verbose_name=_("Edit"), | ||||
|         orderable=False, | ||||
|     ) | ||||
|  | ||||
|     hideshow = tables.Column( | ||||
|         verbose_name=_("Hide/Show"), | ||||
|         accessor="pk", | ||||
|         orderable=False, | ||||
|         attrs={ | ||||
|             'td': { | ||||
|                 'class': 'col-sm-1', | ||||
| @@ -276,7 +278,8 @@ class ButtonTable(tables.Table): | ||||
|     delete_col = tables.TemplateColumn(template_code=DELETE_TEMPLATE, | ||||
|                                        extra_context={"delete_trans": _('delete')}, | ||||
|                                        attrs={'td': {'class': 'col-sm-1'}}, | ||||
|                                        verbose_name=_("Delete"), ) | ||||
|                                        verbose_name=_("Delete"), | ||||
|                                        orderable=False, ) | ||||
|  | ||||
|     def render_amount(self, value): | ||||
|         return pretty_money(value) | ||||
|   | ||||
							
								
								
									
										65
									
								
								apps/note/templates/note/mails/summary_notes_report.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								apps/note/templates/note/mails/summary_notes_report.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| {% load pretty_money %} | ||||
| {% load i18n %} | ||||
|  | ||||
| <!DOCTYPE html> | ||||
| <html lang="fr"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <title>[Note Kfet] Récapitulatif de trésorerie</title> | ||||
| </head> | ||||
| <body> | ||||
| <h1> | ||||
|   Récapitulatif de trésorerie au {{ summary.date|date:"d/m/Y" }} à {{ summary.date|date:"H:i:s" }} : | ||||
| </h1> | ||||
|  | ||||
| <h2> | ||||
|   Tous les utilisateur⋅rices : | ||||
| </h2> | ||||
| <ul> | ||||
|   <li>Positifs : {{ summary.total_positive_user }} soit {{ summary.balance_positive_user / 100 }} €</li> | ||||
|   <li>Neutres : {{ summary.total_zero_user }}</li> | ||||
|   <li>Négatifs : {{ summary.total_negative_user }} soit {{ summary.balance_negative_user / 100 }} €</li> | ||||
| </ul> | ||||
|  | ||||
| <h2> | ||||
|   Les {{ summary.total_positive_user_bde + summary.total_zero_user_bde + summary.total_negative_user_bde }} adhérent⋅es BDE : | ||||
| </h2> | ||||
| <ul> | ||||
|   <li>Positifs : {{ summary.total_positive_user_bde }} soit {{ summary.balance_positive_user_bde / 100 }} €</li> | ||||
|   <li>Neutres : {{ summary.total_zero_user_bde }}</li> | ||||
|   <li>Négatifs : {{ summary.total_negative_user_bde }} soit {{ summary.balance_negative_user_bde / 100 }} €</li> | ||||
| </ul> | ||||
|  | ||||
| <h2> | ||||
|   Clubs : | ||||
| </h2> | ||||
| <ul> | ||||
|   <li>Positifs : {{ summary.total_positive_club }} soit {{ summary.balance_positive_club / 100 }} €</li> | ||||
|   <li>Neutres : {{ summary.total_zero_club }}</li> | ||||
|   <li>Négatifs : {{ summary.total_negative_club }} soit {{ summary.balance_negative_club / 100 }} €</li> | ||||
| </ul> | ||||
|  | ||||
| <h2> | ||||
|   Clubs hors BDE / Kfet et club dont le nom fini par "- BDE" : | ||||
| </h2> | ||||
| <ul> | ||||
|   <li>Positifs : {{ summary.total_positive_club_nbde }} soit {{ summary.balance_positive_club_nbde / 100 }} €</li> | ||||
|   <li>Neutres : {{ summary.total_zero_club_nbde }}</li> | ||||
|   <li>Négatifs : {{ summary.total_negative_club_nbde }} soit {{ summary.balance_negative_club_nbde / 100 }} €</li> | ||||
| </ul> | ||||
|  | ||||
| <h2> | ||||
|   Progression : | ||||
| </h2> | ||||
| <ul> | ||||
|   <li>Ceci correspond à une différence de {{ balance_difference_user / 100 }} € pour les utilisateur⋅rices</li> | ||||
|   <li>Ceci correspond à une différence de {{ balance_difference_club / 100 }} € pour les clubs</li> | ||||
| </ul> | ||||
|  | ||||
| -- | ||||
| <p> | ||||
|     Le BDE<br> | ||||
|     {% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %} | ||||
| </p> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										33
									
								
								apps/note/templates/note/mails/summary_notes_report.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								apps/note/templates/note/mails/summary_notes_report.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| {% load pretty_money %} | ||||
| {% load i18n %} | ||||
|  | ||||
| Récapitulatif de trésorerie au {{ summary.date|date:"d/m/Y" }} à {{ summary.date|date:"H:i:s" }} : | ||||
|  | ||||
| Tous les utilisateur⋅rices : | ||||
|   - Positifs : {{ summary.total_positive_user }} soit {{ summary.balance_positive_user / 100 }} € | ||||
|   - Neutres : {{ summary.total_zero_user }} | ||||
|   - Négatifs : {{ summary.total_negative_user }} soit {{ summary.balance_negative_user / 100 }} € | ||||
|  | ||||
| Les {{ summary.total_positive_user_bde + summary.total_zero_user_bde + summary.total_negative_user_bde }} adhérent⋅es BDE : | ||||
|   - Positifs : {{ summary.total_positive_user_bde }} soit {{ summary.balance_positive_user_bde / 100 }} € | ||||
|   - Neutres : {{ summary.total_zero_user_bde }} | ||||
|   - Négatifs : {{ summary.total_negative_user_bde }} soit {{ summary.balance_negative_user_bde /100 }} € | ||||
|  | ||||
| Clubs : | ||||
|   - Positifs : {{ summary.total_positive_club }} soit {{ summary.balance_positive_club / 100 }} € | ||||
|   - Neutres : {{ summary.total_zero_club }} | ||||
|   - Négatifs : {{ summary.total_negative_club }} soit {{ summary.balance_negative_club / 100 }} € | ||||
|  | ||||
| Clubs hors BDE / Kfet et club dont le nom fini par "- BDE" : | ||||
|   - Positifs : {{ summary.total_positive_club_nbde }} soit {{ summary.balance_positive_club_nbde / 100 }} € | ||||
|   - Neutres : {{ summary.total_zero_club_nbde }} | ||||
|   - Négatifs : {{ summary.total_negative_club_nbde }} soit {{ summary.balance_negative_club_nbde / 100 }} € | ||||
|  | ||||
| Progression : | ||||
|   - Ceci correspond à une différence de {{ balance_difference_user / 100 }} € pour les utilisateur⋅rices | ||||
|   - Ceci correspond à une différence de {{ balance_difference_club / 100 }} € pour les clubs | ||||
|  | ||||
| -- | ||||
| Le BDE | ||||
|  | ||||
| {% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %} | ||||
| @@ -31,3 +31,4 @@ class RoleAdmin(admin.ModelAdmin): | ||||
|     Admin customisation for Role | ||||
|     """ | ||||
|     list_display = ('name', ) | ||||
|     filter_horizontal = ('permissions',) | ||||
|   | ||||
| @@ -3752,6 +3752,86 @@ | ||||
|             "description": "Modifier bouffe" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "model": "permission.permission", | ||||
|         "pk": 239, | ||||
|         "fields": { | ||||
|             "model": [ | ||||
|                 "note", | ||||
|                 "alias" | ||||
|             ], | ||||
|             "query": "[\"AND\", {\"note__noteuser__user__memberships__club\": [\"club\"], \"note__noteuser__user__memberships__date_start__lte\": [\"today\"], \"note__noteuser__user__memberships__date_end__gte\": [\"today\"]}, {\"note__is_active\": true}]", | ||||
|             "type": "view", | ||||
|             "mask": 2, | ||||
|             "field": "", | ||||
|             "permanent": false, | ||||
|             "description": "Voir les alias des notes des adhérent⋅es du club" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "model": "permission.permission", | ||||
|         "pk": 240, | ||||
|         "fields": { | ||||
|             "model": [ | ||||
|                 "note", | ||||
|                 "alias" | ||||
|             ], | ||||
|             "query": "[\"AND\", {\"note__noteuser__user__memberships__club\": [\"club\", \"parent_club\"], \"note__noteuser__user__memberships__date_start__lte\": [\"today\"], \"note__noteuser__user__memberships__date_end__gte\": [\"today\"]}, {\"note__is_active\": true}]", | ||||
|             "type": "view", | ||||
|             "mask": 2, | ||||
|             "field": "", | ||||
|             "permanent": false, | ||||
|             "description": "Voir les alias des notes des adhérent⋅es du club parent" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "model": "permission.permission", | ||||
|         "pk": 241, | ||||
|         "fields": { | ||||
|             "model": [ | ||||
|                 "auth", | ||||
|                 "user" | ||||
|             ], | ||||
|             "query": "[\"AND\", {\"memberships__club\": [\"club\", \"parent_club\"], \"memberships__date_start__lte\": [\"today\"], \"memberships__date_end__gte\": [\"today\"]}, {\"note__is_active\": true}]", | ||||
|             "type": "view", | ||||
|             "mask": 2, | ||||
|             "field": "", | ||||
|             "permanent": false, | ||||
|             "description": "Voir les utilisateurs adhérents au club parent" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "model": "permission.permission", | ||||
|         "pk": 242, | ||||
|         "fields": { | ||||
|             "model": [ | ||||
|                 "note", | ||||
|                 "transaction" | ||||
|             ], | ||||
|             "query": "[\"AND\", {\"destination\": [\"club\", \"note\"]}, [\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 2000]}}, {\"valid\": false}]]", | ||||
|             "type": "add", | ||||
|             "mask": 2, | ||||
|             "field": "", | ||||
|             "permanent": false, | ||||
|             "description": "Créer une transaction vers la note d'un club" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "model": "permission.permission", | ||||
|         "pk": 243, | ||||
|         "fields": { | ||||
|             "model": [ | ||||
|                 "member", | ||||
|                 "profile" | ||||
|             ], | ||||
|             "query": "{\"user__memberships__club\": [\"club\"], \"user__memberships__date_start__lte\": [\"today\"],\"user__memberships__date_end__gte\": [\"today\"]}", | ||||
|             "type": "view", | ||||
|             "mask": 3, | ||||
|             "field": "", | ||||
|             "permanent": false, | ||||
|             "description": "Voir les profils des membres du club" | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "model": "permission.role", | ||||
|         "pk": 1, | ||||
| @@ -3851,7 +3931,21 @@ | ||||
|             "for_club": null, | ||||
|             "name": "Membre de club", | ||||
|             "permissions": [ | ||||
| 				22 | ||||
|                 1, | ||||
|                 2, | ||||
|                 3, | ||||
|                 4, | ||||
|                 5, | ||||
|                 7, | ||||
|                 8, | ||||
|                 9, | ||||
|                 10, | ||||
|                 11, | ||||
|                 12, | ||||
|                 13, | ||||
|                 14, | ||||
|                 22, | ||||
|                 48 | ||||
|             ] | ||||
|         } | ||||
|     }, | ||||
| @@ -3900,6 +3994,7 @@ | ||||
|             "for_club": null, | ||||
|             "name": "Tr\u00e9sorièr\u22c5e de club", | ||||
|             "permissions": [ | ||||
|                 6, | ||||
|                 19, | ||||
|                 20, | ||||
|                 21, | ||||
| @@ -3913,7 +4008,10 @@ | ||||
|                 142, | ||||
|                 182, | ||||
|                 184, | ||||
| 				185 | ||||
|                 185, | ||||
|                 239, | ||||
|                 240, | ||||
|                 241 | ||||
|             ] | ||||
|         } | ||||
|     }, | ||||
|   | ||||
| @@ -135,18 +135,18 @@ class Permission(models.Model): | ||||
|  | ||||
|     # A json encoded Q object with the following grammar | ||||
|     #  query -> [] | {}  (the empty query representing all objects) | ||||
|     #  query -> ["AND", query, …]            AND multiple queries | ||||
|     #         | ["OR", query, …]             OR multiple queries | ||||
|     #  query -> ["AND", query, ...]          AND multiple queries | ||||
|     #         | ["OR", query, ...]           OR multiple queries | ||||
|     #         | ["NOT", query]               Opposite of query | ||||
|     #  query -> {key: value, …}              A list of fields and values of a Q object | ||||
|     #  query -> {key: value, ...}            A list of fields and values of a Q object | ||||
|     #  key   -> string                       A field name | ||||
|     #  value -> int | string | bool | null   Literal values | ||||
|     #         | [parameter, …]               A parameter. See compute_param for more details. | ||||
|     #         | [parameter, ...]             A parameter. See compute_param for more details. | ||||
|     #         | {"F": oper}                  An F object | ||||
|     #  oper  -> [string, …]                  A parameter. See compute_param for more details. | ||||
|     #         | ["ADD", oper, …]             Sum multiple F objects or literal | ||||
|     #  oper  -> [string, ...]                A parameter. See compute_param for more details. | ||||
|     #         | ["ADD", oper, ...]           Sum multiple F objects or literal | ||||
|     #         | ["SUB", oper, oper]          Substract two F objects or literal | ||||
|     #         | ["MUL", oper, …]             Multiply F objects or literals | ||||
|     #         | ["MUL", oper, ...]           Multiply F objects or literals | ||||
|     #         | int | string | bool | null   Literal values | ||||
|     #         | ["F", string]                A field | ||||
|     # | ||||
|   | ||||
| @@ -300,9 +300,13 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, | ||||
| #            join_bde = True | ||||
| #            join_kfet = True | ||||
|  | ||||
|         if not join_bde: | ||||
|         if not (join_bde or any(b for _, b in join_clubs)): | ||||
|             # This software belongs to the BDE. | ||||
|             form.add_error('join_bde', _("You must join the BDE.")) | ||||
|             form.add_error('join_bde', _("You must join a club.")) | ||||
|             return super().form_invalid(form) | ||||
|  | ||||
|         if join_kfet and not join_bde: | ||||
|             form.add_error('join_bde', _("You must also join the parent club BDE.")) | ||||
|             return super().form_invalid(form) | ||||
|  | ||||
|         # Calculate required registration fee | ||||
|   | ||||
 Submodule apps/scripts updated: f580f9b9e9...f76acb3248
									
								
							| @@ -5,13 +5,13 @@ from django.contrib import admin | ||||
| from note_kfet.admin import admin_site | ||||
|  | ||||
| from .forms import ProductForm | ||||
| from .models import RemittanceType, Remittance, SogeCredit, Invoice, Product | ||||
| from .models import Invoice, NoteSummary, Product, RemittanceType, Remittance, SogeCredit | ||||
|  | ||||
|  | ||||
| @admin.register(RemittanceType, site=admin_site) | ||||
| class RemittanceTypeAdmin(admin.ModelAdmin): | ||||
|     """ | ||||
|     Admin customisation for RemiitanceType | ||||
|     Admin customisation for RemittanceType | ||||
|     """ | ||||
|     list_display = ('note', ) | ||||
|  | ||||
| @@ -55,3 +55,19 @@ class InvoiceAdmin(admin.ModelAdmin): | ||||
|     """ | ||||
|     list_display = ('object', 'id', 'bde', 'name', 'date', 'acquitted',) | ||||
|     inlines = (ProductInline,) | ||||
|  | ||||
|  | ||||
| @admin.register(NoteSummary, site=admin_site) | ||||
| class NoteSummaryAdmin(admin.ModelAdmin): | ||||
|     """ | ||||
|     Admin customisation for NoteSummary | ||||
|     """ | ||||
|     list_display = ( | ||||
|         'date', 'total_positive_user', 'balance_positive_user', 'total_positive_user_bde', | ||||
|         'balance_positive_user_bde', 'total_zero_user', 'total_zero_user_bde', 'total_negative_user', | ||||
|         'balance_negative_user', 'total_negative_user_bde', 'balance_negative_user_bde', | ||||
|         'total_vnegative_user', 'balance_vnegative_user', 'total_vnegative_user_bde', | ||||
|         'balance_vnegative_user_bde', 'total_positive_club', 'balance_positive_club', | ||||
|         'total_positive_club_nbde', 'balance_positive_club_nbde', 'total_zero_club', 'total_zero_club_nbde', | ||||
|         'total_negative_club', 'balance_negative_club', 'total_negative_club_nbde', 'balance_negative_club_nbde', | ||||
|     ) | ||||
|   | ||||
							
								
								
									
										49
									
								
								apps/treasury/migrations/0009_notesummary.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								apps/treasury/migrations/0009_notesummary.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| # Generated by Django 2.2.28 on 2024-08-07 12:09 | ||||
|  | ||||
| import datetime | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('treasury', '0008_auto_20240322_0045'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='NoteSummary', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('date', models.DateField(default=datetime.date.today, verbose_name='Date')), | ||||
|                 ('total_positive_user', models.PositiveIntegerField(verbose_name='Total positive user')), | ||||
|                 ('balance_positive_user', models.PositiveIntegerField(verbose_name='Balance positive user')), | ||||
|                 ('total_positive_user_bde', models.PositiveIntegerField(verbose_name='Total positive user BDE')), | ||||
|                 ('balance_positive_user_bde', models.PositiveIntegerField(verbose_name='Balance positive user BDE')), | ||||
|                 ('total_zero_user', models.PositiveIntegerField(verbose_name='Total zero user')), | ||||
|                 ('total_zero_user_bde', models.PositiveIntegerField(verbose_name='Total zero user BDE')), | ||||
|                 ('total_negative_user', models.PositiveIntegerField(verbose_name='Total negative user')), | ||||
|                 ('balance_negative_user', models.PositiveIntegerField(verbose_name='Balance negative user')), | ||||
|                 ('total_negative_user_bde', models.PositiveIntegerField(verbose_name='Total negative user BDE')), | ||||
|                 ('balance_negative_user_bde', models.PositiveIntegerField(verbose_name='Balance negative user BDE')), | ||||
|                 ('total_vnegative_user', models.PositiveIntegerField(verbose_name='Total very negative user')), | ||||
|                 ('balance_vnegative_user', models.PositiveIntegerField(verbose_name='Balance very negative user')), | ||||
|                 ('total_vnegative_user_bde', models.PositiveIntegerField(verbose_name='Total very negative user BDE')), | ||||
|                 ('balance_vnegative_user_bde', models.PositiveIntegerField(verbose_name='Balance very negative user BDE')), | ||||
|                 ('total_positive_club', models.PositiveIntegerField(verbose_name='Total positive club')), | ||||
|                 ('balance_positive_club', models.PositiveIntegerField(verbose_name='Balance positive club')), | ||||
|                 ('total_positive_club_nbde', models.PositiveIntegerField(verbose_name='Total positive club nbde')), | ||||
|                 ('balance_positive_club_nbde', models.PositiveIntegerField(verbose_name='Balance positive club nbde')), | ||||
|                 ('total_zero_club', models.PositiveIntegerField(verbose_name='Total zero club')), | ||||
|                 ('total_zero_club_nbde', models.PositiveIntegerField(verbose_name='Total zero club nbde')), | ||||
|                 ('total_negative_club', models.PositiveIntegerField(verbose_name='Total negative club')), | ||||
|                 ('balance_negative_club', models.PositiveIntegerField(verbose_name='Balance negative club')), | ||||
|                 ('total_negative_club_nbde', models.PositiveIntegerField(verbose_name='Total negative club nbde')), | ||||
|                 ('balance_negative_club_nbde', models.PositiveIntegerField(verbose_name='Balance negative club nbde')), | ||||
|             ], | ||||
|             options={ | ||||
|                 'verbose_name': 'Summary', | ||||
|                 'verbose_name_plural': 'Summaries', | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
| @@ -460,3 +460,117 @@ class SogeCredit(models.Model): | ||||
|             self.credit_transaction._force_save = True | ||||
|             self.credit_transaction.save() | ||||
|         super().delete(**kwargs) | ||||
|  | ||||
|  | ||||
| class NoteSummary(models.Model): | ||||
|     """ | ||||
|     Summary of every notes | ||||
|     """ | ||||
|  | ||||
|     date = models.DateField( | ||||
|         default=date.today, | ||||
|         verbose_name=_("Date"), | ||||
|     ) | ||||
|  | ||||
|     total_positive_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total positive user"), | ||||
|     ) | ||||
|  | ||||
|     balance_positive_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance positive user"), | ||||
|     ) | ||||
|  | ||||
|     total_positive_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total positive user BDE"), | ||||
|     ) | ||||
|  | ||||
|     balance_positive_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance positive user BDE"), | ||||
|     ) | ||||
|  | ||||
|     total_zero_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total zero user"), | ||||
|     ) | ||||
|  | ||||
|     total_zero_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total zero user BDE"), | ||||
|     ) | ||||
|  | ||||
|     total_negative_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total negative user"), | ||||
|     ) | ||||
|  | ||||
|     balance_negative_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance negative user"), | ||||
|     ) | ||||
|  | ||||
|     total_negative_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total negative user BDE"), | ||||
|     ) | ||||
|  | ||||
|     balance_negative_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance negative user BDE"), | ||||
|     ) | ||||
|  | ||||
|     total_vnegative_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total very negative user"), | ||||
|     ) | ||||
|  | ||||
|     balance_vnegative_user = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance very negative user"), | ||||
|     ) | ||||
|  | ||||
|     total_vnegative_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total very negative user BDE"), | ||||
|     ) | ||||
|  | ||||
|     balance_vnegative_user_bde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance very negative user BDE"), | ||||
|     ) | ||||
|  | ||||
|     total_positive_club = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total positive club"), | ||||
|     ) | ||||
|  | ||||
|     balance_positive_club = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance positive club"), | ||||
|     ) | ||||
|  | ||||
|     total_positive_club_nbde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total positive club nbde"), | ||||
|     ) | ||||
|  | ||||
|     balance_positive_club_nbde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance positive club nbde"), | ||||
|     ) | ||||
|  | ||||
|     total_zero_club = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total zero club"), | ||||
|     ) | ||||
|  | ||||
|     total_zero_club_nbde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total zero club nbde"), | ||||
|     ) | ||||
|  | ||||
|     total_negative_club = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total negative club"), | ||||
|     ) | ||||
|  | ||||
|     balance_negative_club = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance negative club"), | ||||
|     ) | ||||
|  | ||||
|     total_negative_club_nbde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Total negative club nbde"), | ||||
|     ) | ||||
|  | ||||
|     balance_negative_club_nbde = models.PositiveIntegerField( | ||||
|         verbose_name=_("Balance negative club nbde"), | ||||
|     ) | ||||
|  | ||||
|     class Meta: | ||||
|         verbose_name = _("Summary") | ||||
|         verbose_name_plural = _("Summaries") | ||||
|  | ||||
|     def __str__(self): | ||||
|         return "Note summary of {date}".format(date=self.date) | ||||
|   | ||||
| @@ -37,6 +37,7 @@ class InvoiceTable(tables.Table): | ||||
|         args=[A('id')], | ||||
|         verbose_name=_("delete"), | ||||
|         text=_("Delete"), | ||||
|         orderable=False, | ||||
|         attrs={ | ||||
|             'th': { | ||||
|                 'id': 'delete-membership-header' | ||||
| @@ -70,6 +71,7 @@ class RemittanceTable(tables.Table): | ||||
|                              verbose_name=_("View"), | ||||
|                              args=[A("pk")], | ||||
|                              text=_("View"), | ||||
|                              orderable=False, | ||||
|                              attrs={ | ||||
|                                  'a': {'class': 'btn btn-primary'} | ||||
|                              }, ) | ||||
| @@ -97,6 +99,7 @@ class SpecialTransactionTable(tables.Table): | ||||
|                                        verbose_name=_("Remittance"), | ||||
|                                        args=[A("specialtransactionproxy__pk")], | ||||
|                                        text=_("Add"), | ||||
|                                        orderable=False, | ||||
|                                        attrs={ | ||||
|                                            'a': {'class': 'btn btn-primary'} | ||||
|                                        }, ) | ||||
| @@ -105,6 +108,7 @@ class SpecialTransactionTable(tables.Table): | ||||
|                                           verbose_name=_("Remittance"), | ||||
|                                           args=[A("specialtransactionproxy__pk")], | ||||
|                                           text=_("Remove"), | ||||
|                                           orderable=False, | ||||
|                                           attrs={ | ||||
|                                               'a': {'class': 'btn btn-primary btn-danger'} | ||||
|                                           }, ) | ||||
| @@ -130,10 +134,12 @@ class SogeCreditTable(tables.Table): | ||||
|  | ||||
|     amount = tables.Column( | ||||
|         verbose_name=_("Amount"), | ||||
|         orderable=False, | ||||
|     ) | ||||
|  | ||||
|     valid = tables.Column( | ||||
|         verbose_name=_("Valid"), | ||||
|         orderable=False, | ||||
|     ) | ||||
|  | ||||
|     def render_amount(self, value): | ||||
|   | ||||
| @@ -82,7 +82,7 @@ WORDS = { | ||||
|         5: "La quoi ?" | ||||
|     }], | ||||
|     "kokarde": ["Qu'est-ce que le mot Kokarde t'évoque ?", { | ||||
|         1: "Vraiment pas mon truc les soirées…", | ||||
|         1: "Vraiment pas mon truc les soirées...", | ||||
|         2: "Bof, je viens pour manger et je repars aussitôt", | ||||
|         3: "Je kiffe, good vibes", | ||||
|         4: "Perso, je ne m'arrêterai pas de danser sur la piste !", | ||||
| @@ -117,15 +117,15 @@ WORDS = { | ||||
|         5: "Je pourrais en faire à n'importe qui. Pourquoi ne pas créer le club Câl[ENS] ?" | ||||
|     }], | ||||
|     "vomi": ["Quel est ton rapport au vomi ?", { | ||||
|         1: "C'est compliqué…", | ||||
|         1: "C'est compliqué...", | ||||
|         2: "Jamais je ne vomis mais je nettoie quand mes potes vomissent", | ||||
|         3: "Jamais je ne vomis et jamais je ne nettoie celui de quelqu'un d'autre", | ||||
|         4: "Je vomis quelquefois, ça arrive, faites pas cette tête, mais je fins toujours par nettoyer !", | ||||
|         5: "Je vomis à chaque soirée et ce n'est jamais moi qui nettoie" | ||||
|     }], | ||||
|     "kfet": ["Qu'est ce que la Kfet t'évoque ?", { | ||||
|         1: "La Kfet, quel lieu de dépravé⋅es sérieux…", | ||||
|         2: "C'est un endroit à l'hygiène plus que douteuse…", | ||||
|         1: "La Kfet, quel lieu de dépravé⋅es sérieux...", | ||||
|         2: "C'est un endroit à l'hygiène plus que douteuse...", | ||||
|         3: "Téma les prix des boissons et des snacks, c'est aberrant !", | ||||
|         4: "En vrai, c'est cool, petit billard, petit canapé, chill !", | ||||
|         5: "Banger, j'y reste jusqu'à la fin de mes jours" | ||||
| @@ -147,7 +147,7 @@ WORDS = { | ||||
|     "scolarite": ["Comment tu vois ton cursus à l'ENS ?", { | ||||
|         1: "La tranquillité et le travail", | ||||
|         2: "On va s'amuser tout en bossant", | ||||
|         3: "Ça va profiter et réviser au dernier moment pour les exams…", | ||||
|         3: "Ça va profiter et réviser au dernier moment pour les exams...", | ||||
|         4: "Nous festoierons sans songer aux conséquences", | ||||
|         5: "Je ne vois qu'une seule issue : la débauche" | ||||
|     }] | ||||
|   | ||||
| @@ -279,7 +279,6 @@ class WEISurveyAlgorithm2024(WEISurveyAlgorithm): | ||||
|         # surveys = [s for s in surveys if s.bus_id != None] | ||||
|         # surveys = [s for s in surveys if not hasattr(s.information, 'hardcoded') or not s.information.hardcoded] | ||||
|  | ||||
|  | ||||
|         # surveys = [s for s in surveys if s.registration.user_id in free_users] | ||||
|  | ||||
|         # hardcoded_first_year_mb = WEIMembership.objects.filter(bus != None,registration__first_year=True) | ||||
| @@ -288,15 +287,13 @@ class WEISurveyAlgorithm2024(WEISurveyAlgorithm): | ||||
|         hardcoded_first_year_mb = WEIMembership.objects.filter(registration__first_year=True) | ||||
|         hardcoded_first_year = {mb.user.id if mb.bus else None: mb.bus.id if mb.bus else None for mb in hardcoded_first_year_mb} | ||||
|  | ||||
|  | ||||
|         # Reset previous algorithm run | ||||
|         for survey in surveys: | ||||
|             survey.free() | ||||
|             if survey.registration.user_id in hardcoded_first_year.keys(): | ||||
|                 survey.select_bus(hardcoded_first_year[s.registration.user_id]) | ||||
|                 survey.select_bus(hardcoded_first_year[survey.registration.user_id]) | ||||
|             survey.save() | ||||
|  | ||||
|  | ||||
|         non_men = [s for s in surveys if s.registration.gender != 'male'] | ||||
|         men = [s for s in surveys if s.registration.gender == 'male'] | ||||
|  | ||||
|   | ||||
| @@ -32,7 +32,7 @@ Applications indispensables | ||||
| * `Note <note>`_ : | ||||
|    Les notes associées à des utilisateur⋅rices ou des clubs. | ||||
| * `Activity <activity>`_ : | ||||
|    La gestion des activités (créations, gestion, entrées,…) | ||||
|    La gestion des activités (créations, gestion, entrées, ...) | ||||
| * `Permission <permission>`_ : | ||||
|    Backend de droits, limites les pouvoirs des utilisateur⋅rices | ||||
| * `API <../api>`_ : | ||||
| @@ -64,9 +64,9 @@ Applications facultatives | ||||
| * ``cas-server`` | ||||
|     Serveur central d'authentification, permet d'utiliser son compte de la NoteKfet2020 pour se connecter à d'autre application ayant intégrer un client. | ||||
| * `Scripts <https://gitlab.crans.org/bde/nk20-scripts>`_ | ||||
|      Ensemble de commande `./manage.py` pour la gestion de la note: import de données, verification d'intégrité, etc… | ||||
|      Ensemble de commande `./manage.py` pour la gestion de la note: import de données, verification d'intégrité, etc... | ||||
| * `Treasury <treasury>`_ : | ||||
|     Interface de gestion pour les trésorièr⋅es, émission de factures, remises de chèque, statistiques ... | ||||
|     Interface de gestion pour les trésorièr⋅es, émission de factures, remises de chèque, statistiques... | ||||
| * `WEI <wei>`_ : | ||||
|     Interface de gestion du WEI. | ||||
|  | ||||
|   | ||||
| @@ -43,7 +43,7 @@ l'utilisateur⋅rice, utiles pour l'adhésion au BDE : | ||||
| * ``address`` : ``CharField``, adresse physique de l'utilisateur⋅rice | ||||
| * ``paid`` : ``BooleanField``, indique si l'utilisateur⋅rice normalien⋅ne est rémunéré⋅e ou non (utile pour différencier les montants d'adhésion aux clubs) | ||||
| * ``phone_number`` : ``CharField``, numéro de téléphone de l'utilisateur⋅rice | ||||
| * ``section`` : ``CharField``, section de l'ENS à laquelle appartient l'utilisateur⋅rice (exemple : 1A0,…) | ||||
| * ``section`` : ``CharField``, section de l'ENS à laquelle appartient l'utilisateur⋅rice (exemple : 1A0, ...) | ||||
|  | ||||
| Clubs | ||||
| ~~~~~ | ||||
| @@ -101,7 +101,7 @@ Adhésions | ||||
|  | ||||
| La Note Kfet offre la possibilité aux clubs de gérer l'adhésion de leurs membres. En plus de réguler les cotisations | ||||
| des adhérent⋅es, des permissions sont octroyées sur la note en fonction des rôles au sein des clubs. Un rôle est une | ||||
| fonction occupée au sein d'un club (Trésorièr⋅e de club, président⋅e de club, GC Kfet, Res[pot], respo info,…). | ||||
| fonction occupée au sein d'un club (Trésorièr⋅e de club, président⋅e de club, GC Kfet, Res[pot], respo info, ...). | ||||
| Une adhésion attribue à un⋅e adhérent⋅e ses rôles. Les rôles fournissent les permissions. Par exemple, læ trésorièr⋅e d'un | ||||
| club a le droit de faire des transferts de et vers la note du club, tant que la source reste au-dessus de -50 €. | ||||
| Une adhésion est considérée comme valide si la date du jour est comprise (au sens large) entre les dates de début et | ||||
|   | ||||
| @@ -49,7 +49,7 @@ Une fois l'inscription validée, détail de ce qu'il se passe : | ||||
|   lui octroyant un faible nombre de permissions de base, telles que la visualisation de son compte. | ||||
| * On adhère la personne au club Kfet si cela est demandé, l'adhésion commence aujourd'hui. Iel dispose d'un unique rôle : | ||||
|   « Adhérent⋅e Kfet » , lui octroyant un nombre un peu plus conséquent de permissions basiques, telles que la possibilité de | ||||
|   faire des transactions, d'accéder aux activités, au WEI,… | ||||
|   faire des transactions, d'accéder aux activités, au WEI, ... | ||||
| * Si læ nouvelleau membre a indiqué avoir ouvert un compte à la société générale, alors les transactions sont invalidées, | ||||
|   la note n'est pas débitée (commence alors à 0 €). | ||||
|  | ||||
|   | ||||
| @@ -3744,8 +3744,8 @@ msgid "FAQ (FR)" | ||||
| msgstr "FAQ (FR)" | ||||
|  | ||||
| #: note_kfet/templates/base_search.html:15 | ||||
| msgid "Search by attribute such as name…" | ||||
| msgstr "Suche nach Attributen wie Name…" | ||||
| msgid "Search by attribute such as name..." | ||||
| msgstr "Suche nach Attributen wie Name..." | ||||
|  | ||||
| #: note_kfet/templates/base_search.html:23 | ||||
| msgid "There is no results." | ||||
|   | ||||
| @@ -3694,8 +3694,8 @@ msgid "FAQ (FR)" | ||||
| msgstr "FAQ (FR)" | ||||
|  | ||||
| #: note_kfet/templates/base_search.html:15 | ||||
| msgid "Search by attribute such as name…" | ||||
| msgstr "Buscar con atributo, como el nombre…" | ||||
| msgid "Search by attribute such as name..." | ||||
| msgstr "Buscar con atributo, como el nombre..." | ||||
|  | ||||
| #: note_kfet/templates/base_search.html:23 | ||||
| msgid "There is no results." | ||||
|   | ||||
| @@ -1032,6 +1032,7 @@ msgid "" | ||||
| "Register on the mailing list to stay informed of the sport events of the " | ||||
| "campus (1 mail/week)" | ||||
| msgstr "" | ||||
| "S'inscrire sur la liste de diffusion pour rester informé·e des actualités " | ||||
| "sportives sur le campus (1 mail par semaine)" | ||||
|  | ||||
| #: apps/member/models.py:113 | ||||
| @@ -1930,8 +1931,8 @@ msgstr "Consommer" | ||||
| #: apps/note/templates/note/conso_form.html:43 | ||||
| #: apps/note/templates/note/transaction_form.html:69 | ||||
| #: apps/note/templates/note/transaction_form.html:96 | ||||
| msgid "Name or alias…" | ||||
| msgstr "Pseudo ou alias…" | ||||
| msgid "Name or alias..." | ||||
| msgstr "Pseudo ou alias..." | ||||
|  | ||||
| #: apps/note/templates/note/conso_form.html:53 | ||||
| msgid "Select consumptions" | ||||
| @@ -1970,6 +1971,8 @@ msgstr "Historique des transactions récentes" | ||||
| #: apps/note/templates/note/mails/negative_balance.txt:25 | ||||
| #: apps/note/templates/note/mails/negative_notes_report.html:46 | ||||
| #: apps/note/templates/note/mails/negative_notes_report.txt:13 | ||||
| #: apps/note/templates/note/mails/summary_notes_report.html:62 | ||||
| #: apps/note/templates/note/mails/summary_ntoes_report.txt:33 | ||||
| #: apps/note/templates/note/mails/weekly_report.html:51 | ||||
| #: apps/note/templates/note/mails/weekly_report.txt:32 | ||||
| #: apps/registration/templates/registration/mails/email_validation_email.html:40 | ||||
| @@ -2031,8 +2034,8 @@ msgid "Current price" | ||||
| msgstr "Prix actuel" | ||||
|  | ||||
| #: apps/note/templates/note/transactiontemplate_list.html:13 | ||||
| msgid "Name of the button…" | ||||
| msgstr "Nom du bouton…" | ||||
| msgid "Name of the button..." | ||||
| msgstr "Nom du bouton..." | ||||
|  | ||||
| #: apps/note/templates/note/transactiontemplate_list.html:15 | ||||
| msgid "New button" | ||||
| @@ -2526,6 +2529,7 @@ msgid "Address" | ||||
| msgstr "Adresse" | ||||
|  | ||||
| #: apps/treasury/models.py:69 apps/treasury/models.py:202 | ||||
| #: apps/treasury/models.py:472 | ||||
| msgid "Date" | ||||
| msgstr "Date" | ||||
|  | ||||
| @@ -2644,6 +2648,102 @@ msgstr "" | ||||
| "Cet·te utilisateur·rice n'a pas assez d'argent pour payer les adhésions avec sa " | ||||
| "note. Merci de lui demander de recharger sa note avant d'invalider ce crédit." | ||||
|  | ||||
| #: apps/treasury/models.py:476 | ||||
| msgid "Total positive user" | ||||
| msgstr "Nombre d'utilisateur⋅rices en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:480 | ||||
| msgid "Balance positive user" | ||||
| msgstr "Solde des utilisateur⋅rices en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:484 | ||||
| msgid "Total positive user BDE" | ||||
| msgstr "Nombre d'adhérent⋅es au BDE en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:488 | ||||
| msgid "Balance positive user BDE" | ||||
| msgstr "Solde des adhérent⋅es au BDE en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:492 | ||||
| msgid "Total zero user" | ||||
| msgstr "Nombre d'utilisateur⋅rices à zéro" | ||||
|  | ||||
| #: apps/treasury/models.py:496 | ||||
| msgid "Total zero user BDE" | ||||
| msgstr "Nombre d'adhérent⋅es au BDE à zéro" | ||||
|  | ||||
| #: apps/treasury/models.py:500 | ||||
| msgid "Total negative user" | ||||
| msgstr "Nombre d'utilisateur⋅rices en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:504 | ||||
| msgid "Balance negative user" | ||||
| msgstr "Solde des utilisateur⋅rices en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:508 | ||||
| msgid "Total negative user BDE" | ||||
| msgstr "Nombre d'adhérent⋅es au BDE en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:512 | ||||
| msgid "Balance negative user BDE" | ||||
| msgstr "Solde des adhérent⋅es au BDE en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:516 | ||||
| msgid "Total very negative user" | ||||
| msgstr "Nombre d'utilisateur⋅rices en négatif sévère" | ||||
|  | ||||
| #: apps/treasury/models.py:520 | ||||
| msgid "Balance very negative user" | ||||
| msgstr "Solde des utilisateur⋅rices en négatif sévère" | ||||
|  | ||||
| #: apps/treasury/models.py:524 | ||||
| msgid "Total very negative user BDE" | ||||
| msgstr "Nombre d'adhérent⋅es au BDE en négatif sévère" | ||||
|  | ||||
| #: apps/treasury/models.py:528 | ||||
| msgid "Balance very negative user BDE" | ||||
| msgstr "Solde des adhérent⋅es au BDE en négatif sévère" | ||||
|  | ||||
| #: apps/treasury/models.py:532 | ||||
| msgid "Total positive club" | ||||
| msgstr "Nombre de clubs en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:536 | ||||
| msgid "Balance positive club" | ||||
| msgstr "Solde des clubs en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:540 | ||||
| msgid "Total positive club nbde" | ||||
| msgstr "Nombre de clubs non-BDE en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:544 | ||||
| msgid "Balance positive club nbde" | ||||
| msgstr "Solde des clubs non-BDE en positif" | ||||
|  | ||||
| #: apps/treasury/models.py:548 | ||||
| msgid "Total zero club" | ||||
| msgstr "Nombre de clubs à zéro" | ||||
|  | ||||
| #: apps/treasury/models.py:552 | ||||
| msgid "Total zero club nbde" | ||||
| msgstr "Nombre de clubs non-BDE à zéro" | ||||
|  | ||||
| #: apps/treasury/models.py:556 | ||||
| msgid "Total negative club" | ||||
| msgstr "Nombre de clubs en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:560 | ||||
| msgid "Balance negative club" | ||||
| msgstr "Solde des clubs en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:564 | ||||
| msgid "Total negative club nbde" | ||||
| msgstr "Nombre de clubs non-BDE en négatif" | ||||
|  | ||||
| #: apps/treasury/models.py:568 | ||||
| msgid "Balance negative club nbde" | ||||
| msgstr "Solde des clubs non-BDE en négatif" | ||||
|  | ||||
| #: apps/treasury/tables.py:20 | ||||
| msgid "Invoice #{:d}" | ||||
| msgstr "Facture n°{:d}" | ||||
| @@ -3386,8 +3486,8 @@ msgstr "" | ||||
| "coût d'adhésion." | ||||
|  | ||||
| #: apps/wei/templates/wei/weimembership_list.html:27 | ||||
| msgid "View unvalidated registrations…" | ||||
| msgstr "Voir les inscriptions non validées…" | ||||
| msgid "View unvalidated registrations..." | ||||
| msgstr "Voir les inscriptions non validées..." | ||||
|  | ||||
| #: apps/wei/templates/wei/weiregistration_confirm_delete.html:16 | ||||
| msgid "This registration is already validated and can't be deleted." | ||||
| @@ -3407,8 +3507,8 @@ msgid "There is no pre-registration found with this pattern." | ||||
| msgstr "Il n'y a pas de pré-inscription en attente avec cette entrée." | ||||
|  | ||||
| #: apps/wei/templates/wei/weiregistration_list.html:27 | ||||
| msgid "View validated memberships…" | ||||
| msgstr "Voir les adhésions validées…" | ||||
| msgid "View validated membershipis..." | ||||
| msgstr "Voir les adhésions validées..." | ||||
|  | ||||
| #: apps/wei/views.py:58 | ||||
| msgid "Search WEI" | ||||
| @@ -3673,8 +3773,8 @@ msgid "FAQ (FR)" | ||||
| msgstr "FAQ (FR)" | ||||
|  | ||||
| #: note_kfet/templates/base_search.html:15 | ||||
| msgid "Search by attribute such as name…" | ||||
| msgstr "Chercher par un attribut tel que le nom…" | ||||
| msgid "Search by attribute such as name..." | ||||
| msgstr "Chercher par un attribut tel que le nom..." | ||||
|  | ||||
| #: note_kfet/templates/base_search.html:23 | ||||
| msgid "There is no results." | ||||
|   | ||||
| @@ -9,6 +9,7 @@ MAILTO=notekfet2020@lists.crans.org | ||||
|  *   *     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py send_mail -c 1 -v 0 | ||||
|  *   *     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py retry_deferred -c 1 -v 0 | ||||
|  00  0     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py purge_mail_log 7 -v 0 | ||||
|  00  0     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py purge_mail_log -r failure 30 -v 0 | ||||
| # Faire une sauvegarde de la base de données | ||||
|  00  2     *   *   *     root   cd /var/www/note_kfet && apps/scripts/shell/backup_db | ||||
| # Vérifier la cohérence de la base et mailer en cas de problème | ||||
| @@ -19,9 +20,13 @@ MAILTO=notekfet2020@lists.crans.org | ||||
|  00  5     *   *   2     root   cd /var/www/note_kfet && env/bin/python manage.py send_mail_to_negative_balances --spam --negative-amount 1 -v 0 | ||||
| # Envoyer le rapport mensuel aux trésoriers et respos info | ||||
|  00  8     *   *   5     root   cd /var/www/note_kfet && env/bin/python manage.py send_mail_to_negative_balances --report --add-years 1 -v 0 | ||||
| # Envoyer le recap de tresorerie | ||||
|  00  8     *   *   5     root   cd /var/www/note_kfet && env/bin/python manage.py send_summary_notes_report --negative-amount 2000 | ||||
| # Envoyer les rapports aux gens | ||||
|  55  6     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py send_reports -v 0 | ||||
| # Mettre à jour les boutons mis en avant | ||||
|  00  9     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py refresh_highlighted_buttons -v 0 | ||||
| # Vider les tokens Oauth2 | ||||
|  00  6     *   *   *     root   cd /var/www/note_kfet && env/bin/python manage.py cleartokens -v 0 | ||||
| # Envoyer la liste des abonnés à la NL BDA | ||||
|  00  8     *   *   0     root   cd /var/www/note_kfet && env/bin/python manage.py extract_ml_registrations -t art -v 0 | ||||
| @@ -225,6 +225,7 @@ MEDIA_URL = '/media/' | ||||
| # Use mailer in production to place emails in a queue before sending them to avoid spam | ||||
| EMAIL_BACKEND = 'mailer.backend.DbBackend' | ||||
| MAILER_EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' | ||||
| MAILER_EMAIL_MAX_BATCH = 10 | ||||
| EMAIL_USE_SSL = os.getenv('EMAIL_USE_SSL', False) | ||||
| EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.example.org') | ||||
| EMAIL_PORT = os.getenv('EMAIL_PORT', 25) | ||||
| @@ -265,11 +266,9 @@ OAUTH2_PROVIDER = { | ||||
|     'SCOPES_BACKEND_CLASS': 'permission.scopes.PermissionScopes', | ||||
|     'OAUTH2_VALIDATOR_CLASS': "permission.scopes.PermissionOAuth2Validator", | ||||
|     'REFRESH_TOKEN_EXPIRE_SECONDS': timedelta(days=14), | ||||
|     'PKCE_REQUIRED': False, # PKCE (fix a breaking change of django-oauth-toolkit 2.0.0) | ||||
| } | ||||
|  | ||||
| # PKCE (fix a breaking change of django-oauth-toolkit 2.0.0) | ||||
| PKCE_REQUIRED = False | ||||
|  | ||||
| # Take control on how widget templates are sourced | ||||
| # See https://docs.djangoproject.com/en/2.2/ref/forms/renderers/#templatessetting | ||||
| FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' | ||||
|   | ||||
| @@ -72,7 +72,7 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|                             <a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-cutlery"></i> {% trans 'Food' %}</a> | ||||
|                         </li> | ||||
|                     {% endif %} | ||||
|                     {% if user.is_authenticated and user|is_member:"Kfet" %} | ||||
|                     {% if user.is_authenticated %} | ||||
|                         <li class="nav-item"> | ||||
|                             {% url 'note:transfer' as url %} | ||||
|                             <a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-exchange"></i> {% trans 'Transfer' %}</a> | ||||
|   | ||||
| @@ -12,7 +12,7 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|     </h3> | ||||
|     <div class="card-body"> | ||||
|         <input id="searchbar" type="text" class="form-control" | ||||
|             placeholder="{% trans "Search by attribute such as name…" %}"> | ||||
|             placeholder="{% trans "Search by attribute such as name..." %}"> | ||||
|     </div> | ||||
|     <div id="dynamic-table"> | ||||
|         {% if table.data %} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user