1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-07-06 15:24:01 +02:00

Compare commits

...

91 Commits

Author SHA1 Message Date
d36edfc063 Linting
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-09-02 13:44:18 +02:00
e452b7acbf [WEI] Allow a tolerance of 25 %
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-09-02 09:53:27 +02:00
74ab4df9fe [WEI] Extreme test with full buses and quality constraints
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-09-02 01:36:37 +02:00
451851c955 [WEI] Add a small test for the WEI algorithm with a few people
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-09-01 22:53:28 +02:00
e8f4ca1e09 Fix note account
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-29 14:40:55 +02:00
733f145be3 BDE members can now use they note even if they are not in the Kfet club
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-29 14:39:36 +02:00
48c37353ea [WEI] Fix pipeline before the good unit tests for WEI algorithm
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-29 14:38:11 +02:00
8056dc096d [WEI] Old members can create WEI registrations to renew their membership easily
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-29 14:33:17 +02:00
6d5b69cd26 Fix verification of parent club membership
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-29 14:17:09 +02:00
a7bdffd71a [WEI] Change color of validation button of WEI registrations
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-29 14:10:52 +02:00
0887e4bbde [WEI] Fix some tests, without considering WEI algorithm
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-27 13:15:28 +02:00
199f4ca1f2 [WEI] First implementation of algorithm
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-27 10:44:38 +02:00
802a6c68cb [WEI] Update survey words
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-26 00:11:24 +02:00
41a0b3a1c1 [WEI] Request bus size
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-25 23:26:57 +02:00
aa35724be2 Better display for WEI member list
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-23 19:00:26 +02:00
9086d33158 [WEI] Caution check is not required to validate registrations
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-23 18:51:34 +02:00
43d214b982 [WEI] Store seed in WEI Survey to add determinism in RNG
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-02 19:30:36 +02:00
b93e4a8d11 Current WEI year is 2021
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-02 19:22:07 +02:00
b9a9704061 [WEI] Prepare WEI 2021
No need to save WEI 2020 data because there weren't any WEI 2020

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-02 18:22:19 +02:00
fee52f326a [WEI] Add dry mode in WEI algorithm command, output generated data
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-08-02 18:21:06 +02:00
317966d5c1 Merge branch 'l_eveil_du_nanax' into 'beta'
More linting

See merge request bde/nk20!163
2021-06-14 20:25:40 +00:00
9f0a22d3d1 There is not always an error
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-14 22:15:35 +02:00
a5ecdd100c Merge branch '2021' into 'beta'
Update copyright for 2021

See merge request bde/nk20!169
2021-06-14 20:04:15 +00:00
f60691846b Don't block valid payments
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-14 21:54:32 +02:00
d5ecb72a71 Update copyright for 2021
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-14 21:45:56 +02:00
8cf9dfb9b9 Reduce complexity of the validation of a user, add verbosity in comments
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-14 21:43:04 +02:00
c3ab61bd04 Factorize detection of uncomplete payment forms
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-14 21:39:29 +02:00
0b4b6dcb3e Merge branch 'fix-mail-source' into 'beta'
Never use default constants. webmaster@localhost is never allowed to send emails.

See merge request bde/nk20!168
2021-06-14 19:25:26 +00:00
0d5f6c0332 Merge branch 'fix-amounts' into 'beta'
Round amounts to the nearest integer rather than take the floor

See merge request bde/nk20!167
2021-06-14 19:24:26 +00:00
7b28938cde Never use default constants. webmaster@localhost is never allowed to send emails.
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-07 23:49:46 +02:00
35ffb36fbd Round amounts to the nearest integer rather than take the floor
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-06-07 23:47:07 +02:00
c4c4e9594f couleur 4.0 2021-05-22 12:34:31 +02:00
4166823d55 couleurs 3.0 2021-05-22 12:29:02 +02:00
dc0f3dbcef Changement de couleur 3.0 2021-05-22 12:19:29 +02:00
b3abe9ab18 Changement de couleur 2.0 2021-05-22 11:53:13 +02:00
27f23b48b6 Merge branch 'coulour_vieux' into 'beta'
Bonjour c le changement de couleur

See merge request bde/nk20!164
2021-05-22 09:41:54 +00:00
67e170d4a6 Bonjour c le changement de couleur 2021-05-22 11:30:11 +02:00
8f895dc4d7 note: use native selector rather than Query 2021-05-12 18:03:44 +02:00
1187577728 Do not lint scripts submodule 2021-05-12 17:33:11 +02:00
8a58af3b31 Reformat apps/registration/tokens.py 2021-05-05 19:48:19 +02:00
0c23625147 Remove newline in imports 2021-05-05 19:47:16 +02:00
21219b9c62 Rename join_BDE and join_Kfet to lowercase 2021-05-05 19:46:53 +02:00
5ab8beecef Use _ prefix for ignored loop variable 2021-05-05 19:14:59 +02:00
1ca5133026 BaseException.message is removed in Python 3 2021-05-05 19:12:23 +02:00
93bc6bb245 Do not call setattr with a constant attribute value 2021-05-05 19:12:03 +02:00
952c4383e7 Add flake8-bugbear and lint all apps 2021-05-05 19:09:33 +02:00
15dd2b8f0c PC Kfet can update profile section while renewing memberships
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-29 13:11:00 +02:00
c540b6334c Fix minimum amount for the send_mail_to_negative_balances script
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-27 09:52:34 +02:00
0b93968b9e Merge branch 'docs' into 'beta'
More and more documentation

