Remove bank, Kfet and add BDA and BDS (need to fix activity, permission and registration)

This commit is contained in:
Jean-Baptiste Doderlein 2022-08-17 21:29:39 +00:00
parent 3a3e3be64c
commit 838bd2bb23
43 changed files with 128 additions and 639 deletions

View file

@ -20,9 +20,9 @@ from .models import Activity, Guest
class ActivityForm(forms.ModelForm): class ActivityForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
# By default, the Kfet club is attended # By default, the BDE club is attended
self.fields["attendees_club"].initial = Club.objects.get(name="Kfet") self.fields["attendees_club"].initial = Club.objects.get(name="BDE")
self.fields["attendees_club"].widget.attrs["placeholder"] = "Kfet" self.fields["attendees_club"].widget.attrs["placeholder"] = "BDE"
clubs = list(Club.objects.filter(PermissionBackend clubs = list(Club.objects.filter(PermissionBackend
.filter_queryset(get_current_request(), Club, "view")).all()) .filter_queryset(get_current_request(), Club, "view")).all())
shuffle(clubs) shuffle(clubs)

View file

@ -1,4 +1,4 @@
# Generated by Django 2.2.16 on 2020-09-04 21:41 # Generated by Django 2.2.28 on 2022-08-17 20:53
from django.db import migrations, models from django.db import migrations, models
import django.utils.timezone import django.utils.timezone

View file

@ -1,4 +1,4 @@
# Generated by Django 2.2.16 on 2020-09-04 21:41 # Generated by Django 2.2.28 on 2022-08-17 20:53
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
@ -10,10 +10,10 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('activity', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('member', '0001_initial'), ('member', '0001_initial'),
('activity', '0001_initial'),
('note', '0001_initial'), ('note', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [

View file

@ -73,7 +73,7 @@ class Activity(models.Model):
max_length=255, max_length=255,
blank=True, blank=True,
default="", default="",
help_text=_("Place where the activity is organized, eg. Kfet."), help_text=_("Place where the activity is organized, eg. BDE."),
) )
activity_type = models.ForeignKey( activity_type = models.ForeignKey(
@ -102,7 +102,7 @@ class Activity(models.Model):
on_delete=models.PROTECT, on_delete=models.PROTECT,
related_name='+', related_name='+',
verbose_name=_('attendees club'), verbose_name=_('attendees club'),
help_text=_("Club that is authorized to join the activity. Mostly the Kfet club."), help_text=_("Club that is authorized to join the activity."),
) )
date_start = models.DateTimeField( date_start = models.DateTimeField(

View file

@ -150,8 +150,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
"source": credit_id, "source": credit_id,
"destination": target.attr('data-inviter'), "destination": target.attr('data-inviter'),
"last_name": last_name, "last_name": last_name,
"first_name": first_name, "first_name": first_name
"bank": ""
}).done(function () { }).done(function () {
makeTransaction(); makeTransaction();
reset(); reset();

View file

@ -38,8 +38,8 @@ class TestActivities(TestCase):
location="Earth", location="Earth",
activity_type=ActivityType.objects.get(name="Activit\u00e9 gratuite ouverte"), activity_type=ActivityType.objects.get(name="Activit\u00e9 gratuite ouverte"),
creater=self.user, creater=self.user,
organizer=Club.objects.get(name="Kfet"), organizer=Club.objects.get(name="BDE"),
attendees_club=Club.objects.get(name="Kfet"), attendees_club=Club.objects.get(name="BDE"),
date_start=timezone.now(), date_start=timezone.now(),
date_end=timezone.now() + timedelta(days=2), date_end=timezone.now() + timedelta(days=2),
valid=True, valid=True,
@ -72,8 +72,8 @@ class TestActivities(TestCase):
location="Earth", location="Earth",
activity_type=ActivityType.objects.get(name="Soir\u00e9e").id, activity_type=ActivityType.objects.get(name="Soir\u00e9e").id,
creater=self.user.id, creater=self.user.id,
organizer=Club.objects.get(name="Kfet").id, organizer=Club.objects.get(name="BDE").id,
attendees_club=Club.objects.get(name="Kfet").id, attendees_club=Club.objects.get(name="BDE").id,
date_start="{:%Y-%m-%d %H:%M}".format(timezone.now()), date_start="{:%Y-%m-%d %H:%M}".format(timezone.now()),
date_end="{:%Y-%m-%d %H:%M}".format(timezone.now() + timedelta(days=2)), date_end="{:%Y-%m-%d %H:%M}".format(timezone.now() + timedelta(days=2)),
valid=True, valid=True,
@ -102,8 +102,8 @@ class TestActivities(TestCase):
location="Earth", location="Earth",
activity_type=ActivityType.objects.get(name="Soir\u00e9e").id, activity_type=ActivityType.objects.get(name="Soir\u00e9e").id,
creater=self.user.id, creater=self.user.id,
organizer=Club.objects.get(name="Kfet").id, organizer=Club.objects.get(name="BDE").id,
attendees_club=Club.objects.get(name="Kfet").id, attendees_club=Club.objects.get(name="BDE").id,
date_start="{:%Y-%m-%d %H:%M}".format(timezone.now()), date_start="{:%Y-%m-%d %H:%M}".format(timezone.now()),
date_end="{:%Y-%m-%d %H:%M}".format(timezone.now() + timedelta(days=2)), date_end="{:%Y-%m-%d %H:%M}".format(timezone.now() + timedelta(days=2)),
valid=True, valid=True,
@ -188,8 +188,8 @@ class TestActivityAPI(TestAPI):
location="Earth", location="Earth",
activity_type=ActivityType.objects.get(name="Activit\u00e9 gratuite ouverte"), activity_type=ActivityType.objects.get(name="Activit\u00e9 gratuite ouverte"),
creater=self.user, creater=self.user,
organizer=Club.objects.get(name="Kfet"), organizer=Club.objects.get(name="BDE"),
attendees_club=Club.objects.get(name="Kfet"), attendees_club=Club.objects.get(name="BDE"),
date_start=timezone.now(), date_start=timezone.now(),
date_end=timezone.now() + timedelta(days=2), date_end=timezone.now() + timedelta(days=2),
valid=True, valid=True,

View file

@ -340,7 +340,7 @@ UID:{md5((activity.name + "$" + str(activity.id) + str(activity.date_start)).enc
SUMMARY;CHARSET=UTF-8:{self.multilines(activity.name, 75, 22)} SUMMARY;CHARSET=UTF-8:{self.multilines(activity.name, 75, 22)}
DTSTART;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_start)} DTSTART;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_start)}
DTEND;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_end)} DTEND;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_end)}
LOCATION:{self.multilines(activity.location, 75, 9) if activity.location else "Kfet"} LOCATION:{self.multilines(activity.location, 75, 9) if activity.location else "BDA"}
DESCRIPTION;CHARSET=UTF-8:""" + self.multilines(activity.description.replace("\n", "\\n"), 75, 26) + """ DESCRIPTION;CHARSET=UTF-8:""" + self.multilines(activity.description.replace("\n", "\\n"), 75, 26) + """
-- {activity.organizer.name} -- {activity.organizer.name}
END:VEVENT END:VEVENT

