diff --git a/cotisations/forms.py b/cotisations/forms.py
index 5659d495..02ee3e3c 100644
--- a/cotisations/forms.py
+++ b/cotisations/forms.py
@@ -5,6 +5,7 @@
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
+# Copyright © 2018 Hugo Levy-Falk
#
# 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
@@ -78,24 +79,6 @@ class NewFactureForm(FormRevMixin, ModelForm):
return cleaned_data
-class CreditSoldeForm(NewFactureForm):
- """
- Form used to make some operations on the user's balance if the option is
- activated.
- """
- class Meta(NewFactureForm.Meta):
- model = Facture
- fields = ['paiement', 'banque', 'cheque']
-
- def __init__(self, *args, **kwargs):
- super(CreditSoldeForm, self).__init__(*args, **kwargs)
- # TODO : change solde to balance
- self.fields['paiement'].queryset = Paiement.objects.exclude(
- is_balance=True)
-
- montant = forms.DecimalField(max_digits=5, decimal_places=2, required=True)
-
-
class SelectUserArticleForm(FormRevMixin, Form):
"""
Form used to select an article during the creation of an invoice for a
@@ -300,57 +283,6 @@ class DelBanqueForm(FormRevMixin, Form):
self.fields['banques'].queryset = Banque.objects.all()
-# TODO : change facture to Invoice
-class NewFactureSoldeForm(NewFactureForm):
- """
- Form used to create an invoice
- """
-
- def __init__(self, *args, **kwargs):
- prefix = kwargs.pop('prefix', self.Meta.model.__name__)
- super(NewFactureSoldeForm, self).__init__(
- *args,
- prefix=prefix,
- **kwargs
- )
- self.fields['cheque'].required = False
- self.fields['banque'].required = False
- self.fields['cheque'].label = _('Cheque number')
- self.fields['banque'].empty_label = _("Not specified")
- self.fields['paiement'].empty_label = \
- _("Select a payment method")
- # TODO : change paiement to payment
- paiement_list = Paiement.objects.filter(type_paiement=1)
- if paiement_list:
- self.fields['paiement'].widget\
- .attrs['data-cheque'] = paiement_list.first().id
-
- class Meta:
- # TODO : change facture to invoice
- model = Facture
- # TODO : change paiement to payment and baque to bank
- fields = ['paiement', 'banque']
-
- def clean(self):
- cleaned_data = super(NewFactureSoldeForm, self).clean()
- # TODO : change paiement to payment
- paiement = cleaned_data.get("paiement")
- cheque = cleaned_data.get("cheque")
- # TODO : change banque to bank
- banque = cleaned_data.get("banque")
- # TODO : change paiement to payment
- if not paiement:
- raise forms.ValidationError(
- _("A payment method must be specified.")
- )
- # TODO : change paiement and banque to payment and bank
- elif paiement.type_paiement == "check" and not (cheque and banque):
- raise forms.ValidationError(
- _("A cheque number and a bank must be specified.")
- )
- return cleaned_data
-
-
# TODO : Better name and docstring
class RechargeForm(FormRevMixin, Form):
"""
diff --git a/cotisations/models.py b/cotisations/models.py
index d6280045..37d030ea 100644
--- a/cotisations/models.py
+++ b/cotisations/models.py
@@ -6,6 +6,7 @@
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
+# Copyright © 2018 Hugo Levy-Falk
#
# 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
diff --git a/cotisations/templates/cotisations/new_facture_solde.html b/cotisations/templates/cotisations/new_facture_solde.html
deleted file mode 100644
index dac68c54..00000000
--- a/cotisations/templates/cotisations/new_facture_solde.html
+++ /dev/null
@@ -1,158 +0,0 @@
-{% extends "cotisations/sidebar.html" %}
-{% 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 bootstrap3 %}
-{% load staticfiles%}
-{% load i18n %}
-
-{% block title %}{% trans "Invoices creation and edition" %}{% endblock %}
-
-{% block content %}
-{% bootstrap_form_errors venteform.management_form %}
-
-
-
-
-
-{% endblock %}
-
diff --git a/cotisations/templates/cotisations/recharge.html b/cotisations/templates/cotisations/recharge.html
deleted file mode 100644
index 6f4e9d9c..00000000
--- a/cotisations/templates/cotisations/recharge.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% extends "cotisations/sidebar.html" %}
-{% 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 bootstrap3 %}
-{% load staticfiles%}
-{% load i18n %}
-
-{% block title %}{% trans "Balance refill" %}{% endblock %}
-
-{% block content %}
- {% trans "Balance refill" %}
-
- {% blocktrans %}
- Balance : {{ solde }} €
- {% endblocktrans %}
-
-
-{% endblock %}
diff --git a/cotisations/urls.py b/cotisations/urls.py
index ce6aa0f4..c906c54a 100644
--- a/cotisations/urls.py
+++ b/cotisations/urls.py
@@ -133,11 +133,5 @@ urlpatterns = [
views.control,
name='control'
),
- url(
- r'^new_facture_solde/(?P[0-9]+)$',
- views.new_facture_solde,
- name='new_facture_solde'
- ),
url(r'^$', views.index, name='index'),
] + payment_methods.urls.urlpatterns
-
diff --git a/cotisations/views.py b/cotisations/views.py
index 80f89ea1..aa60aa8b 100644
--- a/cotisations/views.py
+++ b/cotisations/views.py
@@ -5,6 +5,7 @@
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
+# Copyright © 2018 Hugo Levy-Falk
#
# 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
@@ -56,7 +57,7 @@ from re2o.acl import (
can_delete_set,
can_change,
)
-from preferences.models import OptionalUser, AssoOption, GeneralOption
+from preferences.models import AssoOption, GeneralOption
from .models import Facture, Article, Vente, Paiement, Banque
from .forms import (
NewFactureForm,
@@ -70,7 +71,6 @@ from .forms import (
NewFactureFormPdf,
SelectUserArticleForm,
SelectClubArticleForm,
- CreditSoldeForm,
RechargeForm
)
from .tex import render_invoice
@@ -88,10 +88,6 @@ def new_facture(request, user, userid):
A bit of JS is used in the template to add articles in a fancier way.
If everything is correct, save each one of the articles, save the
purchase object associated and finally the newly created invoice.
-
- TODO : The whole verification process should be moved to the model. This
- function should only act as a dumb interface between the model and the
- user.
"""
invoice = Facture(user=user)
# The template needs the list of articles (for the JS part)
@@ -670,118 +666,6 @@ def index(request):
})
-# TODO : merge this function with new_facture() which is nearly the same
-# TODO : change facture to invoice
-@login_required
-def new_facture_solde(request, userid):
- """
- View called to create a new invoice when using the balance to pay.
- Currently, send the list of available articles for the user along with
- a formset of a new invoice (based on the `:forms:NewFactureForm()` form.
- A bit of JS is used in the template to add articles in a fancier way.
- If everything is correct, save each one of the articles, save the
- purchase object associated and finally the newly created invoice.
-
- TODO : The whole verification process should be moved to the model. This
- function should only act as a dumb interface between the model and the
- user.
- """
- user = request.user
- invoice = Facture(user=user)
- payment, _created = Paiement.objects.get_or_create(is_balance=True)
- invoice.paiement = payment
- # The template needs the list of articles (for the JS part)
- article_list = Article.objects.filter(
- Q(type_user='All') | Q(type_user=request.user.class_name)
- )
- if request.user.is_class_club:
- article_formset = formset_factory(SelectClubArticleForm)(
- request.POST or None
- )
- else:
- article_formset = formset_factory(SelectUserArticleForm)(
- request.POST or None
- )
-
- if article_formset.is_valid():
- articles = article_formset
- # Check if at leat one article has been selected
- if any(art.cleaned_data for art in articles):
- user_balance = OptionalUser.get_cached_value('user_solde')
- negative_balance = OptionalUser.get_cached_value('solde_negatif')
- # If the paiement using balance has been activated,
- # checking that the total price won't get the user under
- # the authorized minimum (negative_balance)
- if user_balance:
- total_price = 0
- for art_item in articles:
- if art_item.cleaned_data:
- total_price += art_item.cleaned_data['article']\
- .prix*art_item.cleaned_data['quantity']
- if float(user.solde) - float(total_price) < negative_balance:
- messages.error(
- request,
- _("The balance is too low for this operation.")
- )
- return redirect(reverse(
- 'users:profil',
- kwargs={'userid': userid}
- ))
- # Saving the invoice
- invoice.save()
-
- # Building a purchase for each article sold
- for art_item in articles:
- if art_item.cleaned_data:
- article = art_item.cleaned_data['article']
- quantity = art_item.cleaned_data['quantity']
- new_purchase = Vente.objects.create(
- facture=invoice,
- name=article.name,
- prix=article.prix,
- type_cotisation=article.type_cotisation,
- duration=article.duration,
- number=quantity
- )
- new_purchase.save()
-
- # In case a cotisation was bought, inform the user, the
- # cotisation time has been extended too
- if any(art_item.cleaned_data['article'].type_cotisation
- for art_item in articles if art_item.cleaned_data):
- messages.success(
- request,
- _("The cotisation of %(member_name)s has been successfully \
- extended to %(end_date)s.") % {
- 'member_name': user.pseudo,
- 'end_date': user.end_adhesion()
- }
- )
- # Else, only tell the invoice was created
- else:
- messages.success(
- request,
- _("The invoice has been successuflly created.")
- )
- return redirect(reverse(
- 'users:profil',
- kwargs={'userid': userid}
- ))
- messages.error(
- request,
- _("You need to choose at least one article.")
- )
- return redirect(reverse(
- 'users:profil',
- kwargs={'userid': userid}
- ))
-
- return form({
- 'venteform': article_formset,
- 'articlelist': article_list
- }, 'cotisations/new_facture_solde.html', request)
-
-
# TODO : change solde to balance
@login_required
@can_create(Facture)
diff --git a/preferences/aes_field.py b/preferences/aes_field.py
deleted file mode 100644
index 1329b0a7..00000000
--- a/preferences/aes_field.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# coding:utf-8
-# 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
-# Copyright © 2018 Maël Kervella
-#
-# 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.
-
-# App de gestion des machines pour re2o
-# Gabriel Détraz, Augustin Lemesle
-# Gplv2
-"""preferences.aes_field
-Module defining a AESEncryptedField object that can be used in forms
-to handle the use of properly encrypting and decrypting AES keys
-"""
-
-import string
-import binascii
-from random import choice
-from Crypto.Cipher import AES
-
-from django.db import models
-from django.conf import settings
-
-EOD = '`%EofD%`' # This should be something that will not occur in strings
-
-
-def genstring(length=16, chars=string.printable):
- """ Generate a random string of length `length` and composed of
- the characters in `chars` """
- return ''.join([choice(chars) for i in range(length)])
-
-
-def encrypt(key, s):
- """ AES Encrypt a secret `s` with the key `key` """
- obj = AES.new(key)
- datalength = len(s) + len(EOD)
- if datalength < 16:
- saltlength = 16 - datalength
- else:
- saltlength = 16 - datalength % 16
- ss = ''.join([s, EOD, genstring(saltlength)])
- return obj.encrypt(ss)
-
-
-def decrypt(key, s):
- """ AES Decrypt a secret `s` with the key `key` """
- obj = AES.new(key)
- ss = obj.decrypt(s)
- return ss.split(bytes(EOD, 'utf-8'))[0]
-
-
-class AESEncryptedField(models.CharField):
- """ A Field that can be used in forms for adding the support
- of AES ecnrypted fields """
- def save_form_data(self, instance, data):
- setattr(instance, self.name,
- binascii.b2a_base64(encrypt(settings.AES_KEY, data)))
-
- def to_python(self, value):
- if value is None:
- return None
- return decrypt(settings.AES_KEY,
- binascii.a2b_base64(value)).decode('utf-8')
-
- def from_db_value(self, value, *args, **kwargs):
- if value is None:
- return value
- return decrypt(settings.AES_KEY,
- binascii.a2b_base64(value)).decode('utf-8')
-
- def get_prep_value(self, value):
- if value is None:
- return value
- return binascii.b2a_base64(encrypt(
- settings.AES_KEY,
- value
- ))
diff --git a/preferences/migrations/0036_auto_20180705_0840.py b/preferences/migrations/0036_auto_20180705_0840.py
new file mode 100644
index 00000000..9dc67dac
--- /dev/null
+++ b/preferences/migrations/0036_auto_20180705_0840.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2018-07-05 13:40
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('preferences', '0035_optionaluser_allow_self_subscription'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='assooption',
+ name='payment',
+ ),
+ migrations.RemoveField(
+ model_name='assooption',
+ name='payment_id',
+ ),
+ migrations.RemoveField(
+ model_name='assooption',
+ name='payment_pass',
+ ),
+ migrations.RemoveField(
+ model_name='optionaluser',
+ name='allow_self_subscription',
+ ),
+ migrations.RemoveField(
+ model_name='optionaluser',
+ name='max_solde',
+ ),
+ migrations.RemoveField(
+ model_name='optionaluser',
+ name='min_online_payment',
+ ),
+ migrations.RemoveField(
+ model_name='optionaluser',
+ name='solde_negatif',
+ ),
+ migrations.RemoveField(
+ model_name='optionaluser',
+ name='user_solde',
+ ),
+ ]
diff --git a/preferences/migrations/0039_auto_20180115_0003.py b/preferences/migrations/0039_auto_20180115_0003.py
index 3dbe2b4c..f8da5c27 100644
--- a/preferences/migrations/0039_auto_20180115_0003.py
+++ b/preferences/migrations/0039_auto_20180115_0003.py
@@ -3,7 +3,6 @@
from __future__ import unicode_literals
from django.db import migrations, models
-import preferences.aes_field
class Migration(migrations.Migration):
diff --git a/preferences/migrations/0040_auto_20180129_1745.py b/preferences/migrations/0040_auto_20180129_1745.py
index dc7800f4..7b8248fd 100644
--- a/preferences/migrations/0040_auto_20180129_1745.py
+++ b/preferences/migrations/0040_auto_20180129_1745.py
@@ -3,7 +3,10 @@
from __future__ import unicode_literals
from django.db import migrations, models
-import preferences.aes_field
+try:
+ import preferences.aes_field as aes_field
+except ImportError:
+ import cotisations.payment_methods.comnpay.aes_field as aes_field
class Migration(migrations.Migration):
@@ -16,7 +19,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='assooption',
name='payment_pass',
- field=preferences.aes_field.AESEncryptedField(blank=True, max_length=255, null=True),
+ field=aes_field.AESEncryptedField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name='assooption',
diff --git a/preferences/models.py b/preferences/models.py
index 4a22edbe..2fd7d45a 100644
--- a/preferences/models.py
+++ b/preferences/models.py
@@ -35,8 +35,6 @@ import cotisations.models
import machines.models
from re2o.mixins import AclMixin
-from .aes_field import AESEncryptedField
-
class PreferencesModel(models.Model):
""" Base object for the Preferences objects
@@ -67,22 +65,6 @@ class OptionalUser(AclMixin, PreferencesModel):
PRETTY_NAME = "Options utilisateur"
is_tel_mandatory = models.BooleanField(default=True)
- user_solde = models.BooleanField(default=False)
- solde_negatif = models.DecimalField(
- max_digits=5,
- decimal_places=2,
- default=0
- )
- max_solde = models.DecimalField(
- max_digits=5,
- decimal_places=2,
- default=50
- )
- min_online_payment = models.DecimalField(
- max_digits=5,
- decimal_places=2,
- default=10
- )
gpg_fingerprint = models.BooleanField(default=True)
all_can_create_club = models.BooleanField(
default=False,
@@ -96,13 +78,6 @@ class OptionalUser(AclMixin, PreferencesModel):
default=False,
help_text="Un nouvel utilisateur peut se créer son compte sur re2o"
)
- allow_self_subscription = models.BooleanField(
- default=False,
- help_text=(
- "Autoriser les utilisateurs à cotiser par eux mêmes via les"
- " moyens de paiement permettant l'auto-cotisation."
- )
- )
shell_default = models.OneToOneField(
'users.ListShell',
on_delete=models.PROTECT,
@@ -298,25 +273,6 @@ class AssoOption(AclMixin, PreferencesModel):
blank=True,
null=True
)
- PAYMENT = (
- ('NONE', 'NONE'),
- ('COMNPAY', 'COMNPAY'),
- )
- payment = models.CharField(
- max_length=255,
- choices=PAYMENT,
- default='NONE',
- )
- payment_id = models.CharField(
- max_length=255,
- default='',
- blank=True
- )
- payment_pass = AESEncryptedField(
- max_length=255,
- null=True,
- blank=True,
- )
description = models.TextField(
null=True,
blank=True,
diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html
index 99e3e14f..09395b21 100644
--- a/preferences/templates/preferences/display_preferences.html
+++ b/preferences/templates/preferences/display_preferences.html
@@ -31,46 +31,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% block content %}
Préférences utilisateur
-
+
Editer
-
+
Téléphone obligatoirement requis |
{{ useroptions.is_tel_mandatory }} |
- Activation du solde pour les utilisateurs |
- {{ useroptions.user_solde }} |
-
-
Champ gpg fingerprint |
{{ useroptions.gpg_fingerprint }} |
- {% if useroptions.user_solde %}
- Solde négatif |
- {{ useroptions.solde_negatif }} |
- {% endif %}
Creations d'adhérents par tous |
{{ useroptions.all_can_create_adherent }} |
- Creations de clubs par tous |
- {{ useroptions.all_can_create_club }} |
+ Creations de clubs par tous |
+ {{ useroptions.all_can_create_club }} |
- {% if useroptions.user_solde %}
-
- Solde maximum |
- {{ useroptions.max_solde }} |
- Montant minimal de rechargement en ligne |
- {{ useroptions.min_online_payment }} |
-
- {% endif %}
- Auto inscription |
+ Auto inscription |
{{ useroptions.self_adhesion }} |
- Shell par défaut des utilisateurs |
- {{ useroptions.shell_default }} |
-
+ Shell par défaut des utilisateurs |
+ {{ useroptions.shell_default }} |
+
Préférences machines
@@ -91,11 +75,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{{ machineoptions.max_lambdauser_aliases }} |
Support de l'ipv6 |
{{ machineoptions.ipv6_mode }} |
-
-
- Creation de machines |
+
+
+ Creation de machines |
{{ machineoptions.create_machine }} |
-
+
Préférences topologie
@@ -108,7 +92,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
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" |
+ 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" |
|
@@ -144,12 +128,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
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}}
@@ -171,8 +155,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
Adresse |
- {{ assooptions.adresse1 }}
- {{ assooptions.adresse2 }} |
+ {{ assooptions.adresse1 }}
+ {{ assooptions.adresse2 }} |
Contact mail |
{{ assooptions.contact }} |
@@ -185,13 +169,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Objet utilisateur de l'association |
{{ assooptions.utilisateur_asso }} |
- Moyen de paiement automatique |
- {{ assooptions.payment }} |
-
-
- Description de l'association |
- {{ assooptions.description | safe }} |
-
+ Description de l'association |
+ {{ assooptions.description | safe }} |
+
Messages personalisé dans les mails
@@ -205,7 +185,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Mail de bienvenue (Français) |
{{ mailmessageoptions.welcome_mail_fr | safe }} |
-
+
Mail de bienvenue (Anglais) |
{{ mailmessageoptions.welcome_mail_en | safe }} |