diff --git a/preferences/admin.py b/preferences/admin.py index 043370db..3e1c61f1 100644 --- a/preferences/admin.py +++ b/preferences/admin.py @@ -35,6 +35,7 @@ from .models import ( GeneralOption, Service, MailContact, + Reminder, AssoOption, MailMessageOption, HomeOption @@ -85,6 +86,9 @@ class HomeOptionAdmin(VersionAdmin): """Class admin options home""" pass +class ReminderAdmin(VersionAdmin): + """Class reminder""" + pass admin.site.register(OptionalUser, OptionalUserAdmin) admin.site.register(OptionalMachine, OptionalMachineAdmin) @@ -93,5 +97,6 @@ admin.site.register(GeneralOption, GeneralOptionAdmin) admin.site.register(HomeOption, HomeOptionAdmin) admin.site.register(Service, ServiceAdmin) admin.site.register(MailContact, MailContactAdmin) +admin.site.register(Reminder, ReminderAdmin) admin.site.register(AssoOption, AssoOptionAdmin) admin.site.register(MailMessageOption, MailMessageOptionAdmin) diff --git a/preferences/forms.py b/preferences/forms.py index 6f727f3a..be4d1655 100644 --- a/preferences/forms.py +++ b/preferences/forms.py @@ -24,6 +24,7 @@ Formulaire d'edition des réglages : user, machine, topologie, asso... """ from __future__ import unicode_literals +from re2o.mixins import FormRevMixin from django.forms import ModelForm, Form from django import forms @@ -36,7 +37,8 @@ from .models import ( MailMessageOption, HomeOption, Service, - MailContact + MailContact, + Reminder ) class EditOptionalUserForm(ModelForm): @@ -52,18 +54,6 @@ class EditOptionalUserForm(ModelForm): prefix=prefix, **kwargs ) - self.fields['is_tel_mandatory'].label = ( - 'Exiger un numéro de téléphone' - ) - self.fields['user_solde'].label = ( - 'Activation du solde pour les utilisateurs' - ) - self.fields['max_solde'].label = 'Solde maximum' - self.fields['min_online_payment'].label = ( - 'Montant de rechargement minimum en ligne' - ) - self.fields['self_adhesion'].label = 'Auto inscription' - class EditOptionalMachineForm(ModelForm): """Options machines (max de machines, etc)""" @@ -208,7 +198,7 @@ class EditHomeOptionForm(ModelForm): ) -class ServiceForm(ModelForm): +class ServiceForm(FormRevMixin, ModelForm): """Edition, ajout de services sur la page d'accueil""" class Meta: model = Service @@ -218,23 +208,17 @@ class ServiceForm(ModelForm): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(ServiceForm, self).__init__(*args, prefix=prefix, **kwargs) - -class DelServiceForm(Form): - """Suppression de services sur la page d'accueil""" - services = forms.ModelMultipleChoiceField( - queryset=Service.objects.none(), - label="Enregistrements service actuels", - widget=forms.CheckboxSelectMultiple - ) +class ReminderForm(FormRevMixin, ModelForm): + """Edition, ajout de rappel""" + class Meta: + model = Reminder + fields = '__all__' def __init__(self, *args, **kwargs): - instances = kwargs.pop('instances', None) - super(DelServiceForm, self).__init__(*args, **kwargs) - if instances: - self.fields['services'].queryset = instances - else: - self.fields['services'].queryset = Service.objects.all() + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(ReminderForm, self).__init__(*args, prefix=prefix, **kwargs) + class MailContactForm(ModelForm): """Edition, ajout d'adresse de contact""" class Meta: diff --git a/preferences/migrations/0035_reminder.py b/preferences/migrations/0035_reminder.py new file mode 100644 index 00000000..eaba7753 --- /dev/null +++ b/preferences/migrations/0035_reminder.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-05-05 10:53 +from __future__ import unicode_literals + +from django.db import migrations, models +import re2o.mixins + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0034_auto_20180416_1120'), + ] + + operations = [ + migrations.CreateModel( + name='Reminder', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('days', models.IntegerField(default=7, help_text="Délais entre le mail et la fin d'adhésion", unique=True)), + ('message', models.CharField(blank=True, default='', max_length=255, null=True)), + ], + options={ + 'permissions': (('view_reminder', 'Peut voir un objet reminder'),), + }, + bases=(re2o.mixins.AclMixin, models.Model), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index cf4e5a33..9057412c 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -67,24 +67,35 @@ class OptionalUser(AclMixin, PreferencesModel): activation ou non du solde, autorisation du negatif, fingerprint etc""" PRETTY_NAME = "Options utilisateur" - is_tel_mandatory = models.BooleanField(default=True) - user_solde = models.BooleanField(default=False) + is_tel_mandatory = models.BooleanField( + default=True, + help_text="Obligation de renseigner le téléphone" + ) + user_solde = models.BooleanField( + default=False, + help_text="Solde pour les users" + ) solde_negatif = models.DecimalField( max_digits=5, decimal_places=2, - default=0 + default=0, + help_text="Maximum de négatif autorisé" ) max_solde = models.DecimalField( max_digits=5, decimal_places=2, - default=50 + default=50, + help_text="Valeur maximum du solde" ) min_online_payment = models.DecimalField( max_digits=5, decimal_places=2, - default=10 + default=10, + help_text="Montant minimum pour le rechargement online" ) - gpg_fingerprint = models.BooleanField(default=True) + gpg_fingerprint = models.BooleanField( + default=True, + help_text="Gpg fingerprint activée") all_can_create_club = models.BooleanField( default=False, help_text="Les users peuvent créer un club" @@ -101,7 +112,8 @@ class OptionalUser(AclMixin, PreferencesModel): 'users.ListShell', on_delete=models.PROTECT, blank=True, - null=True + null=True, + help_text="Shell par default" ) mail_accounts = models.BooleanField( default=False, @@ -157,13 +169,20 @@ class OptionalMachine(AclMixin, PreferencesModel): (DISABLED, 'Désactivé'), ) - password_machine = models.BooleanField(default=False) - max_lambdauser_interfaces = models.IntegerField(default=10) - max_lambdauser_aliases = models.IntegerField(default=10) + password_machine = models.BooleanField( + default=False, + help_text="Un mot de passe par machine activé") + max_lambdauser_interfaces = models.IntegerField( + default=10, + help_text="Maximum d'interface pour un user sans droits") + max_lambdauser_aliases = models.IntegerField( + default=10, + help_text="Maximum de cname pour un user sans droits") ipv6_mode = models.CharField( max_length=32, choices=CHOICE_IPV6, - default='DISABLED' + default='DISABLED', + help_text="Mode ipv6" ) create_machine = models.BooleanField( default=True, @@ -206,21 +225,24 @@ class OptionalTopologie(AclMixin, PreferencesModel): radius_general_policy = models.CharField( max_length=32, choices=CHOICE_RADIUS, - default='DEFINED' + default='DEFINED', + help_text="Politique par defaut de placement de vlan avec radius" ) vlan_decision_ok = models.OneToOneField( 'machines.Vlan', on_delete=models.PROTECT, related_name='decision_ok', blank=True, - null=True + null=True, + help_text="Placement sur ce vlan par default en cas d'accès OK" ) vlan_decision_nok = models.OneToOneField( 'machines.Vlan', on_delete=models.PROTECT, related_name='decision_nok', blank=True, - null=True + null=True, + help_text="Placement par defaut sur ce vlan en cas de rejet" ) class Meta: @@ -236,6 +258,32 @@ def optionaltopologie_post_save(**kwargs): topologie_pref.set_in_cache() +class Reminder(AclMixin, models.Model): + """Options pour les mails de notification de fin d'adhésion. + Days: liste des nombres de jours pour lesquells un mail est envoyé + optionalMessage: message additionel pour le mail + """ + PRETTY_NAME="Options pour le mail de fin d'adhésion" + + days = models.IntegerField( + default=7, + unique=True, + help_text="Délais entre le mail et la fin d'adhésion" + ) + message = models.CharField( + max_length=255, + default="", + null=True, + blank=True, + help_text="Message affiché spécifiquement pour ce rappel" + ) + + class Meta: + permissions = ( + ("view_reminder", "Peut voir un objet reminder"), + ) + + class GeneralOption(AclMixin, PreferencesModel): """Options générales : nombre de resultats par page, nom du site, temps où les liens sont valides""" @@ -244,23 +292,44 @@ class GeneralOption(AclMixin, PreferencesModel): general_message = models.TextField( default="", blank=True, - help_text="Message général affiché sur le site (maintenance, etc" + help_text="Message général affiché sur le site (maintenance, etc)" + ) + search_display_page = models.IntegerField( + default=15, + help_text="Nombre de résultats affichés dans une recherche" + ) + pagination_number = models.IntegerField( + default=25, + help_text="Nombre d'item par page paginée" + ) + pagination_large_number = models.IntegerField( + default=8, + help_text="Nombre d'item par page paginée, items larges" + ) + req_expire_hrs = models.IntegerField( + default=48, + help_text="Delais d'expiration des token changement de mdp, en heure" + ) + site_name = models.CharField( + max_length=32, + default="Re2o", + help_text="Nom du site web, par defaut re2o" + ) + email_from = models.EmailField( + default="www-data@example.com", + help_text="From des mails envoyés par re2o" ) - search_display_page = models.IntegerField(default=15) - pagination_number = models.IntegerField(default=25) - pagination_large_number = models.IntegerField(default=8) - req_expire_hrs = models.IntegerField(default=48) - site_name = models.CharField(max_length=32, default="Re2o") - email_from = models.EmailField(default="www-data@example.com") GTU_sum_up = models.TextField( default="", blank=True, + help_text="Résumé des CGU à l'inscription" ) GTU = models.FileField( upload_to='', default="", null=True, blank=True, + help_text="CGU et documents réglementaires à l'inscription" ) class Meta: @@ -326,19 +395,43 @@ class AssoOption(AclMixin, PreferencesModel): name = models.CharField( default="Association réseau école machin", - max_length=256 + max_length=256, + help_text="Nom complet de l'asso" + ) + siret = models.CharField( + default="00000000000000", + max_length=32, + help_text="Numero SIRET" + ) + adresse1 = models.CharField( + default="1 Rue de exemple", + max_length=128, + help_text="Adresse" + ) + adresse2 = models.CharField( + default="94230 Cachan", + max_length=128 + ) + contact = models.EmailField( + default="contact@example.org", + help_text="Mail de contact" + ) + telephone = models.CharField( + max_length=15, + default="0000000000", + help_text="Téléphone de contact" + ) + pseudo = models.CharField( + default="Asso", + max_length=32, + help_text="Pseudo de l'asso" ) - siret = models.CharField(default="00000000000000", max_length=32) - adresse1 = models.CharField(default="1 Rue de exemple", max_length=128) - adresse2 = models.CharField(default="94230 Cachan", max_length=128) - contact = models.EmailField(default="contact@example.org") - telephone = models.CharField(max_length=15, default="0000000000") - pseudo = models.CharField(default="Asso", max_length=32) utilisateur_asso = models.OneToOneField( 'users.User', on_delete=models.PROTECT, blank=True, - null=True + null=True, + help_text="Utilisateur dans la db correspondant à l'asso" ) PAYMENT = ( ('NONE', 'NONE'), @@ -348,20 +441,24 @@ class AssoOption(AclMixin, PreferencesModel): max_length=255, choices=PAYMENT, default='NONE', + help_text="Mode de paiement en ligne" ) payment_id = models.CharField( max_length=255, default='', - blank=True + blank=True, + help_text="Id de paiement en ligne" ) payment_pass = AESEncryptedField( max_length=255, null=True, blank=True, + help_text="Clef de paiement en ligne" ) description = models.TextField( null=True, blank=True, + help_text="Description de l'asso" ) class Meta: diff --git a/preferences/templates/preferences/aff_reminder.html b/preferences/templates/preferences/aff_reminder.html new file mode 100644 index 00000000..4bcaacce --- /dev/null +++ b/preferences/templates/preferences/aff_reminder.html @@ -0,0 +1,47 @@ +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} +{% load acl %} +
Nombre de jours avant le rappel | +Message custom pour ce rappel | ++ | + |
---|---|---|---|
{{ reminder.days }} | +{{ reminder.message }} | ++ {% can_edit reminder %} + {% include 'buttons/edit.html' with href='preferences:edit-reminder' id=reminder.id %} + {% acl_end %} + {% include 'buttons/history.html' with href='preferences:history' name='reminder' id=reminder.id %} + | +
-
Mot de passe par machine | -{{ machineoptions.password_machine }} | -Machines/interfaces autorisées par utilisateurs | -{{ machineoptions.max_lambdauser_interfaces }} | -
---|---|---|---|
Alias dns autorisé par utilisateur | -{{ machineoptions.max_lambdauser_aliases }} | -Support de l'ipv6 | -{{ machineoptions.ipv6_mode }} | -
Creation de machines | -{{ machineoptions.create_machine }} | + {% for text, field in line %} +{{ field }} | +{{ text }} | + {% endfor %}
---|
Politique générale de placement de vlan | -{{ topologieoptions.radius_general_policy }} | -Ce réglage défini la politique vlan après acceptation radius : soit sur le vlan de la plage d'ip de la machine, soit sur un vlan prédéfini dans "Vlan où placer les machines après acceptation RADIUS" | -- |
---|---|---|---|
Vlan où placer les machines après acceptation RADIUS | -{{ topologieoptions.vlan_decision_ok }} | -Vlan où placer les machines après rejet RADIUS | -{{ topologieoptions.vlan_decision_nok }} | -
{{ field }} | +{{ text }} | + {% endfor %} +
Nom du site web | -{{ generaloptions.site_name }} | -Adresse mail d'expedition automatique | -{{ generaloptions.email_from }} | -
---|---|---|---|
Affichage de résultats dans le champ de recherche | -{{ generaloptions.search_display_page }} | -Nombre d'items affichés en liste (taille normale) | -{{ generaloptions.pagination_number }} | -
Nombre d'items affichés en liste (taille élevée) | -{{ generaloptions.pagination_large_number }} | -Temps avant expiration du lien de reinitialisation de mot de passe (en heures) | -{{ generaloptions.req_expire_hrs }} | -
Message global affiché sur le site | -{{ generaloptions.general_message }} | -Résumé des CGU | -{{ generaloptions.GTU_sum_up }} | -
CGU | -{{generaloptions.GTU}} - | {{ field }} | +{{ text }} | + {% endfor %} + + {% endfor %}
Nom | -{{ assooptions.name }} | -SIRET | -{{ assooptions.siret }} | -
---|---|---|---|
Adresse | -{{ assooptions.adresse1 }} - {{ assooptions.adresse2 }} |
- Contact mail | -{{ assooptions.contact }} | -
Telephone | -{{ assooptions.telephone }} | -Pseudo d'usage | -{{ assooptions.pseudo }} | -
Objet utilisateur de l'association | -{{ assooptions.utilisateur_asso }} | -Moyen de paiement automatique | -{{ assooptions.payment }} | -
Description de l'association | -{{ assooptions.description | safe }} | -||
{{ field }} | +{{ text }} | + {% endfor %} +
Mail de bienvenue (Français) | -{{ mailmessageoptions.welcome_mail_fr | safe }} | + {% for line in assooptions %} +
---|---|
{{ field }} | +{{ text }} | + {% endfor %}
Mail de bienvenue (Anglais) | -{{ mailmessageoptions.welcome_mail_en | safe }} | -
-
Url du compte twitter | -{{ homeoptions.twitter_url }} | -Nom utilisé pour afficher le compte | -{{ homeoptions.twitter_account_name }} | -
---|---|---|---|
Url du compte facebook | -{{ homeoptions.facebook_url }} | -||
{{ field }} | +{{ text }} | + {% endfor %} +