View file

@ -186,11 +186,6 @@ class MembershipForm(forms.ModelForm):
required=False, required=False,
) )
bank = forms.CharField(
label=_("Bank"),
required=False,
)
class Meta: class Meta:
model = Membership model = Membership
fields = ('user', 'date_start') fields = ('user', 'date_start')

View file

@ -1,4 +1,4 @@
# Generated by Django 2.2.16 on 2020-09-04 21:41 # Generated by Django 2.2.28 on 2022-08-17 20:53
import datetime import datetime
from django.conf import settings from django.conf import settings
@ -40,12 +40,12 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=50, null=True, region=None, verbose_name='phone number')), ('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=50, null=True, region=None, verbose_name='phone number')),
('section', models.CharField(blank=True, help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, null=True, verbose_name='section')), ('section', models.CharField(blank=True, default='', help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, verbose_name='section')),
('department', models.CharField(choices=[('A0', 'Informatics (A0)'), ('A1', 'Mathematics (A1)'), ('A2', 'Physics (A2)'), ("A'2", "Applied physics (A'2)"), ('A2', "Chemistry (A''2)"), ('A3', 'Biology (A3)'), ('B1234', 'SAPHIRE (B1234)'), ('B1', 'Mechanics (B1)'), ('B2', 'Civil engineering (B2)'), ('B3', 'Mechanical engineering (B3)'), ('B4', 'EEA (B4)'), ('C', 'Design (C)'), ('D2', 'Economy-management (D2)'), ('D3', 'Social sciences (D3)'), ('E', 'English (E)'), ('EXT', 'External (EXT)')], max_length=8, verbose_name='department')), ('department', models.CharField(choices=[('INFO', 'Informatique'), ('MATH', 'Mathématiques'), ('DEM', 'Droit - économie - management'), ('MECATRO', 'Mécatronique'), ('2SEP', 'Sciences du sport et éducation physique'), ('SE', 'Sciences pour lEnvironnement'), ('EXT', 'Externe')], max_length=8, verbose_name='department')),
('promotion', models.PositiveSmallIntegerField(default=2020, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion')), ('promotion', models.PositiveSmallIntegerField(default=2022, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion')),
('address', models.CharField(blank=True, max_length=255, null=True, verbose_name='address')), ('address', models.CharField(blank=True, default='', max_length=255, verbose_name='address')),
('paid', models.BooleanField(default=False, help_text='Tells if the user receive a salary.', verbose_name='paid')), ('paid', models.BooleanField(default=False, help_text='Tells if the user receive a salary.', verbose_name='paid')),
('ml_events_registration', models.CharField(blank=True, choices=[(None, 'No'), ('fr', 'Yes (receive them in french)'), ('en', 'Yes (receive them in english)')], default=None, max_length=2, null=True, verbose_name='Register on the mailing list to stay informed of the events of the campus (1 mail/week)')), ('ml_events_registration', models.CharField(blank=True, choices=[('', 'No'), ('fr', 'Yes')], default='', max_length=2, verbose_name='Register on the mailing list to stay informed of the events of the campus (1 mail/week)')),
('ml_sport_registration', models.BooleanField(default=False, verbose_name='Register on the mailing list to stay informed of the sport events of the campus (1 mail/week)')), ('ml_sport_registration', models.BooleanField(default=False, verbose_name='Register on the mailing list to stay informed of the sport events of the campus (1 mail/week)')),
('ml_art_registration', models.BooleanField(default=False, verbose_name='Register on the mailing list to stay informed of the art events of the campus (1 mail/week)')), ('ml_art_registration', models.BooleanField(default=False, verbose_name='Register on the mailing list to stay informed of the art events of the campus (1 mail/week)')),
('report_frequency', models.PositiveSmallIntegerField(default=0, verbose_name='report frequency (in days)')), ('report_frequency', models.PositiveSmallIntegerField(default=0, verbose_name='report frequency (in days)')),

View file

@ -1,42 +0,0 @@
# Generated by Django 2.2.16 on 2020-09-04 21:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('permission', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('member', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='membership',
name='roles',
field=models.ManyToManyField(to='permission.Role', verbose_name='roles'),
),
migrations.AddField(
model_name='membership',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='memberships', to=settings.AUTH_USER_MODEL, verbose_name='user'),
),
migrations.AddField(
model_name='club',
name='parent_club',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='member.Club', verbose_name='parent club'),
),
migrations.AddIndex(
model_name='profile',
index=models.Index(fields=['user'], name='member_prof_user_id_30c316_idx'),
),
migrations.AddIndex(
model_name='membership',
index=models.Index(fields=['user'], name='member_memb_user_id_945dbc_idx'),
),
]

View file