See merge request bde/nk20!156
2021-04-23 19:10:56 +00:00
97375ef6c0 Copy production database to development website
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:57 +02:00
36cfcd533f Documentation on scripts
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:56 +02:00
21dbc53615 Spam negative users if they have less than 0 euro
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:53 +02:00
e6f10ebdac Install production server
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:28 +02:00
47968844ce Install local development server
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:28 +02:00
a435460e29 Personal interface
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:28 +02:00
b7c4360108 How to NK20
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:28 +02:00
8d8c417c50 Fix old markdown remaining in docs 2021-04-23 21:07:28 +02:00
2b189af25b [FAQ] How to create a button?
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-23 21:07:28 +02:00
5a07c8a94f More FAQ
Signed-off-by: ynerant <ynerant@crans.org>
2021-04-23 21:07:27 +02:00
6cc1857eb6 Add FAQ page
Signed-off-by: ynerant <ynerant@crans.org>
2021-04-23 21:07:27 +02:00
601534d610 Add link to the documentatioh on the README
Signed-off-by: ynerant <ynerant@crans.org>
2021-04-23 21:07:27 +02:00
c271593839 Fix markdown typos
Signed-off-by: ynerant <ynerant@crans.org>
2021-04-23 21:07:27 +02:00
f351794aa0 Documentation on documentation
Signed-off-by: ynerant <ynerant@crans.org>
2021-04-23 21:07:27 +02:00
2793fee58c Merge branch 'less-verbosity' into 'beta'
Reduce verbosity of cron scripts

See merge request bde/nk20!161
2021-04-14 13:57:55 +00:00
7a715df121 Treasurers asked to add the list of old members in the monthly reports
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-14 15:48:15 +02:00
9308878054 Adapt verbosity of some scripts
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-14 15:18:49 +02:00
b5ccf5b800 Run cron without verbosity
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-14 15:05:13 +02:00
5e63254439 Merge branch 'fix-reports' into 'beta'
Update last report date only in non-debug mode

See merge request bde/nk20!160
2021-04-14 13:03:04 +00:00
da96506218 Update last report date only in non-debug mode
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-14 14:51:24 +02:00
b4714b896a Merge branch 'fix-reports' into 'beta'
Daily reports were broken

See merge request bde/nk20!159
2021-04-08 17:45:17 +00:00
cdb2647a4d Fix note list when daily reports are sent
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-08 17:33:51 +02:00
cc12e3ec63 Send cron mails to the BDE
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-04-08 17:31:01 +02:00
be168c5ada Decimal value is serialized as a str value
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-21 10:59:58 +01:00
b46ae6f856 [treasury] Product quantities are finally decimal fields 2021-03-21 10:41:15 +01:00
ec0bcbf015 PC Kfet can see all users
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-21 10:28:50 +01:00
81303b8ef8 Merge branch 'floating-quantities' into 'beta'
[invoices] Product quantities can be floating

See merge request bde/nk20!158
2021-03-13 12:13:50 +00:00
910b98fefc Invoices are in french
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-13 13:04:00 +01:00
5a7a219ba8 [invoices] Quantities can be non-integers
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-13 12:35:28 +01:00
116451603c Merge branch 'cas' into 'beta'
CAS + OAuth2

See merge request bde/nk20!155
2021-03-09 16:39:03 +00:00
b2437ef9b5 Remove additional blank lines
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 17:18:43 +01:00
d8c9618772 OAuth2 documentation
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 17:04:16 +01:00
c825dee95a CAS documentation
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 15:42:36 +01:00
73d27e820b Provide also note information (with balance and picture)
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 12:55:19 +01:00
40e1b42078 Fix API path
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 12:54:57 +01:00
72806f0ace Add profile and membership information to OAuth views
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 10:57:35 +01:00
b244e01231 Add simple view to give OAuth information
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 10:41:43 +01:00
76d1784aea Add OAuth2 authentication for Django Rest Framework
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 09:44:25 +01:00
56c5fa4057 We don't need a session to have permissions
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 09:41:27 +01:00
b5ef937a03 Environment file path is absolute
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-09 09:39:57 +01:00
e95a8b6e18 Add normalized name to services
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-03 18:42:51 +01:00
635adf1360 Use cas server to use authentication in other services
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-03-03 18:13:33 +01:00
177 changed files with 3605 additions and 1284 deletions

View File

@ -10,7 +10,6 @@ DJANGO_SECRET_KEY=CHANGE_ME
DJANGO_SETTINGS_MODULE=note_kfet.settings DJANGO_SETTINGS_MODULE=note_kfet.settings
CONTACT_EMAIL=tresorerie.bde@localhost CONTACT_EMAIL=tresorerie.bde@localhost
NOTE_URL=localhost NOTE_URL=localhost
DOMAIN=localhost
# Config for mails. Only used in production # Config for mails. Only used in production
NOTE_MAIL=notekfet@localhost NOTE_MAIL=notekfet@localhost

View File

