diff --git a/.coveragerc b/.coveragerc index f21739a5..61b95053 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,10 +1,11 @@ [run] source = - note_kfet - note_theme - note_adherents + adherents + note + theme omit = - note_theme/tests/*.py - note_theme/migrations/*.py - note_adherents/tests/*.py - note_adherents/migrations/*.py + adherents/tests/*.py + adherents/migrations/*.py + note/tests/*.py + note/migrations/*.py + theme/tests/*.py \ No newline at end of file diff --git a/adherents/admin.py b/adherents/admin.py index 72b4015e..a6918d19 100644 --- a/adherents/admin.py +++ b/adherents/admin.py @@ -11,7 +11,9 @@ from .models import Profile class ProfileInline(admin.StackedInline): - """Inline user profile in user admin""" + """ + Inline user profile in user admin + """ model = Profile can_delete = False diff --git a/adherents/migrations/0001_initial.py b/adherents/migrations/0001_initial.py index 9b0992c9..32433430 100644 --- a/adherents/migrations/0001_initial.py +++ b/adherents/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.3 on 2019-07-08 11:48 +# Generated by Django 2.2.3 on 2019-07-16 07:17 from django.conf import settings from django.db import migrations, models @@ -18,8 +18,14 @@ class Migration(migrations.Migration): name='Profile', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('phone_number', models.CharField(max_length=255, verbose_name='phone number')), + ('avatar', models.ImageField(blank=True, max_length=255, upload_to='', verbose_name='profile picture')), + ('phone_number', models.CharField(blank=True, default='', max_length=50, null=True, verbose_name='phone number')), ('section', models.CharField(help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, verbose_name='section')), + ('genre', models.CharField(blank=True, choices=[(None, 'ND'), ('M', 'M'), ('F', 'F')], max_length=1, null=True)), + ('address', models.TextField(blank=True, null=True)), + ('paid', models.BooleanField(default=False, verbose_name='paid')), + ('is_active', models.BooleanField(default=True, verbose_name='is active')), + ('is_deleted', models.BooleanField(default=False, verbose_name='is deleted')), ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ diff --git a/adherents/models.py b/adherents/models.py index cb81a287..947499bd 100644 --- a/adherents/models.py +++ b/adherents/models.py @@ -17,7 +17,6 @@ class Profile(models.Model): We do not want to patch the Django Contrib Auth User class so this model add an user profile with additional information. """ - GENRES = [ (None, "ND"), ("M", "M"), @@ -31,13 +30,12 @@ class Profile(models.Model): avatar = models.ImageField( max_length=255, blank=True, - verbose_name=_('profile picture') + verbose_name=_('profile picture'), ) - phone_number = models.CharField( max_length=50, blank=True, - null=False, + null=True, default='', verbose_name=_('phone number'), ) @@ -46,33 +44,33 @@ class Profile(models.Model): verbose_name=_('section'), help_text=_('e.g. "1A0", "9A♥", "SAPHIRE"'), ) - genre = models.CharField(max_length=1, - blank=False, - null=False, - choices=GENRES + genre = models.CharField( + max_length=1, + blank=True, + null=True, + choices=GENRES, ) address = models.TextField( blank=True, - null=False, - default='' + null=True, ) - remunere = models.BooleanField(verbose_name=_("rémunéré"), - default=False, + paid = models.BooleanField( + verbose_name=_("paid"), + default=False, ) - is_active = models.BooleanField(verbose_name=_("compte actif"), - default=True + is_active = models.BooleanField( + verbose_name=_("is active"), + default=True, ) - is_deleted = models.BooleanField(verbose_name=_("compte supprimé"), - default=False + is_deleted = models.BooleanField( + verbose_name=_("is deleted"), + default=False, ) class Meta: verbose_name = _('user profile') verbose_name_plural = _('user profile') - def __str__(self): - return self.user.get_username() - class MembershipFee(models.Model): """ @@ -87,7 +85,7 @@ class MembershipFee(models.Model): verbose_name=_('date'), ) amount = models.DecimalField( - max_digits=5, # Max 999.99 € + max_digits=5, # Max 999.99 € decimal_places=2, verbose_name=_('amount'), ) @@ -96,12 +94,9 @@ class MembershipFee(models.Model): verbose_name = _('membership fee') verbose_name_plural = _('membership fees') - def __str__(self): - return self.user.get_username() - @receiver(post_save, sender=User) -def save_user_profile(sender, instance, created, **_kwargs): +def save_user_profile(instance, created, **_kwargs): """ Hook to save an user profile when an user is updated """ diff --git a/note/__init__.py b/note/__init__.py index e69de29b..4773b310 100644 --- a/note/__init__.py +++ b/note/__init__.py @@ -0,0 +1,5 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2018-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +default_app_config = 'note.apps.NoteConfig' diff --git a/note/admin.py b/note/admin.py index d7ff9c07..122c11e3 100644 --- a/note/admin.py +++ b/note/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin -from .models import NoteClub,NoteSpec,NoteUser +from .models import NoteClub, NoteSpec, NoteUser from .models import Alias + # Register your models here. admin.site.register(NoteClub) admin.site.register(NoteSpec) diff --git a/note/apps.py b/note/apps.py index eab40c5e..439140b3 100644 --- a/note/apps.py +++ b/note/apps.py @@ -1,5 +1,11 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2018-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ class NoteConfig(AppConfig): name = 'note' + verbose_name = _('note') diff --git a/note/migrations/0001_initial.py b/note/migrations/0001_initial.py index 5f777cac..b694bbf9 100644 --- a/note/migrations/0001_initial.py +++ b/note/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.3 on 2019-07-08 14:08 +# Generated by Django 2.2.3 on 2019-07-16 07:17 from django.conf import settings from django.db import migrations, models @@ -19,8 +19,8 @@ class Migration(migrations.Migration): name='NoteClub', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('solde', models.IntegerField(help_text="en centime, l' argent crédité pour cette instance", verbose_name='solde du compte')), - ('active', models.BooleanField(default=True, verbose_name='etat du compte')), + ('balance', models.DecimalField(decimal_places=2, default=0, help_text='money credited for this instance', max_digits=8, verbose_name='account balance')), + ('is_active', models.BooleanField(default=True, verbose_name='is active')), ], options={ 'abstract': False, @@ -30,9 +30,9 @@ class Migration(migrations.Migration): name='NoteSpec', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('solde', models.IntegerField(help_text="en centime, l' argent crédité pour cette instance", verbose_name='solde du compte')), - ('active', models.BooleanField(default=True, verbose_name='etat du compte')), - ('account_type', models.CharField(choices=[('CH', 'chèques'), ('CB', 'Carte Bancaire'), ('VB', 'Virement Bancaire'), ('CA', 'Cash'), ('RB', 'Remboursement')], max_length=2, unique=True)), + ('balance', models.DecimalField(decimal_places=2, default=0, help_text='money credited for this instance', max_digits=8, verbose_name='account balance')), + ('is_active', models.BooleanField(default=True, verbose_name='is active')), + ('account_type', models.CharField(choices=[('CH', 'bank check'), ('CB', 'credit card'), ('VB', 'bank transfer'), ('CA', 'cash'), ('RB', 'refund')], max_length=2, unique=True)), ], options={ 'abstract': False, @@ -42,13 +42,13 @@ class Migration(migrations.Migration): name='NoteUser', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('solde', models.IntegerField(help_text="en centime, l' argent crédité pour cette instance", verbose_name='solde du compte')), - ('active', models.BooleanField(default=True, verbose_name='etat du compte')), + ('balance', models.DecimalField(decimal_places=2, default=0, help_text='money credited for this instance', max_digits=8, verbose_name='account balance')), + ('is_active', models.BooleanField(default=True, verbose_name='is active')), ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ - 'verbose_name': "One's Note", - 'verbose_name_plural': 'Users Note', + 'verbose_name': "one's note", + 'verbose_name_plural': 'users note', }, ), migrations.CreateModel( diff --git a/note/models.py b/note/models.py index d5b2ebdd..8424355d 100644 --- a/note/models.py +++ b/note/models.py @@ -17,71 +17,73 @@ class Alias(models.Model): """ alias = models.TextField( "alias", - unique = True, - blank = False, - null = False, + unique=True, + blank=False, + null=False, ) - limit = models.Q(app_label="note", model="NoteUser") | models.Q(app_label="note",model="NoteClub") + # Owner can be linked to an user note or a club note + limit = models.Q(app_label="note", model="NoteUser") | models.Q(app_label="note", model="NoteClub") owner_id = models.PositiveIntegerField() - owner_type = models.ForeignKey(ContentType, - on_delete=models.CASCADE, - limit_choices_to=limit) - owner = GenericForeignKey('owner_type','owner_id') + owner_type = models.ForeignKey( + ContentType, + on_delete=models.CASCADE, + limit_choices_to=limit + ) + owner = GenericForeignKey('owner_type', 'owner_id') + class Note(models.Model): """ An abstract model, use to add transactions capabilities to a user """ - - solde = models.IntegerField( - verbose_name=_('solde du compte'), - help_text=_("en centime, l' argent crédité pour cette instance") + balance = models.DecimalField( + verbose_name=_('account balance'), + help_text=_("money credited for this instance"), + decimal_places=2, # Limit to centimes + max_digits=8, # Limit to 999999,99€ + default=0, ) - active = models.BooleanField( - default = True, - verbose_name=_('etat du compte') + is_active = models.BooleanField( + default=True, + verbose_name=_('is active') ) class Meta: abstract = True + class NoteUser(Note): """ - A Note associated to a User + A Note associated to an User """ user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, ) - class Meta: - verbose_name = _("One's Note") - verbose_name_plural = _("Users Note") - def __str__(self): - return self.user.get_username() + class Meta: + verbose_name = _("one's note") + verbose_name_plural = _("users note") class NoteSpec(Note): """ - A Note for special Account, where real money enter or leave the system. - - Cash - - Credit Card - - Bank Transfert - - Bank Check - - Refund + A Note for special account, where real money enter or leave the system """ account_type = models.CharField( - max_length = 2, - choices = (("CH","chèques"), - ("CB","Carte Bancaire"), - ("VB","Virement Bancaire"), - ("CA","Cash"), - ("RB","Remboursement") + max_length=2, + choices=( + ("CH", _("bank check")), + ("CB", _("credit card")), + ("VB", _("bank transfer")), + ("CA", _("cash")), + ("RB", _("refund")), ), - unique = True + unique=True, ) + class NoteClub(Note): - #to be added + # to be added pass diff --git a/note/tests.py b/note/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/note/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/note/tests/__init__.py b/note/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/note/views.py b/note/views.py deleted file mode 100644 index 91ea44a2..00000000 --- a/note/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/note_kfet/urls.py b/note_kfet/urls.py index e2cd4951..e78fee22 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -15,7 +15,7 @@ urlpatterns = [ path('i18n/', include('django.conf.urls.i18n')), path('accounts/', include('django.contrib.auth.urls')), path('accounts/profile/', - RedirectView.as_view(pattern_name='index')), + RedirectView.as_view(pattern_name='index')), path('admin/doc/', include('django.contrib.admindocs.urls')), path('admin/', admin.site.urls), ]