@ -1,71 +0,0 @@
from django.db import migrations
def create_bde_and_kfet(apps, schema_editor):
"""
The clubs BDE and Kfet are pre-injected.
"""
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
Club.objects.get_or_create(
id=1,
name="BDE",
email="tresorerie.bde@example.com",
require_memberships=True,
membership_fee_paid=500,
membership_fee_unpaid=500,
membership_duration=396,
membership_start="2021-08-01",
membership_end="2022-09-30",
)
Club.objects.get_or_create(
id=2,
name="Kfet",
parent_club_id=1,
email="tresorerie.bde@example.com",
require_memberships=True,
membership_fee_paid=3500,
membership_fee_unpaid=3500,
membership_duration=396,
membership_start="2021-08-01",
membership_end="2022-09-30",
)
NoteClub.objects.get_or_create(
id=5,
club_id=1,
polymorphic_ctype_id=polymorphic_ctype_id,
)
NoteClub.objects.get_or_create(
id=6,
club_id=2,
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 = [
('member', '0002_auto_20200904_2341'),
('note', '0002_create_special_notes'),
]
operations = [
migrations.RunPython(create_bde_and_kfet),
]

View file

@ -1,20 +0,0 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('member', '0003_create_bde_and_kfet'),
]
operations = [
migrations.RunSQL(
"UPDATE member_profile SET address = '' WHERE address IS NULL;",
),
migrations.RunSQL(
"UPDATE member_profile SET ml_events_registration = '' WHERE ml_events_registration IS NULL;",
),
migrations.RunSQL(
"UPDATE member_profile SET section = '' WHERE section IS NULL;",
),
]

View file

@ -1,28 +0,0 @@
# Generated by Django 2.2.16 on 2020-09-06 19:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('member', '0004_replace_null_by_blank'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='address',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='address'),
),
migrations.AlterField(
model_name='profile',
name='ml_events_registration',
field=models.CharField(blank=True, choices=[('', 'No'), ('fr', 'Yes (receive them in french)'), ('en', 'Yes (receive them in english)')], default='', max_length=2, verbose_name='Register on the mailing list to stay informed of the events of the campus (1 mail/week)'),
),
migrations.AlterField(
model_name='profile',
name='section',
field=models.CharField(blank=True, default='', help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, verbose_name='section'),
),
]

View file

@ -1,50 +0,0 @@
import sys
from django.db import migrations
def give_note_account_permissions(apps, schema_editor):
"""
Automatically manage the membership of the Note account.
"""
User = apps.get_model("auth", "user")
Membership = apps.get_model("member", "membership")
Role = apps.get_model("permission", "role")
note = User.objects.filter(username="note")
if not note.exists():
# We are in a test environment, don't log error message
if len(sys.argv) > 1 and sys.argv[1] == 'test':
return
print("Warning: Note account was not found. The note account was not imported.")
print("Make sure you have imported the NK15 database. The new import script handles correctly the permissions.")
print("This migration will be ignored, you can re-run it if you forgot the note account or ignore it if you "
"don't want this account.")
return
note = note.get()
# Set for the two clubs a large expiration date and the correct role.
for m in Membership.objects.filter(user_id=note.id).all():
m.date_end = "3142-12-12"
m.roles.set(Role.objects.filter(name="PC Kfet").all())
m.save()
# By default, the note account is only authorized to be logged from localhost.
note.password = "ipbased$127.0.0.1"
note.is_active = True
note.save()
# Ensure that the note of the account is disabled
note.note.inactivity_reason = 'forced'
note.note.is_active = False
note.save()
class Migration(migrations.Migration):
dependencies = [
('member', '0005_remove_null_tag_on_charfields'),
('permission', '0001_initial'),
]
operations = [
migrations.RunPython(give_note_account_permissions),
]

View file

@ -1,23 +0,0 @@
# 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,18 +0,0 @@
# Generated by Django 2.2.24 on 2021-10-05 13:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('member', '0007_auto_20210313_1235'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='department',
field=models.CharField(choices=[('A0', 'Informatics (A0)'), ('A1', 'Mathematics (A1)'), ('A2', 'Physics (A2)'), ("A'2", "Applied physics (A'2)"), ("A''2", "Chemistry (A''2)"), ('A3', 'Biology (A3)'), ('B1234', 'SAPHIRE (B1234)'), ('B1', 'Mechanics (B1)'), ('B2', 'Civil engineering (B2)'), ('B3', 'Mechanical engineering (B3)'), ('B4', 'EEA (B4)'), ('C', 'Design (C)'), ('D2', 'Economy-management (D2)'), ('D3', 'Social sciences (D3)'), ('E', 'English (E)'), ('EXT', 'External (EXT)')], max_length=8, verbose_name='department'),
),
]

View file

@ -381,9 +381,12 @@ class Membership(models.Model):
if self.club.parent_club.name == "BDE": if self.club.parent_club.name == "BDE":
parent_membership.roles.set( parent_membership.roles.set(
Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).all()) Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).all())
elif self.club.parent_club.name == "Kfet": elif self.club.parent_club.name == "BDA":
parent_membership.roles.set( parent_membership.roles.set(
Role.objects.filter(Q(name="Adhérent Kfet") | Q(name="Membre de club")).all()) Role.objects.filter(Q(name="Adhérent BDA") | Q(name="Membre de club")).all())
elif self.club.parent_club.name == "BDS":
parent_membership.roles.set(
Role.objects.filter(Q(name="Adhérent BDS") | Q(name="Membre de club")).all())
else: else:
parent_membership.roles.set(Role.objects.filter(name="Membre de club").all()) parent_membership.roles.set(Role.objects.filter(name="Membre de club").all())
parent_membership.save() parent_membership.save()

View file

@ -13,29 +13,15 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% if additional_fee_renewal %} {% if additional_fee_renewal %}
<div class="alert alert-warning"> <div class="alert alert-warning">
{% if renewal %} {% if renewal %}
{% if club.name == "Kfet" %} {# Auto-renewal #} {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %}
{% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} The user is not a member of the club·s {{ clubs }}. Please create the required memberships,
The user is not a member of the club·s {{ clubs }}. An additional fee of {{ pretty_fee }} otherwise it will fail.
will be charged to renew automatically the membership in this/these club·s. {% endblocktrans %}
{% endblocktrans %}
{% else %}
{% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %}
The user is not a member of the club·s {{ clubs }}. Please create the required memberships,
otherwise it will fail.
{% endblocktrans %}
{% endif %}
{% else %} {% else %}
{% if club.name == "Kfet" %} {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %}
{% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} This club has parents {{ clubs }}. Please make sure that the user is a member of this or these club·s,
This club has parents {{ clubs }}. An additional fee of {{ pretty_fee }} otherwise the creation of this membership will fail.
will be charged to adhere automatically to this/these club·s. {% endblocktrans %}
{% endblocktrans %}
{% else %}
{% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %}
This club has parents {{ clubs }}. Please make sure that the user is a member of this or these club·s,
otherwise the creation of this membership will fail.
{% endblocktrans %}
{% endif %}
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
@ -69,10 +55,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
let credit_amount = $("#id_credit_amount"); let credit_amount = $("#id_credit_amount");
credit_amount.attr('disabled', true); credit_amount.attr('disabled', true);
credit_amount.val('{{ total_fee }}'); credit_amount.val('{{ total_fee }}');
let bank = $("#id_bank");
bank.attr('disabled', true);
bank.val('Société générale');
} }
</script> </script>
{% endblock %} {% endblock %}

