From 3bcc75c967fd57bea0acd2b42965d9a95571748c Mon Sep 17 00:00:00 2001 From: Dalahro Date: Tue, 5 Jul 2016 00:14:19 +0200 Subject: [PATCH 01/26] Changement d'icone de bouton :D --- cotisations/templates/cotisations/aff_cotisations.html | 2 +- users/templates/users/aff_bans.html | 2 +- users/templates/users/aff_whitelists.html | 2 +- users/templates/users/profil.html | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cotisations/templates/cotisations/aff_cotisations.html b/cotisations/templates/cotisations/aff_cotisations.html index cfb7f25c..c1a88139 100644 --- a/cotisations/templates/cotisations/aff_cotisations.html +++ b/cotisations/templates/cotisations/aff_cotisations.html @@ -18,7 +18,7 @@ {{ facture.prix }} {{ facture.paiement }} {{ facture.date }} - Editer + Editer {% endfor %} diff --git a/users/templates/users/aff_bans.html b/users/templates/users/aff_bans.html index cc94a24b..a32876d8 100644 --- a/users/templates/users/aff_bans.html +++ b/users/templates/users/aff_bans.html @@ -14,7 +14,7 @@ {{ ban.raison }} {{ ban.date_start }} {{ ban.date_end }} - Editer + Editer {% endfor %} diff --git a/users/templates/users/aff_whitelists.html b/users/templates/users/aff_whitelists.html index a23a78ce..cc919628 100644 --- a/users/templates/users/aff_whitelists.html +++ b/users/templates/users/aff_whitelists.html @@ -14,7 +14,7 @@ {{ whitelist.raison }} {{ whitelist.date_start }} {{ whitelist.date_end }} - Editer + Editer {% endfor %} diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 91097c6b..1e8fe834 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -5,7 +5,7 @@ {% block content %}

Adhérent

- Editer + Editer Changer le mot de passe Changer le statut Ajouter un droit @@ -101,7 +101,7 @@

Aucun bannissement

{% endif %}

Accès à titre gracieux :

-

Accorder un accès à titre gracieux

+

Accorder un accès à titre gracieux