@ -279,7 +279,8 @@ Le cahier des charges initial est disponible [sur le Wiki Crans](https://wiki.cr
La documentation des classes et fonctions est directement dans le code et est explorable à partir de la partie documentation de l'interface d'administration de Django. La documentation des classes et fonctions est directement dans le code et est explorable à partir de la partie documentation de l'interface d'administration de Django.
**Commentez votre code !** **Commentez votre code !**
La documentation plus haut niveau sur le développement est disponible sur [le Wiki associé au dépôt Git](https://gitlab.crans.org/bde/nk20/-/wikis/home). La documentation plus haut niveau sur le développement et sur l'utilisation
est disponible sur <https://note.crans.org/doc> et également dans le dossier `docs`.
## FAQ ## FAQ

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'activity.apps.ActivityConfig' default_app_config = 'activity.apps.ActivityConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib import admin from django.contrib import admin

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework import serializers from rest_framework import serializers

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import ActivityTypeViewSet, ActivityViewSet, EntryViewSet, GuestViewSet from .views import ActivityTypeViewSet, ActivityViewSet, EntryViewSet, GuestViewSet

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from api.viewsets import ReadProtectedModelViewSet from api.viewsets import ReadProtectedModelViewSet

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta from datetime import timedelta

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import os import os

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.utils import timezone from django.utils import timezone
from django.utils.html import format_html from django.utils.html import format_html

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta from datetime import timedelta

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path from django.urls import path

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from hashlib import md5 from hashlib import md5

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'api.apps.APIConfig' default_app_config = 'api.apps.APIConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

View File

@ -1,13 +1,17 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework.serializers import ModelSerializer from django.utils import timezone
from rest_framework import serializers
from member.api.serializers import ProfileSerializer, MembershipSerializer
from note.api.serializers import NoteSerializer
from note.models import Alias
class UserSerializer(ModelSerializer): class UserSerializer(serializers.ModelSerializer):
""" """
REST API Serializer for Users. REST API Serializer for Users.
The djangorestframework plugin will analyse the model `User` and parse all fields in the API. The djangorestframework plugin will analyse the model `User` and parse all fields in the API.
@ -22,7 +26,7 @@ class UserSerializer(ModelSerializer):
) )
class ContentTypeSerializer(ModelSerializer): class ContentTypeSerializer(serializers.ModelSerializer):
""" """
REST API Serializer for Users. REST API Serializer for Users.
The djangorestframework plugin will analyse the model `User` and parse all fields in the API. The djangorestframework plugin will analyse the model `User` and parse all fields in the API.
@ -31,3 +35,42 @@ class ContentTypeSerializer(ModelSerializer):
class Meta: class Meta:
model = ContentType model = ContentType
fields = '__all__' fields = '__all__'
class OAuthSerializer(serializers.ModelSerializer):
"""
Informations that are transmitted by OAuth.
For now, this includes user, profile and valid memberships.
This should be better managed later.
"""
normalized_name = serializers.SerializerMethodField()
profile = ProfileSerializer()
note = NoteSerializer()
memberships = serializers.SerializerMethodField()
def get_normalized_name(self, obj):
return Alias.normalize(obj.username)
def get_memberships(self, obj):
return serializers.ListSerializer(child=MembershipSerializer()).to_representation(
obj.memberships.filter(date_start__lte=timezone.now(), date_end__gte=timezone.now()))
class Meta:
model = User
fields = (
'id',
'username',
'normalized_name',
'first_name',
'last_name',
'email',
'is_superuser',
'is_active',
'is_staff',
'profile',
'note',
'memberships',
)

View File

@ -1,8 +1,9 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import json import json
from datetime import datetime, date from datetime import datetime, date
from decimal import Decimal
from urllib.parse import quote_plus from urllib.parse import quote_plus
from warnings import warn from warnings import warn
@ -152,6 +153,8 @@ class TestAPI(TestCase):
value = value.isoformat() value = value.isoformat()
elif isinstance(value, ImageFieldFile): elif isinstance(value, ImageFieldFile):
value = value.name value = value.name
elif isinstance(value, Decimal):
value = str(value)
query = json.dumps({field.name: value}) query = json.dumps({field.name: value})
# Create sample permission # Create sample permission

View File

@ -1,10 +1,11 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings
from django.conf.urls import url, include from django.conf.urls import url, include
from rest_framework import routers from rest_framework import routers
from .views import UserInformationView
from .viewsets import ContentTypeViewSet, UserViewSet from .viewsets import ContentTypeViewSet, UserViewSet
# Routers provide an easy way of automatically determining the URL conf. # Routers provide an easy way of automatically determining the URL conf.
@ -47,5 +48,6 @@ app_name = 'api'
# Additionally, we include login URLs for the browsable API. # Additionally, we include login URLs for the browsable API.
urlpatterns = [ urlpatterns = [
url('^', include(router.urls)), url('^', include(router.urls)),
url('^me/', UserInformationView.as_view()),
url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
] ]

20
apps/api/views.py Normal file
View File

@ -0,0 +1,20 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.auth.models import User
from rest_framework.generics import RetrieveAPIView
from .serializers import OAuthSerializer
class UserInformationView(RetrieveAPIView):
"""
These fields are give to OAuth authenticators.
"""
serializer_class = OAuthSerializer
def get_queryset(self):
return User.objects.filter(pk=self.request.user.pk)
def get_object(self):
return self.request.user

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'logs.apps.LogsConfig' default_app_config = 'logs.apps.LogsConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework import serializers from rest_framework import serializers

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import ChangelogViewSet from .views import ChangelogViewSet

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'member.apps.MemberConfig' default_app_config = 'member.apps.MemberConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib import admin from django.contrib import admin

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework import serializers from rest_framework import serializers

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import ProfileViewSet, ClubViewSet, MembershipViewSet from .views import ProfileViewSet, ClubViewSet, MembershipViewSet

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

17
apps/member/auth.py Normal file
View File

@ -0,0 +1,17 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from cas_server.auth import DjangoAuthUser # pragma: no cover
from note.models import Alias
class CustomAuthUser(DjangoAuthUser): # pragma: no cover
"""
Override Django Auth User model to define a custom Matrix username.
"""
def attributs(self):
d = super().attributs()
if self.user:
d["normalized_name"] = Alias.normalize(self.user.username)
return d

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import io import io

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import hashlib import hashlib