View file

@ -179,20 +179,17 @@ class TestMemberships(TestCase):
# We create a club without any parent and one club with parent BDE (that is the club Kfet) # We create a club without any parent and one club with parent BDE (that is the club Kfet)
for bde_parent in False, True: for bde_parent in False, True:
if bde_parent: club = Club.objects.create(
club = Club.objects.get(name="Kfet") name="Second club " + ("with BDE" if bde_parent else "without BDE"),
else: parent_club=None,
club = Club.objects.create( email="newclub@example.com",
name="Second club " + ("with BDE" if bde_parent else "without BDE"), require_memberships=True,
parent_club=None, membership_fee_paid=1000,
email="newclub@example.com", membership_fee_unpaid=500,
require_memberships=True, membership_start=date.today(),
membership_fee_paid=1000, membership_end=date.today() + timedelta(days=366),
membership_fee_unpaid=500, membership_duration=366,
membership_start=date.today(), )
membership_end=date.today() + timedelta(days=366),
membership_duration=366,
)
response = self.client.get(reverse("member:club_add_member", args=(club.pk,))) response = self.client.get(reverse("member:club_add_member", args=(club.pk,)))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -204,8 +201,7 @@ class TestMemberships(TestCase):
credit_type=NoteSpecial.objects.get(special_type="Espèces").id, credit_type=NoteSpecial.objects.get(special_type="Espèces").id,
credit_amount=4200, credit_amount=4200,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto"
bank="Le matelas",
)) ))
self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
@ -223,11 +219,6 @@ class TestMemberships(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
bde_membership = self.bde_membership bde_membership = self.bde_membership
if bde_parent:
bde_membership = Membership.objects.get(club__name="BDE", user=user)
bde_membership.date_start = date(year=2000, month=1, day=1)
bde_membership.date_end = date(year=2000, month=12, day=31)
bde_membership.save()
response = self.client.get(reverse("member:club_renew_membership", args=(bde_membership.pk,))) response = self.client.get(reverse("member:club_renew_membership", args=(bde_membership.pk,)))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -243,7 +234,6 @@ class TestMemberships(TestCase):
credit_amount=14242, credit_amount=14242,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Bank",
)) ))
self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)

View file

@ -656,12 +656,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
if not credit_type: if not credit_type:
credit_amount = 0 credit_amount = 0
if user.note.balance + credit_amount < fee and not Membership.objects.filter( if user.note.balance + credit_amount < fee:
club__name="Kfet",
user=user,
date_start__lte=date.today(),
date_end__gte=date.today(),
).exists():
# Users without a valid Kfet membership can't have a negative balance. # Users without a valid Kfet membership can't have a negative balance.
# TODO Send a notification to the user (with a mail?) to tell her/him to credit her/his note # TODO Send a notification to the user (with a mail?) to tell her/him to credit her/his note
form.add_error('user', form.add_error('user',
@ -678,7 +673,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
error = True error = True
# Must join the parent club before joining this club, except for the Kfet club where it can be at the same time. # Must join the parent club before joining this club, except for the Kfet club where it can be at the same time.
if club.name != "Kfet" and club.parent_club and not Membership.objects.filter( if 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__gte=club.parent_club.membership_start, date_start__gte=club.parent_club.membership_start,
@ -726,7 +721,6 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
credit_amount = form.cleaned_data["credit_amount"] credit_amount = form.cleaned_data["credit_amount"]
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"]
if credit_type is None: if credit_type is None:
@ -750,7 +744,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
# Now, all is fine, the membership can be created. # Now, all is fine, the membership can be created.
if club.name == "BDE" or club.name == "Kfet": if club.name == "BDE":
# 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
@ -767,7 +761,6 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
reason="Crédit " + credit_type.special_type + " (Adhésion " + club.name + ")", reason="Crédit " + credit_type.special_type + " (Adhésion " + club.name + ")",
last_name=last_name, last_name=last_name,
first_name=first_name, first_name=first_name,
bank=bank,
valid=True, valid=True,
) )
transaction._force_save = True transaction._force_save = True
@ -780,8 +773,10 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
ret = super().form_valid(form) ret = super().form_valid(form)
member_role = Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).all() \ member_role = Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).all() \
if club.name == "BDE" else Role.objects.filter(Q(name="Adhérent Kfet") | Q(name="Membre de club")).all() \ if club.name == "BDE" else Role.objects.filter(Q(name="Adhérent BDA") | Q(name="Membre de club")).all() \
if club.name == "Kfet"else Role.objects.filter(name="Membre de club").all() if club.name == "BDA" else Role.objects.filter(Q(name="Adhérent BDS") | Q(name="Membre de club")).all() \
if club.name == "BDS" else Role.objects.filter(name="Membre de club").all()
# Set the same roles as before # Set the same roles as before
if old_membership: if old_membership:
member_role = member_role.union(old_membership.roles.all()) member_role = member_role.union(old_membership.roles.all())

View file

@ -160,7 +160,7 @@ class ConsumerSerializer(serializers.ModelSerializer):
memberships = Membership.objects.filter( memberships = Membership.objects.filter(
PermissionBackend.filter_queryset(get_current_request(), Membership, "view")).filter( PermissionBackend.filter_queryset(get_current_request(), Membership, "view")).filter(
user=obj.note.user, user=obj.note.user,
club=2, # Kfet club=2, # BDA
).order_by("-date_start") ).order_by("-date_start")
if memberships.exists(): if memberships.exists():
return MembershipSerializer().to_representation(memberships.first()) return MembershipSerializer().to_representation(memberships.first())

View file