{% if white_list %} {% include "users/aff_whitelists.html" with white_list=white_list %} {% else %} From 824c349d9cca5fdb65dd9c24cfd17aa39bcdaded Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 01:15:51 +0200 Subject: [PATCH 02/26] Template de settings --- re2o/settings.py | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 re2o/settings.py diff --git a/re2o/settings.py b/re2o/settings.py new file mode 100644 index 00000000..a627b67d --- /dev/null +++ b/re2o/settings.py @@ -0,0 +1,108 @@ +""" +Django settings for re2o project. + +Generated by 'django-admin startproject' using Django 1.8.13. + +For more information on this file, see +https://docs.djangoproject.com/en/1.8/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.8/ref/settings/ +""" + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os +from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'bootstrap3', + 'users', + 'machines', + 'cotisations', + 'topologie', + 'search', + 'logs', +) + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.security.SecurityMiddleware', +) + +ROOT_URLCONF = 're2o.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(BASE_DIR, 'templates').replace('\\', '/'), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 're2o.wsgi.application' + + +# Internationalization +# https://docs.djangoproject.com/en/1.8/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# django-bootstrap3 config dictionnary +BOOTSTRAP3 = { + 'jquery_url': '/static/js/jquery-2.2.4.min.js', + 'base_url': '/static/bootstrap/', + 'include_jquery': True, + } + +BOOTSTRAP_BASE_URL = '/static/bootstrap/' + +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join( + BASE_DIR, + 'static', + ), +) + +STATIC_URL = '/static/' From cae1f8b8070aa5441fc056634a9eeee7ce1b5986 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 02:22:11 +0200 Subject: [PATCH 03/26] Gestion des ventes multiples sur une meme facture --- cotisations/views.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cotisations/views.py b/cotisations/views.py index 571be4a8..c7570da5 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -34,14 +34,14 @@ def is_adherent(user): else: return True -def create_cotis(facture, user, article): +def create_cotis(facture, user, duration): """ Update et crée l'objet cotisation associé à une facture, prend en argument l'user, la facture pour la quantitéi, et l'article pour la durée""" cotisation=Cotisation(facture=facture) date_max = end_adhesion(user) or timezone.now() if date_max < timezone.now(): datemax = timezone.now() cotisation.date_start=date_max - cotisation.date_end = cotisation.date_start + relativedelta(months=article[0].duration*facture.number) + cotisation.date_end = cotisation.date_start + relativedelta(months=duration) cotisation.save() return @@ -56,11 +56,12 @@ def new_facture(request, userid): if facture_form.is_valid(): new_facture = facture_form.save(commit=False) article = facture_form.cleaned_data['article'] - new_facture.prix = article[0].prix - new_facture.name = article[0].name + new_facture.prix = sum(art.prix for art in article) + new_facture.name = ' - '.join(art.name for art in article) new_facture.save() - if article[0].cotisation == True: - create_cotis(new_facture, user, article) + if any(art.cotisation for art in article): + duration = sum(art.duration*facture.number for art in article if art.cotisation) + create_cotis(new_facture, user, duration) messages.success(request, "La cotisation a été prolongée pour l'adhérent %s " % user.name ) else: messages.success(request, "La facture a été crée") From a0f656b3189cdd19aaf54d34683f4bf84a4cb7d1 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 11:33:27 +0200 Subject: [PATCH 04/26] =?UTF-8?q?Ajoute=20des=20etiquettes,=20factorise=20?= =?UTF-8?q?un=20peu=20le=20code=20des=20mod=C3=A8les=20avec=20de=20l'herit?= =?UTF-8?q?age?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/models.py | 5 +++++ machines/models.py | 3 ++- users/models.py | 22 ++++++++-------------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cotisations/models.py b/cotisations/models.py index 60c6cc33..d72ec60b 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -56,6 +56,8 @@ class NewFactureForm(ModelForm): self.fields['cheque'].required = False self.fields['banque'].required = False self.fields['cheque'].label = 'Numero de chèque' + self.fields['banque'].empty_label = "Non renseigné" + self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement" class Meta: model = Facture @@ -71,6 +73,9 @@ class EditFactureForm(ModelForm): self.fields['cheque'].label = 'Numero de chèque' self.fields['name'].label = 'Designation' self.fields['prix'].label = 'Prix unitaire' + self.fields['banque'].empty_label = "Non renseigné" + self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement" + self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire" class Meta: model = Facture diff --git a/machines/models.py b/machines/models.py index 1cf9c557..778a83fb 100644 --- a/machines/models.py +++ b/machines/models.py @@ -25,7 +25,7 @@ class Interface(models.Model): mac_address = MACAddressField(integer=False, unique=True) machine = models.ForeignKey('Machine', on_delete=models.PROTECT) details = models.CharField(max_length=255, blank=True) - dns = models.CharField(help_text="Obligatoire et unique", max_length=255, unique=True) + dns = models.CharField(help_text="Obligatoire et unique, doit se terminer en .rez et ne pas comporter de points", max_length=255, unique=True) def __str__(self): return self.dns @@ -45,6 +45,7 @@ class EditMachineForm(ModelForm): super(EditMachineForm, self).__init__(*args, **kwargs) self.fields['name'].label = 'Nom de la machine' self.fields['type'].label = 'Type de machine' + self.fields['type'].empty_label = "Séléctionner un type de machine" class NewMachineForm(EditMachineForm): class Meta(EditMachineForm.Meta): diff --git a/users/models.py b/users/models.py index b37f6066..446dac15 100644 --- a/users/models.py +++ b/users/models.py @@ -29,7 +29,7 @@ class User(models.Model): surname = models.CharField(max_length=255) pseudo = models.CharField(max_length=255, unique=True) email = models.EmailField() - school = models.ForeignKey('School', on_delete=models.PROTECT) + school = models.ForeignKey('School', on_delete=models.PROTECT, null=False, blank=False) comment = models.CharField(help_text="Commentaire, promo", max_length=255, blank=True) room = models.OneToOneField('topologie.Room', on_delete=models.PROTECT, blank=True, null=True) pwd_ssha = models.CharField(max_length=255) @@ -80,19 +80,6 @@ class Whitelist(models.Model): def __str__(self): return str(self.user) + ' ' + str(self.raison) -class UserForm(ModelForm): - def __init__(self, *args, **kwargs): - super(InfoForm, self).__init__(*args, **kwargs) - self.fields['name'].label = 'Nom' - self.fields['surname'].label = 'Prénom' - self.fields['school'].label = 'Établissement' - self.fields['comment'].label = 'Commentaire' - self.fields['room'].label = 'Chambre' - - class Meta: - model = User - fields = '__all__' - class InfoForm(ModelForm): force = forms.BooleanField(label="Forcer le déménagement ?", initial=False, required=False) @@ -103,6 +90,8 @@ class InfoForm(ModelForm): self.fields['school'].label = 'Établissement' self.fields['comment'].label = 'Commentaire' self.fields['room'].label = 'Chambre' + self.fields['room'].empty_label = "Pas de chambre" + self.fields['school'].empty_label = "Séléctionner un établissement" def clean_force(self): if self.cleaned_data.get('force', False): @@ -113,6 +102,10 @@ class InfoForm(ModelForm): model = User fields = ['name','surname','pseudo','email', 'school', 'comment', 'room'] +class UserForm(InfoForm): + class Meta(InfoForm.Meta): + fields = '__all__' + class PasswordForm(ModelForm): class Meta: model = User @@ -132,6 +125,7 @@ class RightForm(ModelForm): def __init__(self, *args, **kwargs): super(RightForm, self).__init__(*args, **kwargs) self.fields['right'].label = 'Droit' + self.fields['right'].empty_label = "Choisir un nouveau droit" class Meta: model = Right From 90918c040ef1c2c2676eb1e672a63ec40996d991 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 11:51:29 +0200 Subject: [PATCH 05/26] =?UTF-8?q?Factorisation/h=C3=A9ritage=20dans=20les?= =?UTF-8?q?=20models?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/models.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/cotisations/models.py b/cotisations/models.py index d72ec60b..eec3b1e2 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -61,22 +61,16 @@ class NewFactureForm(ModelForm): class Meta: model = Facture - exclude = ['user', 'prix', 'name', 'valid'] + fields = ['paiement','banque','cheque','number'] + +class EditFactureForm(NewFactureForm): + class Meta(NewFactureForm.Meta): + fields = '__all__' -class EditFactureForm(ModelForm): def __init__(self, *args, **kwargs): super(EditFactureForm, self).__init__(*args, **kwargs) self.fields['user'].label = 'Adherent' - self.fields['number'].label = 'Quantité' - self.fields['cheque'].required = False - self.fields['banque'].required = False - self.fields['cheque'].label = 'Numero de chèque' self.fields['name'].label = 'Designation' self.fields['prix'].label = 'Prix unitaire' - self.fields['banque'].empty_label = "Non renseigné" - self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement" self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire" - - class Meta: - model = Facture - fields = '__all__' + self.fields.pop('article') From 2df375c7c974b3dddbefce0a070b7e5256ce1ead Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 12:21:43 +0200 Subject: [PATCH 06/26] Attribut active/inactive sur une machine --- cotisations/admin.py | 4 ++-- machines/admin.py | 2 +- .../migrations/0013_auto_20160705_1014.py | 24 +++++++++++++++++++ machines/models.py | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 machines/migrations/0013_auto_20160705_1014.py diff --git a/cotisations/admin.py b/cotisations/admin.py index 03a7efbe..40b04591 100644 --- a/cotisations/admin.py +++ b/cotisations/admin.py @@ -3,10 +3,10 @@ from django.contrib import admin from .models import Facture, Article, Banque, Paiement, Cotisation class FactureAdmin(admin.ModelAdmin): - list_display = ('user','paiement','name', 'number', 'date') + list_display = ('user','paiement','name', 'number','prix', 'date','valid') class ArticleAdmin(admin.ModelAdmin): - list_display = ('name','prix','cotisation') + list_display = ('name','prix','cotisation','duration') class BanqueAdmin(admin.ModelAdmin): list_display = ('name',) diff --git a/machines/admin.py b/machines/admin.py index 5931c99d..0122d746 100644 --- a/machines/admin.py +++ b/machines/admin.py @@ -3,7 +3,7 @@ from django.contrib import admin from .models import Machine, MachineType, IpList, Interface class MachineAdmin(admin.ModelAdmin): - list_display = ('user','name','type') + list_display = ('user','name','type','active') class MachineTypeAdmin(admin.ModelAdmin): list_display = ('type',) diff --git a/machines/migrations/0013_auto_20160705_1014.py b/machines/migrations/0013_auto_20160705_1014.py new file mode 100644 index 00000000..68b67758 --- /dev/null +++ b/machines/migrations/0013_auto_20160705_1014.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0012_auto_20160704_0118'), + ] + + operations = [ + migrations.AddField( + model_name='machine', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='interface', + name='dns', + field=models.CharField(max_length=255, unique=True, help_text='Obligatoire et unique, doit se terminer en .rez et ne pas comporter de points'), + ), + ] diff --git a/machines/models.py b/machines/models.py index 778a83fb..0276785c 100644 --- a/machines/models.py +++ b/machines/models.py @@ -8,6 +8,7 @@ class Machine(models.Model): user = models.ForeignKey('users.User', on_delete=models.PROTECT) type = models.ForeignKey('MachineType', on_delete=models.PROTECT) name = models.CharField(max_length=255, help_text="Optionnel", blank=True, null=True) + active = models.BooleanField(default=True) def __str__(self): return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name) From cc6f98f92f6ab9995c20232b14b8f83b08ee2ac3 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 12:36:08 +0200 Subject: [PATCH 07/26] =?UTF-8?q?Fonction=20qui=20permet=20de=20savoir=20s?= =?UTF-8?q?i=20une=20machine=20a=20le=20droit=20=C3=A0=20internet=20ou=20n?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/views.py | 6 ++++++ users/views.py | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/machines/views.py b/machines/views.py index f06eb5ff..5844d16c 100644 --- a/machines/views.py +++ b/machines/views.py @@ -10,6 +10,7 @@ from django.contrib import messages from .models import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, NewInterfaceForm from .models import Machine, Interface, IpList from users.models import User +from users.views import has_access def unassign_ips(user): machines = Interface.objects.filter(machine=Machine.objects.filter(user=user)) @@ -41,6 +42,11 @@ def unassign_ipv4(interface): interface.ipv4 = None interface.save() +def is_active(interface): + machine = interface.machine + user = machine.user + return machine.active and has_access(user) + def form(ctx, template, request): c = ctx c.update(csrf(request)) diff --git a/users/views.py b/users/views.py index d29e0621..2e00b1d7 100644 --- a/users/views.py +++ b/users/views.py @@ -62,10 +62,7 @@ def is_whitelisted(user): def has_access(user): """ Renvoie si un utilisateur a accès à internet""" - if user.state == User.STATE_ACTIVE and not is_ban(user) and ( is_adherent(user) or is_whitelisted(user)): - return True - else: - return False + return user.state == User.STATE_ACTIVE and not is_ban(user) and ( is_adherent(user) or is_whitelisted(user)) def form(ctx, template, request): c = ctx From ee9b6e4c88457c96d7b749d99fbf4b2fec94e7fb Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 12:39:31 +0200 Subject: [PATCH 08/26] =?UTF-8?q?Deplace=20la=20fonction=20precedemment=20?= =?UTF-8?q?cr=C3=A9e=20pour=20=C3=A9viter=20les=20imports=20circulaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/views.py | 6 ------ users/views.py | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/machines/views.py b/machines/views.py index 5844d16c..f06eb5ff 100644 --- a/machines/views.py +++ b/machines/views.py @@ -10,7 +10,6 @@ from django.contrib import messages from .models import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, NewInterfaceForm from .models import Machine, Interface, IpList from users.models import User -from users.views import has_access def unassign_ips(user): machines = Interface.objects.filter(machine=Machine.objects.filter(user=user)) @@ -42,11 +41,6 @@ def unassign_ipv4(interface): interface.ipv4 = None interface.save() -def is_active(interface): - machine = interface.machine - user = machine.user - return machine.active and has_access(user) - def form(ctx, template, request): c = ctx c.update(csrf(request)) diff --git a/users/views.py b/users/views.py index 2e00b1d7..c5d734cc 100644 --- a/users/views.py +++ b/users/views.py @@ -64,6 +64,12 @@ def has_access(user): """ Renvoie si un utilisateur a accès à internet""" return user.state == User.STATE_ACTIVE and not is_ban(user) and ( is_adherent(user) or is_whitelisted(user)) +def is_active(interface): + """ Renvoie si une interface doit avoir accès ou non """ + machine = interface.machine + user = machine.user + return machine.active and has_access(user) + def form(ctx, template, request): c = ctx c.update(csrf(request)) From 209ff89b7d742c191ab4264f41085f38ae80c80b Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 14:01:29 +0200 Subject: [PATCH 09/26] =?UTF-8?q?Rend=20les=20champs=20banque=20et=20numer?= =?UTF-8?q?o=20de=20ch=C3=A8que=20obligatoire=20si=20paiement=20par=20ch?= =?UTF-8?q?=C3=A8que?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/models.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cotisations/models.py b/cotisations/models.py index eec3b1e2..6ea32e65 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -63,6 +63,16 @@ class NewFactureForm(ModelForm): model = Facture fields = ['paiement','banque','cheque','number'] + def clean(self): + cleaned_data=super(NewFactureForm, self).clean() + paiement = cleaned_data.get("paiement") + cheque = cleaned_data.get("cheque") + banque = cleaned_data.get("banque") + print(paiement.moyen) + if paiement.moyen=="chèque" and not (cheque and banque): + raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires") + return cleaned_data + class EditFactureForm(NewFactureForm): class Meta(NewFactureForm.Meta): fields = '__all__' From a9c93b235b7efcbec6a37ae6fcc2fbbfb2712ccc Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 16:19:17 +0200 Subject: [PATCH 10/26] =?UTF-8?q?Classe=20par=20date=20du=20plus=20r=C3=A9?= =?UTF-8?q?cent=20au=20plus=20ancien=20pour=20les=20cotiz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cotisations/views.py b/cotisations/views.py index c7570da5..d7d531e0 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -82,5 +82,5 @@ def edit_facture(request, factureid): return form({'factureform': facture_form}, 'cotisations/facture.html', request) def index(request): - facture_list = Facture.objects.order_by('pk') + facture_list = Facture.objects.order_by('date').reverse() return render(request, 'cotisations/index.html', {'facture_list': facture_list}) From ffb22e96786a088c4286395f02eab052cc926388 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 5 Jul 2016 16:30:46 +0200 Subject: [PATCH 11/26] Passe les dates dans le bon fuseau horraire, en type fr --- re2o/settings.py | 4 ++-- users/models.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/re2o/settings.py b/re2o/settings.py index a627b67d..8d15d917 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -75,9 +75,9 @@ WSGI_APPLICATION = 're2o.wsgi.application' # Internationalization # https://docs.djangoproject.com/en/1.8/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = 'fr-fr' -TIME_ZONE = 'UTC' +TIME_ZONE = 'Europe/Paris' USE_I18N = True diff --git a/users/models.py b/users/models.py index 446dac15..dacb9855 100644 --- a/users/models.py +++ b/users/models.py @@ -66,7 +66,7 @@ class Ban(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) raison = models.CharField(max_length=255) date_start = models.DateTimeField(auto_now_add=True) - date_end = models.DateTimeField(help_text='%m/%d/%y %H:%M:%S') + date_end = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S') def __str__(self): return str(self.user) + ' ' + str(self.raison) @@ -75,7 +75,7 @@ class Whitelist(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) raison = models.CharField(max_length=255) date_start = models.DateTimeField(auto_now_add=True) - date_end = models.DateTimeField(help_text='%m/%d/%y %H:%M:%S') + date_end = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S') def __str__(self): return str(self.user) + ' ' + str(self.raison) From 8dab793a77c6e0d01aa6eb7bc3281f9afa3dc786 Mon Sep 17 00:00:00 2001 From: Dalahro Date: Tue, 5 Jul 2016 18:31:06 +0200 Subject: [PATCH 12/26] Oops, la recherche marche maintenant --- search/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/search/views.py b/search/views.py index b608885a..daf12f60 100644 --- a/search/views.py +++ b/search/views.py @@ -23,7 +23,7 @@ def search_result(search, type): date_fin = None states=[] co=[] - aff=[0,1,2,3,4] + aff=['0','1','2','3','4'] if(type): aff = search.cleaned_data['affichage'] co = search.cleaned_data['connexion'] @@ -32,7 +32,7 @@ def search_result(search, type): date_fin = search.cleaned_data['date_fin'] date_query = Q() if aff==[]: - aff = [0,1,2,3,4] + aff = ['0','1','2','3','4'] if date_deb != None: date_query = date_query & Q(date__gte=date_deb) if date_fin != None: From 13bbfa2f789d54a3542a7b0b4ab836a4274759b7 Mon Sep 17 00:00:00 2001 From: Dalahro Date: Tue, 5 Jul 2016 19:34:57 +0200 Subject: [PATCH 13/26] Liste des bans et aatgs, +/- des liens, petit changement sur le fonctionnement du profil --- cotisations/models.py | 1 - .../templates/cotisations/sidebar.html | 2 - machines/templates/machines/aff_machines.html | 2 +- machines/templates/machines/sidebar.html | 1 - users/templates/users/aff_users.html | 8 +--- users/templates/users/index.html | 1 + users/templates/users/index_ban.html | 13 ++++++ users/templates/users/index_whitelist.html | 13 ++++++ users/templates/users/sidebar.html | 5 +- users/urls.py | 4 +- users/views.py | 46 +++++++++++-------- 11 files changed, 61 insertions(+), 35 deletions(-) create mode 100644 users/templates/users/index_ban.html create mode 100644 users/templates/users/index_whitelist.html diff --git a/cotisations/models.py b/cotisations/models.py index 6ea32e65..2828be38 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -68,7 +68,6 @@ class NewFactureForm(ModelForm): paiement = cleaned_data.get("paiement") cheque = cleaned_data.get("cheque") banque = cleaned_data.get("banque") - print(paiement.moyen) if paiement.moyen=="chèque" and not (cheque and banque): raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires") return cleaned_data diff --git a/cotisations/templates/cotisations/sidebar.html b/cotisations/templates/cotisations/sidebar.html index 8894fcbb..0b4c5c42 100644 --- a/cotisations/templates/cotisations/sidebar.html +++ b/cotisations/templates/cotisations/sidebar.html @@ -1,7 +1,5 @@ {% extends "base.html" %} {% block sidebar %} -