View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.19 on 2021-03-13 11:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('member', '0006_create_note_account_bde_membership'),
]
operations = [
migrations.AlterField(
model_name='membership',
name='roles',
field=models.ManyToManyField(related_name='memberships', to='permission.Role', verbose_name='roles'),
),
migrations.AlterField(
model_name='profile',
name='promotion',
field=models.PositiveSmallIntegerField(default=2021, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion'),
),
]

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import datetime import datetime

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date from datetime import date

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date from datetime import date

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import hashlib import hashlib

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path from django.urls import path

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta, date from datetime import timedelta, date
@ -625,9 +625,6 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
# Retrieve form data # Retrieve form data
credit_type = form.cleaned_data["credit_type"] credit_type = form.cleaned_data["credit_type"]
credit_amount = form.cleaned_data["credit_amount"] credit_amount = form.cleaned_data["credit_amount"]
last_name = form.cleaned_data["last_name"]
first_name = form.cleaned_data["first_name"]
bank = form.cleaned_data["bank"]
soge = form.cleaned_data["soge"] and not user.profile.soge and (club.name == "BDE" or club.name == "Kfet") soge = form.cleaned_data["soge"] and not user.profile.soge and (club.name == "BDE" or club.name == "Kfet")
if not credit_type: if not credit_type:
@ -658,8 +655,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
if club.name != "Kfet" and club.parent_club and not Membership.objects.filter( if club.name != "Kfet" and club.parent_club and not Membership.objects.filter(
user=form.instance.user, user=form.instance.user,
club=club.parent_club, club=club.parent_club,
date_start__lte=timezone.now(), date_start__gte=club.parent_club.membership_start,
date_end__gte=club.parent_club.membership_end,
).exists(): ).exists():
form.add_error('user', _('User is not a member of the parent club') + ' ' + club.parent_club.name) form.add_error('user', _('User is not a member of the parent club') + ' ' + club.parent_club.name)
error = True error = True
@ -674,17 +670,9 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
.format(form.instance.club.membership_end)) .format(form.instance.club.membership_end))
error = True error = True
if credit_amount: if credit_amount and not SpecialTransaction.validate_payment_form(form):
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"): # Check that special information for payment are filled
if not last_name: error = True
form.add_error('last_name', _("This field is required."))
error = True
if not first_name:
form.add_error('first_name', _("This field is required."))
error = True
if not bank and credit_type.special_type == "Chèque":
form.add_error('bank', _("This field is required."))
error = True
return not error return not error
@ -746,6 +734,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
# When we renew the BDE membership, we update the profile section # When we renew the BDE membership, we update the profile section
# that should happens at least once a year. # that should happens at least once a year.
user.profile.section = user.profile.section_generated user.profile.section = user.profile.section_generated
user.profile._force_save = True
user.profile.save() user.profile.save()
# Credit note before the membership is created. # Credit note before the membership is created.

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'note.apps.NoteConfig' default_app_config = 'note.apps.NoteConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib import admin from django.contrib import admin

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import NotePolymorphicViewSet, AliasViewSet, ConsumerViewSet, \ from .views import NotePolymorphicViewSet, AliasViewSet, ConsumerViewSet, \

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings
@ -74,7 +74,7 @@ class AliasViewSet(ReadProtectedModelViewSet):
serializer_class = self.serializer_class serializer_class = self.serializer_class
if self.request.method in ['PUT', 'PATCH']: if self.request.method in ['PUT', 'PATCH']:
# alias owner cannot be change once establish # alias owner cannot be change once establish
setattr(serializer_class.Meta, 'read_only_fields', ('note',)) serializer_class.Meta.read_only_fields = ('note',)
return serializer_class return serializer_class
def destroy(self, request, *args, **kwargs): def destroy(self, request, *args, **kwargs):
@ -82,7 +82,7 @@ class AliasViewSet(ReadProtectedModelViewSet):
try: try:
self.perform_destroy(instance) self.perform_destroy(instance)
except ValidationError as e: except ValidationError as e:
return Response({e.code: e.message}, status.HTTP_400_BAD_REQUEST) return Response({e.code: str(e)}, status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
def get_queryset(self): def get_queryset(self):

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import datetime from datetime import datetime

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.19 on 2021-03-13 11:35
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('note', '0004_remove_null_tag_on_charfields'),
]
operations = [
migrations.AlterField(
model_name='alias',
name='note',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='alias', to='note.Note'),
),
]

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .notes import Alias, Note, NoteClub, NoteSpecial, NoteUser from .notes import Alias, Note, NoteClub, NoteSpecial, NoteUser

View File

@ -1,10 +1,9 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import unicodedata import unicodedata
from django.conf import settings from django.conf import settings
from django.conf.global_settings import DEFAULT_FROM_EMAIL
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.mail import send_mail from django.core.mail import send_mail
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
@ -190,8 +189,8 @@ class NoteClub(Note):
def send_mail_negative_balance(self): def send_mail_negative_balance(self):
plain_text = render_to_string("note/mails/negative_balance.txt", dict(note=self)) plain_text = render_to_string("note/mails/negative_balance.txt", dict(note=self))
html = render_to_string("note/mails/negative_balance.html", dict(note=self)) html = render_to_string("note/mails/negative_balance.html", dict(note=self))
send_mail("[Note Kfet] Passage en négatif (club {})".format(self.club.name), plain_text, DEFAULT_FROM_EMAIL, send_mail("[Note Kfet] Passage en négatif (club {})".format(self.club.name), plain_text,
[self.club.email], html_message=html) settings.DEFAULT_FROM_EMAIL, [self.club.email], html_message=html)
class NoteSpecial(Note): class NoteSpecial(Note):

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -333,6 +333,36 @@ class SpecialTransaction(Transaction):
self.clean() self.clean()
super().save(*args, **kwargs) super().save(*args, **kwargs)
@staticmethod
def validate_payment_form(form):
"""
Ensure that last name and first name are filled for a form that creates a SpecialTransaction,
and check that if the user pays with a check, then the bank field is filled.
Return True iff there is no error.
Whenever there is an error, they are inserted in the form errors.
"""
credit_type = form.cleaned_data["credit_type"]
last_name = form.cleaned_data["last_name"]
first_name = form.cleaned_data["first_name"]
bank = form.cleaned_data["bank"]
error = False
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"):
if not last_name:
form.add_error('last_name', _("This field is required."))
error = True
if not first_name:
form.add_error('first_name', _("This field is required."))
error = True
if not bank and credit_type.special_type == "Chèque":
form.add_error('bank', _("This field is required."))
error = True
return not error
class Meta: class Meta:
verbose_name = _("Special transaction") verbose_name = _("Special transaction")
verbose_name_plural = _("Special transactions") verbose_name_plural = _("Special transactions")

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.utils import timezone from django.utils import timezone