@ -1,4 +1,4 @@
# Generated by Django 2.2.16 on 2020-09-04 21:41 # Generated by Django 2.2.28 on 2022-08-17 20:53
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
@ -11,9 +11,9 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('member', '0001_initial'), ('member', '0001_initial'),
('contenttypes', '0002_remove_content_type_name'), ('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
@ -26,7 +26,7 @@ class Migration(migrations.Migration):
('display_image', models.ImageField(default='pic/default.png', max_length=255, upload_to='pic/', verbose_name='display image')), ('display_image', models.ImageField(default='pic/default.png', max_length=255, upload_to='pic/', verbose_name='display image')),
('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created at')), ('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created at')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this note should be treated as active. Unselect this instead of deleting notes.', verbose_name='active')), ('is_active', models.BooleanField(default=True, help_text='Designates whether this note should be treated as active. Unselect this instead of deleting notes.', verbose_name='active')),
('inactivity_reason', models.CharField(choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default=None, max_length=255, null=True)), ('inactivity_reason', models.CharField(blank=True, choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default='', max_length=255)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_note.note_set+', to='contenttypes.ContentType')), ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_note.note_set+', to='contenttypes.ContentType')),
], ],
options={ options={
@ -56,7 +56,7 @@ class Migration(migrations.Migration):
('amount', models.PositiveIntegerField(verbose_name='amount')), ('amount', models.PositiveIntegerField(verbose_name='amount')),
('reason', models.CharField(max_length=255, verbose_name='reason')), ('reason', models.CharField(max_length=255, verbose_name='reason')),
('valid', models.BooleanField(default=True, verbose_name='valid')), ('valid', models.BooleanField(default=True, verbose_name='valid')),
('invalidity_reason', models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='invalidity reason')), ('invalidity_reason', models.CharField(blank=True, default='', max_length=255, verbose_name='invalidity reason')),
('destination', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.Note', verbose_name='destination')), ('destination', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.Note', verbose_name='destination')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_note.transaction_set+', to='contenttypes.ContentType')), ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_note.transaction_set+', to='contenttypes.ContentType')),
('source', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.Note', verbose_name='source')), ('source', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.Note', verbose_name='source')),
@ -128,7 +128,6 @@ class Migration(migrations.Migration):
('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')), ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')),
('last_name', models.CharField(max_length=255, verbose_name='name')), ('last_name', models.CharField(max_length=255, verbose_name='name')),
('first_name', models.CharField(max_length=255, verbose_name='first_name')), ('first_name', models.CharField(max_length=255, verbose_name='first_name')),
('bank', models.CharField(blank=True, max_length=255, verbose_name='bank')),
], ],
options={ options={
'verbose_name': 'Special transaction', 'verbose_name': 'Special transaction',
@ -142,13 +141,26 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True, verbose_name='name')), ('name', models.CharField(max_length=255, unique=True, verbose_name='name')),
('normalized_name', models.CharField(editable=False, max_length=255, unique=True)), ('normalized_name', models.CharField(editable=False, max_length=255, unique=True)),
('note', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.Note')), ('note', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='alias', to='note.Note')),
], ],
options={ options={
'verbose_name': 'alias', 'verbose_name': 'alias',
'verbose_name_plural': 'aliases', 'verbose_name_plural': 'aliases',
}, },
), ),
migrations.CreateModel(
name='Trust',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('trusted', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusted', to='note.Note', verbose_name='trusted')),
('trusting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusting', to='note.Note', verbose_name='trusting')),
],
options={
'verbose_name': 'frienship',
'verbose_name_plural': 'friendships',
'unique_together': {('trusting', 'trusted')},
},
),
migrations.CreateModel( migrations.CreateModel(
name='TransactionTemplate', name='TransactionTemplate',
fields=[ fields=[

View file

@ -1,17 +0,0 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('note', '0002_create_special_notes'),
]
operations = [
migrations.RunSQL(
"UPDATE note_note SET inactivity_reason = '' WHERE inactivity_reason IS NULL;"
),
migrations.RunSQL(
"UPDATE note_transaction SET invalidity_reason = '' WHERE invalidity_reason IS NULL;"
),
]

View file

@ -1,23 +0,0 @@
# Generated by Django 2.2.16 on 2020-09-06 19:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('note', '0003_replace_null_by_blank'),
]
operations = [
migrations.AlterField(
model_name='note',
name='inactivity_reason',
field=models.CharField(blank=True, choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default='', max_length=255),
),
migrations.AlterField(
model_name='transaction',
name='invalidity_reason',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='invalidity reason'),
),
]

View file

@ -1,19 +0,0 @@
# 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,27 +0,0 @@
# Generated by Django 2.2.24 on 2021-09-05 19:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('note', '0005_auto_20210313_1235'),
]
operations = [
migrations.CreateModel(
name='Trust',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('trusted', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusted', to='note.Note', verbose_name='trusted')),
('trusting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusting', to='note.Note', verbose_name='trusting')),
],
options={
'verbose_name': 'frienship',
'verbose_name_plural': 'friendships',
'unique_together': {('trusting', 'trusted')},
},
),
]

View file

@ -306,11 +306,6 @@ class SpecialTransaction(Transaction):
verbose_name=_("first_name"), verbose_name=_("first_name"),
) )
bank = models.CharField(
max_length=255,
verbose_name=_("bank"),
blank=True,
)
@property @property
def type(self): def type(self):
@ -346,20 +341,16 @@ class SpecialTransaction(Transaction):
credit_type = form.cleaned_data["credit_type"] credit_type = form.cleaned_data["credit_type"]
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"]
error = False error = False
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"): if not last_name or not first_name:
if not last_name: if not last_name:
form.add_error('last_name', _("This field is required.")) form.add_error('last_name', _("This field is required."))
error = True error = True
if not first_name: if not first_name:
form.add_error('first_name', _("This field is required.")) form.add_error('first_name', _("This field is required."))
error = True 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

View file

@ -139,12 +139,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
<input type="text" id="first_name" class="form-control" /> <input type="text" id="first_name" class="form-control" />
</div> </div>
</div> </div>
<div class="form-row">
<div class="col-md-12">
<label for="bank">{% trans "Bank" %} :</label>
<input type="text" id="bank" class="form-control" />
</div>
</div>
</div> </div>
<hr> <hr>
<div class="form-row"> <div class="form-row">

View file

@ -34,7 +34,7 @@ class TestTransactions(TestCase):
membership = Membership.objects.create(club=Club.objects.get(name="BDE"), user=self.user) membership = Membership.objects.create(club=Club.objects.get(name="BDE"), user=self.user)
membership.roles.add(Role.objects.get(name="Respo info")) membership.roles.add(Role.objects.get(name="Respo info"))
membership.save() membership.save()
Membership.objects.create(club=Club.objects.get(name="Kfet"), user=self.user) Membership.objects.create(club=Club.objects.get(name="BDA"), user=self.user)
self.user.note.refresh_from_db() self.user.note.refresh_from_db()
self.second_user = User.objects.create( self.second_user = User.objects.create(
@ -377,7 +377,7 @@ class TestNoteAPI(TestAPI):
membership = Membership.objects.create(club=Club.objects.get(name="BDE"), user=self.user) membership = Membership.objects.create(club=Club.objects.get(name="BDE"), user=self.user)
membership.roles.add(Role.objects.get(name="Respo info")) membership.roles.add(Role.objects.get(name="Respo info"))
membership.save() membership.save()
Membership.objects.create(club=Club.objects.get(name="Kfet"), user=self.user) Membership.objects.create(club=Club.objects.get(name="BDA"), user=self.user)
self.user.note.last_negative = timezone.now() self.user.note.last_negative = timezone.now()
self.user.note.save() self.user.note.save()

View file

@ -1,4 +1,4 @@
# Generated by Django 2.2.16 on 2020-09-04 21:41 # Generated by Django 2.2.28 on 2022-08-17 20:53
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion

View file

@ -11,7 +11,6 @@ from django.utils.crypto import get_random_string
from activity.models import Activity from activity.models import Activity
from member.models import Club, Membership from member.models import Club, Membership
from note.models import NoteUser from note.models import NoteUser
from wei.models import WEIClub, Bus, WEIRegistration
class TestPermissionDenied(TestCase): class TestPermissionDenied(TestCase):
@ -79,56 +78,6 @@ class TestPermissionDenied(TestCase):
response = self.client.get(reverse("member:club_renew_membership", kwargs=dict(pk=membership.pk))) response = self.client.get(reverse("member:club_renew_membership", kwargs=dict(pk=membership.pk)))
self.assertEqual(response.status_code, 403) self.assertEqual(response.status_code, 403)
def test_create_weiclub(self):
response = self.client.get(reverse("wei:wei_create"))
self.assertEqual(response.status_code, 403)
def test_create_wei_bus(self):
wei = WEIClub.objects.create(
membership_start=date.today(),
date_start=date.today() + timedelta(days=1),
date_end=date.today() + timedelta(days=1),
)
response = self.client.get(reverse("wei:add_bus", kwargs=dict(pk=wei.pk)))
self.assertEqual(response.status_code, 403)
def test_create_wei_team(self):
wei = WEIClub.objects.create(
membership_start=date.today(),
date_start=date.today() + timedelta(days=1),
date_end=date.today() + timedelta(days=1),
)
bus = Bus.objects.create(wei=wei)
response = self.client.get(reverse("wei:add_team", kwargs=dict(pk=bus.pk)))
self.assertEqual(response.status_code, 403)
def test_create_1a_weiregistration(self):
wei = WEIClub.objects.create(
membership_start=date.today(),
date_start=date.today() + timedelta(days=1),
date_end=date.today() + timedelta(days=1),
)
response = self.client.get(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=wei.pk)))
self.assertEqual(response.status_code, 403)
def test_create_old_weiregistration(self):
wei = WEIClub.objects.create(
membership_start=date.today(),
date_start=date.today() + timedelta(days=1),
date_end=date.today() + timedelta(days=1),
)
response = self.client.get(reverse("wei:wei_register_2A", kwargs=dict(wei_pk=wei.pk)))
self.assertEqual(response.status_code, 403)
def test_validate_weiregistration(self):
wei = WEIClub.objects.create(
membership_start=date.today(),
date_start=date.today() + timedelta(days=1),
date_end=date.today() + timedelta(days=1),
)
registration = WEIRegistration.objects.create(wei=wei, user=self.user, birth_date="2000-01-01")
response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=registration.pk)))
self.assertEqual(response.status_code, 403)
def test_create_invoice(self): def test_create_invoice(self):
response = self.client.get(reverse("treasury:invoice_create")) response = self.client.get(reverse("treasury:invoice_create"))

View file

@ -11,7 +11,7 @@ from django.test import TestCase
from django.utils import timezone from django.utils import timezone
from member.models import Club, Membership from member.models import Club, Membership
from note.models import NoteUser, Note, NoteClub, NoteSpecial from note.models import NoteUser, Note, NoteClub, NoteSpecial
from wei.models import WEIMembership, WEIRegistration, WEIClub, Bus, BusTeam
from ..models import Permission from ..models import Permission
@ -23,44 +23,16 @@ class PermissionQueryTestCase(TestCase):
def setUpTestData(cls): def setUpTestData(cls):
user = User.objects.create(username="user") user = User.objects.create(username="user")
NoteUser.objects.create(user=user) NoteUser.objects.create(user=user)
wei = WEIClub.objects.create(
name="wei",
date_start=date.today(),
date_end=date.today(),
)
NoteClub.objects.create(club=wei)
weiregistration = WEIRegistration.objects.create(
user=user,
wei=wei,
birth_date=date.today(),
)
bus = Bus.objects.create(
name="bus",
wei=wei,
)
team = BusTeam.objects.create(
name="team",
bus=bus,
color=0xFFFFFF,
)
WEIMembership.objects.create(
user=user,
club=wei,
registration=weiregistration,
bus=bus,
team=team,
)
def test_permission_queries(self): def test_permission_queries(self):
""" """
Check for all permissions that the query is compilable and that the database can parse the query. Check for all permissions that the query is compilable and that the database can parse the query.
We use a random user with a random WEIClub (to use permissions for the WEI) in a random team in a random bus. We use a random user.
""" """
for perm in Permission.objects.all(): for perm in Permission.objects.all():
try: try:
instanced = perm.about( instanced = perm.about(
user=User.objects.get(), user=User.objects.get(),
club=WEIClub.objects.get(),
membership=Membership.objects.get(), membership=Membership.objects.get(),
User=User, User=User,
Club=Club, Club=Club,

View file

@ -74,20 +74,21 @@ class ValidationForm(forms.Form):
required=False, required=False,
) )
bank = forms.CharField(
label=_("Bank"),
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=False,
) )
# The user can join the Kfet club at the inscription join_bda = forms.BooleanField(
join_kfet = forms.BooleanField( label=_("Join BDA Club"),
label=_("Join Kfet Club"),
required=False, required=False,
initial=True, initial=False,
) )
join_bds = forms.BooleanField(
label=_("Join BDS Club"),
required=False,
initial=False,
)

