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
thalia
concrexit
Commits
fa52caf6
Verified
Commit
fa52caf6
authored
Feb 04, 2018
by
Sébastiaan Versteeg
Browse files
Move statistics code to services, separate tests into multiple files and add display name tests
parent
eec023d7
Changes
6
Hide whitespace changes
Inline
Side-by-side
website/members/models.py
View file @
fa52caf6
import
operator
from
datetime
import
date
,
timedelta
import
os
from
datetime
import
timedelta
from
functools
import
reduce
from
PIL
import
Image
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
,
UserManager
from
django.core
import
validators
...
...
@@ -15,10 +17,6 @@ from localflavor.generic.countries.sepa import IBAN_SEPA_COUNTRIES
from
localflavor.generic.models
import
IBANField
from
activemembers.models
import
Committee
from
utils.snippets
import
datetime_to_lectureyear
from
PIL
import
Image
import
os
class
MemberManager
(
UserManager
):
...
...
@@ -362,7 +360,7 @@ class Profile(models.Model):
pref
=
self
.
display_name_preference
if
pref
==
'nickname'
and
self
.
nickname
is
not
None
:
return
self
.
nickname
if
pref
==
'firstname'
:
el
if
pref
==
'firstname'
:
return
self
.
user
.
first_name
elif
pref
==
'initials'
:
if
self
.
initials
:
...
...
@@ -372,7 +370,7 @@ class Profile(models.Model):
return
"{} '{}' {}"
.
format
(
self
.
user
.
first_name
,
self
.
nickname
,
self
.
user
.
last_name
)
elif
pref
==
'nicklast'
:
elif
pref
==
'nicklast'
and
self
.
nickname
is
not
None
:
return
"'{}' {}"
.
format
(
self
.
nickname
,
self
.
user
.
last_name
)
else
:
...
...
@@ -390,7 +388,6 @@ class Profile(models.Model):
return
self
.
user
.
last_name
else
:
return
self
.
user
.
first_name
return
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
().
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -510,56 +507,3 @@ class Membership(models.Model):
def
is_active
(
self
):
return
not
self
.
until
or
self
.
until
>
timezone
.
now
().
date
()
def
gen_stats_member_type
(
member_types
):
total
=
dict
()
for
member_type
in
member_types
:
total
[
member_type
]
=
(
Membership
.
objects
.
filter
(
since__lte
=
date
.
today
())
.
filter
(
Q
(
until__isnull
=
True
)
|
Q
(
until__gt
=
date
.
today
()))
.
filter
(
type
=
member_type
)
.
count
())
return
total
def
gen_stats_year
(
member_types
):
"""
Generate list with 6 entries, where each entry represents the total amount
of Thalia members in a year. The sixth element contains all the multi-year
students.
"""
stats_year
=
[]
current_year
=
datetime_to_lectureyear
(
date
.
today
())
for
i
in
range
(
5
):
new
=
dict
()
for
member_type
in
member_types
:
new
[
member_type
]
=
(
Membership
.
objects
.
filter
(
user__profile__starting_year
=
current_year
-
i
)
.
filter
(
since__lte
=
date
.
today
())
.
filter
(
Q
(
until__isnull
=
True
)
|
Q
(
until__gt
=
date
.
today
()))
.
filter
(
type
=
member_type
)
.
count
())
stats_year
.
append
(
new
)
# Add multi year members
new
=
dict
()
for
member_type
in
member_types
:
new
[
member_type
]
=
(
Membership
.
objects
.
filter
(
user__profile__starting_year__lt
=
current_year
-
4
)
.
filter
(
since__lte
=
date
.
today
())
.
filter
(
Q
(
until__isnull
=
True
)
|
Q
(
until__gt
=
date
.
today
()))
.
filter
(
type
=
member_type
)
.
count
())
stats_year
.
append
(
new
)
return
stats_year
website/members/services.py
View file @
fa52caf6
from
datetime
import
date
from
django.db.models
import
Q
from
members.models
import
Membership
from
utils.snippets
import
datetime_to_lectureyear
def
member_achievements
(
member
):
memberships
=
member
.
committeemembership_set
.
all
()
...
...
@@ -42,3 +47,54 @@ def member_achievements(member):
'earliest'
:
earliest
,
}
return
sorted
(
achievements
.
values
(),
key
=
lambda
x
:
x
[
'earliest'
])
def
gen_stats_member_type
(
member_types
):
total
=
dict
()
for
member_type
in
member_types
:
total
[
member_type
]
=
(
Membership
.
objects
.
filter
(
since__lte
=
date
.
today
())
.
filter
(
Q
(
until__isnull
=
True
)
|
Q
(
until__gt
=
date
.
today
()))
.
filter
(
type
=
member_type
)
.
count
())
return
total
def
gen_stats_year
(
member_types
):
"""
Generate list with 6 entries, where each entry represents the total amount
of Thalia members in a year. The sixth element contains all the multi-year
students.
"""
stats_year
=
[]
current_year
=
datetime_to_lectureyear
(
date
.
today
())
for
i
in
range
(
5
):
new
=
dict
()
for
member_type
in
member_types
:
new
[
member_type
]
=
(
Membership
.
objects
.
filter
(
user__profile__starting_year
=
current_year
-
i
)
.
filter
(
since__lte
=
date
.
today
())
.
filter
(
Q
(
until__isnull
=
True
)
|
Q
(
until__gt
=
date
.
today
()))
.
filter
(
type
=
member_type
)
.
count
())
stats_year
.
append
(
new
)
# Add multi year members
new
=
dict
()
for
member_type
in
member_types
:
new
[
member_type
]
=
(
Membership
.
objects
.
filter
(
user__profile__starting_year__lt
=
current_year
-
4
)
.
filter
(
since__lte
=
date
.
today
())
.
filter
(
Q
(
until__isnull
=
True
)
|
Q
(
until__gt
=
date
.
today
()))
.
filter
(
type
=
member_type
)
.
count
())
stats_year
.
append
(
new
)
return
stats_year
website/members/tests/__init__.py
0 → 100644
View file @
fa52caf6
website/members/tests/test_models.py
0 → 100644
View file @
fa52caf6
from
datetime
import
date
,
datetime
,
timedelta
from
django.test
import
TestCase
from
django.utils
import
timezone
from
members.models
import
(
Profile
,
Member
,
Membership
)
from
members.views
import
filter_users
class
MemberBirthdayTest
(
TestCase
):
fixtures
=
[
'members.json'
]
def
_make_date
(
self
,
date
):
return
timezone
.
make_aware
(
datetime
.
strptime
(
date
,
'%Y-%m-%d'
))
def
_get_members
(
self
,
start
,
end
):
start_date
=
self
.
_make_date
(
start
)
end_date
=
self
.
_make_date
(
end
)
return
Member
.
active_members
.
with_birthdays_in_range
(
start_date
,
end_date
)
def
_assert_none
(
self
,
start
,
end
):
members
=
self
.
_get_members
(
start
,
end
)
self
.
assertEqual
(
len
(
members
),
0
)
def
_assert_thom
(
self
,
start
,
end
):
members
=
self
.
_get_members
(
start
,
end
)
self
.
assertEqual
(
len
(
members
),
1
)
self
.
assertEqual
(
members
[
0
].
get_full_name
(),
'Thom Wiggers'
)
def
test_one_year_contains_birthday
(
self
):
self
.
_assert_thom
(
'2016-03-02'
,
'2016-08-08'
)
def
test_one_year_not_contains_birthday
(
self
):
self
.
_assert_none
(
'2016-01-01'
,
'2016-02-01'
)
def
test_span_year_contains_birthday
(
self
):
self
.
_assert_thom
(
'2015-08-09'
,
'2016-08-08'
)
def
test_span_year_not_contains_birthday
(
self
):
self
.
_assert_none
(
'2015-12-25'
,
'2016-03-01'
)
def
test_span_multiple_years_contains_birthday
(
self
):
self
.
_assert_thom
(
'2012-12-31'
,
'2016-01-01'
)
def
test_range_before_person_born
(
self
):
self
.
_assert_none
(
'1985-12-12'
,
'1985-12-13'
)
def
test_person_born_in_range_in_one_year
(
self
):
self
.
_assert_thom
(
'1993-01-01'
,
'1993-04-01'
)
def
test_person_born_in_range_spanning_one_year
(
self
):
self
.
_assert_thom
(
'1992-12-31'
,
'1993-04-01'
)
def
test_person_born_in_range_spanning_multiple_years
(
self
):
self
.
_assert_thom
(
'1992-12-31'
,
'1995-01-01'
)
class
MemberTest
(
TestCase
):
fixtures
=
[
'members.json'
]
def
test_has_been_member
(
self
):
member
=
Member
.
objects
.
get
(
pk
=
1
)
self
.
assertTrue
(
member
.
has_been_member
())
m1
=
member
.
membership_set
.
all
()[
0
]
m1
.
type
=
'honorary'
m1
.
save
()
self
.
assertFalse
(
member
.
has_been_member
())
def
test_has_been_honorary_member
(
self
):
member
=
Member
.
objects
.
get
(
pk
=
1
)
self
.
assertFalse
(
member
.
has_been_honorary_member
())
m1
=
member
.
membership_set
.
all
()[
0
]
m1
.
type
=
'honorary'
m1
.
save
()
self
.
assertTrue
(
member
.
has_been_honorary_member
())
class
MemberDisplayNameTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
cls
.
member
=
Member
.
objects
.
create
(
username
=
'johnnytest'
,
first_name
=
''
,
last_name
=
''
)
cls
.
profile
=
Profile
.
objects
.
create
(
user_id
=
cls
.
member
.
pk
,
initials
=
None
,
nickname
=
None
,
display_name_preference
=
'full'
,
)
def
setUp
(
self
):
self
.
profile
.
display_name_preference
=
'full'
# Assuming we always have a first and last name
self
.
profile
.
user
.
first_name
=
'Johnny'
self
.
profile
.
user
.
last_name
=
'Test'
self
.
profile
.
nickname
=
None
self
.
profile
.
initials
=
None
def
test_check_display_name_full
(
self
):
self
.
assertEqual
(
'Johnny Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
short_display_name
())
def
test_check_display_name_nickname
(
self
):
self
.
profile
.
display_name_preference
=
'nickname'
self
.
assertEqual
(
'Johnny Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
short_display_name
())
self
.
profile
.
nickname
=
'John'
self
.
assertEqual
(
'John'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'John'
,
self
.
profile
.
short_display_name
())
def
test_check_display_name_firstname
(
self
):
self
.
profile
.
display_name_preference
=
'firstname'
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
short_display_name
())
def
test_check_display_name_initials
(
self
):
self
.
profile
.
display_name_preference
=
'initials'
self
.
assertEqual
(
'Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Test'
,
self
.
profile
.
short_display_name
())
self
.
profile
.
initials
=
'J'
self
.
assertEqual
(
'J Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'J Test'
,
self
.
profile
.
short_display_name
())
def
test_check_display_name_fullnick
(
self
):
self
.
profile
.
display_name_preference
=
'fullnick'
self
.
assertEqual
(
'Johnny Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
short_display_name
())
self
.
profile
.
nickname
=
'John'
self
.
assertEqual
(
'Johnny
\'
John
\'
Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
short_display_name
())
def
test_check_display_name_nicklast
(
self
):
self
.
profile
.
display_name_preference
=
'nicklast'
self
.
assertEqual
(
'Johnny Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'Johnny'
,
self
.
profile
.
short_display_name
())
self
.
profile
.
nickname
=
'John'
self
.
assertEqual
(
'
\'
John
\'
Test'
,
self
.
profile
.
display_name
())
self
.
assertEqual
(
'John'
,
self
.
profile
.
short_display_name
())
class
MembershipFilterTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
# Add 10 members with default membership
members
=
[
Member
(
id
=
i
,
username
=
i
)
for
i
in
range
(
7
)]
Member
.
objects
.
bulk_create
(
members
)
profiles
=
[
Profile
(
user_id
=
i
)
for
i
in
range
(
7
)]
Profile
.
objects
.
bulk_create
(
profiles
)
Membership
(
user_id
=
0
,
type
=
'honorary'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
1
,
type
=
'supporter'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
2
,
type
=
'member'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
3
,
type
=
'member'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
3
,
type
=
'member'
,
until
=
date
.
today
()
-
timedelta
(
days
=
365
*
10
)).
save
()
Membership
(
user_id
=
4
,
type
=
'supporter'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
4
,
type
=
'member'
,
until
=
date
.
today
()
-
timedelta
(
days
=
365
*
10
)).
save
()
Membership
(
user_id
=
5
,
type
=
'member'
,
until
=
date
.
today
()
-
timedelta
(
days
=
365
*
10
)).
save
()
# user_id=6 has no memberships at all
def
test_honorary
(
self
):
members
=
filter_users
(
'honor'
,
''
,
[
date
.
today
().
year
])
self
.
assertEqual
(
len
(
members
),
1
)
self
.
assertEqual
(
members
[
0
].
id
,
0
)
def
test_ex
(
self
):
members
=
filter_users
(
'ex'
,
''
,
[
date
.
today
().
year
])
self
.
assertEqual
(
len
(
members
),
3
)
for
member
in
members
:
self
.
assertIn
(
member
.
id
,
{
4
,
5
,
6
})
# TODO more tests for other cases
website/members/tests.py
→
website/members/tests
/test_services
.py
View file @
fa52caf6
from
datetime
import
date
,
datetime
,
timedelta
from
datetime
import
timedelta
,
date
from
django.test
import
TestCase
from
django.utils
import
timezone
from
members.models
import
(
Profile
,
Member
,
Membership
,
gen_stats_member_type
,
gen_stats_year
)
from
members.views
import
filter_users
from
members.models
import
Member
,
Membership
,
Profile
from
members.services
import
gen_stats_year
,
gen_stats_member_type
from
utils.snippets
import
datetime_to_lectureyear
class
MemberBirthdayTest
(
TestCase
):
fixtures
=
[
'members.json'
]
def
_make_date
(
self
,
date
):
return
timezone
.
make_aware
(
datetime
.
strptime
(
date
,
'%Y-%m-%d'
))
def
_get_members
(
self
,
start
,
end
):
start_date
=
self
.
_make_date
(
start
)
end_date
=
self
.
_make_date
(
end
)
return
Member
.
active_members
.
with_birthdays_in_range
(
start_date
,
end_date
)
def
_assert_none
(
self
,
start
,
end
):
members
=
self
.
_get_members
(
start
,
end
)
self
.
assertEqual
(
len
(
members
),
0
)
def
_assert_thom
(
self
,
start
,
end
):
members
=
self
.
_get_members
(
start
,
end
)
self
.
assertEqual
(
len
(
members
),
1
)
self
.
assertEqual
(
members
[
0
].
get_full_name
(),
'Thom Wiggers'
)
def
test_one_year_contains_birthday
(
self
):
self
.
_assert_thom
(
'2016-03-02'
,
'2016-08-08'
)
def
test_one_year_not_contains_birthday
(
self
):
self
.
_assert_none
(
'2016-01-01'
,
'2016-02-01'
)
def
test_span_year_contains_birthday
(
self
):
self
.
_assert_thom
(
'2015-08-09'
,
'2016-08-08'
)
def
test_span_year_not_contains_birthday
(
self
):
self
.
_assert_none
(
'2015-12-25'
,
'2016-03-01'
)
def
test_span_multiple_years_contains_birthday
(
self
):
self
.
_assert_thom
(
'2012-12-31'
,
'2016-01-01'
)
def
test_range_before_person_born
(
self
):
self
.
_assert_none
(
'1985-12-12'
,
'1985-12-13'
)
def
test_person_born_in_range_in_one_year
(
self
):
self
.
_assert_thom
(
'1993-01-01'
,
'1993-04-01'
)
def
test_person_born_in_range_spanning_one_year
(
self
):
self
.
_assert_thom
(
'1992-12-31'
,
'1993-04-01'
)
def
test_person_born_in_range_spanning_multiple_years
(
self
):
self
.
_assert_thom
(
'1992-12-31'
,
'1995-01-01'
)
class
MemberTest
(
TestCase
):
fixtures
=
[
'members.json'
]
def
test_has_been_member
(
self
):
member
=
Member
.
objects
.
get
(
pk
=
1
)
self
.
assertTrue
(
member
.
has_been_member
())
m1
=
member
.
membership_set
.
all
()[
0
]
m1
.
type
=
'honorary'
m1
.
save
()
self
.
assertFalse
(
member
.
has_been_member
())
def
test_has_been_honorary_member
(
self
):
member
=
Member
.
objects
.
get
(
pk
=
1
)
self
.
assertFalse
(
member
.
has_been_honorary_member
())
m1
=
member
.
membership_set
.
all
()[
0
]
m1
.
type
=
'honorary'
m1
.
save
()
self
.
assertTrue
(
member
.
has_been_honorary_member
())
class
MembershipFilterTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
# Add 10 members with default membership
members
=
[
Member
(
id
=
i
,
username
=
i
)
for
i
in
range
(
7
)]
Member
.
objects
.
bulk_create
(
members
)
profiles
=
[
Profile
(
user_id
=
i
)
for
i
in
range
(
7
)]
Profile
.
objects
.
bulk_create
(
profiles
)
Membership
(
user_id
=
0
,
type
=
'honorary'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
1
,
type
=
'supporter'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
2
,
type
=
'member'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
3
,
type
=
'member'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
3
,
type
=
'member'
,
until
=
date
.
today
()
-
timedelta
(
days
=
365
*
10
)).
save
()
Membership
(
user_id
=
4
,
type
=
'supporter'
,
until
=
date
.
today
()
+
timedelta
(
days
=
1
)).
save
()
Membership
(
user_id
=
4
,
type
=
'member'
,
until
=
date
.
today
()
-
timedelta
(
days
=
365
*
10
)).
save
()
Membership
(
user_id
=
5
,
type
=
'member'
,
until
=
date
.
today
()
-
timedelta
(
days
=
365
*
10
)).
save
()
# user_id=6 has no memberships at all
def
test_honorary
(
self
):
members
=
filter_users
(
'honor'
,
''
,
[
date
.
today
().
year
])
self
.
assertEqual
(
len
(
members
),
1
)
self
.
assertEqual
(
members
[
0
].
id
,
0
)
def
test_ex
(
self
):
members
=
filter_users
(
'ex'
,
''
,
[
date
.
today
().
year
])
self
.
assertEqual
(
len
(
members
),
3
)
for
member
in
members
:
self
.
assertIn
(
member
.
id
,
{
4
,
5
,
6
})
# TODO more tests for other cases
class
StatisticsTest
(
TestCase
):
@
classmethod
...
...
website/members/views.py
View file @
fa52caf6
...
...
@@ -12,6 +12,7 @@ from rest_framework.authtoken.models import Token
from
rest_framework.authtoken.views
import
ObtainAuthToken
from
rest_framework.response
import
Response
from
members
import
services
from
.services
import
member_achievements
from
.
import
models
from
.forms
import
ProfileForm
...
...
@@ -213,9 +214,9 @@ def statistics(request):
context
=
{
"total_members"
:
total
,
"total_stats_year"
:
json
.
dumps
(
model
s
.
gen_stats_year
(
member_types
)),
"total_stats_year"
:
json
.
dumps
(
service
s
.
gen_stats_year
(
member_types
)),
"total_stats_member_type"
:
json
.
dumps
(
model
s
.
gen_stats_member_type
(
member_types
)),
service
s
.
gen_stats_member_type
(
member_types
)),
}
return
render
(
request
,
'members/statistics.html'
,
context
)
Write
Preview
Markdown
is supported
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