View File

@ -1,4 +1,4 @@
// Copyright (C) 2018-2020 by BDE ENS Paris-Saclay // Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// When a transaction is performed, lock the interface to prevent spam clicks. // When a transaction is performed, lock the interface to prevent spam clicks.
@ -28,7 +28,7 @@ $(document).ready(function () {
// Switching in double consumptions mode should update the layout // Switching in double consumptions mode should update the layout
$('#double_conso').change(function () { $('#double_conso').change(function () {
$('#consos_list_div').removeClass('d-none') document.getElementById('consos_list_div').classList.remove('d-none')
$('#infos_div').attr('class', 'col-sm-5 col-xl-6') $('#infos_div').attr('class', 'col-sm-5 col-xl-6')
const note_list_obj = $('#note_list') const note_list_obj = $('#note_list')
@ -37,7 +37,7 @@ $(document).ready(function () {
note_list_obj.html('') note_list_obj.html('')
buttons.forEach(function (button) { buttons.forEach(function (button) {
$('#conso_button_' + button.id).click(function () { document.getElementById(`conso_button_${button.id}`).addEventListener('click', () => {
if (LOCK) { return } if (LOCK) { return }
removeNote(button, 'conso_button', buttons, 'consos_list')() removeNote(button, 'conso_button', buttons, 'consos_list')()
}) })
@ -46,7 +46,7 @@ $(document).ready(function () {
}) })
$('#single_conso').change(function () { $('#single_conso').change(function () {
$('#consos_list_div').addClass('d-none') document.getElementById('consos_list_div').classList.add('d-none')
$('#infos_div').attr('class', 'col-sm-5 col-md-4') $('#infos_div').attr('class', 'col-sm-5 col-md-4')
const consos_list_obj = $('#consos_list') const consos_list_obj = $('#consos_list')
@ -68,9 +68,9 @@ $(document).ready(function () {
}) })
// Ensure we begin in single consumption. Fix issue with TurboLinks and BootstrapJS // Ensure we begin in single consumption. Fix issue with TurboLinks and BootstrapJS
$("label[for='double_conso']").removeClass('active') document.querySelector("label[for='double_conso']").classList.remove('active')
$('#consume_all').click(consumeAll) document.getElementById("consume_all").addEventListener('click', consumeAll)
}) })
notes = [] notes = []
@ -127,11 +127,10 @@ function addConso (dest, amount, type, category_id, category_name, template_id,
html += li('conso_button_' + button.id, button.name + html += li('conso_button_' + button.id, button.name +
'<span class="badge badge-dark badge-pill">' + button.quantity + '</span>') '<span class="badge badge-dark badge-pill">' + button.quantity + '</span>')
}) })
document.getElementById(list).innerHTML = html
$('#' + list).html(html) buttons.forEach((button) => {
document.getElementById(`conso_button_${button.id}`).addEventListener('click', () => {
buttons.forEach(function (button) {
$('#conso_button_' + button.id).click(function () {
if (LOCK) { return } if (LOCK) { return }
removeNote(button, 'conso_button', buttons, list)() removeNote(button, 'conso_button', buttons, list)()
}) })
@ -146,12 +145,13 @@ function reset () {
notes_display.length = 0 notes_display.length = 0
notes.length = 0 notes.length = 0
buttons.length = 0 buttons.length = 0
$('#note_list').html('') document.getElementById('note_list').innerHTML = ''
$('#consos_list').html('') document.getElementById('consos_list').innerHTML = ''
$('#note').val('') document.getElementById('note').value = ''
$('#note').attr('data-original-title', '').tooltip('hide') document.getElementById('note').dataset.originTitle = ''
$('#profile_pic').attr('src', '/static/member/img/default_picture.png') $('#note').tooltip('hide')
$('#profile_pic_link').attr('href', '#') document.getElementById('profile_pic').src = '/static/member/img/default_picture.png'
document.getElementById('profile_pic_link').href = '#'
refreshHistory() refreshHistory()
refreshBalance() refreshBalance()
LOCK = false LOCK = false
@ -168,7 +168,7 @@ function consumeAll () {
let error = false let error = false
if (notes_display.length === 0) { if (notes_display.length === 0) {
$('#note').addClass('is-invalid') document.getElementById('note').classList.add('is-invalid')
$('#note_list').html(li('', '<strong>Ajoutez des émetteurs.</strong>', 'text-danger')) $('#note_list').html(li('', '<strong>Ajoutez des émetteurs.</strong>', 'text-danger'))
error = true error = true
} }

View File

@ -243,7 +243,7 @@ $('#btn_transfer').click(function () {
error = true error = true
} }
const amount = Math.floor(100 * amount_field.val()) const amount = Math.round(100 * amount_field.val())
if (amount > 2147483647) { if (amount > 2147483647) {
amount_field.addClass('is-invalid') amount_field.addClass('is-invalid')
$('#amount-required').html('<strong>' + gettext('The amount must stay under 21,474,836.47 €.') + '</strong>') $('#amount-required').html('<strong>' + gettext('The amount must stay under 21,474,836.47 €.') + '</strong>')

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import html import html

View File

@ -57,7 +57,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<ul class="list-group list-group-flush" id="source_note_list"> <ul class="list-group list-group-flush" id="source_note_list">
</ul> </ul>
<div class="card-body"> <div class="card-body">
<select id="credit_type" class="custom-select d-none"> <select id="credit_type" class="form-control custom-select d-none">
{% for special_type in special_types %} {% for special_type in special_types %}
<option value="{{ special_type.id }}">{{ special_type.special_type }}</option> <option value="{{ special_type.id }}">{{ special_type.special_type }}</option>
{% endfor %} {% endfor %}
@ -84,7 +84,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<ul class="list-group list-group-flush" id="dest_note_list"> <ul class="list-group list-group-flush" id="dest_note_list">
</ul> </ul>
<div class="card-body"> <div class="card-body">
<select id="debit_type" class="custom-select d-none"> <select id="debit_type" class="form-control custom-select d-none">
{% for special_type in special_types %} {% for special_type in special_types %}
<option value="{{ special_type.id }}">{{ special_type.special_type }}</option> <option value="{{ special_type.id }}">{{ special_type.special_type }}</option>
{% endfor %} {% endfor %}

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django import template from django import template

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django import template from django import template

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from api.tests import TestAPI from api.tests import TestAPI

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path from django.urls import path

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import json import json

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'permission.apps.PermissionConfig' default_app_config = 'permission.apps.PermissionConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-lateré # SPDX-License-Identifier: GPL-3.0-or-lateré
from django.contrib import admin from django.contrib import admin

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework import serializers from rest_framework import serializers

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import PermissionViewSet, RoleViewSet from .views import PermissionViewSet, RoleViewSet

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from api.viewsets import ReadOnlyProtectedModelViewSet from api.viewsets import ReadOnlyProtectedModelViewSet

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date from datetime import date
@ -134,8 +134,6 @@ class PermissionBackend(ModelBackend):
return False return False
sess = get_current_session() sess = get_current_session()
if sess is not None and sess.session_key is None:
return False
if user_obj.is_superuser and sess.get("permission_mask", -1) >= 42: if user_obj.is_superuser and sess.get("permission_mask", -1) >= 42:
return True return True

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import sys import sys
from functools import lru_cache from functools import lru_cache

View File

@ -1235,7 +1235,7 @@
"type": "view", "type": "view",
"mask": 1, "mask": 1,
"field": "", "field": "",
"permanent": false, "permanent": true,
"description": "Voir le dernier WEI" "description": "Voir le dernier WEI"
} }
}, },
@ -1267,7 +1267,7 @@
"type": "add", "type": "add",
"mask": 1, "mask": 1,
"field": "", "field": "",
"permanent": false, "permanent": true,
"description": "M'inscrire au dernier WEI" "description": "M'inscrire au dernier WEI"
} }
}, },
@ -1331,7 +1331,7 @@
"type": "view", "type": "view",
"mask": 1, "mask": 1,
"field": "", "field": "",
"permanent": false, "permanent": true,
"description": "Voir ma propre inscription WEI" "description": "Voir ma propre inscription WEI"
} }
}, },
@ -1379,7 +1379,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "soge_credit", "field": "soge_credit",
"permanent": false, "permanent": true,
"description": "Indiquer si mon inscription WEI est payée par la Société générale tant qu'elle n'est pas validée" "description": "Indiquer si mon inscription WEI est payée par la Société générale tant qu'elle n'est pas validée"
} }
}, },
@ -1427,7 +1427,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "birth_date", "field": "birth_date",
"permanent": false, "permanent": true,
"description": "Modifier la date de naissance de ma propre inscription WEI" "description": "Modifier la date de naissance de ma propre inscription WEI"
} }
}, },
@ -1459,7 +1459,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "gender", "field": "gender",
"permanent": false, "permanent": true,
"description": "Modifier le genre de ma propre inscription WEI" "description": "Modifier le genre de ma propre inscription WEI"
} }
}, },
@ -1491,7 +1491,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "health_issues", "field": "health_issues",
"permanent": false, "permanent": true,
"description": "Modifier mes problèmes de santé de mon inscription WEI" "description": "Modifier mes problèmes de santé de mon inscription WEI"
} }
}, },
@ -1523,7 +1523,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "emergency_contact_name", "field": "emergency_contact_name",
"permanent": false, "permanent": true,
"description": "Modifier le nom du contact en cas d'urgence de mon inscription WEI" "description": "Modifier le nom du contact en cas d'urgence de mon inscription WEI"
} }
}, },
@ -1555,7 +1555,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "emergency_contact_phone", "field": "emergency_contact_phone",
"permanent": false, "permanent": true,
"description": "Modifier le téléphone du contact en cas d'urgence de mon inscription WEI" "description": "Modifier le téléphone du contact en cas d'urgence de mon inscription WEI"
} }
}, },
@ -1699,7 +1699,7 @@
"type": "add", "type": "add",
"mask": 3, "mask": 3,
"field": "", "field": "",
"permanent": false, "permanent": true,
"description": "Créer une adhésion WEI pour le dernier WEI" "description": "Créer une adhésion WEI pour le dernier WEI"
} }
}, },
@ -2003,7 +2003,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "clothing_cut", "field": "clothing_cut",
"permanent": false, "permanent": true,
"description": "Modifier ma coupe de vêtements de mon inscription WEI" "description": "Modifier ma coupe de vêtements de mon inscription WEI"
} }
}, },
@ -2035,7 +2035,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "clothing_size", "field": "clothing_size",
"permanent": false, "permanent": true,
"description": "Modifier la taille de vêtements de mon inscription WEI" "description": "Modifier la taille de vêtements de mon inscription WEI"
} }
}, },
@ -2243,7 +2243,7 @@
"type": "change", "type": "change",
"mask": 1, "mask": 1,
"field": "information_json", "field": "information_json",
"permanent": false, "permanent": true,
"description": "Modifier mes préférences en terme de bus et d'équipe si mon inscription n'est pas validée et que je suis en 2A+" "description": "Modifier mes préférences en terme de bus et d'équipe si mon inscription n'est pas validée et que je suis en 2A+"
} }
}, },
@ -3495,7 +3495,7 @@
"model": "permission.role", "model": "permission.role",
"pk": 20, "pk": 20,
"fields": { "fields": {
"for_club": 2, "for_club": 1,
"name": "PC Kfet", "name": "PC Kfet",
"permissions": [ "permissions": [
6, 6,
@ -3511,6 +3511,7 @@
56, 56,
57, 57,
58, 58,
135,
137, 137,
143, 143,
147, 147,
@ -3521,8 +3522,7 @@
176, 176,
177, 177,
180, 180,
181, 181
182
] ]
} }
}, },

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import functools import functools

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework.permissions import DjangoObjectPermissions from rest_framework.permissions import DjangoObjectPermissions

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import django_tables2 as tables import django_tables2 as tables

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta, date from datetime import timedelta, date

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date from datetime import date

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.auth.models import User from django.contrib.auth.models import User

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path from django.urls import path

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date from datetime import date

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'registration.apps.RegistrationConfig' default_app_config = 'registration.apps.RegistrationConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig from django.apps import AppConfig

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django import forms from django import forms
@ -101,14 +101,14 @@ class ValidationForm(forms.Form):
required=False, required=False,
) )
join_BDE = forms.BooleanField( join_bde = forms.BooleanField(
label=_("Join BDE Club"), label=_("Join BDE Club"),
required=False, required=False,
initial=True, initial=True,
) )
# The user can join the Kfet club at the inscription # The user can join the Kfet club at the inscription
join_Kfet = forms.BooleanField( join_kfet = forms.BooleanField(
label=_("Join Kfet Club"), label=_("Join Kfet Club"),
required=False, required=False,
initial=True, initial=True,

View File

@ -1,9 +1,8 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import django_tables2 as tables import django_tables2 as tables
from django.contrib.auth.models import User from django.contrib.auth.models import User
from treasury.models import SogeCredit from treasury.models import SogeCredit

View File

@ -100,13 +100,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
bank.attr('disabled', true); bank.attr('disabled', true);
bank.val('Société générale'); bank.val('Société générale');
let join_BDE = $("#id_join_BDE"); let join_bde = $("#id_join_bde");
join_BDE.attr('disabled', true);
join_BDE.attr('checked', 'checked');
let join_Kfet = $("#id_join_Kfet"); join_bde.attr('disabled', true);
join_Kfet.attr('disabled', true); join_bde.attr('checked', 'checked');
join_Kfet.attr('checked', 'checked');
let join_kfet = $("#id_join_kfet");
join_kfet.attr('disabled', true);
join_kfet.attr('checked', 'checked');
} }
soge_field.change(fillFields); soge_field.change(fillFields);
@ -116,4 +117,4 @@ SPDX-License-Identifier: GPL-3.0-or-later
fillFields(); fillFields();
{% endif %} {% endif %}
</script> </script>
{% endblock %} {% endblock %}

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -196,8 +196,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
join_BDE=False, join_bde=False,
join_Kfet=False, join_kfet=False,
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTrue(response.context["form"].errors) self.assertTrue(response.context["form"].errors)
@ -210,8 +210,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
join_BDE=False, join_bde=False,
join_Kfet=True, join_kfet=True,
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTrue(response.context["form"].errors) self.assertTrue(response.context["form"].errors)
@ -224,8 +224,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="J'ai pas d'argent", bank="J'ai pas d'argent",
join_BDE=True, join_bde=True,
join_Kfet=True, join_kfet=True,
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTrue(response.context["form"].errors) self.assertTrue(response.context["form"].errors)
@ -238,8 +238,8 @@ class TestValidateRegistration(TestCase):
last_name="", last_name="",
first_name="", first_name="",
bank="", bank="",
join_BDE=True, join_bde=True,
join_Kfet=True, join_kfet=True,
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTrue(response.context["form"].errors) self.assertTrue(response.context["form"].errors)
@ -255,8 +255,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
join_BDE=True, join_bde=True,
join_Kfet=False, join_kfet=False,
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTrue(response.context["form"].errors) self.assertTrue(response.context["form"].errors)
@ -281,8 +281,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
join_BDE=True, join_bde=True,
join_Kfet=False, join_kfet=False,
)) ))
self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200) self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
self.user.profile.refresh_from_db() self.user.profile.refresh_from_db()
@ -317,8 +317,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
join_BDE=True, join_bde=True,
join_Kfet=True, join_kfet=True,
)) ))
self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200) self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
self.user.profile.refresh_from_db() self.user.profile.refresh_from_db()
@ -353,8 +353,8 @@ class TestValidateRegistration(TestCase):
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
join_BDE=True, join_bde=True,
join_Kfet=True, join_kfet=True,
)) ))
self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200) self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
self.user.profile.refresh_from_db() self.user.profile.refresh_from_db()

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# Copied from https://gitlab.crans.org/bombar/codeflix/-/blob/master/codeflix/codeflix/tokens.py # Copied from https://gitlab.crans.org/bombar/codeflix/-/blob/master/codeflix/codeflix/tokens.py
@ -9,6 +9,7 @@ class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
""" """
Create a unique token generator to confirm email addresses. Create a unique token generator to confirm email addresses.
""" """
def _make_hash_value(self, user, timestamp): def _make_hash_value(self, user, timestamp):
""" """
Hash the user's primary key and some user state that's sure to change Hash the user's primary key and some user state that's sure to change
@ -23,9 +24,18 @@ class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
""" """
# Truncate microseconds so that tokens are consistent even if the # Truncate microseconds so that tokens are consistent even if the
# database doesn't support microseconds. # database doesn't support microseconds.
login_timestamp = '' if user.last_login is None else user.last_login.replace(microsecond=0, tzinfo=None) login_timestamp = (
return str(user.pk) + str(user.email) + str(user.profile.email_confirmed)\ ""
+ str(login_timestamp) + str(timestamp) if user.last_login is None
else user.last_login.replace(microsecond=0, tzinfo=None)
)
return (
str(user.pk)
+ str(user.email)
+ str(user.profile.email_confirmed)
+ str(login_timestamp)
+ str(timestamp)
)
email_validation_token = AccountActivationTokenGenerator() email_validation_token = AccountActivationTokenGenerator()

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path from django.urls import path

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings
@ -248,9 +248,13 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
@transaction.atomic @transaction.atomic
def form_valid(self, form): def form_valid(self, form):
"""
Finally validate the registration, with creating the membership.
"""
user = self.get_object() user = self.get_object()
if Alias.objects.filter(normalized_name=Alias.normalize(user.username)).exists(): if Alias.objects.filter(normalized_name=Alias.normalize(user.username)).exists():
# Don't try to hack an existing account.
form.add_error(None, _("An alias with a similar name already exists.")) form.add_error(None, _("An alias with a similar name already exists."))
return self.form_invalid(form) return self.form_invalid(form)
@ -261,35 +265,36 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
last_name = form.cleaned_data["last_name"] last_name = form.cleaned_data["last_name"]
first_name = form.cleaned_data["first_name"] first_name = form.cleaned_data["first_name"]
bank = form.cleaned_data["bank"] bank = form.cleaned_data["bank"]
join_BDE = form.cleaned_data["join_BDE"] join_bde = form.cleaned_data["join_bde"]
join_Kfet = form.cleaned_data["join_Kfet"] join_kfet = form.cleaned_data["join_kfet"]
if soge: if soge:
# If Société Générale pays the inscription, the user joins the two clubs # If Société Générale pays the inscription, the user automatically joins the two clubs.
join_BDE = True join_bde = True
join_Kfet = True join_kfet = True
if not join_BDE: if not join_bde:
form.add_error('join_BDE', _("You must join the BDE.")) # This software belongs to the BDE.
form.add_error('join_bde', _("You must join the BDE."))
return super().form_invalid(form) return super().form_invalid(form)
# Calculate required registration fee
fee = 0 fee = 0
bde = Club.objects.get(name="BDE") bde = Club.objects.get(name="BDE")
bde_fee = bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid bde_fee = bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid
if join_BDE: # This is mandatory.
fee += bde_fee fee += bde_fee if join_bde else 0
kfet = Club.objects.get(name="Kfet") kfet = Club.objects.get(name="Kfet")
kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid
if join_Kfet: # Add extra fee for the full membership
fee += kfet_fee fee += kfet_fee if join_kfet else 0
if soge: # If the bank pays, then we don't credit now. Treasurers will validate the transaction
# If the bank pays, then we don't credit now. Treasurers will validate the transaction # and credit the note later.
# and credit the note later. credit_type = None if soge else credit_type
credit_type = None
if credit_type is None: # If the user does not select any payment method, then no credit will be performed.
credit_amount = 0 credit_amount = 0 if credit_type is None else credit_amount
if fee > credit_amount and not soge: if fee > credit_amount and not soge:
# Check if the user credits enough money # Check if the user credits enough money
@ -298,15 +303,9 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
.format(pretty_money(fee))) .format(pretty_money(fee)))
return self.form_invalid(form) return self.form_invalid(form)
if credit_type is not None and credit_amount > 0: # Check that payment information are filled, like last name and first name
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"): if credit_type is not None and credit_amount > 0 and not SpecialTransaction.validate_payment_form(form):
if not last_name: return self.form_invalid(form)
form.add_error('last_name', _("This field is required."))
if not first_name:
form.add_error('first_name', _("This field is required."))
if not bank and credit_type.special_type == "Chèque":
form.add_error('bank', _("This field is required."))
return self.form_invalid(form)
# Save the user and finally validate the registration # Save the user and finally validate the registration
# Saving the user creates the associated note # Saving the user creates the associated note
@ -338,7 +337,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
valid=True, valid=True,
) )
if join_BDE: if join_bde:
# Create membership for the user to the BDE starting today # Create membership for the user to the BDE starting today
membership = Membership( membership = Membership(
club=bde, club=bde,
@ -352,7 +351,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
membership.roles.add(Role.objects.get(name="Adhérent BDE")) membership.roles.add(Role.objects.get(name="Adhérent BDE"))
membership.save() membership.save()
if join_Kfet: if join_kfet:
# Create membership for the user to the Kfet starting today # Create membership for the user to the Kfet starting today
membership = Membership( membership = Membership(
club=kfet, club=kfet,

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
default_app_config = 'treasury.apps.TreasuryConfig' default_app_config = 'treasury.apps.TreasuryConfig'

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-lateré # SPDX-License-Identifier: GPL-3.0-or-lateré
from django.contrib import admin from django.contrib import admin

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework import serializers from rest_framework import serializers

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet, SogeCreditViewSet from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet, SogeCreditViewSet

Some files were not shown because too many files have changed in this diff Show More