Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BDE
nk20
Commits
1c5e951c
Commit
1c5e951c
authored
Oct 07, 2020
by
ynerant
Browse files
Merge branch 'beta' into 'master'
Various fixes See merge request
!133
parents
536f0ec2
beb1853a
Pipeline
#8780
passed with stages
in 11 minutes and 53 seconds
Changes
23
Pipelines
2
Expand all
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
1c5e951c
...
...
@@ -95,7 +95,7 @@ Sinon vous pouvez suivre les étapes décrites ci-dessous.
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 ipython3 \
python3-bs4 python3-setuptools \
python3-bs4 python3-setuptools
python3-docutils
\
memcached uwsgi uwsgi-plugin-python3 \
texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome \
nginx python3-venv git acl
...
...
apps/member/forms.py
View file @
1c5e951c
...
...
@@ -150,6 +150,7 @@ class ClubForm(forms.ModelForm):
"membership_fee_unpaid"
:
AmountInput
(),
"parent_club"
:
Autocomplete
(
Club
,
resetable
=
True
,
attrs
=
{
'api_url'
:
'/api/members/club/'
,
}
...
...
apps/member/migrations/0003_create_bde_and_kfet.py
View file @
1c5e951c
...
...
@@ -7,6 +7,7 @@ def create_bde_and_kfet(apps, schema_editor):
"""
Club
=
apps
.
get_model
(
"member"
,
"club"
)
NoteClub
=
apps
.
get_model
(
"note"
,
"noteclub"
)
Alias
=
apps
.
get_model
(
"note"
,
"alias"
)
ContentType
=
apps
.
get_model
(
'contenttypes'
,
'ContentType'
)
polymorphic_ctype_id
=
ContentType
.
objects
.
get_for_model
(
NoteClub
).
id
...
...
@@ -45,6 +46,19 @@ def create_bde_and_kfet(apps, schema_editor):
polymorphic_ctype_id
=
polymorphic_ctype_id
,
)
Alias
.
objects
.
get_or_create
(
id
=
5
,
note_id
=
5
,
name
=
"BDE"
,
normalized_name
=
"bde"
,
)
Alias
.
objects
.
get_or_create
(
id
=
6
,
note_id
=
6
,
name
=
"Kfet"
,
normalized_name
=
"kfet"
,
)
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
...
...
apps/member/templatetags/__init__.py
0 → 100644
View file @
1c5e951c
apps/member/templatetags/memberinfo.py
0 → 100644
View file @
1c5e951c
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from
datetime
import
date
from
django
import
template
from
django.contrib.auth.models
import
User
from
..models
import
Club
,
Membership
def
is_member
(
user
,
club
):
if
isinstance
(
user
,
str
):
club
=
User
.
objects
.
get
(
username
=
user
)
if
isinstance
(
club
,
str
):
club
=
Club
.
objects
.
get
(
name
=
club
)
return
Membership
.
objects
\
.
filter
(
user
=
user
,
club
=
club
,
date_start__lte
=
date
.
today
(),
date_end__gte
=
date
.
today
()).
exists
()
register
=
template
.
Library
()
register
.
filter
(
"is_member"
,
is_member
)
apps/member/tests/test_login.py
View file @
1c5e951c
...
...
@@ -41,7 +41,7 @@ class TemplateLoggedInTests(TestCase):
password
=
"adminadmin"
,
permission_mask
=
3
,
))
self
.
assertRedirects
(
response
,
settings
.
LOGIN_REDIRECT_URL
,
302
,
200
)
self
.
assertRedirects
(
response
,
settings
.
LOGIN_REDIRECT_URL
,
302
,
302
)
def
test_logout
(
self
):
response
=
self
.
client
.
get
(
reverse
(
"logout"
))
...
...
apps/member/views.py
View file @
1c5e951c
...
...
@@ -158,7 +158,11 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
context
[
'history_list'
]
=
history_table
club_list
=
Membership
.
objects
.
filter
(
user
=
user
,
date_end__gte
=
date
.
today
()
-
timedelta
(
days
=
15
))
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Membership
,
"view"
))
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Membership
,
"view"
))
\
.
order_by
(
"club__name"
,
"-date_start"
)
# Display only the most recent membership
club_list
=
club_list
.
distinct
(
"club__name"
)
\
if
settings
.
DATABASES
[
"default"
][
"ENGINE"
]
==
'django.db.backends.postgresql'
else
club_list
membership_table
=
MembershipTable
(
data
=
club_list
,
prefix
=
'membership-'
)
membership_table
.
paginate
(
per_page
=
10
,
page
=
self
.
request
.
GET
.
get
(
"membership-page"
,
1
))
context
[
'club_list'
]
=
membership_table
...
...
@@ -410,7 +414,11 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
club_member
=
Membership
.
objects
.
filter
(
club
=
club
,
date_end__gte
=
date
.
today
()
-
timedelta
(
days
=
15
),
).
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Membership
,
"view"
))
).
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Membership
,
"view"
))
\
.
order_by
(
"user__username"
,
"-date_start"
)
# Display only the most recent membership
club_member
=
club_member
.
distinct
(
"user__username"
)
\
if
settings
.
DATABASES
[
"default"
][
"ENGINE"
]
==
'django.db.backends.postgresql'
else
club_member
membership_table
=
MembershipTable
(
data
=
club_member
,
prefix
=
"membership-"
)
membership_table
.
paginate
(
per_page
=
5
,
page
=
self
.
request
.
GET
.
get
(
'membership-page'
,
1
))
...
...
apps/note/static/note/js/transfer.js
View file @
1c5e951c
...
...
@@ -67,7 +67,11 @@ $(document).ready(function () {
last
.
quantity
=
1
if
(
!
last
.
note
.
user
)
{
if
(
last
.
note
.
club
)
{
$
(
'
#last_name
'
).
val
(
last
.
note
.
name
)
$
(
'
#first_name
'
).
val
(
last
.
note
.
name
)
}
else
if
(
!
last
.
note
.
user
)
{
$
.
getJSON
(
'
/api/note/note/
'
+
last
.
note
.
id
+
'
/?format=json
'
,
function
(
note
)
{
last
.
note
.
user
=
note
.
user
$
.
getJSON
(
'
/api/user/
'
+
last
.
note
.
user
+
'
/
'
,
function
(
user
)
{
...
...
@@ -246,7 +250,7 @@ $('#btn_transfer').click(function () {
error
=
true
}
if
(
!
reason_field
.
val
())
{
if
(
!
reason_field
.
val
()
&&
$
(
'
#type_transfer
'
).
is
(
'
:checked
'
)
)
{
reason_field
.
addClass
(
'
is-invalid
'
)
$
(
'
#reason-required
'
).
html
(
'
<strong>Ce champ est requis.</strong>
'
)
error
=
true
...
...
apps/permission/fixtures/initial.json
View file @
1c5e951c
...
...
@@ -115,7 +115,7 @@
"type"
:
"view"
,
"mask"
:
1
,
"field"
:
""
,
"permanent"
:
tru
e
,
"permanent"
:
fals
e
,
"description"
:
"Voir les aliases des notes des clubs et des adhérents du club Kfet"
}
},
...
...
@@ -2791,6 +2791,22 @@
"description"
:
"Voir tous les alias, y compris ceux des non adhérents"
}
},
{
"model"
:
"permission.permission"
,
"pk"
:
179
,
"fields"
:
{
"model"
:
[
"note"
,
"alias"
],
"query"
:
"{
\"
note__noteuser__user
\"
: [
\"
user
\"
]}"
,
"type"
:
"view"
,
"mask"
:
1
,
"field"
:
""
,
"permanent"
:
true
,
"description"
:
"Voir ses propres alias, pour toujours"
}
},
{
"model"
:
"permission.role"
,
"pk"
:
1
,
...
...
@@ -2861,7 +2877,8 @@
157
,
158
,
159
,
160
160
,
179
]
}
},
...
...
@@ -2965,6 +2982,7 @@
31
,
32
,
33
,
51
,
53
,
54
,
55
,
...
...
apps/registration/forms.py
View file @
1c5e951c
...
...
@@ -44,6 +44,15 @@ class SignUpForm(UserCreationForm):
fields
=
(
'first_name'
,
'last_name'
,
'username'
,
'email'
,
)
class
DeclareSogeAccountOpenedForm
(
forms
.
Form
):
soge_account
=
forms
.
BooleanField
(
label
=
_
(
"I declare that I opened a bank account in the Société générale with the BDE partnership."
),
help_text
=
_
(
"Warning: this engages you to open your bank account. If you finally decides to don't open your "
"account, you will have to pay the BDE membership."
),
required
=
False
,
)
class
WEISignupForm
(
forms
.
Form
):
wei_registration
=
forms
.
BooleanField
(
label
=
_
(
"Register to the WEI"
),
...
...
apps/registration/templates/registration/future_profile_detail.html
View file @
1c5e951c
...
...
@@ -56,6 +56,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
<div
class=
"card-header text-center"
>
<h4>
{% trans "Validate account" %}
</h4>
</div>
{% if declare_soge_account %}
<div
class=
"alert alert-info"
>
{% trans "The user declared that he/she opened a bank account in the Société générale." %}
</div>
{% endif %}
<div
class=
"card-body"
id=
"profile_infos"
>
{% csrf_token %}
{{ form|crispy }}
...
...
@@ -104,7 +111,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
soge_field
.
change
(
fillFields
);
{
%
if
object
.
profile
.
soge
%
}
{
%
if
declare_soge_account
%
}
soge_field
.
attr
(
'
checked
'
,
true
);
fillFields
();
{
%
endif
%
}
...
...
apps/registration/views.py
View file @
1c5e951c
...
...
@@ -24,7 +24,7 @@ from permission.models import Role
from
permission.views
import
ProtectQuerysetMixin
from
treasury.models
import
SogeCredit
from
.forms
import
SignUpForm
,
ValidationForm
from
.forms
import
SignUpForm
,
ValidationForm
,
DeclareSogeAccountOpenedForm
from
.tables
import
FutureUserTable
from
.tokens
import
email_validation_token
...
...
@@ -42,6 +42,7 @@ class UserCreateView(CreateView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
context
[
"profile_form"
]
=
self
.
second_form
(
self
.
request
.
POST
if
self
.
request
.
POST
else
None
)
context
[
"soge_form"
]
=
DeclareSogeAccountOpenedForm
(
self
.
request
.
POST
if
self
.
request
.
POST
else
None
)
del
context
[
"profile_form"
].
fields
[
"section"
]
del
context
[
"profile_form"
].
fields
[
"report_frequency"
]
del
context
[
"profile_form"
].
fields
[
"last_report"
]
...
...
@@ -72,6 +73,13 @@ class UserCreateView(CreateView):
user
.
profile
.
send_email_validation_link
()
soge_form
=
DeclareSogeAccountOpenedForm
(
self
.
request
.
POST
)
if
"soge_account"
in
soge_form
.
data
and
soge_form
.
data
[
"soge_account"
]:
# If the user declares that a bank account got opened, prepare the soge credit to warn treasurers
soge_credit
=
SogeCredit
(
user
=
user
)
soge_credit
.
_force_save
=
True
soge_credit
.
save
()
return
super
().
form_valid
(
form
)
def
get_success_url
(
self
):
...
...
@@ -227,6 +235,8 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
fee
+=
8000
ctx
[
"total_fee"
]
=
"{:.02f}"
.
format
(
fee
/
100
,
)
ctx
[
"declare_soge_account"
]
=
True
return
ctx
def
get_form
(
self
,
form_class
=
None
):
...
...
@@ -307,6 +317,13 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
user
.
profile
.
save
()
user
.
refresh_from_db
()
if
not
soge
and
SogeCredit
.
objects
.
filter
(
user
=
user
).
exists
():
# If the user declared that a bank account was opened but in the validation form the SoGé case was
# unchecked, delete the associated credit
soge_credit
=
SogeCredit
.
objects
.
get
(
user
=
user
)
soge_credit
.
_force_delete
=
True
soge_credit
.
delete
()
if
credit_type
is
not
None
and
credit_amount
>
0
:
# Credit the note
SpecialTransaction
.
objects
.
create
(
...
...
@@ -373,6 +390,8 @@ class FutureUserInvalidateView(ProtectQuerysetMixin, LoginRequiredMixin, View):
user
=
User
.
objects
.
filter
(
profile__registration_valid
=
False
)
\
.
filter
(
PermissionBackend
.
filter_queryset
(
request
.
user
,
User
,
"change"
,
"is_valid"
))
\
.
get
(
pk
=
self
.
kwargs
[
"pk"
])
# Delete associated soge credits before
SogeCredit
.
objects
.
filter
(
user
=
user
).
delete
()
user
.
delete
()
...
...
apps/treasury/models.py
View file @
1c5e951c
...
...
@@ -10,7 +10,7 @@ from django.db.models import Q
from
django.template.loader
import
render_to_string
from
django.utils
import
timezone
from
django.utils.translation
import
gettext_lazy
as
_
from
note.models
import
NoteSpecial
,
SpecialTransaction
,
MembershipTransaction
from
note.models
import
NoteSpecial
,
SpecialTransaction
,
MembershipTransaction
,
NoteUser
class
Invoice
(
models
.
Model
):
...
...
@@ -335,6 +335,11 @@ class SogeCredit(models.Model):
@
transaction
.
atomic
def
save
(
self
,
*
args
,
**
kwargs
):
# This is a pre-registered user that declared that a SoGé account was opened.
# No note exists yet.
if
not
NoteUser
.
objects
.
filter
(
user
=
self
.
user
).
exists
():
return
super
().
save
(
*
args
,
**
kwargs
)
if
not
self
.
credit_transaction
:
credit_transaction
=
SpecialTransaction
(
source
=
NoteSpecial
.
objects
.
get
(
special_type
=
"Virement bancaire"
),
...
...
apps/treasury/templates/treasury/sogecredit_list.html
View file @
1c5e951c
...
...
@@ -60,7 +60,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
let
pattern
=
searchbar_obj
.
val
();
$
(
"
#credits_table
"
).
load
(
location
.
pathname
+
"
?search=
"
+
pattern
.
replace
(
"
"
,
"
%20
"
)
+
(
invalid_only_obj
.
is
(
'
:checked
'
)
?
"
&valid=
false
"
:
"
"
)
+
"
#credits_table
"
);
invalid_only_obj
.
is
(
'
:checked
'
)
?
""
:
"
&valid=
1
"
)
+
"
#credits_table
"
);
$
(
"
.table-row
"
).
click
(
function
()
{
window
.
document
.
location
=
$
(
this
).
data
(
"
href
"
);
...
...
apps/treasury/views.py
View file @
1c5e951c
...
...
@@ -431,7 +431,7 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
if
"valid"
not
in
self
.
request
.
GET
or
not
self
.
request
.
GET
[
"valid"
]:
qs
=
qs
.
filter
(
credit_transaction__valid
=
False
)
return
qs
[:
20
]
return
qs
class
SogeCreditManageView
(
LoginRequiredMixin
,
ProtectQuerysetMixin
,
BaseFormView
,
DetailView
):
...
...
locale/de/LC_MESSAGES/django.po
View file @
1c5e951c
This diff is collapsed.
Click to expand it.
locale/es/LC_MESSAGES/django.po
View file @
1c5e951c
This diff is collapsed.
Click to expand it.
locale/fr/LC_MESSAGES/django.po
View file @
1c5e951c
This diff is collapsed.
Click to expand it.
note_kfet/settings/base.py
View file @
1c5e951c
...
...
@@ -245,7 +245,7 @@ REST_FRAMEWORK = {
FORM_RENDERER
=
'django.forms.renderers.TemplatesSetting'
# After login redirect user to transfer page
LOGIN_REDIRECT_URL
=
'/
note/transfer/
'
LOGIN_REDIRECT_URL
=
'/'
# An user session will expired after 3 hours
SESSION_COOKIE_AGE
=
60
*
60
*
3
...
...
note_kfet/templates/base.html
View file @
1c5e951c
{% load static i18n pretty_money static getenv perms %}
{% load static i18n pretty_money static getenv perms
memberinfo
%}
{% comment %}
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
...
...
@@ -64,7 +64,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-coffee"
></i>
{% trans 'Consumptions' %}
</a>
</li>
{% endif %}
{% if
"note.transaction"|not_empty_model_list
%}
{% if
user.is_authenticated and user|is_member:"Kfet"
%}
<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>
...
...
@@ -150,12 +150,36 @@ SPDX-License-Identifier: GPL-3.0-or-later
</div>
</nav>
<div
class=
"{% block containertype %}container{% endblock %} my-3"
>
{% if request.user.is_authenticated and not request.user.profile.email_confirmed %}
<div
class=
"alert alert-warning"
>
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
</div>
{% endif %}
<div
id=
"messages"
></div>
<div
id=
"messages"
>
{% if user.is_authenticated %}
{% if not user|is_member:"BDE" %}
<div
class=
"alert alert-danger"
>
{% trans "You are not a BDE member anymore. Please renew your membership if you want to use the note." %}
</div>
{% elif not user|is_member:"Kfet" %}
<div
class=
"alert alert-warning"
>
{% trans "You are not a Kfet member, so you can't use your note account." %}
</div>
{% endif %}
{% if not user.profile.email_confirmed %}
<div
class=
"alert alert-warning"
>
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
</div>
{% endif %}
{% endif %}
{% if user.sogecredit and not user.sogecredit.valid %}
<div
class=
"alert alert-info"
>
{% blocktrans trimmed %}
You declared that you opened a bank account in the Société générale. The bank did not validate the creation of the account to the BDE,
so the registration bonus of 80 € is not credited and the membership is not paid yet.
This verification procedure may last a few days.
Please make sure that you go to the end of the account creation.
{% endblocktrans %}
</div>
{% endif %}
{# TODO Add banners #}
</div>
{% block content %}
<p>
Default content...
</p>
{% endblock %}
...
...
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment