Verified Commit 0d26a638 authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg
Browse files

Add registrations feature

Move members welcome email to emails.py

Remove BecomeAMemberDocument model

Add registrations app with models

Add emails.py and email templates

Model changes:
- Remove email_confirmed boolean from Registration model
- Change default value of Registration model status to 'confirm'
- Make Registration model email unique

Add first model tests for Registration

Write clean() for Registration

Fix PEP8 errors

Add init file to tests directory

Make Membership types constants instead of using the string value everywhere

Change membership lengths to constants in Entry model

Mention upgrade behaviour in registrations README

Use constants in registrations models test

Use constants for Entry status and fix membership_type argument in models test

Convert payment types to constants

Override translation language in registration emails by preferred language

Add services.py and tests

Implemented services.py

Add admin.py, fix docs in services.py and add app to sphinx

Wrote email contents

Make Registration email not unique

Fix call to renewal complete email in services.py

Add mail outbox assert to test_process_payment

Fix email formatting and do not completely block payment permissions

Make welcome mail non-trimmed

Change model admin changeform and add accept/reject buttons for registration and renewal

Add process buttons to payment admin and add permissions for reviewing and processing

Make some changes to the registrations admin (RenewalAdmin now inherits from RegistrationsAdmin) and add some tests

Add confirmation messages to custom admin calls, and redirect back to change form

Improve automatic username generation

Prevent processing payment for member with already active study membership

Rewrite registrations views to classes

Add tests for views

Fix sending confirmation email and related tests

Send confirmation mail after registration creation

Change README to reflect new supposed behaviour

Add frontend views

Update migration file to reflect model changes

Update view tests to reflect url changes

Add tests for forms

Change birthday field to SelectDateWidget

Generate username when accepting registration, not when processing payment

Change README to reflect new rules

Improve renewal admin

Move programme and starting year checks to model

Rename views and form to be member only

Make changes to model

Fix typo's and price for renewal

Fix tests

Move renewal validation to model instead of form

Change rules for processing in August

Update migration

Make renewal member field not readonly for new obj

Fix lecture year in test

Add confirmation to accept/reject buttons

Add localization for registrations

Change until date for new memberships to 01-09

Add processing date to payments

Add updated_at field to Entry model

Creation of renewal determines price

Fix tests

Always start membership renewals in August in September

Add board notifications

Move become a member page to registrations app

Update localisation

Add link to registration renewal on account page

Change file names and add link to documents page
parent 5f5421ca
......@@ -16,6 +16,7 @@ website
partners
photos
pizzas
registrations
thabloid
thaliawebsite
utils
registrations package
=====================
.. automodule:: registrations
:members:
:undoc-members:
:show-inheritance:
Submodules
----------
registrations\.admin module
---------------------------
.. automodule:: registrations.admin
:members:
:undoc-members:
:show-inheritance:
registrations\.apps module
--------------------------
.. automodule:: registrations.apps
:members:
:undoc-members:
:show-inheritance:
registrations\.emails module
----------------------------
.. automodule:: registrations.emails
:members:
:undoc-members:
:show-inheritance:
registrations\.models module
----------------------------
.. automodule:: registrations.models
:members:
:undoc-members:
:show-inheritance:
registrations\.services module
------------------------------
.. automodule:: registrations.services
:members:
:undoc-members:
:show-inheritance:
registrations\.urls module
--------------------------
.. automodule:: registrations.urls
:members:
:undoc-members:
:show-inheritance:
"""
This module registers admin pages for the models
"""
import csv
import datetime
from django.contrib import admin
......@@ -10,7 +11,6 @@ from django.db.models import Q
from django.http import HttpResponse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
import csv
from . import forms, models
......@@ -145,8 +145,6 @@ class MemberAdmin(UserAdmin):
return False
admin.site.register(models.BecomeAMemberDocument)
# re-register User admin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
......@@ -107,3 +107,17 @@ def send_expiration_announcement(dry_run=False):
{'members': members}),
connection=connection,
)
def send_welcome_message(user, password, language):
with translation.override(language):
email_body = loader.render_to_string(
'members/email/welcome.txt',
{
'full_name': user.get_full_name(),
'username': user.username,
'password': password
})
user.email_user(
_('Welcome to Study Association Thalia'),
email_body)
......@@ -27,7 +27,7 @@
"username": "testuser",
"first_name": "",
"last_name": "",
"email": "",
"email": "testuser@example.com",
"is_staff": true,
"is_active": true,
"date_joined": "2016-07-07T12:00:21Z",
......@@ -53,6 +53,24 @@
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 4,
"fields": {
"password": "",
"last_login": null,
"is_superuser": false,
"username": "testuser3",
"first_name": "",
"last_name": "",
"email": "",
"is_staff": true,
"is_active": true,
"date_joined": "2016-07-07T14:50:26Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "members.profile",
"pk": 1,
......@@ -131,6 +149,32 @@
"bank_account": ""
}
},
{
"model": "members.profile",
"pk": 4,
"fields": {
"user": 4,
"programme": null,
"student_number": "",
"address_street": "testuser 3",
"address_street2": "",
"address_postal_code": "6525 TE",
"address_city": "Nijmegen",
"phone_number": "",
"emergency_contact": "",
"emergency_contact_phone_number": "",
"birthday": "2016-07-07",
"show_birthday": true,
"website": "",
"profile_description": "",
"nickname": "",
"display_name_preference": "full",
"language": "nl",
"receive_optin": true,
"direct_debit_authorized": false,
"bank_account": ""
}
},
{
"model": "members.membership",
"pk": 1,
......
from __future__ import unicode_literals
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserChangeForm as BaseUserChangeForm
from django.contrib.auth.forms import UserCreationForm as BaseUserCreationForm
from django.template import loader
from django.utils import translation
from django.utils.translation import ugettext
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from .models import Profile
from members import emails
class ProfileForm(forms.ModelForm):
......@@ -74,17 +72,7 @@ class UserCreationForm(BaseUserCreationForm):
language = str(self.data.get('profile-0-language', 'en'))
if language not in ('nl', 'en'):
language = 'en'
with translation.override(language):
email_body = loader.render_to_string(
'members/email/welcome.txt',
{
'full_name': user.get_full_name(),
'username': user.username,
'password': password
})
user.email_user(
ugettext('Welcome to Study Association Thalia'),
email_body)
emails.send_welcome_message(user, password, language)
return user
class Meta:
......
......@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-10-18 21:31+0200\n"
"POT-Creation-Date: 2017-11-22 15:49+0100\n"
"PO-Revision-Date: 2017-10-18 21:32+0200\n"
"Last-Translator: Sébastiaan Versteeg <se_bastiaan@outlook.com>\n"
"Language-Team: \n"
......@@ -54,11 +54,11 @@ msgstr "Adres"
msgid "Address line 2"
msgstr "Tweede adresregel"
#: admin.py:113 models.py:202
#: admin.py:113 models.py:201
msgid "Postal code"
msgstr "Postcode"
#: admin.py:113 models.py:208
#: admin.py:113 models.py:207
msgid "City"
msgstr "Woonplaats"
......@@ -66,7 +66,7 @@ msgstr "Woonplaats"
msgid "Download address label for selected users"
msgstr "Download adreslabels voor geselecteerde gebruikers"
#: admin.py:131 models.py:165
#: admin.py:131 models.py:164
msgid "Student number"
msgstr "Studentnummer"
......@@ -98,99 +98,99 @@ msgstr "Verlopen lidmaatschap"
msgid "Membership expiration announcement sent"
msgstr "Meldingen vervallen lidmaatschap verzonden"
#: forms.py:33
#: emails.py:122
msgid "Welcome to Study Association Thalia"
msgstr "Welkom bij Studievereniging Thalia"
#: forms.py:31
msgid "Please enter a bank account"
msgstr "Voer een bankrekening in"
#: forms.py:53
#: forms.py:51
msgid "Send welcome email"
msgstr "Stuur welkomste-mails"
#: forms.py:54
#: forms.py:52
msgid "This email will include the generated password"
msgstr "Deze e-mail zal het gegenereerde wachtwoord bevatten"
#: forms.py:86
msgid "Welcome to Study Association Thalia"
msgstr "Welkom bij Studievereniging Thalia"
#: models.py:110
#: models.py:109
msgid "Is this user currently active"
msgstr "Is deze user op dit moment actief"
#: models.py:144
#: models.py:143
msgid "Computing Science"
msgstr "Informatica"
#: models.py:145
#: models.py:144
msgid "Information Sciences"
msgstr "Informatiekunde"
#: models.py:159 templates/members/profile.html:40
#: models.py:158 templates/members/profile.html:40
msgid "Study programme"
msgstr "Studie"
#: models.py:169
#: models.py:168
msgid "Enter a valid student- or e/z/u-number."
msgstr "Voer een geldig student- of e/z/u-nummer in."
#: models.py:175
#: models.py:174
msgid "Starting year"
msgstr "Startjaar"
#: models.py:176
#: models.py:175
msgid "The year this member started studying."
msgstr "Het jaar waarop dit lid begon met studeren."
#: models.py:187
#: models.py:186
msgid "Include the house number"
msgstr "Inclusief huisnummer"
#: models.py:189
#: models.py:188
msgid "Street and house number"
msgstr "Straat en huisnummer"
#: models.py:195
#: models.py:194
msgid "Second address line"
msgstr "Tweede adresregel"
#: models.py:214
#: models.py:213
msgid "Phone number"
msgstr "Telefoonnummer"
#: models.py:215
#: models.py:214
msgid "Enter a phone number so Thalia may reach you"
msgstr "Voer een telefoonnummer in zodat Thalia je kan bereiken"
#: models.py:218 models.py:240
#: models.py:217 models.py:239
msgid "Please enter a valid phone number"
msgstr "Voer svp een geldig telefoonnummer in"
#: models.py:228
#: models.py:227
msgid "Emergency contact name"
msgstr "Contact voor noodgevallen"
#: models.py:229
#: models.py:228
msgid "Who should we contact in case of emergencies"
msgstr "Wie Thalia moet bereiken in bij noodgevallen"
#: models.py:236
#: models.py:235
msgid "Emergency contact phone number"
msgstr "Telefoonnummer noodcontact"
#: models.py:237
#: models.py:236
msgid "The phone number for the emergency contact"
msgstr "Het telefoonummer van de noodcontact"
#: models.py:249 templates/members/profile.html:47
#: models.py:248 templates/members/profile.html:47
msgid "Birthday"
msgstr "Verjaardag"
#: models.py:254
#: models.py:253
msgid "Display birthday"
msgstr "Laat verjaardag zien"
#: models.py:256
#: models.py:255
msgid ""
"Show your birthday to other members on your profile page and in the birthday "
"calendar"
......@@ -198,107 +198,107 @@ msgstr ""
"Toon je verjaardag aan andere leden op je profielpagina en in de "
"verjaardagskalender"
#: models.py:263 templates/members/profile.html:43
#: models.py:262 templates/members/profile.html:43
msgid "Website"
msgstr "Website"
#: models.py:264
#: models.py:263
msgid "Website to display on your profile page"
msgstr "Website om op je profiel te linken"
#: models.py:270
#: models.py:269
msgid "Profile text"
msgstr "Profieltekst"
#: models.py:271
#: models.py:270
msgid "Text to display on your profile"
msgstr "Tekst om te laten zien op je profielpagina"
#: models.py:278
#: models.py:277
msgid "Initials"
msgstr "Initialen"
#: models.py:285
#: models.py:284
msgid "Nickname"
msgstr "Bijnaam"
#: models.py:292
#: models.py:291
msgid "How to display name"
msgstr "Weergave naam"
#: models.py:293
#: models.py:292
msgid "Show full name"
msgstr "Volledige naam"
#: models.py:294
#: models.py:293
msgid "Show only nickname"
msgstr "Alleen initialen"
#: models.py:295
#: models.py:294
msgid "Show only first name"
msgstr "Alleen voornaam"
#: models.py:296
#: models.py:295
msgid "Show initials and last name"
msgstr "Alleen initialen en achternaam"
#: models.py:297
#: models.py:296
msgid "Show name like \"John 'nickname' Doe\""
msgstr "Laat zien als \"John 'bijnaam' Doe\""
#: models.py:298
#: models.py:297
msgid "Show nickname and last name"
msgstr "Laat bijnaam en achternaam zien"
#: models.py:303
#: models.py:302
msgid "Photo"
msgstr "Foto"
#: models.py:311
#: models.py:310
msgid "Which events can this member attend"
msgstr "Welke evenementen mag dit lid bijwonen"
#: models.py:312
#: models.py:311
msgid "All events"
msgstr "Alle evenementen"
#: models.py:313
#: models.py:312
msgid "User may not attend events"
msgstr "Gebruiker mag niet naar evenementen"
#: models.py:314
#: models.py:313
msgid "User may not attend drinks"
msgstr "Gebruiker mag niet naar borrels"
#: models.py:315
#: models.py:314
msgid "User may not attend anything"
msgstr "Gebruiker mag nergens heen"
#: models.py:322
#: models.py:321
msgid "Preferred language"
msgstr "Voorkeurstaal"
#: models.py:323
#: models.py:322
msgid "Preferred language for e.g. newsletters"
msgstr "Voorkeurstaal voor b.v.b. nieuwsbrieven"
#: models.py:330
#: models.py:329
msgid "Receive opt-in mailings"
msgstr "Ontvang opt-in mailings"
#: models.py:331
#: models.py:330
msgid "Receive mailings about vacancies and events from Thalia's sponsors."
msgstr "Ontvang mailings over vacatures en evenementen van Thalia's sponsoren."
#: models.py:337
#: models.py:336
msgid "Receive newsletter"
msgstr "Ontvang nieuwsbrief"
#: models.py:338
#: models.py:337
msgid "Receive the Thalia Newsletter"
msgstr "Ontvang de Thalia nieuwsbrief"
#: models.py:345
#: models.py:344
msgid ""
"Yes, I want Thalia to take the membership fees from my bank account through "
"direct debit for each year."
......@@ -306,69 +306,69 @@ msgstr ""
"Ja, ik wil dat Thalia verschuldigde lidmaatschapsgelden elk jaar van mijn "
"bankrekening afschrijft."
#: models.py:348
#: models.py:347
msgid "No, I will pay the contribution myself"
msgstr "Nee, ik zal de contributie zelf betalen"
#: models.py:349
#: models.py:348
msgid "Direct debit"
msgstr "Automatische afschijving"
#: models.py:350
#: models.py:349
msgid "Each year, have Thalia take the membership fees from my bank account"
msgstr ""
"Laat Thalia elk jaar het lidmaatschapsgeld van mijn bankrekening afschrijven"
#: models.py:356
#: models.py:355
msgid "Bank account"
msgstr "Bankrekening"
#: models.py:357
#: models.py:356
msgid "Bank account for direct debit"
msgstr "Bankrekening voor automatische afschrijving"
#: models.py:381
#: models.py:380
msgid "Display name"
msgstr "Weergavenaam"
#: models.py:410
#: models.py:409
msgid "You need to enter a nickname to use it as display name"
msgstr ""
"Je moet een bijnaam invoeren voordat je deze kunt gebruiken als weergavenaam"
#: models.py:444
#: models.py:447
msgid "Member"
msgstr "Lid"
#: models.py:445
#: models.py:448
msgid "Supporter"
msgstr "Begunstiger"
#: models.py:446
#: models.py:449
msgid "Honorary Member"
msgstr "Erelid"
#: models.py:451 templates/members/profile.html:37
#: models.py:454 templates/members/profile.html:37
msgid "Membership type"
msgstr "Lidtype"
#: models.py:459
#: models.py:462
msgid "User"
msgstr "Gebruiker"
#: models.py:463
#: models.py:466
msgid "Membership since"
msgstr "Lid sinds"
#: models.py:464
#: models.py:467
msgid "The date the member started holding this membership."
msgstr "De datum waarop het lid dit lidmaatschap is begonnen."
#: models.py:469
#: models.py:472
msgid "Membership until"
msgstr "Lid tot"
#: models.py:470
#: models.py:473
msgid "The date the member stops holding this membership."
msgstr "De datum waarop het lid dit lidmaatschap beëindigd."
......@@ -401,28 +401,36 @@ msgstr "bekijk publieke profielpagina"
msgid "Take a look at your own profile."
msgstr "Bekijk je eigen profielpagina."
#: templates/members/account.html:27 templates/members/edit_profile.html:5
#: templates/members/account.html:25
msgid "manage membership"
msgstr "lidmaatschap beheren"
#: templates/members/account.html:26
msgid "Get information about your membership or renew it."
msgstr "Bekijk je lidmaatschap of vernieuw deze indien nodig."
#: templates/members/account.html:32 templates/members/edit_profile.html:5
#: templates/members/edit_profile.html:6 templates/members/edit_profile.html:9
msgid "edit profile"
msgstr "profiel bewerken"
#: templates/members/account.html:28
#: templates/members/account.html:33
msgid "Edit your profile and avatar."
msgstr "Bewerk je profiel en profielafbeelding."
#: templates/members/account.html:34
#: templates/members/account.html:39
msgid "change password"
msgstr "wachtwoord wijzigen"
#: templates/members/account.html:35
#: templates/members/account.html:40
msgid "Change your accounts' password."
msgstr "Wijzig het wachtwoord van je account."
#: templates/members/account.html:41
#: templates/members/account.html:46
msgid "logout"
msgstr "uitloggen"
#: templates/members/account.html:42
#: templates/members/account.html:47