Créer une facture

-

Editer une facture

Liste des factures

{% endblock %} diff --git a/machines/templates/machines/aff_machines.html b/machines/templates/machines/aff_machines.html index 8840a7b7..612c1366 100644 --- a/machines/templates/machines/aff_machines.html +++ b/machines/templates/machines/aff_machines.html @@ -16,7 +16,7 @@ {{ machine.machine.type }} {{ machine.mac_address }} {{ machine.ipv4 }} - Editer + Editer {% endfor %} diff --git a/machines/templates/machines/sidebar.html b/machines/templates/machines/sidebar.html index a7464bb5..2d6342fc 100644 --- a/machines/templates/machines/sidebar.html +++ b/machines/templates/machines/sidebar.html @@ -1,5 +1,4 @@ {% extends "base.html" %} {% block sidebar %} -

Nouvelle machine

{% endblock %} diff --git a/users/templates/users/aff_users.html b/users/templates/users/aff_users.html index d9cfaab7..8ad206cc 100644 --- a/users/templates/users/aff_users.html +++ b/users/templates/users/aff_users.html @@ -21,12 +21,8 @@ Désactivée {% endif %} -
- {% csrf_token %} - - -
- + + {% endfor %} diff --git a/users/templates/users/index.html b/users/templates/users/index.html index 34a4f3d7..690399d2 100644 --- a/users/templates/users/index.html +++ b/users/templates/users/index.html @@ -4,6 +4,7 @@ {% block title %}Utilisateurs{% endblock %} {% block content %} +

Adhérents

{% include "users/aff_users.html" with users_list=users_list %}

diff --git a/users/templates/users/index_ban.html b/users/templates/users/index_ban.html new file mode 100644 index 00000000..86428706 --- /dev/null +++ b/users/templates/users/index_ban.html @@ -0,0 +1,13 @@ +{% extends "users/sidebar.html" %} +{% load bootstrap3 %} + +{% block title %}Utilisateurs{% endblock %} + +{% block content %} +

Bannissements