View file

@ -82,10 +82,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
credit_amount.attr('disabled', true); credit_amount.attr('disabled', true);
credit_amount.val('{{ total_fee }}'); credit_amount.val('{{ total_fee }}');
let bank = $("#id_bank");
bank.attr('disabled', true);
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('disabled', true);

View file

@ -193,7 +193,6 @@ class TestValidateRegistration(TestCase):
credit_amount=4200, credit_amount=4200,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
join_bde=False, join_bde=False,
join_kfet=False, join_kfet=False,
)) ))
@ -206,7 +205,6 @@ class TestValidateRegistration(TestCase):
credit_amount=0, credit_amount=0,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
join_bde=False, join_bde=False,
join_kfet=True, join_kfet=True,
)) ))
@ -219,7 +217,6 @@ class TestValidateRegistration(TestCase):
credit_amount=0, credit_amount=0,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="J'ai pas d'argent",
join_bde=True, join_bde=True,
join_kfet=True, join_kfet=True,
)) ))
@ -232,7 +229,6 @@ class TestValidateRegistration(TestCase):
credit_amount=4000, credit_amount=4000,
last_name="", last_name="",
first_name="", first_name="",
bank="",
join_bde=True, join_bde=True,
join_kfet=True, join_kfet=True,
)) ))
@ -248,7 +244,6 @@ class TestValidateRegistration(TestCase):
credit_amount=500, credit_amount=500,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
join_bde=True, join_bde=True,
join_kfet=False, join_kfet=False,
)) ))
@ -273,7 +268,6 @@ class TestValidateRegistration(TestCase):
credit_amount=500, credit_amount=500,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
join_bde=True, join_bde=True,
join_kfet=False, join_kfet=False,
)) ))
@ -307,16 +301,17 @@ class TestValidateRegistration(TestCase):
credit_amount=4000, credit_amount=4000,
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
join_bde=True, join_bde=True,
join_kfet=True, join_bda=True,
join_bds=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()
self.assertTrue(self.user.profile.registration_valid) self.assertTrue(self.user.profile.registration_valid)
self.assertTrue(NoteUser.objects.filter(user=self.user).exists()) self.assertTrue(NoteUser.objects.filter(user=self.user).exists())
self.assertTrue(Membership.objects.filter(club__name="BDE", user=self.user).exists()) self.assertTrue(Membership.objects.filter(club__name="BDE", user=self.user).exists())
self.assertTrue(Membership.objects.filter(club__name="Kfet", user=self.user).exists()) self.assertTrue(Membership.objects.filter(club__name="BDA", user=self.user).exists())
self.assertTrue(Membership.objects.filter(club__name="BDS", user=self.user).exists())
self.assertEqual(Transaction.objects.filter( self.assertEqual(Transaction.objects.filter(
Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3) Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)

View file

@ -225,9 +225,10 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
user = self.get_object() user = self.get_object()
fee = 0 fee = 0
bde = Club.objects.get(name="BDE") bde = Club.objects.get(name="BDE")
fee += bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid bda = Club.objects.get(name="BDA")
kfet = Club.objects.get(name="Kfet") bds = Club.objects.get(name="BDS")
fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid for auto_club in [bde, bda, bds]:
fee += auto_club.membership_fee_paid if user.profile.paid else auto_club.membership_fee_unpaid
ctx["total_fee"] = "{:.02f}".format(fee / 100, ) ctx["total_fee"] = "{:.02f}".format(fee / 100, )
return ctx return ctx
@ -256,30 +257,20 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
credit_amount = form.cleaned_data["credit_amount"] credit_amount = form.cleaned_data["credit_amount"]
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"]
join_bde = form.cleaned_data["join_bde"] join_bde = form.cleaned_data["join_bde"]
join_kfet = form.cleaned_data["join_kfet"] join_bda = form.cleaned_data["join_bda"]
join_bds = form.cleaned_data["join_bds"]
if not join_bde:
# This software belongs to the BDE.
form.add_error('join_bde', _("You must join the BDE."))
return super().form_invalid(form)
# Calculate required registration fee # 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 bda = Club.objects.get(name="BDA")
# This is mandatory. bds = Club.objects.get(name="BDS")
fee += bde_fee if join_bde else 0 for auto_club, auto_join in zip([bde, bda, bds], [join_bde, join_bda, join_bds]):
kfet = Club.objects.get(name="Kfet") bd_fee = auto_club.membership_fee_paid if user.profile.paid else auto_club.membership_fee_unpaid
kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid fee += bd_fee if auto_join else 0
# Add extra fee for the full membership
fee += kfet_fee if join_kfet else 0
# If the bank pays, then we don't credit now. Treasurers will validate the transaction
# and credit the note later.
credit_type = credit_type
# If the user does not select any payment method, then no credit will be performed. # If the user does not select any payment method, then no credit will be performed.
credit_amount = 0 if credit_type is None else credit_amount credit_amount = 0 if credit_type is None else credit_amount
@ -314,36 +305,23 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
reason="Crédit " + credit_type.special_type + " (Inscription)", reason="Crédit " + credit_type.special_type + " (Inscription)",
last_name=last_name, last_name=last_name,
first_name=first_name, first_name=first_name,
bank=bank,
valid=True, valid=True,
) )
for auto_club, auto_join, name in zip([bde, bda, bds], [join_bde, join_bda, join_bds], ["Adhérent BDE", "Adhérent BDA", "Adhérent BDS"]):
bd_fee = auto_club.membership_fee_paid if user.profile.paid else auto_club.membership_fee_unpaid
if join_bde: if auto_join:
# Create membership for the user to the BDE starting today # Create membership for the user to the BDEAS starting today
membership = Membership( membership = Membership(
club=bde, club=auto_club,
user=user, user=user,
fee=bde_fee, fee=bd_fee,
) )
membership.save() membership.save()
membership.refresh_from_db() membership.refresh_from_db()
membership.roles.add(Role.objects.get(name="Adhérent BDE")) membership.roles.add(Role.objects.get(name=name))
membership.save() membership.save()
if join_kfet:
# Create membership for the user to the Kfet starting today
membership = Membership(
club=kfet,
user=user,
fee=kfet_fee,
)
membership.save()
membership.refresh_from_db()
membership.roles.add(Role.objects.get(name="Adhérent Kfet"))
membership.save()
return ret return ret
def get_success_url(self): def get_success_url(self):

