From 56a09106da338f4fa754785a6847c6c75f3f3a0f 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 1f707ff6d8eb828c5226ca82809324fc0804a1a8 Mon Sep 17 00:00:00 2001 From: chirac 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 49a3041c61fbca5304ac55d92f2183e25bb852cd Mon Sep 17 00:00:00 2001 From: chirac 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 9436331c26e87bca862c4ef369811807389c6efa Mon Sep 17 00:00:00 2001 From: chirac 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 036c4fc7744bd4dcbe36ff4b709c6c2ff465679e Mon Sep 17 00:00:00 2001 From: chirac 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 2cb9ccd0f80b0c54df4d4cfba7cc43708b3ce680 Mon Sep 17 00:00:00 2001 From: chirac 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 2bcf765c57e06bd73ec17d2ecf7c12d5b9001f85 Mon Sep 17 00:00:00 2001 From: chirac 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 4639276bbd8d3ef9d2a28aa9b87d0546567c15a5 Mon Sep 17 00:00:00 2001 From: chirac 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 19cf3b4f83960a077cdb646e98b05d7c559ad068 Mon Sep 17 00:00:00 2001 From: chirac 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 20218f0bfd5b9e29be185d814aadbba76bb25112 Mon Sep 17 00:00:00 2001 From: chirac 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 c744dd599214f8bc17a7d292e3b695d3030897f3 Mon Sep 17 00:00:00 2001 From: chirac 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 39f89a21b6024edf9af085809efb4e134bab89c9 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 4f2236c9e0726decc64d05277d44529030d09455 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 b7b76ba05a29336c6ebf1e20ecf86813d5dd4ff8 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 a80490879b64e64d4d752179d2ba4604cac3234f Mon Sep 17 00:00:00 2001 From: chirac 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 5eff4f7667e4e7c84e69359ee82a938e59c26c1f Mon Sep 17 00:00:00 2001 From: chirac 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 a58e90cc2fc066840e44ec61100d0b9496c1e502 Mon Sep 17 00:00:00 2001 From: chirac 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 48d76b3f3fb0828f2627be7c3bcee884c3b715c4 Mon Sep 17 00:00:00 2001 From: chirac 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 e9d70713324307a8d9511e2f20691e61bbc243ee Mon Sep 17 00:00:00 2001 From: chirac 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 387515d410bc404cdcdcc85a69075a293f47f3d4 Mon Sep 17 00:00:00 2001 From: chirac 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 6d1b41ff3107e42a0ef1c9fd0f40bf1fb362fd60 Mon Sep 17 00:00:00 2001 From: chirac 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 0670a0c8a20048e4c7510957a482466c91011083 Mon Sep 17 00:00:00 2001 From: chirac 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 db638966973f0318b9fb975bdf12ff168652b08d Mon Sep 17 00:00:00 2001 From: chirac 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 880503971b43ae9f13f3c1c47921479ca691c6d4 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