+ {% include "users/aff_bans.html" with ban_list=ban_list %} +
+
+
+{% endblock %} + diff --git a/users/templates/users/index_whitelist.html b/users/templates/users/index_whitelist.html new file mode 100644 index 00000000..009fb06f --- /dev/null +++ b/users/templates/users/index_whitelist.html @@ -0,0 +1,13 @@ +{% extends "users/sidebar.html" %} +{% load bootstrap3 %} + +{% block title %}Utilisateurs{% endblock %} + +{% block content %} +

Accès à titre gracieux

+ {% include "users/aff_whitelists.html" with white_list=white_list %} +
+
+
+{% endblock %} + diff --git a/users/templates/users/sidebar.html b/users/templates/users/sidebar.html index a976d4ac..1cc97e47 100644 --- a/users/templates/users/sidebar.html +++ b/users/templates/users/sidebar.html @@ -2,9 +2,8 @@ {% block sidebar %}

Créer un adhérent

-

Editer un adhérent

Liste des adhérents

-

Ajouter un bannissement

-

Gérer les bannissements

+

Liste des bannissements

+

Liste des accès à titre gracieux

Retirer un droit rezo

{% endblock %} diff --git a/users/urls.py b/users/urls.py index e4a92a27..a7d8b89a 100644 --- a/users/urls.py +++ b/users/urls.py @@ -13,7 +13,9 @@ urlpatterns = [ url(r'^edit_whitelist/(?P[0-9]+)$', views.edit_whitelist, name='edit-whitelist'), url(r'^add_right/(?P[0-9]+)$', views.add_right, name='add-right'), url(r'^del_right/$', views.del_right, name='del-right'), - url(r'^profil/$', views.profil, name='profil'), + url(r'^profil/(?P[0-9]+)$', views.profil, name='profil'), + url(r'^index_ban/$', views.index_ban, name='index-ban'), + url(r'^index_white/$', views.index_white, name='index-white'), url(r'^$', views.index, name='index'), ] diff --git a/users/views.py b/users/views.py index c5d734cc..a4ae76c4 100644 --- a/users/views.py +++ b/users/views.py @@ -224,24 +224,30 @@ def index(request): connexion.append([user, has_access(user)]) return render(request, 'users/index.html', {'users_list': connexion}) -def profil(request): - if request.method == 'POST': - profil = ProfilForm(request.POST or None) - if profil.is_valid(): - profils = profil.cleaned_data['user'] - users = User.objects.get(pseudo = profils) - machines = Interface.objects.filter(machine=Machine.objects.filter(user__pseudo = users)) - factures = Facture.objects.filter(user__pseudo = users) - bans = Ban.objects.filter(user__pseudo = users) - whitelists = Whitelist.objects.filter(user__pseudo = users) - end_bans = None - end_whitelists = None - if(is_ban(users)): - end_bans=end_ban(users) - if(is_whitelisted(users)): - end_whitelists=end_whitelist(users) - list_droits = Right.objects.filter(user=users) - return render(request, 'users/profil.html', {'user': users, 'machine_list' :machines, 'facture_list':factures, 'ban_list':bans, 'white_list':whitelists,'end_ban':end_bans,'end_whitelist':end_whitelists, 'end_adhesion':end_adhesion(users), 'actif':has_access(users), 'list_droits': list_droits}) - return redirect("/users/") - return redirect("/users/") +def index_ban(request): + ban_list = Ban.objects.order_by('date_start') + return render(request, 'users/index_ban.html', {'ban_list':ban_list}) + +def index_white(request): + white_list = Whitelist.objects.order_by('date_start') + return render(request, 'users/index_whitelist.html', {'white_list':white_list}) + +def profil(request, userid): + try: + users = User.objects.get(pk=userid) + except User.DoesNotExist: + messages.error(request, u"Utilisateur inexistant" ) + return redirect("/users/") + machines = Interface.objects.filter(machine=Machine.objects.filter(user__pseudo = users)) + factures = Facture.objects.filter(user__pseudo = users) + bans = Ban.objects.filter(user__pseudo = users) + whitelists = Whitelist.objects.filter(user__pseudo = users) + end_bans = None + end_whitelists = None + if(is_ban(users)): + end_bans=end_ban(users) + if(is_whitelisted(users)): + end_whitelists=end_whitelist(users) + list_droits = Right.objects.filter(user=users) + return render(request, 'users/profil.html', {'user': users, 'machine_list' :machines, 'facture_list':factures, 'ban_list':bans, 'white_list':whitelists,'end_ban':end_bans,'end_whitelist':end_whitelists, 'end_adhesion':end_adhesion(users), 'actif':has_access(users), 'list_droits': list_droits}) From 01a63d361b9f6057aaf3f31e212dc909858ef814 Mon Sep 17 00:00:00 2001 From: Dalahro Date: Tue, 5 Jul 2016 20:01:37 +0200 Subject: [PATCH 14/26] Remplacement date inscription par date fin cotis dans liste Petit tiret --- search/views.py | 7 ++++++- users/templates/users/aff_users.html | 4 ++-- users/templates/users/profil.html | 2 +- users/views.py | 7 ++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/search/views.py b/search/views.py index daf12f60..28830313 100644 --- a/search/views.py +++ b/search/views.py @@ -12,6 +12,7 @@ from machines.models import Machine, Interface from cotisations.models import Facture from search.models import SearchForm, SearchFormPlus from users.views import has_access +from cotisations.views import end_adhesion def form(ctx, template, request): c = ctx @@ -54,9 +55,13 @@ def search_result(search, type): users = User.objects.filter((Q(pseudo__icontains = search) | Q(name__icontains = search) | Q(surname__icontains = search)) & query) connexion = [] for user in users: + end=end_adhesion(user) access=has_access(user) if(len(co)==0 or (len(co)==1 and bool(co[0])==access) or (len(co)==2 and (bool(co[0])==access or bool(co[1])==access))): - connexion.append([user, access]) + if(end!=None): + connexion.append([user, access, end]) + else: + connexion.append([user, access, "Non adhérent"]) query = Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search) if i == '1': machines = Interface.objects.filter(machine=Machine.objects.filter(query)) | Interface.objects.filter(Q(dns__icontains = search)) diff --git a/users/templates/users/aff_users.html b/users/templates/users/aff_users.html index 8ad206cc..07dd5bef 100644 --- a/users/templates/users/aff_users.html +++ b/users/templates/users/aff_users.html @@ -4,7 +4,7 @@ Prénom Nom Pseudo - Inscrit le + Fin de cotisation le Connexion Profil @@ -14,7 +14,7 @@ {{ donnee.0.name }} {{ donnee.0.surname }} {{ donnee.0.pseudo }} - {{ donnee.0.registered }} + {{ donnee.2 }} {% if donnee.1 == True %} Active {% else %} diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 1e8fe834..ea5793fd 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -74,7 +74,7 @@ {% endif %} Droits {% if list_droits %} - {% for droit in list_droits %}{{ droit.right }} - {% endfor %} + {% for droit in list_droits %}{{ droit.right }}{% if list_droits|length != forloop.counter %} - {% endif %} {% endfor %} {% else %} Aucun {% endif %} diff --git a/users/views.py b/users/views.py index a4ae76c4..a2cc32a9 100644 --- a/users/views.py +++ b/users/views.py @@ -221,7 +221,12 @@ def index(request): users_list = User.objects.order_by('pk') connexion = [] for user in users_list: - connexion.append([user, has_access(user)]) + end = end_adhesion(user) + access = has_access(user) + if(end!=None): + connexion.append([user, access, end]) + else: + connexion.append([user, access, "Non adhérent"]) return render(request, 'users/index.html', {'users_list': connexion}) def index_ban(request): From 0d7f4a97ce7d73a988d237b8e7c0dbf2ffa74b3b Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 02:03:52 +0200 Subject: [PATCH 15/26] Validateur pour le nom de l'interface --- machines/models.py | 29 +++++++++++++++++++++++++++-- re2o/settings.py | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/machines/models.py b/machines/models.py index 0276785c..f8d243d4 100644 --- a/machines/models.py +++ b/machines/models.py @@ -1,8 +1,33 @@ from django.db import models -from django.forms import ModelForm, Form +from django.forms import ModelForm, Form, ValidationError from macaddress.fields import MACAddressField from users.models import User +from django.conf import settings +import re + +def full_domain_validator(hostname): + """ Validation du nom de domaine, extensions dans settings, prefixe pas plus long que 63 caractères """ + HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(? 63: + raise ValidationError( + ", le nom de domaine '%(label)s' est trop long (maximum de 63 caractères).", + params={'label': hostname}, + ) + if not HOSTNAME_LABEL_PATTERN.match(hostname): + raise ValidationError( + ", ce nom de domaine '%(label)s' contient des carractères interdits.", + params={'label': hostname}, + ) class Machine(models.Model): user = models.ForeignKey('users.User', on_delete=models.PROTECT) @@ -26,7 +51,7 @@ class Interface(models.Model): mac_address = MACAddressField(integer=False, unique=True) machine = models.ForeignKey('Machine', on_delete=models.PROTECT) details = models.CharField(max_length=255, blank=True) - dns = models.CharField(help_text="Obligatoire et unique, doit se terminer en .rez et ne pas comporter de points", max_length=255, unique=True) + dns = models.CharField(help_text="Obligatoire et unique, doit se terminer en %s et ne pas comporter d'autres points" % ", ".join(settings.ALLOWED_EXTENSIONS), max_length=255, unique=True, validators=[full_domain_validator]) def __str__(self): return self.dns diff --git a/re2o/settings.py b/re2o/settings.py index 8d15d917..51604a9d 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/1.8/ref/settings/ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os -from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS +from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS, ALLOWED_EXTENSIONS BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) From 5b0ea19070af5369f43910bdfa1ca905ee554051 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 02:56:30 +0200 Subject: [PATCH 16/26] Validateur pour le login/pseudo --- users/models.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/users/models.py b/users/models.py index dacb9855..a6a29168 100644 --- a/users/models.py +++ b/users/models.py @@ -1,6 +1,7 @@ from django.db import models from django.forms import ModelForm, Form from django import forms +import re from django.utils import timezone @@ -15,6 +16,15 @@ def remove_user_room(room): user.room = None user.save() +def linux_user_validator(login): + """ Validation du pseudo pour respecter les contraintes unix""" + UNIX_LOGIN_PATTERN = re.compile("^[a-z_][a-z0-9_-]*[$]?$") + if not UNIX_LOGIN_PATTERN.match(login): + raise forms.ValidationError( + ", ce pseudo ('%(label)s') contient des carractères interdits", + params={'label': login}, + ) + class User(models.Model): STATE_ACTIVE = 0 STATE_DEACTIVATED = 1 @@ -27,7 +37,7 @@ class User(models.Model): name = models.CharField(max_length=255) surname = models.CharField(max_length=255) - pseudo = models.CharField(max_length=255, unique=True) + pseudo = models.CharField(max_length=255, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator]) email = models.EmailField() school = models.ForeignKey('School', on_delete=models.PROTECT, null=False, blank=False) comment = models.CharField(help_text="Commentaire, promo", max_length=255, blank=True) From 36bcdcbcbf3982f88a0761298bb0ff2393830cc9 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 12:02:49 +0200 Subject: [PATCH 17/26] =?UTF-8?q?32=20caract=C3=A8res=20pour=20le=20login,?= =?UTF-8?q?=20et=20minuscules=20pour=20le=20dns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/models.py | 3 +++ users/models.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/machines/models.py b/machines/models.py index f8d243d4..b7aad3e1 100644 --- a/machines/models.py +++ b/machines/models.py @@ -56,6 +56,9 @@ class Interface(models.Model): def __str__(self): return self.dns + def clean(self): + self.dns=self.dns.lower() + class IpList(models.Model): ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True) diff --git a/users/models.py b/users/models.py index a6a29168..8e5af681 100644 --- a/users/models.py +++ b/users/models.py @@ -37,7 +37,7 @@ class User(models.Model): name = models.CharField(max_length=255) surname = models.CharField(max_length=255) - pseudo = models.CharField(max_length=255, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator]) + pseudo = models.CharField(max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator]) email = models.EmailField() school = models.ForeignKey('School', on_delete=models.PROTECT, null=False, blank=False) comment = models.CharField(help_text="Commentaire, promo", max_length=255, blank=True) From df252c3060405bc4ba86cf8dd634854c7d65a080 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 12:23:45 +0200 Subject: [PATCH 18/26] =?UTF-8?q?Simplification,=20=C3=A9vite=20les=20impo?= =?UTF-8?q?rts=20circulaires,=20permet=20donc=20=C3=A0=20un=20port=20d'avo?= =?UTF-8?q?ir=20une=20interface,=20et=20=C3=A0=20une=20chambre=20d'avoir?= =?UTF-8?q?=20un=20port=20(<->)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +-- cotisations/models.py | 1 - .../migrations/0014_auto_20160706_1220.py | 20 ++++++++++++ machines/models.py | 1 - search/models.py | 3 -- topologie/admin.py | 2 +- .../migrations/0012_port_machine_interface.py | 21 ++++++++++++ .../0009_auto_20160703_1200.cpython-34.pyc | Bin 800 -> 789 bytes topologie/models.py | 2 +- users/migrations/0016_auto_20160706_1220.py | 30 ++++++++++++++++++ 10 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 machines/migrations/0014_auto_20160706_1220.py create mode 100644 topologie/migrations/0012_port_machine_interface.py create mode 100644 users/migrations/0016_auto_20160706_1220.py diff --git a/.gitignore b/.gitignore index 96622d0f..3828edd8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -settings.py -settings* +settings_local.py *.swp *.pyc +__pycache__ diff --git a/cotisations/models.py b/cotisations/models.py index 2828be38..a7e89292 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -2,7 +2,6 @@ from django.db import models from django import forms from django.forms import ModelForm -from users.models import User class Facture(models.Model): user = models.ForeignKey('users.User', on_delete=models.PROTECT) diff --git a/machines/migrations/0014_auto_20160706_1220.py b/machines/migrations/0014_auto_20160706_1220.py new file mode 100644 index 00000000..c7d7bf04 --- /dev/null +++ b/machines/migrations/0014_auto_20160706_1220.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import machines.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0013_auto_20160705_1014'), + ] + + operations = [ + migrations.AlterField( + model_name='interface', + name='dns', + field=models.CharField(unique=True, validators=[machines.models.full_domain_validator], max_length=255, help_text="Obligatoire et unique, doit se terminer en .rez et ne pas comporter d'autres points"), + ), + ] diff --git a/machines/models.py b/machines/models.py index b7aad3e1..da9289ab 100644 --- a/machines/models.py +++ b/machines/models.py @@ -2,7 +2,6 @@ from django.db import models from django.forms import ModelForm, Form, ValidationError from macaddress.fields import MACAddressField -from users.models import User from django.conf import settings import re diff --git a/search/models.py b/search/models.py index 6e3c14d3..60b776fe 100644 --- a/search/models.py +++ b/search/models.py @@ -3,9 +3,6 @@ from django import forms from django.forms import Form from django.forms import ModelForm -from users.models import User -# Create your models here. - CHOICES = ( ('0', 'Actifs'), ('1', 'Désactivés'), diff --git a/topologie/admin.py b/topologie/admin.py index cc32c4ff..f388c688 100644 --- a/topologie/admin.py +++ b/topologie/admin.py @@ -7,7 +7,7 @@ class SwitchAdmin(admin.ModelAdmin): list_display = ('building','number','details') class PortAdmin(admin.ModelAdmin): - list_display = ('switch', 'port','room','details') + list_display = ('switch', 'port','room','machine_interface','details') class RoomAdmin(admin.ModelAdmin): list_display = ('name',) diff --git a/topologie/migrations/0012_port_machine_interface.py b/topologie/migrations/0012_port_machine_interface.py new file mode 100644 index 00000000..558680a8 --- /dev/null +++ b/topologie/migrations/0012_port_machine_interface.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0014_auto_20160706_1220'), + ('topologie', '0011_auto_20160704_2153'), + ] + + operations = [ + migrations.AddField( + model_name='port', + name='machine_interface', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, null=True, blank=True, to='machines.Interface'), + ), + ] diff --git a/topologie/migrations/__pycache__/0009_auto_20160703_1200.cpython-34.pyc b/topologie/migrations/__pycache__/0009_auto_20160703_1200.cpython-34.pyc index 91251c86ce2fb7c4e58f5c2160c6a7400ae8de71..128040d537a4572445f1da57da1037f1273307eb 100644 GIT binary patch delta 27 jcmZ3$HkFP29S<*8-_5Fx?8_Kgi`W?$7&h-^OlAZCckT!6 delta 38 ucmbQrwt$WO9S<*; Date: Wed, 6 Jul 2016 12:29:49 +0200 Subject: [PATCH 19/26] Exemple de settings_local --- re2o/settings_local.example.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 re2o/settings_local.example.py diff --git a/re2o/settings_local.example.py b/re2o/settings_local.example.py new file mode 100644 index 00000000..3da70fb2 --- /dev/null +++ b/re2o/settings_local.example.py @@ -0,0 +1,20 @@ +SECRET_KEY = 'SUPER_SECRET' + +DB_PASSWORD = 'SUPER_SECRET' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + +ALLOWED_HOSTS = [] + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 're2o', + 'USER': 're2o', + 'PASSWORD': DB_PASSWORD, + 'HOST': 'localhost', + } +} + +ALLOWED_EXTENSIONS = ['.example'] From 881340ae1f97af669ff70765e3067fccdcc4da5b Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 15:52:33 +0200 Subject: [PATCH 20/26] Prise en charge de la liaison port-port --- topologie/models.py | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/topologie/models.py b/topologie/models.py index e469eefb..441a9f78 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -1,7 +1,17 @@ from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey +from django.core.exceptions import ValidationError +def make_port_related(port): + related_port = port.related + related_port.related = port + related_port.save() + +def clean_port_related(port): + related_port = port.related_port + related_port.related = None + related_port.save() class Switch(models.Model): building = models.CharField(max_length=10) @@ -20,22 +30,23 @@ class Port(models.Model): details = models.CharField(max_length=255, blank=True) room = models.ForeignKey('Room', on_delete=models.PROTECT, blank=True, null=True) machine_interface = models.OneToOneField('machines.Interface', on_delete=models.PROTECT, blank=True, null=True) + related = models.OneToOneField('self', null=True, blank=True, related_name='related_port') class Meta: - unique_together = ('_content_type', '_object_id') + unique_together = ('switch', 'port') - _content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True) - _object_id = models.PositiveIntegerField(blank=True, null=True) - goto = GenericForeignKey('_content_type', '_object_id') - - @property - def comefrom(self): - ctype = ContentType.objects.get_for_model(self.__class__) - try: - event = Port.objects.get(_content_type__pk=ctype.id, _object_id=self.id) - except: - return None - return event + def clean(self): + if self.room and self.machine_interface or self.room and self.related or self.machine_interface and self.related: + raise ValidationError("Chambre, interface et related_port sont mutuellement exclusifs") + if self.related==self: + raise ValidationError("On ne peut relier un port à lui même") + if self.related and not self.related.related: + if self.related.machine_interface or self.related.room: + raise ValidationError("Le port relié est déjà occupé, veuillez le libérer avant de créer une relation") + else: + make_port_related(self) + elif hasattr(self, 'related_port'): + clean_port_related(self) def __str__(self): return str(self.switch) + " - " + str(self.port) From cf5b55b31a889d4d074d7d5b28d6d9fd62db5084 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 19:45:36 +0200 Subject: [PATCH 21/26] =?UTF-8?q?Vue=20pour=20g=C3=A9rer=20la=20liste=20de?= =?UTF-8?q?s=20=C3=A9coles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/migrations/0013_port_related.py | 19 ++++++++++++++ .../migrations/0014_auto_20160706_1238.py | 26 +++++++++++++++++++ .../migrations/0015_auto_20160706_1452.py | 23 ++++++++++++++++ .../migrations/0016_auto_20160706_1531.py | 23 ++++++++++++++++ users/models.py | 11 ++++++++ users/templates/users/sidebar.html | 2 ++ users/urls.py | 2 ++ users/views.py | 25 ++++++++++++++++-- 8 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 topologie/migrations/0013_port_related.py create mode 100644 topologie/migrations/0014_auto_20160706_1238.py create mode 100644 topologie/migrations/0015_auto_20160706_1452.py create mode 100644 topologie/migrations/0016_auto_20160706_1531.py diff --git a/topologie/migrations/0013_port_related.py b/topologie/migrations/0013_port_related.py new file mode 100644 index 00000000..afce7dce --- /dev/null +++ b/topologie/migrations/0013_port_related.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('topologie', '0012_port_machine_interface'), + ] + + operations = [ + migrations.AddField( + model_name='port', + name='related', + field=models.OneToOneField(null=True, to='topologie.Port', blank=True, related_name='related_port'), + ), + ] diff --git a/topologie/migrations/0014_auto_20160706_1238.py b/topologie/migrations/0014_auto_20160706_1238.py new file mode 100644 index 00000000..3be29e79 --- /dev/null +++ b/topologie/migrations/0014_auto_20160706_1238.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('topologie', '0013_port_related'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='port', + unique_together=set([('switch', 'port')]), + ), + migrations.RemoveField( + model_name='port', + name='_content_type', + ), + migrations.RemoveField( + model_name='port', + name='_object_id', + ), + ] diff --git a/topologie/migrations/0015_auto_20160706_1452.py b/topologie/migrations/0015_auto_20160706_1452.py new file mode 100644 index 00000000..29f9ca99 --- /dev/null +++ b/topologie/migrations/0015_auto_20160706_1452.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('topologie', '0014_auto_20160706_1238'), + ] + + operations = [ + migrations.RemoveField( + model_name='port', + name='related', + ), + migrations.AddField( + model_name='port', + name='related', + field=models.ManyToManyField(related_name='_port_related_+', to='topologie.Port', blank=True), + ), + ] diff --git a/topologie/migrations/0016_auto_20160706_1531.py b/topologie/migrations/0016_auto_20160706_1531.py new file mode 100644 index 00000000..649eab2d --- /dev/null +++ b/topologie/migrations/0016_auto_20160706_1531.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('topologie', '0015_auto_20160706_1452'), + ] + + operations = [ + migrations.RemoveField( + model_name='port', + name='related', + ), + migrations.AddField( + model_name='port', + name='related', + field=models.OneToOneField(blank=True, to='topologie.Port', related_name='related_port', null=True), + ), + ] diff --git a/users/models.py b/users/models.py index 8e5af681..c12def82 100644 --- a/users/models.py +++ b/users/models.py @@ -131,6 +131,17 @@ class SchoolForm(ModelForm): model = School fields = ['name'] + def __init__(self, *args, **kwargs): + super(SchoolForm, self).__init__(*args, **kwargs) + self.fields['name'].label = 'Établissement à ajouter' + +class DelSchoolForm(ModelForm): + schools = forms.ModelMultipleChoiceField(queryset=School.objects.all(), label="Etablissements actuels", widget=forms.CheckboxSelectMultiple) + + class Meta: + exclude = ['name'] + model = School + class RightForm(ModelForm): def __init__(self, *args, **kwargs): super(RightForm, self).__init__(*args, **kwargs) diff --git a/users/templates/users/sidebar.html b/users/templates/users/sidebar.html index 1cc97e47..d4d34a19 100644 --- a/users/templates/users/sidebar.html +++ b/users/templates/users/sidebar.html @@ -5,5 +5,7 @@

Liste des adhérents

Liste des bannissements

Liste des accès à titre gracieux

+

Ajouter un établissement

+

Supprimer un établissement

Retirer un droit rezo

{% endblock %} diff --git a/users/urls.py b/users/urls.py index a7d8b89a..616f3a88 100644 --- a/users/urls.py +++ b/users/urls.py @@ -13,6 +13,8 @@ urlpatterns = [ url(r'^edit_whitelist/(?P[0-9]+)$', views.edit_whitelist, name='edit-whitelist'), url(r'^add_right/(?P[0-9]+)$', views.add_right, name='add-right'), url(r'^del_right/$', views.del_right, name='del-right'), + url(r'^add_school/$', views.add_school, name='add-school'), + url(r'^del_school/$', views.del_school, name='del-school'), url(r'^profil/(?P[0-9]+)$', views.profil, name='profil'), url(r'^index_ban/$', views.index_ban, name='index-ban'), url(r'^index_white/$', views.index_white, name='index-white'), diff --git a/users/views.py b/users/views.py index a2cc32a9..c3e60a9b 100644 --- a/users/views.py +++ b/users/views.py @@ -6,11 +6,11 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.core.context_processors import csrf from django.template import Context, RequestContext, loader from django.contrib import messages -from django.db.models import Max +from django.db.models import Max, ProtectedError from django.db import IntegrityError from django.utils import timezone -from users.models import User, Right, Ban, DelRightForm, UserForm, InfoForm, PasswordForm, StateForm, RightForm, BanForm, ProfilForm, Whitelist, WhitelistForm +from users.models import User, Right, Ban, DelRightForm, UserForm, InfoForm, PasswordForm, StateForm, RightForm, BanForm, ProfilForm, Whitelist, WhitelistForm, DelSchoolForm, SchoolForm from cotisations.models import Facture from machines.models import Machine, Interface from users.forms import PassForm @@ -217,6 +217,27 @@ def edit_whitelist(request, whitelistid): return redirect("/users/") return form({'userform': whitelist}, 'users/user.html', request) +def add_school(request): + school = SchoolForm(request.POST or None) + if school.is_valid(): + school.save() + messages.success(request, "L'établissement a été ajouté") + return redirect("/users/") + return form({'userform': school}, 'users/user.html', request) + +def del_school(request): + school = DelSchoolForm(request.POST or None) + if school.is_valid(): + school_dels = school.cleaned_data['schools'] + for school_del in school_dels: + try: + school_del.delete() + messages.success(request, "L'établissement a été supprimé") + except ProtectedError: + messages.error(request, "L'établissement %s est affecté à au moins un user, vous ne pouvez pas le supprimer" % school_del) + return redirect("/users/") + return form({'userform': school}, 'users/user.html', request) + def index(request): users_list = User.objects.order_by('pk') connexion = [] From fc78790c59e8d979c873a507ba1f078866baaa8e Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 20:57:31 +0200 Subject: [PATCH 22/26] =?UTF-8?q?Vues=20pour=20g=C3=A9rer=20la=20liste=20d?= =?UTF-8?q?es=20articles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/models.py | 32 ++++++++++++++++++++++++++++++++ cotisations/urls.py | 2 ++ cotisations/views.py | 21 +++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/cotisations/models.py b/cotisations/models.py index a7e89292..a8d3a3bf 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -82,3 +82,35 @@ class EditFactureForm(NewFactureForm): self.fields['prix'].label = 'Prix unitaire' self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire" self.fields.pop('article') + +class ArticleForm(ModelForm): + class Meta: + model = Article + fields = '__all__' + + def __init__(self, *args, **kwargs): + super(ArticleForm, self).__init__(*args, **kwargs) + self.fields['name'].label = "Désignation de l'article" + +class DelArticleForm(ModelForm): + articles = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Articles actuels", widget=forms.CheckboxSelectMultiple) + + class Meta: + fields = ['articles'] + model = Article + +class PaiementForm(ModelForm): + class Meta: + model = Paiement + fields = ['moyen'] + + def __init__(self, *args, **kwargs): + super(PaiementForm, self).__init__(*args, **kwargs) + self.fields['moyen'].label = 'Moyen de paiement à ajouter' + +class DelPaiementForm(ModelForm): + paiements = forms.ModelMultipleChoiceField(queryset=Paiement.objects.all(), label="Moyens de paiement actuels", widget=forms.CheckboxSelectMultiple) + + class Meta: + exclude = ['moyen'] + model = Paiement diff --git a/cotisations/urls.py b/cotisations/urls.py index 3c0bbdf7..9e5e02a2 100644 --- a/cotisations/urls.py +++ b/cotisations/urls.py @@ -5,6 +5,8 @@ from . import views urlpatterns = [ url(r'^new_facture/(?P[0-9]+)$', views.new_facture, name='new-facture'), url(r'^edit_facture/(?P[0-9]+)$', views.edit_facture, name='edit-facture'), + url(r'^add_article/$', views.add_article, name='add-article'), + url(r'^del_article/$', views.del_article, name='del-article'), url(r'^$', views.index, name='index'), ] diff --git a/cotisations/views.py b/cotisations/views.py index d7d531e0..c1e545fd 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -6,9 +6,9 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.core.context_processors import csrf from django.template import Context, RequestContext, loader from django.contrib import messages -from django.db.models import Max +from django.db.models import Max, ProtectedError -from cotisations.models import NewFactureForm, EditFactureForm, Facture, Article, Cotisation +from cotisations.models import NewFactureForm, EditFactureForm, Facture, Article, Cotisation, Article, ArticleForm, DelArticleForm, Paiement, PaiementForm, DelPaiementForm from users.models import User from dateutil.relativedelta import relativedelta @@ -81,6 +81,23 @@ def edit_facture(request, factureid): return redirect("/cotisations/") return form({'factureform': facture_form}, 'cotisations/facture.html', request) +def add_article(request): + article = ArticleForm(request.POST or None) + if article.is_valid(): + article.save() + messages.success(request, "L'article a été ajouté") + return redirect("/cotisations/") + return form({'factureform': article}, 'cotisations/facture.html', request) + +def del_article(request): + article = DelArticleForm(request.POST or None) + if article.is_valid(): + article_del = article.cleaned_data['articles'] + article_del.delete() + messages.success(request, "Le/les articles ont été supprimé") + return redirect("/cotisations/") + return form({'factureform': article}, 'cotisations/facture.html', request) + def index(request): facture_list = Facture.objects.order_by('date').reverse() return render(request, 'cotisations/index.html', {'facture_list': facture_list}) From 21f0631d3b0fda75d311f1d878c05e170e6ed49d Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 21:23:05 +0200 Subject: [PATCH 23/26] =?UTF-8?q?Bouge=20les=20modelforms=20dans=20forms?= =?UTF-8?q?=20pour=20=C3=A9viter=20les=20imports=20circulaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/forms.py | 73 +++++++++++++++++++++++++++++++++++++++++++ cotisations/models.py | 70 ----------------------------------------- cotisations/views.py | 3 +- 3 files changed, 75 insertions(+), 71 deletions(-) create mode 100644 cotisations/forms.py diff --git a/cotisations/forms.py b/cotisations/forms.py new file mode 100644 index 00000000..7285e5e5 --- /dev/null +++ b/cotisations/forms.py @@ -0,0 +1,73 @@ +from django import forms +from django.forms import ModelForm +from .models import Article, Paiement, Facture + +class NewFactureForm(ModelForm): + article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article") + + def __init__(self, *args, **kwargs): + super(NewFactureForm, self).__init__(*args, **kwargs) + self.fields['number'].label = 'Quantité' + self.fields['cheque'].required = False + self.fields['banque'].required = False + self.fields['cheque'].label = 'Numero de chèque' + self.fields['banque'].empty_label = "Non renseigné" + self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement" + + class Meta: + model = Facture + fields = ['paiement','banque','cheque','number'] + + def clean(self): + cleaned_data=super(NewFactureForm, self).clean() + paiement = cleaned_data.get("paiement") + cheque = cleaned_data.get("cheque") + banque = cleaned_data.get("banque") + if paiement.moyen=="chèque" and not (cheque and banque): + raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires") + return cleaned_data + +class EditFactureForm(NewFactureForm): + class Meta(NewFactureForm.Meta): + fields = '__all__' + + def __init__(self, *args, **kwargs): + super(EditFactureForm, self).__init__(*args, **kwargs) + self.fields['user'].label = 'Adherent' + self.fields['name'].label = 'Designation' + self.fields['prix'].label = 'Prix unitaire' + self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire" + self.fields.pop('article') + +class ArticleForm(ModelForm): + class Meta: + model = Article + fields = '__all__' + + def __init__(self, *args, **kwargs): + super(ArticleForm, self).__init__(*args, **kwargs) + self.fields['name'].label = "Désignation de l'article" + +class DelArticleForm(ModelForm): + articles = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Articles actuels", widget=forms.CheckboxSelectMultiple) + + class Meta: + fields = ['articles'] + model = Article + +class PaiementForm(ModelForm): + class Meta: + model = Paiement + fields = ['moyen'] + + def __init__(self, *args, **kwargs): + super(PaiementForm, self).__init__(*args, **kwargs) + self.fields['moyen'].label = 'Moyen de paiement à ajouter' + +class DelPaiementForm(ModelForm): + paiements = forms.ModelMultipleChoiceField(queryset=Paiement.objects.all(), label="Moyens de paiement actuels", widget=forms.CheckboxSelectMultiple) + + class Meta: + exclude = ['moyen'] + model = Paiement + diff --git a/cotisations/models.py b/cotisations/models.py index a8d3a3bf..db064d7f 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -1,6 +1,4 @@ from django.db import models -from django import forms -from django.forms import ModelForm class Facture(models.Model): @@ -46,71 +44,3 @@ class Cotisation(models.Model): def __str__(self): return str(self.facture) -class NewFactureForm(ModelForm): - article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article") - - def __init__(self, *args, **kwargs): - super(NewFactureForm, self).__init__(*args, **kwargs) - self.fields['number'].label = 'Quantité' - self.fields['cheque'].required = False - self.fields['banque'].required = False - self.fields['cheque'].label = 'Numero de chèque' - self.fields['banque'].empty_label = "Non renseigné" - self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement" - - class Meta: - model = Facture - fields = ['paiement','banque','cheque','number'] - - def clean(self): - cleaned_data=super(NewFactureForm, self).clean() - paiement = cleaned_data.get("paiement") - cheque = cleaned_data.get("cheque") - banque = cleaned_data.get("banque") - if paiement.moyen=="chèque" and not (cheque and banque): - raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires") - return cleaned_data - -class EditFactureForm(NewFactureForm): - class Meta(NewFactureForm.Meta): - fields = '__all__' - - def __init__(self, *args, **kwargs): - super(EditFactureForm, self).__init__(*args, **kwargs) - self.fields['user'].label = 'Adherent' - self.fields['name'].label = 'Designation' - self.fields['prix'].label = 'Prix unitaire' - self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire" - self.fields.pop('article') - -class ArticleForm(ModelForm): - class Meta: - model = Article - fields = '__all__' - - def __init__(self, *args, **kwargs): - super(ArticleForm, self).__init__(*args, **kwargs) - self.fields['name'].label = "Désignation de l'article" - -class DelArticleForm(ModelForm): - articles = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Articles actuels", widget=forms.CheckboxSelectMultiple) - - class Meta: - fields = ['articles'] - model = Article - -class PaiementForm(ModelForm): - class Meta: - model = Paiement - fields = ['moyen'] - - def __init__(self, *args, **kwargs): - super(PaiementForm, self).__init__(*args, **kwargs) - self.fields['moyen'].label = 'Moyen de paiement à ajouter' - -class DelPaiementForm(ModelForm): - paiements = forms.ModelMultipleChoiceField(queryset=Paiement.objects.all(), label="Moyens de paiement actuels", widget=forms.CheckboxSelectMultiple) - - class Meta: - exclude = ['moyen'] - model = Paiement diff --git a/cotisations/views.py b/cotisations/views.py index c1e545fd..3d8847f6 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -8,7 +8,8 @@ from django.template import Context, RequestContext, loader from django.contrib import messages from django.db.models import Max, ProtectedError -from cotisations.models import NewFactureForm, EditFactureForm, Facture, Article, Cotisation, Article, ArticleForm, DelArticleForm, Paiement, PaiementForm, DelPaiementForm +from .models import Facture, Article, Cotisation, Article +from .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, DelPaiementForm from users.models import User from dateutil.relativedelta import relativedelta From 7be1e768d3b22a2a4ad1544eb348c197e0d6dd0a Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 6 Jul 2016 21:43:39 +0200 Subject: [PATCH 24/26] =?UTF-8?q?Permet=20de=20g=C3=A9rer=20les=20moyens?= =?UTF-8?q?=20de=20paiement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/cotisations/sidebar.html | 4 ++++ cotisations/urls.py | 2 ++ cotisations/views.py | 23 ++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cotisations/templates/cotisations/sidebar.html b/cotisations/templates/cotisations/sidebar.html index 0b4c5c42..6f39d00f 100644 --- a/cotisations/templates/cotisations/sidebar.html +++ b/cotisations/templates/cotisations/sidebar.html @@ -2,4 +2,8 @@ {% block sidebar %}

Liste des factures

+

Ajouter un article

+

Retirer un article

+

Ajouter un moyen de paiement

+

Retirer un moyen de paiement

{% endblock %} diff --git a/cotisations/urls.py b/cotisations/urls.py index 9e5e02a2..7589e5c1 100644 --- a/cotisations/urls.py +++ b/cotisations/urls.py @@ -7,6 +7,8 @@ urlpatterns = [ url(r'^edit_facture/(?P[0-9]+)$', views.edit_facture, name='edit-facture'), url(r'^add_article/$', views.add_article, name='add-article'), url(r'^del_article/$', views.del_article, name='del-article'), + url(r'^add_paiement/$', views.add_paiement, name='add-paiement'), + url(r'^del_paiement/$', views.del_paiement, name='del-paiement'), url(r'^$', views.index, name='index'), ] diff --git a/cotisations/views.py b/cotisations/views.py index 3d8847f6..308eb588 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -9,7 +9,7 @@ from django.contrib import messages from django.db.models import Max, ProtectedError from .models import Facture, Article, Cotisation, Article -from .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, DelPaiementForm +from .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, PaiementForm, DelPaiementForm from users.models import User from dateutil.relativedelta import relativedelta @@ -99,6 +99,27 @@ def del_article(request): return redirect("/cotisations/") return form({'factureform': article}, 'cotisations/facture.html', request) +def add_paiement(request): + paiement = PaiementForm(request.POST or None) + if paiement.is_valid(): + paiement.save() + messages.success(request, "Le moyen de paiement a été ajouté") + return redirect("/cotisations/") + return form({'factureform': paiement}, 'cotisations/facture.html', request) + +def del_paiement(request): + paiement = DelPaiementForm(request.POST or None) + if paiement.is_valid(): + paiement_dels = paiement.cleaned_data['paiements'] + for paiement_del in paiement_dels: + try: + paiement_del.delete() + messages.success(request, "Le moyen de paiement a été supprimé") + except ProtectedError: + messages.error(request, "Le moyen de paiement %s est affecté à au moins une facture, vous ne pouvez pas le supprimer" % paiement_del) + return redirect("/cotisations/") + return form({'factureform': paiement}, 'cotisations/facture.html', request) + def index(request): facture_list = Facture.objects.order_by('date').reverse() return render(request, 'cotisations/index.html', {'facture_list': facture_list}) From e8b55e5b55480a57c7dfcc8a3b843a1abc121067 Mon Sep 17 00:00:00 2001 From: Dalahro Date: Wed, 6 Jul 2016 21:50:15 +0200 Subject: [PATCH 25/26] Affichage de la topologie Modification d'un port --- re2o/urls.py | 1 + templates/base.html | 2 +- topologie/forms.py | 11 ++++++ topologie/models.py | 3 +- topologie/templates/topologie/aff_port.html | 23 ++++++++++++ topologie/templates/topologie/aff_switch.html | 18 ++++++++++ topologie/templates/topologie/index.html | 11 ++++++ topologie/templates/topologie/index_p.html | 11 ++++++ topologie/templates/topologie/port.html | 17 +++++++++ topologie/templates/topologie/sidebar.html | 5 +++ topologie/urls.py | 10 ++++++ topologie/views.py | 36 +++++++++++++++++-- 12 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 topologie/forms.py create mode 100644 topologie/templates/topologie/aff_port.html create mode 100644 topologie/templates/topologie/aff_switch.html create mode 100644 topologie/templates/topologie/index.html create mode 100644 topologie/templates/topologie/index_p.html create mode 100644 topologie/templates/topologie/port.html create mode 100644 topologie/templates/topologie/sidebar.html create mode 100644 topologie/urls.py diff --git a/re2o/urls.py b/re2o/urls.py index 96ae98be..fe6776d8 100644 --- a/re2o/urls.py +++ b/re2o/urls.py @@ -24,5 +24,6 @@ urlpatterns = [ url(r'^search/', include('search.urls', namespace='search')), url(r'^cotisations/', include('cotisations.urls', namespace='cotisations')), url(r'^machines/', include('machines.urls', namespace='machines')), + url(r'^topologie/', include('topologie.urls', namespace='topologie')), #url(r'^logs/', include('logs.urls', namespace='logs')), ] diff --git a/templates/base.html b/templates/base.html index 34079495..544c0952 100644 --- a/templates/base.html +++ b/templates/base.html @@ -30,7 +30,7 @@
  • Adhérents
  • Machines
  • Cotisations
  • -
  • Topologie
  • +
  • Topologie
  • Statistiques