View file

@ -132,8 +132,6 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
first_name = forms.Field(label=_("First name")) first_name = forms.Field(label=_("First name"))
bank = forms.Field(label=_("Bank"))
amount = forms.IntegerField(label=_("Amount"), min_value=0, widget=AmountInput(), disabled=True, required=False) amount = forms.IntegerField(label=_("Amount"), min_value=0, widget=AmountInput(), disabled=True, required=False)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -148,7 +146,6 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
cleaned_data = super().clean() cleaned_data = super().clean()
self.instance.transaction.last_name = cleaned_data["last_name"] self.instance.transaction.last_name = cleaned_data["last_name"]
self.instance.transaction.first_name = cleaned_data["first_name"] self.instance.transaction.first_name = cleaned_data["first_name"]
self.instance.transaction.bank = cleaned_data["bank"]
return cleaned_data return cleaned_data
@transaction.atomic @transaction.atomic

View file

@ -1,4 +1,4 @@
# Generated by Django 2.2.28 on 2022-08-06 13:33 # Generated by Django 2.2.28 on 2022-08-17 20:53
import datetime import datetime
import django.core.validators import django.core.validators
@ -12,7 +12,7 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('note', '0006_trust'), ('note', '0001_initial'),
] ]
operations = [ operations = [

View file

@ -118,5 +118,5 @@ class SpecialTransactionTable(tables.Table):
} }
model = SpecialTransaction model = SpecialTransaction
template_name = 'django_tables2/bootstrap4.html' template_name = 'django_tables2/bootstrap4.html'
fields = ('created_at', 'source', 'destination', 'last_name', 'first_name', 'bank', 'amount', 'reason',) fields = ('created_at', 'source', 'destination', 'last_name', 'first_name', 'amount', 'reason',)
order_by = ('-created_at',) order_by = ('-created_at',)

View file

@ -187,7 +187,6 @@ class TestRemittances(TestCase):
reason="Credit", reason="Credit",
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
) )
self.second_credit = SpecialTransaction.objects.create( self.second_credit = SpecialTransaction.objects.create(
@ -197,7 +196,6 @@ class TestRemittances(TestCase):
reason="Second credit", reason="Second credit",
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto",
bank="Société générale",
) )
self.remittance = Remittance.objects.create( self.remittance = Remittance.objects.create(
@ -275,7 +273,6 @@ class TestRemittances(TestCase):
remittance=self.remittance.pk, remittance=self.remittance.pk,
last_name="Last Name", last_name="Last Name",
first_name="First Name", first_name="First Name",
bank="Bank",
)) ))
self.assertRedirects(response, reverse("treasury:remittance_list"), 302, 200) self.assertRedirects(response, reverse("treasury:remittance_list"), 302, 200)
self.credit.refresh_from_db() self.credit.refresh_from_db()
@ -320,8 +317,7 @@ class TestTreasuryAPI(TestAPI):
amount=4200, amount=4200,
reason="Credit", reason="Credit",
last_name="TOTO", last_name="TOTO",
first_name="Toto", first_name="Toto"
bank="Société générale",
) )
self.remittance = Remittance.objects.create( self.remittance = Remittance.objects.create(
@ -332,7 +328,7 @@ class TestTreasuryAPI(TestAPI):
self.credit.specialtransactionproxy.remittance = self.remittance self.credit.specialtransactionproxy.remittance = self.remittance
self.credit.specialtransactionproxy.save() self.credit.specialtransactionproxy.save()
self.kfet = Club.objects.get(name="Kfet") self.kfet = Club.objects.get(name="BDA")
self.bde = self.kfet.parent_club self.bde = self.kfet.parent_club
self.kfet_membership = Membership( self.kfet_membership = Membership(

View file

@ -174,7 +174,7 @@ class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
class InvoiceDeleteView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView): class InvoiceDeleteView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView):
""" """
Delete a non-validated WEI registration Delete a non-validated registration
""" """
model = Invoice model = Invoice
extra_context = {"title": _("Delete invoice")} extra_context = {"title": _("Delete invoice")}
@ -368,7 +368,6 @@ class LinkTransactionToRemittanceView(ProtectQuerysetMixin, LoginRequiredMixin,
form = context["form"] form = context["form"]
form.fields["last_name"].initial = self.object.transaction.last_name form.fields["last_name"].initial = self.object.transaction.last_name
form.fields["first_name"].initial = self.object.transaction.first_name form.fields["first_name"].initial = self.object.transaction.first_name
form.fields["bank"].initial = self.object.transaction.bank
form.fields["amount"].initial = self.object.transaction.amount form.fields["amount"].initial = self.object.transaction.amount
form.fields["remittance"].queryset = form.fields["remittance"] \ form.fields["remittance"].queryset = form.fields["remittance"] \
.queryset.filter(remittance_type__note=self.object.transaction.source) .queryset.filter(remittance_type__note=self.object.transaction.source)

View file

@ -148,29 +148,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
<div class="{% block containertype %}container{% endblock %} my-3"> <div class="{% block containertype %}container{% endblock %} my-3">
<div id="messages"> <div id="messages">
{% if user.is_authenticated %} {% 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>
{% endif %}
{% if not user.profile.email_confirmed %} {% if not user.profile.email_confirmed %}
<div class="alert alert-warning"> <div class="alert alert-warning">
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %} {% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
</div> </div>
{% endif %} {% endif %}
{% 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 membership and the WEI are 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> </div>
{% block content %} {% block content %}
<p>Default content...</p> <p>Default content...</p>