mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-21 19:03:11 +00:00
Merge branch 'release-2.9' into 'master'
Release 2.9 It is that time of the year again. See [CHANGELOG.md](https://gitlab.federez.net/re2o/re2o/-/blob/release-2.9/CHANGELOG.md). Many thanks to the people who made Re2o2.9 possible, thanks to their 575 commits in almost one year of development! * Jean-Romain Garnier * Gabriel Detraz * Hugo Levy-Falk * Arthur Grisel-Davy * Corentin Canebier * Yoann Piétri * Jean-Marie Mineau * Leila Bekaddour * Maxime Bombar See merge request re2o/re2o!592
This commit is contained in:
commit
7c18f1f5ab
608 changed files with 28568 additions and 15026 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -44,5 +44,10 @@ static/logo/
|
|||
|
||||
# re2o specific
|
||||
settings_local.py
|
||||
local_routers.py
|
||||
re2o.png
|
||||
media/
|
||||
|
||||
# themes
|
||||
static/css/themes/*
|
||||
!static/css/themes/default.css
|
86
.mailmap
Normal file
86
.mailmap
Normal file
|
@ -0,0 +1,86 @@
|
|||
Gabriel Detraz <chirac@crans.org> <detraz@crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@arachne>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@re2o-test.auro.re>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@federez.net>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@raspberrypi>
|
||||
Gabriel Detraz <chirac@crans.org> <detraz@re2o-test.crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <detraz@re2o.adm.crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <chibrac@re2o-server.crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <detraz@crans.crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@re2o-server.crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@hydra>
|
||||
Gabriel Detraz <chirac@crans.org> <chirac@re2o-bcfg2.adm.crans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <detrazcrans.org>
|
||||
Gabriel Detraz <chirac@crans.org> <detraz@vo.crans.org>
|
||||
Maël Kervella <kervella.mael@gmail.com>
|
||||
Maël Kervella <kervella.mael@gmail.com> <dev@maelkervella.eu>
|
||||
Maël Kervella <kervella.mael@gmail.com> <mael.kervella@supelec.fr>
|
||||
Jean-Romain Garnier <jean-romain.garnier@supelec.fr>
|
||||
Jean-Romain Garnier <jean-romain.garnier@supelec.fr> <git@jean-romain.com>
|
||||
Hugo Levy-Falk <hugo@klafyvel.me> <hugo.levy--falk@supelec.fr>
|
||||
Hugo Levy-Falk <hugo@klafyvel.me> <klafyvel@gmail.com>
|
||||
Hugo Levy-Falk <hugo@klafyvel.me> <klafyvel@klafyvel.me>
|
||||
Hugo Levy-Falk <hugo@klafyvel.me> <klafyvel@federez.net>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grisel-davy@crans.org>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grisel-davy@re2o-server.crans.org>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grisel-davy@re2o-test.crans.org>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grisel-davy@re2o.adm.crans.org>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grisel-davy@nazgul.rezometz.org>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grisel-davy@re2o-test.auro.re>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grizzly@crans.org>
|
||||
Arthur Grisel-Davy <grisel-davy@crans.org> <grizzly@raspberrypi>
|
||||
Lara Kermarec <lhark@lharktop> <lhark@lharktop>
|
||||
Lara Kermarec <lhark@lharktop> <lhark@arachne>
|
||||
Lara Kermarec <lhark@lharktop> <lhark@pwc>
|
||||
Lara Kermarec <lhark@lharktop> <goulven.kermarec@supelec.fr>
|
||||
Lara Kermarec <lhark@lharktop> <lhark@federez-test>
|
||||
Lara Kermarec <lhark@lharktop> <lhark@hydra>
|
||||
Augustin Lemesle <augustin.lemesle@supelec.fr> <augustin.lemesle@supelec.fr>
|
||||
Augustin Lemesle <augustin.lemesle@supelec.fr> <Dalahro@arachne>
|
||||
Corentin Canebier <corentin@canebier.fr>
|
||||
Corentin Canebier <corentin@canebier.fr> <corentin.canebier@student-cs.fr>
|
||||
Root `root` Root <root@arachne>
|
||||
Root `root` Root <root@arachne> <root@hydra.rezometz.org>
|
||||
Root `root` Root <root@arachne> <root@federez-test.crans.org>
|
||||
Root `root` Root <root@arachne> <root@gorgoroth>
|
||||
Root `root` Root <root@arachne> <root@raspberrypi>
|
||||
Root `root` Root <root@arachne> <root@nevrast>
|
||||
Root `root` Root <root@arachne> <root@pwc>
|
||||
Root `root` Root <root@arachne> <root@federez.net>
|
||||
Root `root` Root <root@arachne> <root@hydra>
|
||||
Root `root` Root <root@arachne> <root@morgoth.rez>
|
||||
Root `root` Root <root@arachne> <root@re2o-server.crans.org>
|
||||
Yoann Piétri <me@nanoy.fr>
|
||||
Yoann Piétri <me@nanoy.fr> <yoann.pietri@supelec.fr>
|
||||
Guillaume Goessel <rezo@guimoz.fr>
|
||||
Guillaume Goessel <rezo@guimoz.fr> <guillaume.goessel@supelec.fr>
|
||||
Guillaume Goessel <rezo@guimoz.fr> <guillaume.goessel@hotmail.com>
|
||||
Guillaume Goessel <rezo@guimoz.fr> <me+federez@guimoz.fr>
|
||||
David Sinquin <david.RezoMetz@sinquin.eu>
|
||||
David Sinquin <david.RezoMetz@sinquin.eu> <david.rezo@sinquin.eu>
|
||||
David Sinquin <david.RezoMetz@sinquin.eu> <david.federez.ldap@sinquin.eu>
|
||||
Matthieu Michelet <matthieu.michelet@supelec.fr>
|
||||
Matthieu Michelet <matthieu.michelet@supelec.fr> <michelet.matthieu@supelec.fr>
|
||||
Jean-Marie Mineau <mineau.jean.marie@gmail.com>
|
||||
~anonymised~ <sellem+re2o@crans.org>
|
||||
~anonymised~ <sellem+re2o@crans.org> <sellem@crans.org>
|
||||
Thibault de Boutray <me@thibaultdeboutray.pro>
|
||||
Thibault de Boutray <me@thibaultdeboutray.pro> <thibaultdeboutray@gmail.com>
|
||||
Fardale <fardale+git@crans.org>
|
||||
Fardale <fardale+git@crans.org> <arrighi@crans.org>
|
||||
Laouen Fernet <laouen.fernet@supelec.fr>
|
||||
Laouen Fernet <laouen.fernet@supelec.fr> FERNET Laouen <laouen.fernet@supelec.fr>
|
||||
Bombar Maxime <bombar@crans.org>
|
||||
Leïla Bekaddour <leila.bekaddour@student-cs.fr>
|
||||
Leïla Bekaddour <leila.bekaddour@student-cs.fr> <leila@ec-mac-cr-sho.home>
|
||||
edpibu <edpibu@crans.org>
|
||||
edpibu <edpibu@crans.org> <edpibu@re2o-test.crans.org>
|
||||
Éloi Alain <eloi.alain@supelec.fr>
|
||||
Éloi Alain <eloi.alain@supelec.fr> <eloi.alain@metz.supelec.fr>
|
||||
Gabriel Le Bouder <lebouder@crans.org>
|
||||
Gabriel Le Bouder <lebouder@crans.org> <lebouder@re2o-server.crans.org>
|
||||
Charlie Jacomme <jacomme@crans.org>
|
||||
Charlie Jacomme <jacomme@crans.org> <jacomme@crans.org>
|
||||
Benjamin Graillot <graillot@crans.org>
|
||||
Benjamin Graillot <graillot@crans.org> <graillot@crans.org>
|
102
CHANGELOG.md
102
CHANGELOG.md
|
@ -1,3 +1,72 @@
|
|||
# Re2o 2.9
|
||||
|
||||
## Install steps
|
||||
|
||||
To install the latest version of Re2o, checkout the [dedicated wiki entry](https://gitlab.federez.net/re2o/re2o/-/wikis/User-Documentation/Quick-Start#update-re2o).
|
||||
|
||||
## Post-install steps
|
||||
|
||||
### MR 531: FreeRADIUS Python3 backend
|
||||
|
||||
On the Radius server, add `buster-backports` to your `/etc/apt/sources.list`:
|
||||
```bash
|
||||
echo "deb http://deb.debian.org/debian buster-backports main contrib" >> /etc/apt/sources.list
|
||||
```
|
||||
|
||||
**Note:** If you are running Debian Bullseye, the package should already be available without going through backports.
|
||||
|
||||
Then install the new required packages:
|
||||
```bash
|
||||
apt update
|
||||
apt install -t buster-backports freeradius
|
||||
cat apt_requirements_radius.txt | xargs sudo apt -y install
|
||||
```
|
||||
|
||||
### MR 582: Autocomplete light
|
||||
|
||||
On the Re2o server, install the new dependency and run `collectstatic`:
|
||||
```bash
|
||||
sudo pip3 install -r pip_requirements.txt
|
||||
python3 manage.py collectstatic
|
||||
```
|
||||
|
||||
### MR 589: Move LDAP to optional app
|
||||
|
||||
Add `ldap_sync` to your optional apps in your local settings (`re2o/settings_local.py`) if you want to keep using the LDAP synchronisation.
|
||||
|
||||
### Final steps
|
||||
|
||||
As usual, run the following commands after updating:
|
||||
```bash
|
||||
python3 manage.py migrate
|
||||
python3 manage.py compilemessages
|
||||
sudo service apache2 reload
|
||||
```
|
||||
|
||||
## New features
|
||||
|
||||
Here is a list of noteworthy features brought by this update:
|
||||
|
||||
* [!488](https://gitlab.federez.net/re2o/re2o/-/merge_requests/488): Use `+` in searches to combine keywords (e.g. `John+Doe`).
|
||||
* [!495](https://gitlab.federez.net/re2o/re2o/-/merge_requests/495): Add optional behavior allowing users to override another user's room, if that user is no longer active.
|
||||
* [!496](https://gitlab.federez.net/re2o/re2o/-/merge_requests/496): Add option to allow users to choose their password during account creation. They will have to separately confirm their email address.
|
||||
* [!504](https://gitlab.federez.net/re2o/re2o/-/merge_requests/504): Add setting to change the minimum password length.
|
||||
* [!507](https://gitlab.federez.net/re2o/re2o/-/merge_requests/507): New form for editing lists of rights that should make everyone happier.
|
||||
* [!512](https://gitlab.federez.net/re2o/re2o/-/merge_requests/512): Add ability to comment on tickets.
|
||||
* [!513](https://gitlab.federez.net/re2o/re2o/-/merge_requests/513): IP and MAC address history (`Statistics > Machine history` tab) which also works for deleted interfaces. Uses already existing history so events before the upgrade are taken into account.
|
||||
* [!516](https://gitlab.federez.net/re2o/re2o/-/merge_requests/516): Detailed events in history views (e.g. show `old_email -> new_email`).
|
||||
* [!519](https://gitlab.federez.net/re2o/re2o/-/merge_requests/519): Add ability to filter event logs (e.g. to show all the subscriptions added by an admin).
|
||||
* [!569](https://gitlab.federez.net/re2o/re2o/-/merge_requests/569): Refactor navbar to make menu navigation easier.
|
||||
* [!569](https://gitlab.federez.net/re2o/re2o/-/merge_requests/569): Add ability to install custom themes (checkout [this repository](https://gitlab.federez.net/re2o/re2o-themes) for a list of Re2o themes).
|
||||
* [!578](https://gitlab.federez.net/re2o/re2o/-/merge_requests/578) : Migrations squashed to ease the installation process.
|
||||
* [!582](https://gitlab.federez.net/re2o/re2o/-/merge_requests/582): Improve autocomplete fields so they load faster and have a clearer behavior (no more entering a value without clicking and thinking it was taken into account).
|
||||
* [!589](https://gitlab.federez.net/re2o/re2o/-/merge_requests/589): Move LDAP to a separate optional app.
|
||||
* Plenty of bug fixes.
|
||||
|
||||
You can view the full list of closed issues [here](https://gitlab.federez.net/re2o/re2o/-/issues?scope=all&state=all&milestone_title=Re2o%202.9).
|
||||
|
||||
# Before Re2o 2.9
|
||||
|
||||
## MR 160: Datepicker
|
||||
|
||||
Install libjs-jquery libjs-jquery-ui libjs-jquery-timepicker libjs-bootstrap javascript-common
|
||||
|
@ -21,7 +90,6 @@ rm static_files/js/jquery-2.2.4.min.js
|
|||
rm static/css/jquery-ui-timepicker-addon.css
|
||||
```
|
||||
|
||||
|
||||
## MR 159: Graph topo & MR 164: branche de création de graph
|
||||
|
||||
Add a graph of the network topology
|
||||
|
@ -34,7 +102,6 @@ Create the *media/images* directory:
|
|||
mkdir -p media/images
|
||||
```
|
||||
|
||||
|
||||
## MR 163: Fix install re2o
|
||||
|
||||
Refactored install_re2o.sh script.
|
||||
|
@ -45,8 +112,6 @@ install_re2o.sh help
|
|||
|
||||
* The installation templates (LDIF files and `re2o/settings_locale.example.py`) have been changed to use `example.net` instead of `example.org` (more neutral and generic)
|
||||
|
||||
|
||||
|
||||
## MR 176: Add awesome Logo
|
||||
|
||||
Add the logo and fix somme issues on the navbar and home page. Only collecting the statics is needed:
|
||||
|
@ -54,7 +119,6 @@ Add the logo and fix somme issues on the navbar and home page. Only collecting t
|
|||
python3 manage.py collectstatic
|
||||
```
|
||||
|
||||
|
||||
## MR 172: Refactor API
|
||||
|
||||
Creates a new (nearly) REST API to expose all models of Re2o. See [the dedicated wiki page](https://gitlab.federez.net/federez/re2o/wikis/API/Raw-Usage) for more details on how to use it.
|
||||
|
@ -75,7 +139,6 @@ OPTIONAL_APPS = (
|
|||
)
|
||||
```
|
||||
|
||||
|
||||
## MR 177: Add django-debug-toolbar support
|
||||
|
||||
Add the possibility to enable `django-debug-toolbar` in debug mode. First install the APT package:
|
||||
|
@ -203,3 +266,30 @@ If you use MySQL, please run
|
|||
```
|
||||
SET GLOBAL SQL_MODE=ANSI_QUOTES;
|
||||
```
|
||||
|
||||
## MR 531
|
||||
|
||||
To use the freeradius python3 backend, please add buster-backports sources to
|
||||
your apt lists.
|
||||
|
||||
Then, install and update freeradius :
|
||||
```bash
|
||||
apt install -t buster-backports freeradius
|
||||
apt install python3-dev
|
||||
```
|
||||
|
||||
Make sure that all depending packages (python3-django etc) provided in the new
|
||||
apt_requirements_radius.txt are installed.
|
||||
|
||||
## MR 535 : Routers
|
||||
|
||||
It is now possible to use a custom router file, if you want to have mutli database
|
||||
support, with for example one as master database and one as replica database.
|
||||
If you want to add a database routers, please fill in in settings_local.py
|
||||
and add your databse.
|
||||
Then, add a file "local_routers.py" in folder app re2o, and add your router path
|
||||
in the settings_local.py file :
|
||||
|
||||
```python
|
||||
LOCAL_ROUTERS = ["re2o.local_routers.DbRouter"]
|
||||
```
|
||||
|
|
85
README.md
85
README.md
|
@ -1,75 +1,64 @@
|
|||
**Note:** English version below.
|
||||
|
||||
# Re2o
|
||||
|
||||
GNU public license v2.0
|
||||
|
||||
## Avant propos
|
||||
|
||||
Re2o est un logiciel d'administration développé initialement au rezometz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
Re2o est un logiciel d'administration développé initialement au [Rézo Metz](https://www.rezometz.org/). Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable et configurable facilement.
|
||||
|
||||
Il utilise le framework django avec python3. Il permet de gérer les adhérents,
|
||||
les machines, les factures, les droits d'accès, les switchs et la topologie du
|
||||
réseau.
|
||||
De cette manière, il est possible de pluguer très facilement des services
|
||||
dessus, qui accèdent à la base de donnée en passant par django (ex : dhcp), en
|
||||
chargeant la liste de toutes les mac-ip, ou la liste des mac-ip autorisées sur
|
||||
le réseau (adhérent à jour de cotisation).
|
||||
Il est possible d'activer très facilement des services qui améliorerons les possibilités de Re2o pour convenir au mieux aux besoins de chaque association.
|
||||
|
||||
# Installation
|
||||
## Installation
|
||||
|
||||
Un tutoriel pour installer le projet est disponible [sur le wiki](https://gitlab.federez.net/federez/re2o/wikis/User%20Documentation/Quick%20Start).
|
||||
|
||||
# Installations Optionnelles
|
||||
## Générer le schéma des dépendances
|
||||
## Fonctionnement Général
|
||||
|
||||
Pour cela :
|
||||
* apt install python3-django-extensions
|
||||
* python3 manage.py graph_models -a -g -o re2o.png
|
||||
Re2o utilise le Framework Django et suit donc le principe de toutes les applications Django. Les différents composants sont les models (qui définissent les entrées de la base de données), les templates (qui définissent les pages), les views (qui génèrent les templates avec les données pertinentes), et les forms (qui définissent les pages de modification des objets). Ce framework permet de manipuler les données comme des objets Python.
|
||||
|
||||
# Fonctionnement interne
|
||||
Tous ces composants sont regroupés en apps (users, machines, topologie,...). Certaines de ces apps constituent le coeur de Re2o et sont indispensables à son fonctionnement. Certaines autres apps sont optionnelles et peuvent être activées en fonction des besoins de chaque association.
|
||||
|
||||
## Fonctionnement général
|
||||
## API Rest
|
||||
|
||||
Re2o est séparé entre les models, qui sont visibles sur le schéma des
|
||||
dépendances. Il s'agit en réalité des tables sql, et les fields étant les
|
||||
colonnes.
|
||||
Ceci dit il n'est jamais nécessaire de toucher directement au sql, django
|
||||
procédant automatiquement à tout cela.
|
||||
On crée donc différents models (user, right pour les droits des users,
|
||||
interfaces, IpList pour l'ensemble des adresses ip, etc)
|
||||
Les données stockées dans Re2o sont disponibles via un API Rest. Les services installés sur d'autres machines (dhcp, dns, firewall,...) utilisent cet API pour avoir accès aux données des utilisateurs et fonctionner.
|
||||
|
||||
Du coté des forms, il s'agit des formulaires d'édition des models. Il
|
||||
s'agit de ModelForms django, qui héritent des models très simplement, voir la
|
||||
documentation django models forms.
|
||||
# Wiki
|
||||
|
||||
Enfin les views, générent les pages web à partir des forms et des templates.
|
||||
Le [Wiki](https://gitlab.federez.net/federez/re2o/-/wikis/home) est accessible sur le gitlab de Federez. Il regroupe les informations et instructions pour la plupart des composants de Re2o.
|
||||
|
||||
## Fonctionnement avec les services
|
||||
----
|
||||
|
||||
Les services dhcp.py, dns.py etc accèdent aux données via des vues rest.
|
||||
Celles-ci se trouvent dans machines/views.py. Elles sont générées via
|
||||
machines/serializers.py qui génère les vues. IL s'agit de vues en json utilisées
|
||||
par re2o-tools pour récupérer les données.
|
||||
Il est nécessaire de créer un user dans re2o avec le droit serveur qui permet
|
||||
d'accéder à ces vues, utilisé par re2o-tools.
|
||||
# Re2o
|
||||
|
||||
# Requète en base de donnée
|
||||
GNU Public license v2.0
|
||||
|
||||
Pour avoir un shell, lancer :
|
||||
```.bash
|
||||
python3 manage.py shell
|
||||
```
|
||||
## Foreword
|
||||
|
||||
Pour charger des objets (exemple avec User), faire :
|
||||
```.python
|
||||
from users.models import User
|
||||
```
|
||||
Re2o is a management software initially developed at [Rézo Metz](https://www.rezometz.org/). It is now in use in several student organizations. It aims to remain agnostic of the organization that uses it and be easy to setup.
|
||||
|
||||
Pour charger les objets django, il suffit de faire `User.objects.all()`
|
||||
pour tous les users par exemple.
|
||||
Il est ensuite aisé de faire des requêtes, par exemple
|
||||
`User.objects.filter(pseudo='test')`
|
||||
Re2o is based on the Django framework and Python3. Its core functionalities include managing the members, their machines, their invoices and their rights to the network but also the topology of the network and its devices.
|
||||
On top of this, it is possible to plug services to enhance the possibilities and fit the need of each organization.
|
||||
|
||||
Des exemples et la documentation complète sur les requêtes django sont
|
||||
disponible sur le site officiel.
|
||||
# Setup
|
||||
|
||||
A tutorial is available on the [Wiki](https://gitlab.federez.net/federez/re2o/wikis/User%20Documentation/Quick%20Start) to describe the setup process.
|
||||
|
||||
# General Functioning
|
||||
|
||||
Re2o follow the general functioning of a Django project and split its components between the models (describe the database objects), the templates (that define the front end), the views (that populate and serve the templates) and the forms (that provide front end object edition/creation/removal). This framework provide an abstraction layer to manipulate SQL objects as Python objects.
|
||||
|
||||
Functionalities are grouped in apps (users, machines, topologie,...). Along the core functionalities, optional functionalities are available and can be activated in the preferences.
|
||||
|
||||
## Rest API
|
||||
|
||||
Re2o provide a Rest API to allow external services (dhcp, dns, firewall,...) installed on remote machines to access database informations in Json format. Those services are optional and should be installed and activated to fit each organization needs.
|
||||
|
||||
# Wiki
|
||||
|
||||
The [Wiki](https://gitlab.federez.net/federez/re2o/-/wikis/home) is available to provide information and instruction for most components of Re2o.
|
||||
|
|
29
api/acl.py
29
api/acl.py
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -31,32 +31,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
||||
def _create_api_permission():
|
||||
"""Creates the 'use_api' permission if not created.
|
||||
|
||||
The 'use_api' is a fake permission in the sense it is not associated with an
|
||||
existing model and this ensure the permission is created every time this file
|
||||
is imported.
|
||||
"""
|
||||
api_content_type, created = ContentType.objects.get_or_create(
|
||||
app_label=settings.API_CONTENT_TYPE_APP_LABEL,
|
||||
model=settings.API_CONTENT_TYPE_MODEL,
|
||||
)
|
||||
if created:
|
||||
api_content_type.save()
|
||||
api_permission, created = Permission.objects.get_or_create(
|
||||
name=settings.API_PERMISSION_NAME,
|
||||
content_type=api_content_type,
|
||||
codename=settings.API_PERMISSION_CODENAME,
|
||||
)
|
||||
if created:
|
||||
api_permission.save()
|
||||
|
||||
|
||||
_create_api_permission()
|
||||
|
||||
|
||||
def can_view(user):
|
||||
def can_view(user, *args, **kwargs):
|
||||
"""Check if an user can view the application.
|
||||
|
||||
Args:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -21,7 +21,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 2.5\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-11-19 23:43+0100\n"
|
||||
"POT-Creation-Date: 2021-01-24 11:51+0100\n"
|
||||
"PO-Revision-Date: 2019-01-07 01:37+0100\n"
|
||||
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
|
||||
"Language-Team: \n"
|
||||
|
@ -31,7 +31,7 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: api/acl.py:77
|
||||
#: api/acl.py:52
|
||||
msgid "You don't have the right to view this application."
|
||||
msgstr "Vous n'avez pas le droit de voir cette application."
|
||||
|
||||
|
|
34
api/migrations/0001_initial.py
Normal file
34
api/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
from django.conf import settings
|
||||
|
||||
def create_api_permission(apps, schema_editor):
|
||||
"""Creates the 'use_api' permission if not created.
|
||||
|
||||
The 'use_api' is a fake permission in the sense it is not associated with an
|
||||
existing model and this ensure the permission is created.
|
||||
"""
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
Permission = apps.get_model("auth", "Permission")
|
||||
api_content_type, created = ContentType.objects.get_or_create(
|
||||
app_label=settings.API_CONTENT_TYPE_APP_LABEL,
|
||||
model=settings.API_CONTENT_TYPE_MODEL,
|
||||
)
|
||||
if created:
|
||||
api_content_type.save()
|
||||
api_permission, created = Permission.objects.get_or_create(
|
||||
name=settings.API_PERMISSION_NAME,
|
||||
content_type=api_content_type,
|
||||
codename=settings.API_PERMISSION_CODENAME,
|
||||
)
|
||||
if created:
|
||||
api_permission.save()
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
dependencies = []
|
||||
operations = [
|
||||
migrations.RunPython(create_api_permission)
|
||||
]
|
0
api/migrations/__init__.py
Normal file
0
api/migrations/__init__.py
Normal file
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -239,6 +239,11 @@ class AutodetectACLPermission(permissions.BasePermission):
|
|||
if getattr(view, "_ignore_model_permissions", False):
|
||||
return True
|
||||
|
||||
# Bypass permission verifications if it is a functional view
|
||||
# (permissions are handled by ACL)
|
||||
if not hasattr(view, "queryset") and not hasattr(view, "get_queryset"):
|
||||
return True
|
||||
|
||||
if not request.user or not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
# Copyright © 2018 Mael Kervella
|
||||
# Copyright © 2020 Corentin Canebier
|
||||
#
|
||||
# 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
|
||||
|
@ -41,6 +42,7 @@ class AllViewsRouter(DefaultRouter):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.view_registry = []
|
||||
self.functional_view_registry = []
|
||||
super(AllViewsRouter, self).__init__(*args, **kwargs)
|
||||
|
||||
def register_viewset(self, *args, **kwargs):
|
||||
|
@ -64,6 +66,19 @@ class AllViewsRouter(DefaultRouter):
|
|||
name = self.get_default_name(pattern)
|
||||
self.view_registry.append((pattern, view, name))
|
||||
|
||||
def register_functional_view(self, pattern, view, name=None):
|
||||
"""Register a functional view in the router.
|
||||
|
||||
Args:
|
||||
pattern: The URL pattern to use for this view.
|
||||
view: The functional view to register.
|
||||
name: An optional name for the route generated. Defaults is
|
||||
based on the pattern last section (delimited by '/').
|
||||
"""
|
||||
if name is None:
|
||||
name = self.get_default_name(pattern)
|
||||
self.functional_view_registry.append((pattern, view, name))
|
||||
|
||||
@staticmethod
|
||||
def get_default_name(pattern):
|
||||
"""Returns the name to use for the route if none was specified.
|
||||
|
@ -155,4 +170,7 @@ class AllViewsRouter(DefaultRouter):
|
|||
for pattern, view, name in self.view_registry:
|
||||
urls.append(url(pattern, view.as_view(), name=name))
|
||||
|
||||
for pattern, view, name in self.functional_view_registry:
|
||||
urls.append(url(pattern, view, name=name))
|
||||
|
||||
return urls
|
||||
|
|
1371
api/serializers.py
1371
api/serializers.py
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
134
api/urls.py
134
api/urls.py
|
@ -1,9 +1,10 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
# Copyright © 2018 Maël Kervella
|
||||
# Copyright © 2020 Corentin Canebier
|
||||
#
|
||||
# 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
|
||||
|
@ -28,114 +29,39 @@ can be generated automatically.
|
|||
"""
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from importlib import import_module
|
||||
|
||||
from . import views
|
||||
from .routers import AllViewsRouter
|
||||
from django.conf import settings
|
||||
|
||||
router = AllViewsRouter()
|
||||
# COTISATIONS
|
||||
router.register_viewset(r"cotisations/facture", views.FactureViewSet)
|
||||
router.register_viewset(r"cotisations/vente", views.VenteViewSet)
|
||||
router.register_viewset(r"cotisations/article", views.ArticleViewSet)
|
||||
router.register_viewset(r"cotisations/banque", views.BanqueViewSet)
|
||||
router.register_viewset(r"cotisations/paiement", views.PaiementViewSet)
|
||||
router.register_viewset(r"cotisations/cotisation", views.CotisationViewSet)
|
||||
# MACHINES
|
||||
router.register_viewset(r"machines/machine", views.MachineViewSet)
|
||||
router.register_viewset(r"machines/machinetype", views.MachineTypeViewSet)
|
||||
router.register_viewset(r"machines/iptype", views.IpTypeViewSet)
|
||||
router.register_viewset(r"machines/vlan", views.VlanViewSet)
|
||||
router.register_viewset(r"machines/nas", views.NasViewSet)
|
||||
router.register_viewset(r"machines/soa", views.SOAViewSet)
|
||||
router.register_viewset(r"machines/extension", views.ExtensionViewSet)
|
||||
router.register_viewset(r"machines/mx", views.MxViewSet)
|
||||
router.register_viewset(r"machines/ns", views.NsViewSet)
|
||||
router.register_viewset(r"machines/txt", views.TxtViewSet)
|
||||
router.register_viewset(r"machines/dname", views.DNameViewSet)
|
||||
router.register_viewset(r"machines/srv", views.SrvViewSet)
|
||||
router.register_viewset(r"machines/sshfp", views.SshFpViewSet)
|
||||
router.register_viewset(r"machines/interface", views.InterfaceViewSet)
|
||||
router.register_viewset(r"machines/ipv6list", views.Ipv6ListViewSet)
|
||||
router.register_viewset(r"machines/domain", views.DomainViewSet)
|
||||
router.register_viewset(r"machines/iplist", views.IpListViewSet)
|
||||
router.register_viewset(r"machines/service", views.ServiceViewSet)
|
||||
router.register_viewset(
|
||||
r"machines/servicelink", views.ServiceLinkViewSet, base_name="servicelink"
|
||||
)
|
||||
router.register_viewset(r"machines/ouvertureportlist", views.OuverturePortListViewSet)
|
||||
router.register_viewset(r"machines/ouvertureport", views.OuverturePortViewSet)
|
||||
router.register_viewset(r"machines/role", views.RoleViewSet)
|
||||
# PREFERENCES
|
||||
router.register_view(r"preferences/optionaluser", views.OptionalUserView),
|
||||
router.register_view(r"preferences/optionalmachine", views.OptionalMachineView),
|
||||
router.register_view(r"preferences/optionaltopologie", views.OptionalTopologieView),
|
||||
router.register_view(r"preferences/radiusoption", views.RadiusOptionView),
|
||||
router.register_view(r"preferences/generaloption", views.GeneralOptionView),
|
||||
router.register_viewset(
|
||||
r"preferences/service", views.HomeServiceViewSet, base_name="homeservice"
|
||||
),
|
||||
router.register_view(r"preferences/assooption", views.AssoOptionView),
|
||||
router.register_view(r"preferences/homeoption", views.HomeOptionView),
|
||||
router.register_view(r"preferences/mailmessageoption", views.MailMessageOptionView),
|
||||
# TOPOLOGIE
|
||||
router.register_viewset(r"topologie/stack", views.StackViewSet)
|
||||
router.register_viewset(r"topologie/acesspoint", views.AccessPointViewSet)
|
||||
router.register_viewset(r"topologie/switch", views.SwitchViewSet)
|
||||
router.register_viewset(r"topologie/server", views.ServerViewSet)
|
||||
router.register_viewset(r"topologie/modelswitch", views.ModelSwitchViewSet)
|
||||
router.register_viewset(r"topologie/constructorswitch", views.ConstructorSwitchViewSet)
|
||||
router.register_viewset(r"topologie/switchbay", views.SwitchBayViewSet)
|
||||
router.register_viewset(r"topologie/building", views.BuildingViewSet)
|
||||
router.register_viewset(
|
||||
r"topologie/switchport", views.SwitchPortViewSet, base_name="switchport"
|
||||
)
|
||||
router.register_viewset(
|
||||
r"topologie/portprofile", views.PortProfileViewSet, base_name="portprofile"
|
||||
)
|
||||
router.register_viewset(r"topologie/room", views.RoomViewSet)
|
||||
router.register(r"topologie/portprofile", views.PortProfileViewSet)
|
||||
# USERS
|
||||
router.register_viewset(r"users/user", views.UserViewSet, base_name="user")
|
||||
router.register_viewset(
|
||||
r"users/homecreation", views.HomeCreationViewSet, base_name="homecreation"
|
||||
)
|
||||
router.register_viewset(
|
||||
r"users/normaluser", views.NormalUserViewSet, base_name="normaluser"
|
||||
)
|
||||
router.register_viewset(
|
||||
r"users/criticaluser", views.CriticalUserViewSet, base_name="criticaluser"
|
||||
)
|
||||
router.register_viewset(r"users/club", views.ClubViewSet)
|
||||
router.register_viewset(r"users/adherent", views.AdherentViewSet)
|
||||
router.register_viewset(r"users/serviceuser", views.ServiceUserViewSet)
|
||||
router.register_viewset(r"users/school", views.SchoolViewSet)
|
||||
router.register_viewset(r"users/listright", views.ListRightViewSet)
|
||||
router.register_viewset(r"users/shell", views.ShellViewSet, base_name="shell")
|
||||
router.register_viewset(r"users/ban", views.BanViewSet)
|
||||
router.register_viewset(r"users/whitelist", views.WhitelistViewSet)
|
||||
router.register_viewset(r"users/emailaddress", views.EMailAddressViewSet)
|
||||
# SERVICE REGEN
|
||||
router.register_viewset(
|
||||
r"services/regen", views.ServiceRegenViewSet, base_name="serviceregen"
|
||||
)
|
||||
# DHCP
|
||||
router.register_view(r"dhcp/hostmacip", views.HostMacIpView),
|
||||
# LOCAL EMAILS
|
||||
router.register_view(r"localemail/users", views.LocalEmailUsersView),
|
||||
# Firewall
|
||||
router.register_view(r"firewall/subnet-ports", views.SubnetPortsOpenView),
|
||||
router.register_view(r"firewall/interface-ports", views.InterfacePortsOpenView),
|
||||
# Switches config
|
||||
router.register_view(r"switchs/ports-config", views.SwitchPortView),
|
||||
router.register_view(r"switchs/role", views.RoleView),
|
||||
# Reminder
|
||||
router.register_view(r"reminder/get-users", views.ReminderView),
|
||||
# DNS
|
||||
router.register_view(r"dns/zones", views.DNSZonesView),
|
||||
router.register_view(r"dns/reverse-zones", views.DNSReverseZonesView),
|
||||
# MAILING
|
||||
router.register_view(r"mailing/standard", views.StandardMailingView),
|
||||
router.register_view(r"mailing/club", views.ClubMailingView),
|
||||
|
||||
urls_viewset = []
|
||||
urls_view = []
|
||||
urls_functional_view = []
|
||||
|
||||
for app in settings.INSTALLED_APPS:
|
||||
try:
|
||||
module = import_module(".api.urls", package=app)
|
||||
urls_viewset += getattr(module, "urls_viewset", [])
|
||||
urls_view += getattr(module, "urls_view", [])
|
||||
urls_functional_view += getattr(module, "urls_functional_view", [])
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
for _url, viewset, name in urls_viewset:
|
||||
if name == None:
|
||||
router.register_viewset(_url, viewset)
|
||||
else:
|
||||
router.register_viewset(_url, viewset, basename=name)
|
||||
|
||||
for _url, view in urls_view:
|
||||
router.register_view(_url, view)
|
||||
|
||||
for _url, view, name in urls_functional_view:
|
||||
router.register_functional_view(_url, view, name)
|
||||
|
||||
# TOKEN AUTHENTICATION
|
||||
router.register_view(r"token-auth", views.ObtainExpiringAuthToken)
|
||||
|
||||
|
|
739
api/views.py
739
api/views.py
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -30,752 +30,17 @@ import datetime
|
|||
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.models import Group
|
||||
from rest_framework import viewsets, generics, views
|
||||
from rest_framework.authtoken.models import Token
|
||||
from rest_framework.authtoken.views import ObtainAuthToken
|
||||
from rest_framework.response import Response
|
||||
|
||||
import cotisations.models as cotisations
|
||||
import machines.models as machines
|
||||
import preferences.models as preferences
|
||||
import topologie.models as topologie
|
||||
import users.models as users
|
||||
from re2o.utils import all_active_interfaces, all_has_access
|
||||
from . import serializers
|
||||
from .pagination import PageSizedPagination
|
||||
from .permissions import ACLPermission
|
||||
|
||||
|
||||
# COTISATIONS
|
||||
|
||||
|
||||
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Facture` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Facture.objects.all()
|
||||
serializer_class = serializers.FactureSerializer
|
||||
|
||||
|
||||
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Facture` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.BaseInvoice.objects.all()
|
||||
serializer_class = serializers.BaseInvoiceSerializer
|
||||
|
||||
|
||||
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Vente` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Vente.objects.all()
|
||||
serializer_class = serializers.VenteSerializer
|
||||
|
||||
|
||||
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Article` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Article.objects.all()
|
||||
serializer_class = serializers.ArticleSerializer
|
||||
|
||||
|
||||
class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Banque` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Banque.objects.all()
|
||||
serializer_class = serializers.BanqueSerializer
|
||||
|
||||
|
||||
class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Paiement` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Paiement.objects.all()
|
||||
serializer_class = serializers.PaiementSerializer
|
||||
|
||||
|
||||
class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Cotisation` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Cotisation.objects.all()
|
||||
serializer_class = serializers.CotisationSerializer
|
||||
|
||||
|
||||
# MACHINES
|
||||
|
||||
|
||||
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Machine` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Machine.objects.all()
|
||||
serializer_class = serializers.MachineSerializer
|
||||
|
||||
|
||||
class MachineTypeViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.MachineType` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.MachineType.objects.all()
|
||||
serializer_class = serializers.MachineTypeSerializer
|
||||
|
||||
|
||||
class IpTypeViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.IpType` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.IpType.objects.all()
|
||||
serializer_class = serializers.IpTypeSerializer
|
||||
|
||||
|
||||
class VlanViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Vlan` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Vlan.objects.all()
|
||||
serializer_class = serializers.VlanSerializer
|
||||
|
||||
|
||||
class NasViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Nas` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Nas.objects.all()
|
||||
serializer_class = serializers.NasSerializer
|
||||
|
||||
|
||||
class SOAViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.SOA` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.SOA.objects.all()
|
||||
serializer_class = serializers.SOASerializer
|
||||
|
||||
|
||||
class ExtensionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Extension` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Extension.objects.all()
|
||||
serializer_class = serializers.ExtensionSerializer
|
||||
|
||||
|
||||
class MxViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Mx` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Mx.objects.all()
|
||||
serializer_class = serializers.MxSerializer
|
||||
|
||||
|
||||
class NsViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Ns` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Ns.objects.all()
|
||||
serializer_class = serializers.NsSerializer
|
||||
|
||||
|
||||
class TxtViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Txt` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Txt.objects.all()
|
||||
serializer_class = serializers.TxtSerializer
|
||||
|
||||
|
||||
class DNameViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.DName` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.DName.objects.all()
|
||||
serializer_class = serializers.DNameSerializer
|
||||
|
||||
|
||||
class SrvViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Srv` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Srv.objects.all()
|
||||
serializer_class = serializers.SrvSerializer
|
||||
|
||||
|
||||
class SshFpViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.SshFp` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.SshFp.objects.all()
|
||||
serializer_class = serializers.SshFpSerializer
|
||||
|
||||
|
||||
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Interface` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Interface.objects.all()
|
||||
serializer_class = serializers.InterfaceSerializer
|
||||
|
||||
|
||||
class Ipv6ListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Ipv6List` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Ipv6List.objects.all()
|
||||
serializer_class = serializers.Ipv6ListSerializer
|
||||
|
||||
|
||||
class DomainViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Domain` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Domain.objects.all()
|
||||
serializer_class = serializers.DomainSerializer
|
||||
|
||||
|
||||
class IpListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.IpList` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.IpList.objects.all()
|
||||
serializer_class = serializers.IpListSerializer
|
||||
|
||||
|
||||
class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Service` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Service.objects.all()
|
||||
serializer_class = serializers.ServiceSerializer
|
||||
|
||||
|
||||
class ServiceLinkViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Service_link` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Service_link.objects.all()
|
||||
serializer_class = serializers.ServiceLinkSerializer
|
||||
|
||||
|
||||
class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.OuverturePortList`
|
||||
objects.
|
||||
"""
|
||||
|
||||
queryset = machines.OuverturePortList.objects.all()
|
||||
serializer_class = serializers.OuverturePortListSerializer
|
||||
|
||||
|
||||
class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.OuverturePort` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.OuverturePort.objects.all()
|
||||
serializer_class = serializers.OuverturePortSerializer
|
||||
|
||||
|
||||
class RoleViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `machines.models.Machine` objects.
|
||||
"""
|
||||
|
||||
queryset = machines.Role.objects.all()
|
||||
serializer_class = serializers.RoleSerializer
|
||||
|
||||
|
||||
# PREFERENCES
|
||||
# Those views differ a bit because there is only one object
|
||||
# to display, so we don't bother with the listing part
|
||||
|
||||
|
||||
class OptionalUserView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.OptionalUser.can_view_all]}
|
||||
serializer_class = serializers.OptionalUserSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.OptionalUser.objects.first()
|
||||
|
||||
|
||||
class OptionalMachineView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.OptionalMachine` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.OptionalMachine.can_view_all]}
|
||||
serializer_class = serializers.OptionalMachineSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.OptionalMachine.objects.first()
|
||||
|
||||
|
||||
class OptionalTopologieView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.OptionalTopologie` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.OptionalTopologie.can_view_all]}
|
||||
serializer_class = serializers.OptionalTopologieSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.OptionalTopologie.objects.first()
|
||||
|
||||
|
||||
class RadiusOptionView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.OptionalTopologie` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.RadiusOption.can_view_all]}
|
||||
serializer_class = serializers.RadiusOptionSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.RadiusOption.objects.first()
|
||||
|
||||
|
||||
class GeneralOptionView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.GeneralOption` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.GeneralOption.can_view_all]}
|
||||
serializer_class = serializers.GeneralOptionSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.GeneralOption.objects.first()
|
||||
|
||||
|
||||
class HomeServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `preferences.models.Service` objects.
|
||||
"""
|
||||
|
||||
queryset = preferences.Service.objects.all()
|
||||
serializer_class = serializers.HomeServiceSerializer
|
||||
|
||||
|
||||
class AssoOptionView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.AssoOption` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.AssoOption.can_view_all]}
|
||||
serializer_class = serializers.AssoOptionSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.AssoOption.objects.first()
|
||||
|
||||
|
||||
class HomeOptionView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.HomeOption` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.HomeOption.can_view_all]}
|
||||
serializer_class = serializers.HomeOptionSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.HomeOption.objects.first()
|
||||
|
||||
|
||||
class MailMessageOptionView(generics.RetrieveAPIView):
|
||||
"""Exposes details of `preferences.models.MailMessageOption` settings.
|
||||
"""
|
||||
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [preferences.MailMessageOption.can_view_all]}
|
||||
serializer_class = serializers.MailMessageOptionSerializer
|
||||
|
||||
def get_object(self):
|
||||
return preferences.MailMessageOption.objects.first()
|
||||
|
||||
|
||||
# TOPOLOGIE
|
||||
|
||||
|
||||
class StackViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.Stack` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.Stack.objects.all()
|
||||
serializer_class = serializers.StackSerializer
|
||||
|
||||
|
||||
class AccessPointViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.AccessPoint` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.AccessPoint.objects.all()
|
||||
serializer_class = serializers.AccessPointSerializer
|
||||
|
||||
|
||||
class SwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.Switch` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.Switch.objects.all()
|
||||
serializer_class = serializers.SwitchSerializer
|
||||
|
||||
|
||||
class ServerViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.Server` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.Server.objects.all()
|
||||
serializer_class = serializers.ServerSerializer
|
||||
|
||||
|
||||
class ModelSwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.ModelSwitch` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.ModelSwitch.objects.all()
|
||||
serializer_class = serializers.ModelSwitchSerializer
|
||||
|
||||
|
||||
class ConstructorSwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.ConstructorSwitch`
|
||||
objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.ConstructorSwitch.objects.all()
|
||||
serializer_class = serializers.ConstructorSwitchSerializer
|
||||
|
||||
|
||||
class SwitchBayViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.SwitchBay` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.SwitchBay.objects.all()
|
||||
serializer_class = serializers.SwitchBaySerializer
|
||||
|
||||
|
||||
class BuildingViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.Building` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.Building.objects.all()
|
||||
serializer_class = serializers.BuildingSerializer
|
||||
|
||||
|
||||
class SwitchPortViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.Port` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.Port.objects.all()
|
||||
serializer_class = serializers.SwitchPortSerializer
|
||||
|
||||
|
||||
class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.PortProfile` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.PortProfile.objects.all()
|
||||
serializer_class = serializers.PortProfileSerializer
|
||||
|
||||
|
||||
class RoomViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.Room` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.Room.objects.all()
|
||||
serializer_class = serializers.RoomSerializer
|
||||
|
||||
|
||||
class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `topologie.models.PortProfile` objects.
|
||||
"""
|
||||
|
||||
queryset = topologie.PortProfile.objects.all()
|
||||
serializer_class = serializers.PortProfileSerializer
|
||||
|
||||
|
||||
# USER
|
||||
|
||||
|
||||
class UserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.Users` objects.
|
||||
"""
|
||||
|
||||
queryset = users.User.objects.all()
|
||||
serializer_class = serializers.UserSerializer
|
||||
|
||||
|
||||
class HomeCreationViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes infos of `users.models.Users` objects to create homes.
|
||||
"""
|
||||
|
||||
queryset = users.User.objects.exclude(
|
||||
Q(state=users.User.STATE_DISABLED)
|
||||
| Q(state=users.User.STATE_NOT_YET_ACTIVE)
|
||||
| Q(state=users.User.STATE_FULL_ARCHIVE)
|
||||
)
|
||||
serializer_class = serializers.BasicUserSerializer
|
||||
|
||||
|
||||
class NormalUserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes infos of `users.models.Users`without specific rights objects."""
|
||||
|
||||
queryset = users.User.objects.exclude(groups__listright__critical=True).distinct()
|
||||
serializer_class = serializers.BasicUserSerializer
|
||||
|
||||
|
||||
class CriticalUserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes infos of `users.models.Users`without specific rights objects."""
|
||||
|
||||
queryset = users.User.objects.filter(groups__listright__critical=True).distinct()
|
||||
serializer_class = serializers.BasicUserSerializer
|
||||
|
||||
|
||||
class ClubViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.Club` objects.
|
||||
"""
|
||||
|
||||
queryset = users.Club.objects.all()
|
||||
serializer_class = serializers.ClubSerializer
|
||||
|
||||
|
||||
class AdherentViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.Adherent` objects.
|
||||
"""
|
||||
|
||||
queryset = users.Adherent.objects.all()
|
||||
serializer_class = serializers.AdherentSerializer
|
||||
|
||||
|
||||
class ServiceUserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.ServiceUser` objects.
|
||||
"""
|
||||
|
||||
queryset = users.ServiceUser.objects.all()
|
||||
serializer_class = serializers.ServiceUserSerializer
|
||||
|
||||
|
||||
class SchoolViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.School` objects.
|
||||
"""
|
||||
|
||||
queryset = users.School.objects.all()
|
||||
serializer_class = serializers.SchoolSerializer
|
||||
|
||||
|
||||
class ListRightViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.ListRight` objects.
|
||||
"""
|
||||
|
||||
queryset = users.ListRight.objects.all()
|
||||
serializer_class = serializers.ListRightSerializer
|
||||
|
||||
|
||||
class ShellViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.ListShell` objects.
|
||||
"""
|
||||
|
||||
queryset = users.ListShell.objects.all()
|
||||
serializer_class = serializers.ShellSerializer
|
||||
|
||||
|
||||
class BanViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.Ban` objects.
|
||||
"""
|
||||
|
||||
queryset = users.Ban.objects.all()
|
||||
serializer_class = serializers.BanSerializer
|
||||
|
||||
|
||||
class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.Whitelist` objects.
|
||||
"""
|
||||
|
||||
queryset = users.Whitelist.objects.all()
|
||||
serializer_class = serializers.WhitelistSerializer
|
||||
|
||||
|
||||
class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.EMailAddress` objects.
|
||||
"""
|
||||
|
||||
serializer_class = serializers.EMailAddressSerializer
|
||||
queryset = users.EMailAddress.objects.none()
|
||||
|
||||
def get_queryset(self):
|
||||
if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"):
|
||||
return users.EMailAddress.objects.filter(user__local_email_enabled=True)
|
||||
else:
|
||||
return users.EMailAddress.objects.none()
|
||||
|
||||
|
||||
# SERVICE REGEN
|
||||
|
||||
|
||||
class ServiceRegenViewSet(viewsets.ModelViewSet):
|
||||
"""Exposes list and details of the services to regen
|
||||
"""
|
||||
|
||||
serializer_class = serializers.ServiceRegenSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = machines.Service_link.objects.select_related(
|
||||
"server__domain"
|
||||
).select_related("service")
|
||||
if "hostname" in self.request.GET:
|
||||
hostname = self.request.GET["hostname"]
|
||||
queryset = queryset.filter(server__domain__name__iexact=hostname)
|
||||
return queryset
|
||||
|
||||
|
||||
# Config des switches
|
||||
|
||||
|
||||
class SwitchPortView(generics.ListAPIView):
|
||||
"""Output each port of a switch, to be serialized with
|
||||
additionnal informations (profiles etc)
|
||||
"""
|
||||
|
||||
queryset = (
|
||||
topologie.Switch.objects.all()
|
||||
.select_related("switchbay")
|
||||
.select_related("model__constructor")
|
||||
.prefetch_related("ports__custom_profile__vlan_tagged")
|
||||
.prefetch_related("ports__custom_profile__vlan_untagged")
|
||||
.prefetch_related("ports__machine_interface__domain__extension")
|
||||
.prefetch_related("ports__room")
|
||||
)
|
||||
|
||||
serializer_class = serializers.SwitchPortSerializer
|
||||
|
||||
|
||||
# Rappel fin adhésion
|
||||
|
||||
|
||||
class ReminderView(generics.ListAPIView):
|
||||
"""Output for users to remind an end of their subscription.
|
||||
"""
|
||||
|
||||
queryset = preferences.Reminder.objects.all()
|
||||
serializer_class = serializers.ReminderSerializer
|
||||
|
||||
|
||||
class RoleView(generics.ListAPIView):
|
||||
"""Output of roles for each server
|
||||
"""
|
||||
|
||||
queryset = machines.Role.objects.all().prefetch_related("servers")
|
||||
serializer_class = serializers.RoleSerializer
|
||||
|
||||
|
||||
# LOCAL EMAILS
|
||||
|
||||
|
||||
class LocalEmailUsersView(generics.ListAPIView):
|
||||
"""Exposes all the aliases of the users that activated the internal address
|
||||
"""
|
||||
|
||||
serializer_class = serializers.LocalEmailUsersSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"):
|
||||
return users.User.objects.filter(local_email_enabled=True)
|
||||
else:
|
||||
return users.User.objects.none()
|
||||
|
||||
|
||||
# DHCP
|
||||
|
||||
|
||||
class HostMacIpView(generics.ListAPIView):
|
||||
"""Exposes the associations between hostname, mac address and IPv4 in
|
||||
order to build the DHCP lease files.
|
||||
"""
|
||||
|
||||
serializer_class = serializers.HostMacIpSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return all_active_interfaces()
|
||||
|
||||
|
||||
# Firewall
|
||||
|
||||
|
||||
class SubnetPortsOpenView(generics.ListAPIView):
|
||||
queryset = machines.IpType.objects.all()
|
||||
serializer_class = serializers.SubnetPortsOpenSerializer
|
||||
|
||||
|
||||
class InterfacePortsOpenView(generics.ListAPIView):
|
||||
queryset = machines.Interface.objects.filter(port_lists__isnull=False).distinct()
|
||||
serializer_class = serializers.InterfacePortsOpenSerializer
|
||||
|
||||
|
||||
# DNS
|
||||
|
||||
|
||||
class DNSZonesView(generics.ListAPIView):
|
||||
"""Exposes the detailed information about each extension (hostnames,
|
||||
IPs, DNS records, etc.) in order to build the DNS zone files.
|
||||
"""
|
||||
|
||||
queryset = (
|
||||
machines.Extension.objects.prefetch_related("soa")
|
||||
.prefetch_related("ns_set")
|
||||
.prefetch_related("ns_set__ns")
|
||||
.prefetch_related("origin")
|
||||
.prefetch_related("mx_set")
|
||||
.prefetch_related("mx_set__name")
|
||||
.prefetch_related("txt_set")
|
||||
.prefetch_related("srv_set")
|
||||
.prefetch_related("srv_set__target")
|
||||
.all()
|
||||
)
|
||||
serializer_class = serializers.DNSZonesSerializer
|
||||
|
||||
|
||||
class DNSReverseZonesView(generics.ListAPIView):
|
||||
"""Exposes the detailed information about each extension (hostnames,
|
||||
IPs, DNS records, etc.) in order to build the DNS zone files.
|
||||
"""
|
||||
|
||||
queryset = machines.IpType.objects.all()
|
||||
serializer_class = serializers.DNSReverseZonesSerializer
|
||||
|
||||
|
||||
# MAILING
|
||||
|
||||
|
||||
class StandardMailingView(views.APIView):
|
||||
"""Exposes list and details of standard mailings (name and members) in
|
||||
order to building the corresponding mailing lists.
|
||||
"""
|
||||
|
||||
pagination_class = PageSizedPagination
|
||||
permission_classes = (ACLPermission,)
|
||||
perms_map = {"GET": [users.User.can_view_all]}
|
||||
|
||||
def get(self, request, format=None):
|
||||
adherents_data = serializers.MailingMemberSerializer(
|
||||
all_has_access(), many=True
|
||||
).data
|
||||
data = [{"name": "adherents", "members": adherents_data}]
|
||||
paginator = self.pagination_class()
|
||||
paginator.paginate_queryset(data, request)
|
||||
return paginator.get_paginated_response(data)
|
||||
|
||||
|
||||
class ClubMailingView(generics.ListAPIView):
|
||||
"""Exposes list and details of club mailings (name, members and admins) in
|
||||
order to build the corresponding mailing lists.
|
||||
"""
|
||||
|
||||
queryset = users.Club.objects.all()
|
||||
serializer_class = serializers.MailingSerializer
|
||||
|
||||
|
||||
# TOKEN AUTHENTICATION
|
||||
|
||||
|
||||
class ObtainExpiringAuthToken(ObtainAuthToken):
|
||||
"""Exposes a view to obtain a authentication token.
|
||||
|
|
|
@ -6,7 +6,8 @@ python3-djangorestframework
|
|||
python3-django-reversion
|
||||
python3-pip
|
||||
python3-pil
|
||||
libsasl2-dev libldap2-dev
|
||||
libsasl2-dev
|
||||
libldap2-dev
|
||||
libssl-dev
|
||||
python3-crypto
|
||||
python3-git
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
python-django
|
||||
python-dateutil
|
||||
python3-django
|
||||
python3-dateutil
|
||||
texlive-latex-base
|
||||
texlive-fonts-recommended
|
||||
python-djangorestframework
|
||||
python-django-reversion
|
||||
python-pip
|
||||
libsasl2-dev libldap2-dev
|
||||
python3-djangorestframework
|
||||
python3-django-reversion
|
||||
python3-pip
|
||||
python3-pil
|
||||
libsasl2-dev
|
||||
libldap2-dev
|
||||
libssl-dev
|
||||
python-crypto
|
||||
python-git
|
||||
python3-crypto
|
||||
python3-git
|
||||
javascript-common
|
||||
libjs-jquery
|
||||
libjs-jquery-ui
|
||||
|
@ -18,6 +20,11 @@ fonts-font-awesome
|
|||
graphviz
|
||||
git
|
||||
gettext
|
||||
libfreeradius3=3.0.21+dfsg-1~bpo10+1
|
||||
freeradius-utils=3.0.21+dfsg-1~bpo10+1
|
||||
freeradius=3.0.21+dfsg-1~bpo10+1
|
||||
freeradius-common
|
||||
freeradius-python2
|
||||
python-mysqldb
|
||||
freeradius-python3
|
||||
python3-dev
|
||||
python3-mysqldb
|
||||
python3-django-ldapdb
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -28,7 +28,7 @@ Here are defined some functions to check acl on the application.
|
|||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
||||
def can_view(user):
|
||||
def can_view(user, *args, **kwargs):
|
||||
"""Check if an user can view the application.
|
||||
|
||||
Args:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -34,7 +34,7 @@ from .models import CustomInvoice, CostEstimate
|
|||
|
||||
|
||||
class FactureAdmin(VersionAdmin):
|
||||
"""Class admin d'une facture, tous les champs"""
|
||||
"""Admin class for invoices."""
|
||||
|
||||
pass
|
||||
|
||||
|
@ -52,32 +52,31 @@ class CustomInvoiceAdmin(VersionAdmin):
|
|||
|
||||
|
||||
class VenteAdmin(VersionAdmin):
|
||||
"""Class admin d'une vente, tous les champs (facture related)"""
|
||||
"""Admin class for purchases."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ArticleAdmin(VersionAdmin):
|
||||
"""Class admin d'un article en vente"""
|
||||
"""Admin class for articles."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class BanqueAdmin(VersionAdmin):
|
||||
"""Class admin de la liste des banques (facture related)"""
|
||||
"""Admin class for banks."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PaiementAdmin(VersionAdmin):
|
||||
"""Class admin d'un moyen de paiement (facture related"""
|
||||
"""Admin class for payment methods."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class CotisationAdmin(VersionAdmin):
|
||||
"""Class admin d'une cotisation (date de debut et de fin),
|
||||
Vente related"""
|
||||
"""Admin class for subscriptions."""
|
||||
|
||||
pass
|
||||
|
||||
|
|
0
cotisations/api/__init__.py
Normal file
0
cotisations/api/__init__.py
Normal file
129
cotisations/api/serializers.py
Normal file
129
cotisations/api/serializers.py
Normal file
|
@ -0,0 +1,129 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
import cotisations.models as cotisations
|
||||
import preferences.models as preferences
|
||||
from api.serializers import NamespacedHRField, NamespacedHIField, NamespacedHMSerializer
|
||||
from users.api.serializers import UserSerializer
|
||||
|
||||
|
||||
class FactureSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `cotisations.models.Facture` objects.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = cotisations.Facture
|
||||
fields = (
|
||||
"user",
|
||||
"paiement",
|
||||
"banque",
|
||||
"cheque",
|
||||
"date",
|
||||
"valid",
|
||||
"control",
|
||||
"prix_total",
|
||||
"name",
|
||||
"api_url",
|
||||
)
|
||||
|
||||
|
||||
class BaseInvoiceSerializer(NamespacedHMSerializer):
|
||||
class Meta:
|
||||
model = cotisations.BaseInvoice
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class VenteSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `cotisations.models.Vente` objects.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = cotisations.Vente
|
||||
fields = (
|
||||
"facture",
|
||||
"number",
|
||||
"name",
|
||||
"prix",
|
||||
"duration_connection",
|
||||
"duration_days_connection",
|
||||
"duration_membership",
|
||||
"duration_days_membership",
|
||||
"prix_total",
|
||||
"api_url",
|
||||
)
|
||||
|
||||
|
||||
class ArticleSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `cotisations.models.Article` objects.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = cotisations.Article
|
||||
fields = ("name", "prix", "duration_membership", "duration_days_membership", "duration_connection", "duration_days_connection", "type_user", "api_url")
|
||||
|
||||
|
||||
class BanqueSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `cotisations.models.Banque` objects.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = cotisations.Banque
|
||||
fields = ("name", "api_url")
|
||||
|
||||
|
||||
class PaiementSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `cotisations.models.Paiement` objects.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = cotisations.Paiement
|
||||
fields = ("moyen", "api_url")
|
||||
|
||||
|
||||
class CotisationSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `cotisations.models.Cotisation` objects.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = cotisations.Cotisation
|
||||
fields = ("vente", "type_cotisation", "date_start_con", "date_end_con", "date_start_memb", "date_end_memb", "api_url")
|
||||
|
||||
|
||||
class ReminderUsersSerializer(UserSerializer):
|
||||
"""Serialize the data about a mailing member.
|
||||
"""
|
||||
|
||||
class Meta(UserSerializer.Meta):
|
||||
fields = ("get_full_name", "get_mail")
|
||||
|
||||
|
||||
class ReminderSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Serialize the data about a reminder
|
||||
"""
|
||||
|
||||
users_to_remind = ReminderUsersSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = preferences.Reminder
|
||||
fields = ("days", "message", "users_to_remind")
|
38
cotisations/api/urls.py
Normal file
38
cotisations/api/urls.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from . import views
|
||||
|
||||
urls_viewset = [
|
||||
(r"cotisations/facture", views.FactureViewSet, None),
|
||||
(r"cotisations/vente", views.VenteViewSet, None),
|
||||
(r"cotisations/article", views.ArticleViewSet, None),
|
||||
(r"cotisations/banque", views.BanqueViewSet, None),
|
||||
(r"cotisations/paiement", views.PaiementViewSet, None),
|
||||
(r"cotisations/cotisation", views.CotisationViewSet, None)
|
||||
]
|
||||
|
||||
urls_view = [
|
||||
(r"cotisations/reminder-get-users", views.ReminderView),
|
||||
|
||||
# Deprecated
|
||||
(r"reminder/get-users", views.ReminderView),
|
||||
]
|
89
cotisations/api/views.py
Normal file
89
cotisations/api/views.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from rest_framework import viewsets, generics
|
||||
|
||||
from . import serializers
|
||||
import cotisations.models as cotisations
|
||||
import preferences.models as preferences
|
||||
|
||||
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Facture` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Facture.objects.all()
|
||||
serializer_class = serializers.FactureSerializer
|
||||
|
||||
|
||||
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Facture` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.BaseInvoice.objects.all()
|
||||
serializer_class = serializers.BaseInvoiceSerializer
|
||||
|
||||
|
||||
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Vente` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Vente.objects.all()
|
||||
serializer_class = serializers.VenteSerializer
|
||||
|
||||
|
||||
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Article` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Article.objects.all()
|
||||
serializer_class = serializers.ArticleSerializer
|
||||
|
||||
|
||||
class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Banque` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Banque.objects.all()
|
||||
serializer_class = serializers.BanqueSerializer
|
||||
|
||||
|
||||
class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Paiement` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Paiement.objects.all()
|
||||
serializer_class = serializers.PaiementSerializer
|
||||
|
||||
|
||||
class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `cotisations.models.Cotisation` objects.
|
||||
"""
|
||||
|
||||
queryset = cotisations.Cotisation.objects.all()
|
||||
serializer_class = serializers.CotisationSerializer
|
||||
|
||||
|
||||
class ReminderView(generics.ListAPIView):
|
||||
"""Output for users to remind an end of their subscription.
|
||||
"""
|
||||
|
||||
queryset = preferences.Reminder.objects.all()
|
||||
serializer_class = serializers.ReminderSerializer
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -46,6 +46,7 @@ from django.shortcuts import get_object_or_404
|
|||
|
||||
from re2o.field_permissions import FieldPermissionFormMixin
|
||||
from re2o.mixins import FormRevMixin
|
||||
from re2o.widgets import AutocompleteModelWidget
|
||||
from .models import (
|
||||
Article,
|
||||
Paiement,
|
||||
|
@ -79,6 +80,10 @@ class FactureForm(FieldPermissionFormMixin, FormRevMixin, ModelForm):
|
|||
class Meta:
|
||||
model = Facture
|
||||
fields = "__all__"
|
||||
widgets = {
|
||||
"user": AutocompleteModelWidget(url="/users/user-autocomplete"),
|
||||
"banque": AutocompleteModelWidget(url="/cotisations/banque-autocomplete"),
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(FactureForm, self).clean()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -21,9 +21,9 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 2.5\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-11-20 01:24+0100\n"
|
||||
"POT-Creation-Date: 2021-01-24 11:51+0100\n"
|
||||
"PO-Revision-Date: 2018-03-31 16:09+0002\n"
|
||||
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
|
||||
"Last-Translator: Yoann Piétri <me@nanoy.fr>\n"
|
||||
"Language: fr_FR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
@ -33,83 +33,83 @@ msgstr ""
|
|||
msgid "You don't have the right to view this application."
|
||||
msgstr "Vous n'avez pas le droit de voir cette application."
|
||||
|
||||
#: cotisations/forms.py:70 cotisations/forms.py:296
|
||||
#: cotisations/forms.py:71 cotisations/forms.py:301
|
||||
msgid "Select a payment method"
|
||||
msgstr "Sélectionnez un moyen de paiement"
|
||||
|
||||
#: cotisations/forms.py:73 cotisations/models.py:676
|
||||
#: cotisations/forms.py:74 cotisations/models.py:706
|
||||
msgid "Member"
|
||||
msgstr "Adhérent"
|
||||
|
||||
#: cotisations/forms.py:74
|
||||
#: cotisations/forms.py:75
|
||||
msgid "Select the proprietary member"
|
||||
msgstr "Sélectionnez l'adhérent propriétaire"
|
||||
|
||||
#: cotisations/forms.py:75
|
||||
#: cotisations/forms.py:76
|
||||
msgid "Validated invoice"
|
||||
msgstr "Facture validée"
|
||||
|
||||
#: cotisations/forms.py:87
|
||||
#: cotisations/forms.py:92
|
||||
msgid "A payment method must be specified."
|
||||
msgstr "Un moyen de paiement doit être renseigné."
|
||||
|
||||
#: cotisations/forms.py:98
|
||||
#: cotisations/forms.py:103
|
||||
#: cotisations/templates/cotisations/aff_article.html:33
|
||||
#: cotisations/templates/cotisations/facture.html:64
|
||||
msgid "Article"
|
||||
msgstr "Article"
|
||||
|
||||
#: cotisations/forms.py:101
|
||||
#: cotisations/forms.py:106
|
||||
#: cotisations/templates/cotisations/edit_facture.html:50
|
||||
msgid "Quantity"
|
||||
msgstr "Quantité"
|
||||
|
||||
#: cotisations/forms.py:119
|
||||
#: cotisations/forms.py:124
|
||||
msgid "Discount is in percentage."
|
||||
msgstr "La réduction est en pourcentage."
|
||||
|
||||
#: cotisations/forms.py:122 cotisations/templates/cotisations/facture.html:75
|
||||
#: cotisations/forms.py:127 cotisations/templates/cotisations/facture.html:75
|
||||
msgid "Discount"
|
||||
msgstr "Réduction"
|
||||
|
||||
#: cotisations/forms.py:139
|
||||
#: cotisations/forms.py:144
|
||||
#, python-format
|
||||
msgid "{}% discount"
|
||||
msgstr "{}% de réduction"
|
||||
|
||||
#: cotisations/forms.py:139
|
||||
#: cotisations/forms.py:144
|
||||
msgid "{} € discount"
|
||||
msgstr "{} € de réduction"
|
||||
|
||||
#: cotisations/forms.py:176
|
||||
#: cotisations/forms.py:181
|
||||
msgid "Article name"
|
||||
msgstr "Nom de l'article"
|
||||
|
||||
#: cotisations/forms.py:187
|
||||
#: cotisations/forms.py:192
|
||||
msgid "Current articles"
|
||||
msgstr "Articles actuels"
|
||||
|
||||
#: cotisations/forms.py:216
|
||||
#: cotisations/forms.py:221
|
||||
msgid "Payment method name"
|
||||
msgstr "Nom du moyen de paiement"
|
||||
|
||||
#: cotisations/forms.py:229
|
||||
#: cotisations/forms.py:234
|
||||
msgid "Current payment methods"
|
||||
msgstr "Moyens de paiement actuels"
|
||||
|
||||
#: cotisations/forms.py:256
|
||||
#: cotisations/forms.py:261
|
||||
msgid "Bank name"
|
||||
msgstr "Nom de la banque"
|
||||
|
||||
#: cotisations/forms.py:269
|
||||
#: cotisations/forms.py:274
|
||||
msgid "Current banks"
|
||||
msgstr "Banques actuelles"
|
||||
|
||||
#: cotisations/forms.py:288
|
||||
#: cotisations/forms.py:293
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
#: cotisations/forms.py:290
|
||||
#: cotisations/forms.py:295
|
||||
#: cotisations/templates/cotisations/aff_cost_estimate.html:42
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:44
|
||||
#: cotisations/templates/cotisations/aff_custom_invoice.html:42
|
||||
|
@ -117,7 +117,7 @@ msgstr "Montant"
|
|||
msgid "Payment method"
|
||||
msgstr "Moyen de paiement"
|
||||
|
||||
#: cotisations/forms.py:314
|
||||
#: cotisations/forms.py:319
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Requested amount is too high. Your balance can't exceed "
|
||||
|
@ -126,52 +126,56 @@ msgstr ""
|
|||
"Le montant demandé est trop grand. Votre solde ne peut excéder "
|
||||
"%(max_online_balance)s €."
|
||||
|
||||
#: cotisations/models.py:59
|
||||
#: cotisations/models.py:61
|
||||
msgid "date"
|
||||
msgstr "date"
|
||||
|
||||
#: cotisations/models.py:130
|
||||
#: cotisations/models.py:66
|
||||
msgid "Can view an base invoice object"
|
||||
msgstr "Peut voir un objet BaseInvoice"
|
||||
|
||||
#: cotisations/models.py:148
|
||||
msgid "cheque number"
|
||||
msgstr "numéro de chèque"
|
||||
|
||||
#: cotisations/models.py:133
|
||||
#: cotisations/models.py:151
|
||||
msgid "validated"
|
||||
msgstr "validé"
|
||||
|
||||
#: cotisations/models.py:135
|
||||
#: cotisations/models.py:153
|
||||
msgid "controlled"
|
||||
msgstr "contrôlé"
|
||||
|
||||
#: cotisations/models.py:141
|
||||
#: cotisations/models.py:159
|
||||
msgid "Can edit the \"controlled\" state"
|
||||
msgstr "Peut modifier l'état \"contrôlé\""
|
||||
|
||||
#: cotisations/models.py:142
|
||||
#: cotisations/models.py:160
|
||||
msgid "Can view an invoice object"
|
||||
msgstr "Peut voir un objet facture"
|
||||
|
||||
#: cotisations/models.py:143
|
||||
#: cotisations/models.py:161
|
||||
msgid "Can edit all the previous invoices"
|
||||
msgstr "Peut modifier toutes les factures précédentes"
|
||||
|
||||
#: cotisations/models.py:145 cotisations/models.py:431 cotisations/views.py:378
|
||||
#: cotisations/views.py:573
|
||||
#: cotisations/models.py:163 cotisations/models.py:458 cotisations/views.py:380
|
||||
#: cotisations/views.py:575
|
||||
msgid "invoice"
|
||||
msgstr "facture"
|
||||
|
||||
#: cotisations/models.py:146
|
||||
#: cotisations/models.py:164
|
||||
msgid "invoices"
|
||||
msgstr "factures"
|
||||
|
||||
#: cotisations/models.py:160
|
||||
#: cotisations/models.py:178
|
||||
msgid "You don't have the right to edit an invoice."
|
||||
msgstr "Vous n'avez pas le droit de modifier une facture."
|
||||
|
||||
#: cotisations/models.py:168
|
||||
#: cotisations/models.py:186
|
||||
msgid "You don't have the right to edit this user's invoices."
|
||||
msgstr "Vous n'avez pas le droit de modifier les factures de cet utilisateur."
|
||||
|
||||
#: cotisations/models.py:177
|
||||
#: cotisations/models.py:195
|
||||
msgid ""
|
||||
"You don't have the right to edit an invoice already controlled or "
|
||||
"invalidated."
|
||||
|
@ -179,15 +183,15 @@ msgstr ""
|
|||
"Vous n'avez pas le droit de modifier une facture précédemment contrôlée ou "
|
||||
"invalidée."
|
||||
|
||||
#: cotisations/models.py:192
|
||||
#: cotisations/models.py:210
|
||||
msgid "You don't have the right to delete an invoice."
|
||||
msgstr "Vous n'avez pas le droit de supprimer une facture."
|
||||
|
||||
#: cotisations/models.py:200
|
||||
#: cotisations/models.py:218
|
||||
msgid "You don't have the right to delete this user's invoices."
|
||||
msgstr "Vous n'avez pas le droit de supprimer les factures de cet utilisateur."
|
||||
|
||||
#: cotisations/models.py:209
|
||||
#: cotisations/models.py:227
|
||||
msgid ""
|
||||
"You don't have the right to delete an invoice already controlled or "
|
||||
"invalidated."
|
||||
|
@ -195,137 +199,123 @@ msgstr ""
|
|||
"Vous n'avez pas le droit de supprimer une facture précédemment contrôlée ou "
|
||||
"invalidée."
|
||||
|
||||
#: cotisations/models.py:223
|
||||
#: cotisations/models.py:241
|
||||
msgid "You don't have the right to view someone else's invoices history."
|
||||
msgstr ""
|
||||
"Vous n'avez pas le droit de voir l'historique des factures d'un autre "
|
||||
"utilisateur."
|
||||
|
||||
#: cotisations/models.py:231
|
||||
#: cotisations/models.py:249
|
||||
msgid "The invoice has been invalidated."
|
||||
msgstr "La facture a été invalidée."
|
||||
|
||||
#: cotisations/models.py:246
|
||||
#: cotisations/models.py:264
|
||||
msgid "You don't have the right to edit the \"controlled\" state."
|
||||
msgstr "Vous n'avez pas le droit de modifier le statut \"contrôlé\"."
|
||||
|
||||
#: cotisations/models.py:265
|
||||
#: cotisations/models.py:283
|
||||
msgid "There are no payment methods that you can use."
|
||||
msgstr "Il n'y a pas de moyens de paiement que vous puissiez utiliser."
|
||||
|
||||
#: cotisations/models.py:271
|
||||
#: cotisations/models.py:289
|
||||
msgid "There are no articles that you can buy."
|
||||
msgstr "Il n'y a pas d'articles que vous puissiez acheter."
|
||||
|
||||
#: cotisations/models.py:347
|
||||
#: cotisations/models.py:381
|
||||
msgid "Can view a custom invoice object"
|
||||
msgstr "Peut voir un objet facture personnalisée"
|
||||
|
||||
#: cotisations/models.py:349
|
||||
#: cotisations/models.py:383
|
||||
msgid "recipient"
|
||||
msgstr "destinataire"
|
||||
|
||||
#: cotisations/models.py:350
|
||||
#: cotisations/models.py:384
|
||||
msgid "payment type"
|
||||
msgstr "type de paiement"
|
||||
|
||||
#: cotisations/models.py:351
|
||||
#: cotisations/models.py:385
|
||||
msgid "address"
|
||||
msgstr "adresse"
|
||||
|
||||
#: cotisations/models.py:352
|
||||
#: cotisations/models.py:386
|
||||
msgid "paid"
|
||||
msgstr "payé"
|
||||
|
||||
#: cotisations/models.py:353
|
||||
#: cotisations/models.py:387
|
||||
msgid "remark"
|
||||
msgstr "remarque"
|
||||
|
||||
#: cotisations/models.py:358
|
||||
#: cotisations/models.py:392
|
||||
msgid "Can view a cost estimate object"
|
||||
msgstr "Peut voir un objet devis"
|
||||
|
||||
#: cotisations/models.py:361
|
||||
#: cotisations/models.py:395
|
||||
msgid "period of validity"
|
||||
msgstr "période de validité"
|
||||
|
||||
#: cotisations/models.py:396
|
||||
#: cotisations/models.py:430
|
||||
msgid "You don't have the right to delete a cost estimate."
|
||||
msgstr "Vous n'avez pas le droit de supprimer un devis."
|
||||
|
||||
#: cotisations/models.py:402
|
||||
#: cotisations/models.py:436
|
||||
msgid "The cost estimate has an invoice and can't be deleted."
|
||||
msgstr "Le devis a une facture et ne peut pas être supprimé."
|
||||
|
||||
#: cotisations/models.py:424 cotisations/models.py:682
|
||||
#: cotisations/models.py:940
|
||||
msgid "Connection"
|
||||
msgstr "Connexion"
|
||||
|
||||
#: cotisations/models.py:425 cotisations/models.py:683
|
||||
#: cotisations/models.py:941
|
||||
msgid "Membership"
|
||||
msgstr "Adhésion"
|
||||
|
||||
#: cotisations/models.py:426 cotisations/models.py:678
|
||||
#: cotisations/models.py:684 cotisations/models.py:942
|
||||
msgid "Both of them"
|
||||
msgstr "Les deux"
|
||||
|
||||
#: cotisations/models.py:435
|
||||
#: cotisations/models.py:462
|
||||
msgid "amount"
|
||||
msgstr "montant"
|
||||
|
||||
#: cotisations/models.py:438
|
||||
#: cotisations/models.py:467
|
||||
msgid "article"
|
||||
msgstr "article"
|
||||
|
||||
#: cotisations/models.py:441
|
||||
#: cotisations/models.py:470
|
||||
msgid "price"
|
||||
msgstr "prix"
|
||||
|
||||
#: cotisations/models.py:444 cotisations/models.py:696
|
||||
msgid "duration (in months)"
|
||||
msgstr "durée (en mois)"
|
||||
#: cotisations/models.py:473 cotisations/models.py:726
|
||||
msgid "duration of the connection (in months)"
|
||||
msgstr "durée de la connexion (en mois)"
|
||||
|
||||
#: cotisations/models.py:450 cotisations/models.py:702
|
||||
msgid "duration (in days, will be added to duration in months)"
|
||||
msgstr "durée (en jours, sera ajoutée à la durée en mois)"
|
||||
#: cotisations/models.py:478 cotisations/models.py:730
|
||||
msgid ""
|
||||
"duration of the connection (in days, will be added to duration in months)"
|
||||
msgstr "durée de la connexion (en jours, sera ajoutée à la durée en mois)"
|
||||
|
||||
#: cotisations/models.py:458 cotisations/models.py:716
|
||||
#: cotisations/models.py:953
|
||||
msgid "subscription type"
|
||||
msgstr "type de cotisation"
|
||||
#: cotisations/models.py:482 cotisations/models.py:718
|
||||
msgid "duration of the membership (in months)"
|
||||
msgstr "durée de l'adhésion (en mois)"
|
||||
|
||||
#: cotisations/models.py:463
|
||||
#: cotisations/models.py:487 cotisations/models.py:722
|
||||
msgid ""
|
||||
"duration of the membership (in days, will be added to duration in months)"
|
||||
msgstr "durée de l'adhésion (en jours, sera ajoutée à la durée en mois)"
|
||||
|
||||
#: cotisations/models.py:493
|
||||
msgid "Can view a purchase object"
|
||||
msgstr "Peut voir un objet achat"
|
||||
|
||||
#: cotisations/models.py:464
|
||||
#: cotisations/models.py:494
|
||||
msgid "Can edit all the previous purchases"
|
||||
msgstr "Peut modifier tous les achats précédents"
|
||||
|
||||
#: cotisations/models.py:466 cotisations/models.py:947
|
||||
#: cotisations/models.py:496 cotisations/models.py:970
|
||||
msgid "purchase"
|
||||
msgstr "achat"
|
||||
|
||||
#: cotisations/models.py:467
|
||||
#: cotisations/models.py:497
|
||||
msgid "purchases"
|
||||
msgstr "achats"
|
||||
|
||||
#: cotisations/models.py:539 cotisations/models.py:736
|
||||
msgid "Duration must be specified for a subscription."
|
||||
msgstr "La durée doit être renseignée pour une cotisation."
|
||||
|
||||
#: cotisations/models.py:550
|
||||
#: cotisations/models.py:572
|
||||
msgid "You don't have the right to edit a purchase."
|
||||
msgstr "Vous n'avez pas le droit de modifier un achat."
|
||||
|
||||
#: cotisations/models.py:556
|
||||
#: cotisations/models.py:578
|
||||
msgid "You don't have the right to edit this user's purchases."
|
||||
msgstr "Vous n'avez pas le droit de modifier les achats de cet utilisateur."
|
||||
|
||||
#: cotisations/models.py:565
|
||||
#: cotisations/models.py:587
|
||||
msgid ""
|
||||
"You don't have the right to edit a purchase already controlled or "
|
||||
"invalidated."
|
||||
|
@ -333,15 +323,15 @@ msgstr ""
|
|||
"Vous n'avez pas le droit de modifier un achat précédemment contrôlé ou "
|
||||
"invalidé."
|
||||
|
||||
#: cotisations/models.py:580
|
||||
#: cotisations/models.py:602
|
||||
msgid "You don't have the right to delete a purchase."
|
||||
msgstr "Vous n'avez pas le droit de supprimer un achat."
|
||||
|
||||
#: cotisations/models.py:586
|
||||
#: cotisations/models.py:608
|
||||
msgid "You don't have the right to delete this user's purchases."
|
||||
msgstr "Vous n'avez pas le droit de supprimer les achats de cet utilisateur."
|
||||
|
||||
#: cotisations/models.py:593
|
||||
#: cotisations/models.py:615
|
||||
msgid ""
|
||||
"You don't have the right to delete a purchase already controlled or "
|
||||
"invalidated."
|
||||
|
@ -349,134 +339,150 @@ msgstr ""
|
|||
"Vous n'avez pas le droit de supprimer un achat précédemment contrôlé ou "
|
||||
"invalidé."
|
||||
|
||||
#: cotisations/models.py:609
|
||||
#: cotisations/models.py:631
|
||||
msgid "You don't have the right to view someone else's purchase history."
|
||||
msgstr ""
|
||||
"Vous n'avez pas le droit de voir l'historique des achats d'un autre "
|
||||
"utilisateur."
|
||||
|
||||
#: cotisations/models.py:677
|
||||
#: cotisations/models.py:707
|
||||
msgid "Club"
|
||||
msgstr "Club"
|
||||
|
||||
#: cotisations/models.py:687
|
||||
#: cotisations/models.py:708
|
||||
msgid "Both of them"
|
||||
msgstr "Les deux"
|
||||
|
||||
#: cotisations/models.py:711
|
||||
msgid "designation"
|
||||
msgstr "désignation"
|
||||
|
||||
#: cotisations/models.py:690
|
||||
#: cotisations/models.py:714
|
||||
msgid "unit price"
|
||||
msgstr "prix unitaire"
|
||||
|
||||
#: cotisations/models.py:708
|
||||
#: cotisations/models.py:736
|
||||
msgid "need membership to be purchased"
|
||||
msgstr "nécessite une adhésion pour être acheté"
|
||||
|
||||
#: cotisations/models.py:743
|
||||
msgid "type of users concerned"
|
||||
msgstr "type d'utilisateurs concernés"
|
||||
|
||||
#: cotisations/models.py:719 cotisations/models.py:820
|
||||
#: cotisations/models.py:746 cotisations/models.py:847
|
||||
msgid "is available for every user"
|
||||
msgstr "est disponible pour chaque utilisateur"
|
||||
|
||||
#: cotisations/models.py:726
|
||||
#: cotisations/models.py:753
|
||||
msgid "Can view an article object"
|
||||
msgstr "Peut voir un objet article"
|
||||
|
||||
#: cotisations/models.py:727
|
||||
#: cotisations/models.py:754
|
||||
msgid "Can buy every article"
|
||||
msgstr "Peut acheter chaque article"
|
||||
|
||||
#: cotisations/models.py:734
|
||||
#: cotisations/models.py:761
|
||||
msgid "Solde is a reserved article name."
|
||||
msgstr "Solde est un nom d'article réservé."
|
||||
|
||||
#: cotisations/models.py:759
|
||||
#: cotisations/models.py:784
|
||||
msgid "You can't buy this article."
|
||||
msgstr "Vous ne pouvez pas acheter cet article."
|
||||
|
||||
#: cotisations/models.py:800
|
||||
#: cotisations/models.py:827
|
||||
msgid "Can view a bank object"
|
||||
msgstr "Peut voir un objet banque"
|
||||
|
||||
#: cotisations/models.py:801
|
||||
#: cotisations/models.py:828
|
||||
msgid "bank"
|
||||
msgstr "banque"
|
||||
|
||||
#: cotisations/models.py:802
|
||||
#: cotisations/models.py:829
|
||||
msgid "banks"
|
||||
msgstr "banques"
|
||||
|
||||
#: cotisations/models.py:818
|
||||
#: cotisations/models.py:845
|
||||
msgid "method"
|
||||
msgstr "moyen"
|
||||
|
||||
#: cotisations/models.py:825
|
||||
#: cotisations/models.py:852
|
||||
msgid "is user balance"
|
||||
msgstr "est solde utilisateur"
|
||||
|
||||
#: cotisations/models.py:826
|
||||
#: cotisations/models.py:853
|
||||
msgid "There should be only one balance payment method."
|
||||
msgstr "Il ne devrait y avoir qu'un moyen de paiement solde."
|
||||
|
||||
#: cotisations/models.py:832
|
||||
#: cotisations/models.py:859
|
||||
msgid "Can view a payment method object"
|
||||
msgstr "Peut voir un objet moyen de paiement"
|
||||
|
||||
#: cotisations/models.py:833
|
||||
#: cotisations/models.py:860
|
||||
msgid "Can use every payment method"
|
||||
msgstr "Peut utiliser chaque moyen de paiement"
|
||||
|
||||
#: cotisations/models.py:835
|
||||
#: cotisations/models.py:862
|
||||
msgid "payment method"
|
||||
msgstr "moyen de paiement"
|
||||
|
||||
#: cotisations/models.py:836
|
||||
#: cotisations/models.py:863
|
||||
msgid "payment methods"
|
||||
msgstr "moyens de paiement"
|
||||
|
||||
#: cotisations/models.py:875 cotisations/payment_methods/comnpay/views.py:62
|
||||
#: cotisations/models.py:904 cotisations/payment_methods/comnpay/views.py:62
|
||||
#, python-format
|
||||
msgid "The subscription of %(member_name)s was extended to %(end_date)s."
|
||||
msgstr "La cotisation de %(member_name)s a été étendue au %(end_date)s."
|
||||
|
||||
#: cotisations/models.py:885
|
||||
#: cotisations/models.py:914
|
||||
msgid "The invoice was created."
|
||||
msgstr "La facture a été créée."
|
||||
|
||||
#: cotisations/models.py:905
|
||||
#: cotisations/models.py:934
|
||||
msgid "You can't use this payment method."
|
||||
msgstr "Vous ne pouvez pas utiliser ce moyen de paiement."
|
||||
|
||||
#: cotisations/models.py:924
|
||||
#: cotisations/models.py:953
|
||||
msgid "No custom payment methods."
|
||||
msgstr "Pas de moyens de paiement personnalisés."
|
||||
|
||||
#: cotisations/models.py:955
|
||||
msgid "start date"
|
||||
msgstr "date de début"
|
||||
#: cotisations/models.py:973
|
||||
msgid "start date for the connection"
|
||||
msgstr "date de début pour la connexion"
|
||||
|
||||
#: cotisations/models.py:956
|
||||
msgid "end date"
|
||||
msgstr "date de fin"
|
||||
#: cotisations/models.py:975
|
||||
msgid "end date for the connection"
|
||||
msgstr "date de fin pour la connexion"
|
||||
|
||||
#: cotisations/models.py:960
|
||||
#: cotisations/models.py:977
|
||||
msgid "start date for the membership"
|
||||
msgstr "date de début pour l'adhésion"
|
||||
|
||||
#: cotisations/models.py:979
|
||||
msgid "end date for the membership"
|
||||
msgstr "date de fin pour l'adhésion"
|
||||
|
||||
#: cotisations/models.py:983
|
||||
msgid "Can view a subscription object"
|
||||
msgstr "Peut voir un objet cotisation"
|
||||
|
||||
#: cotisations/models.py:961
|
||||
#: cotisations/models.py:984
|
||||
msgid "Can edit the previous subscriptions"
|
||||
msgstr "Peut modifier les cotisations précédentes"
|
||||
|
||||
#: cotisations/models.py:963
|
||||
#: cotisations/models.py:986
|
||||
msgid "subscription"
|
||||
msgstr "cotisation"
|
||||
|
||||
#: cotisations/models.py:964
|
||||
#: cotisations/models.py:987
|
||||
msgid "subscriptions"
|
||||
msgstr "cotisations"
|
||||
|
||||
#: cotisations/models.py:970
|
||||
#: cotisations/models.py:993
|
||||
msgid "You don't have the right to edit a subscription."
|
||||
msgstr "Vous n'avez pas le droit de modifier une cotisation."
|
||||
|
||||
#: cotisations/models.py:979
|
||||
#: cotisations/models.py:1002
|
||||
msgid ""
|
||||
"You don't have the right to edit a subscription already controlled or "
|
||||
"invalidated."
|
||||
|
@ -484,11 +490,11 @@ msgstr ""
|
|||
"Vous n'avez pas le droit de modifier une cotisation précédemment contrôlée "
|
||||
"ou invalidée."
|
||||
|
||||
#: cotisations/models.py:991
|
||||
#: cotisations/models.py:1014
|
||||
msgid "You don't have the right to delete a subscription."
|
||||
msgstr "Vous n'avez pas le droit de supprimer une cotisation."
|
||||
|
||||
#: cotisations/models.py:998
|
||||
#: cotisations/models.py:1021
|
||||
msgid ""
|
||||
"You don't have the right to delete a subscription already controlled or "
|
||||
"invalidated."
|
||||
|
@ -496,7 +502,7 @@ msgstr ""
|
|||
"Vous n'avez pas le droit de supprimer une cotisation précédemment contrôlée "
|
||||
"ou invalidée."
|
||||
|
||||
#: cotisations/models.py:1014
|
||||
#: cotisations/models.py:1037
|
||||
msgid "You don't have the right to view someone else's subscription history."
|
||||
msgstr ""
|
||||
"Vous n'avez pas le droit de voir l'historique des cotisations d'un autre "
|
||||
|
@ -646,22 +652,26 @@ msgid "Price"
|
|||
msgstr "Prix"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_article.html:35
|
||||
msgid "Subscription type"
|
||||
msgstr "Type de cotisation"
|
||||
msgid "Duration membership (in months)"
|
||||
msgstr "Durée adhésion (en mois)"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_article.html:36
|
||||
msgid "Duration (in months)"
|
||||
msgstr "Durée (en mois)"
|
||||
msgid "Duration membership (in days)"
|
||||
msgstr "Durée adhésion (en jours)"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_article.html:37
|
||||
msgid "Duration (in days)"
|
||||
msgstr "Durée (en jours)"
|
||||
msgid "Duration connection (in months)"
|
||||
msgstr "Durée connexion (en mois)"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_article.html:38
|
||||
msgid "Duration connection (in days)"
|
||||
msgstr "Durée connexion (en jours)"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_article.html:39
|
||||
msgid "Concerned users"
|
||||
msgstr "Utilisateurs concernés"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_article.html:39
|
||||
#: cotisations/templates/cotisations/aff_article.html:40
|
||||
#: cotisations/templates/cotisations/aff_paiement.html:34
|
||||
msgid "Available for everyone"
|
||||
msgstr "Disponible pour tous"
|
||||
|
@ -710,7 +720,7 @@ msgid "Invoice created"
|
|||
msgstr "Facture créée"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_cost_estimate.html:91
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:81
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:91
|
||||
#: cotisations/templates/cotisations/aff_custom_invoice.html:79
|
||||
msgid "PDF"
|
||||
msgstr "PDF"
|
||||
|
@ -725,15 +735,15 @@ msgstr "Utilisateur"
|
|||
msgid "Invoice ID"
|
||||
msgstr "ID facture"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:71
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:81
|
||||
msgid "Controlled invoice"
|
||||
msgstr "Facture contrôlée"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:84
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:94
|
||||
msgid "Invalidated invoice"
|
||||
msgstr "Facture invalidée"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:88
|
||||
#: cotisations/templates/cotisations/aff_cotisations.html:98
|
||||
msgid "Voucher"
|
||||
msgstr "Reçu"
|
||||
|
||||
|
@ -749,6 +759,23 @@ msgstr "Type de paiement"
|
|||
msgid "Custom payment method"
|
||||
msgstr "Moyen de paiement personnalisé"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_profil.html:35
|
||||
#: cotisations/templates/cotisations/index.html:32
|
||||
msgid "Subscriptions"
|
||||
msgstr "Cotisations"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_profil.html:43
|
||||
msgid "Add a subscription"
|
||||
msgstr "Ajouter une cotisation"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_profil.html:48
|
||||
msgid "Edit the balance"
|
||||
msgstr "Modifier le solde utilisateur"
|
||||
|
||||
#: cotisations/templates/cotisations/aff_profil.html:57
|
||||
msgid "No invoice"
|
||||
msgstr "Pas de facture"
|
||||
|
||||
#: cotisations/templates/cotisations/control.html:30
|
||||
msgid "Invoice control"
|
||||
msgstr "Contrôle des factures"
|
||||
|
@ -784,7 +811,7 @@ msgstr "Contrôlé"
|
|||
#: cotisations/templates/cotisations/control.html:107
|
||||
#: cotisations/templates/cotisations/delete.html:38
|
||||
#: cotisations/templates/cotisations/edit_facture.html:64
|
||||
#: cotisations/views.py:168 cotisations/views.py:222 cotisations/views.py:278
|
||||
#: cotisations/views.py:172 cotisations/views.py:224 cotisations/views.py:280
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmer"
|
||||
|
||||
|
@ -801,7 +828,7 @@ msgstr ""
|
|||
"Attention: voulez-vous vraiment supprimer cet objet %(objet_name)s "
|
||||
"( %(objet)s ) ?"
|
||||
|
||||
#: cotisations/templates/cotisations/edit_facture.html:31
|
||||
#: cotisations/templates/cotisations/edit_facture.html:30
|
||||
#: cotisations/templates/cotisations/facture.html:30
|
||||
msgid "Creation and editing of invoices"
|
||||
msgstr "Création et modification de factures"
|
||||
|
@ -813,7 +840,6 @@ msgstr "Modifier la facture"
|
|||
#: cotisations/templates/cotisations/edit_facture.html:45
|
||||
#: cotisations/templates/cotisations/facture.html:59
|
||||
#: cotisations/templates/cotisations/index_article.html:30
|
||||
#: cotisations/templates/cotisations/sidebar.html:55
|
||||
msgid "Articles"
|
||||
msgstr "Articles"
|
||||
|
||||
|
@ -840,14 +866,9 @@ msgid "Total price: <span id=\"total_price\">0,00</span> €"
|
|||
msgstr "Prix total : <span id=\"total_price\">0,00</span> €"
|
||||
|
||||
#: cotisations/templates/cotisations/index.html:29
|
||||
#: cotisations/templates/cotisations/sidebar.html:40
|
||||
msgid "Invoices"
|
||||
msgstr "Factures"
|
||||
|
||||
#: cotisations/templates/cotisations/index.html:32
|
||||
msgid "Subscriptions"
|
||||
msgstr "Cotisations"
|
||||
|
||||
#: cotisations/templates/cotisations/index_article.html:33
|
||||
msgid "List of articles"
|
||||
msgstr "Liste des articles"
|
||||
|
@ -861,7 +882,6 @@ msgid "Delete one or several articles"
|
|||
msgstr "Supprimer un ou plusieurs articles"
|
||||
|
||||
#: cotisations/templates/cotisations/index_banque.html:30
|
||||
#: cotisations/templates/cotisations/sidebar.html:60
|
||||
msgid "Banks"
|
||||
msgstr "Banques"
|
||||
|
||||
|
@ -878,7 +898,6 @@ msgid "Delete one or several banks"
|
|||
msgstr "Supprimer une ou plusieurs banques"
|
||||
|
||||
#: cotisations/templates/cotisations/index_cost_estimate.html:28
|
||||
#: cotisations/templates/cotisations/sidebar.html:50
|
||||
msgid "Cost estimates"
|
||||
msgstr "Devis"
|
||||
|
||||
|
@ -887,7 +906,6 @@ msgid "List of cost estimates"
|
|||
msgstr "Liste des devis"
|
||||
|
||||
#: cotisations/templates/cotisations/index_custom_invoice.html:28
|
||||
#: cotisations/templates/cotisations/sidebar.html:45
|
||||
msgid "Custom invoices"
|
||||
msgstr "Factures personnalisées"
|
||||
|
||||
|
@ -896,7 +914,6 @@ msgid "List of custom invoices"
|
|||
msgstr "Liste des factures personnalisées"
|
||||
|
||||
#: cotisations/templates/cotisations/index_paiement.html:30
|
||||
#: cotisations/templates/cotisations/sidebar.html:65
|
||||
msgid "Payment methods"
|
||||
msgstr "Moyens de paiement"
|
||||
|
||||
|
@ -921,132 +938,124 @@ msgstr "Rechargement de solde"
|
|||
msgid "Pay %(amount)s €"
|
||||
msgstr "Payer %(amount)s €"
|
||||
|
||||
#: cotisations/templates/cotisations/payment.html:42 cotisations/views.py:1028
|
||||
#: cotisations/templates/cotisations/payment.html:42 cotisations/views.py:1030
|
||||
msgid "Pay"
|
||||
msgstr "Payer"
|
||||
|
||||
#: cotisations/templates/cotisations/sidebar.html:32
|
||||
msgid "Create an invoice"
|
||||
msgstr "Créer une facture"
|
||||
|
||||
#: cotisations/templates/cotisations/sidebar.html:35
|
||||
msgid "Control the invoices"
|
||||
msgstr "Contrôler les factures"
|
||||
|
||||
#: cotisations/views.py:155
|
||||
#: cotisations/views.py:159
|
||||
msgid "You need to choose at least one article."
|
||||
msgstr "Vous devez choisir au moins un article."
|
||||
|
||||
#: cotisations/views.py:169
|
||||
#: cotisations/views.py:173
|
||||
msgid "New invoice"
|
||||
msgstr "Nouvelle facture"
|
||||
|
||||
#: cotisations/views.py:216
|
||||
#: cotisations/views.py:218
|
||||
msgid "The cost estimate was created."
|
||||
msgstr "Le devis a été créé."
|
||||
|
||||
#: cotisations/views.py:226
|
||||
#: cotisations/views.py:228
|
||||
msgid "New cost estimate"
|
||||
msgstr "Nouveau devis"
|
||||
|
||||
#: cotisations/views.py:272
|
||||
#: cotisations/views.py:274
|
||||
msgid "The custom invoice was created."
|
||||
msgstr "La facture personnalisée a été créée."
|
||||
|
||||
#: cotisations/views.py:282
|
||||
#: cotisations/views.py:284
|
||||
msgid "New custom invoice"
|
||||
msgstr "Nouvelle facture personnalisée"
|
||||
|
||||
#: cotisations/views.py:357 cotisations/views.py:438
|
||||
#: cotisations/views.py:359 cotisations/views.py:440
|
||||
msgid "The invoice was edited."
|
||||
msgstr "La facture a été modifiée."
|
||||
|
||||
#: cotisations/views.py:375 cotisations/views.py:570
|
||||
#: cotisations/views.py:377 cotisations/views.py:572
|
||||
msgid "The invoice was deleted."
|
||||
msgstr "La facture a été supprimée."
|
||||
|
||||
#: cotisations/views.py:398
|
||||
#: cotisations/views.py:400
|
||||
msgid "The cost estimate was edited."
|
||||
msgstr "Le devis a été modifié."
|
||||
|
||||
#: cotisations/views.py:405
|
||||
#: cotisations/views.py:407
|
||||
msgid "Edit cost estimate"
|
||||
msgstr "Modifier le devis"
|
||||
|
||||
#: cotisations/views.py:419
|
||||
#: cotisations/views.py:421
|
||||
msgid "An invoice was successfully created from your cost estimate."
|
||||
msgstr "Une facture a bien été créée à partir de votre devis."
|
||||
|
||||
#: cotisations/views.py:445
|
||||
#: cotisations/views.py:447
|
||||
msgid "Edit custom invoice"
|
||||
msgstr "Modifier la facture personnalisée"
|
||||
|
||||
#: cotisations/views.py:507
|
||||
#: cotisations/views.py:509
|
||||
msgid "The cost estimate was deleted."
|
||||
msgstr "Le devis a été supprimé."
|
||||
|
||||
#: cotisations/views.py:510
|
||||
#: cotisations/views.py:512
|
||||
msgid "cost estimate"
|
||||
msgstr "devis"
|
||||
|
||||
#: cotisations/views.py:594
|
||||
#: cotisations/views.py:596
|
||||
msgid "The article was created."
|
||||
msgstr "L'article a été créé."
|
||||
|
||||
#: cotisations/views.py:599 cotisations/views.py:673 cotisations/views.py:767
|
||||
#: cotisations/views.py:601 cotisations/views.py:675 cotisations/views.py:769
|
||||
msgid "Add"
|
||||
msgstr "Ajouter"
|
||||
|
||||
#: cotisations/views.py:600
|
||||
#: cotisations/views.py:602
|
||||
msgid "New article"
|
||||
msgstr "Nouvel article"
|
||||
|
||||
#: cotisations/views.py:617
|
||||
#: cotisations/views.py:619
|
||||
msgid "The article was edited."
|
||||
msgstr "L'article a été modifié."
|
||||
|
||||
#: cotisations/views.py:622 cotisations/views.py:705 cotisations/views.py:791
|
||||
#: cotisations/views.py:624 cotisations/views.py:707 cotisations/views.py:793
|
||||
msgid "Edit"
|
||||
msgstr "Modifier"
|
||||
|
||||
#: cotisations/views.py:623
|
||||
#: cotisations/views.py:625
|
||||
msgid "Edit article"
|
||||
msgstr "Modifier l'article"
|
||||
|
||||
#: cotisations/views.py:640
|
||||
#: cotisations/views.py:642
|
||||
msgid "The articles were deleted."
|
||||
msgstr "Les articles ont été supprimés."
|
||||
|
||||
#: cotisations/views.py:645 cotisations/views.py:744 cotisations/views.py:829
|
||||
#: cotisations/views.py:647 cotisations/views.py:746 cotisations/views.py:831
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
#: cotisations/views.py:646
|
||||
#: cotisations/views.py:648
|
||||
msgid "Delete article"
|
||||
msgstr "Supprimer l'article"
|
||||
|
||||
#: cotisations/views.py:667
|
||||
#: cotisations/views.py:669
|
||||
msgid "The payment method was created."
|
||||
msgstr "Le moyen de paiment a été créé."
|
||||
|
||||
#: cotisations/views.py:674
|
||||
#: cotisations/views.py:676
|
||||
msgid "New payment method"
|
||||
msgstr "Nouveau moyen de paiement"
|
||||
|
||||
#: cotisations/views.py:699
|
||||
#: cotisations/views.py:701
|
||||
msgid "The payment method was edited."
|
||||
msgstr "Le moyen de paiment a été modifié."
|
||||
|
||||
#: cotisations/views.py:706
|
||||
#: cotisations/views.py:708
|
||||
msgid "Edit payment method"
|
||||
msgstr "Modifier le moyen de paiement"
|
||||
|
||||
#: cotisations/views.py:728
|
||||
#: cotisations/views.py:730
|
||||
#, python-format
|
||||
msgid "The payment method %(method_name)s was deleted."
|
||||
msgstr "Le moyen de paiement %(method_name)s a été supprimé."
|
||||
|
||||
#: cotisations/views.py:735
|
||||
#: cotisations/views.py:737
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The payment method %(method_name)s can't be deleted because there are "
|
||||
|
@ -1055,32 +1064,32 @@ msgstr ""
|
|||
"Le moyen de paiement %(method_name)s ne peut pas être supprimé car il y a "
|
||||
"des factures qui l'utilisent."
|
||||
|
||||
#: cotisations/views.py:745
|
||||
#: cotisations/views.py:747
|
||||
msgid "Delete payment method"
|
||||
msgstr "Supprimer le moyen de paiement"
|
||||
|
||||
#: cotisations/views.py:762
|
||||
#: cotisations/views.py:764
|
||||
msgid "The bank was created."
|
||||
msgstr "La banque a été créée."
|
||||
|
||||
#: cotisations/views.py:768
|
||||
#: cotisations/views.py:770
|
||||
msgid "New bank"
|
||||
msgstr "Nouvelle banque"
|
||||
|
||||
#: cotisations/views.py:786
|
||||
#: cotisations/views.py:788
|
||||
msgid "The bank was edited."
|
||||
msgstr "La banque a été modifiée."
|
||||
|
||||
#: cotisations/views.py:792
|
||||
#: cotisations/views.py:794
|
||||
msgid "Edit bank"
|
||||
msgstr "Modifier la banque"
|
||||
|
||||
#: cotisations/views.py:814
|
||||
#: cotisations/views.py:816
|
||||
#, python-format
|
||||
msgid "The bank %(bank_name)s was deleted."
|
||||
msgstr "La banque %(bank_name)s a été supprimée."
|
||||
|
||||
#: cotisations/views.py:820
|
||||
#: cotisations/views.py:822
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The bank %(bank_name)s can't be deleted because there are invoices using it."
|
||||
|
@ -1088,22 +1097,22 @@ msgstr ""
|
|||
"La banque %(bank_name)s ne peut pas être supprimée car il y a des factures "
|
||||
"qui l'utilisent."
|
||||
|
||||
#: cotisations/views.py:830
|
||||
#: cotisations/views.py:832
|
||||
msgid "Delete bank"
|
||||
msgstr "Supprimer la banque"
|
||||
|
||||
#: cotisations/views.py:864
|
||||
#: cotisations/views.py:866
|
||||
msgid "Your changes have been properly taken into account."
|
||||
msgstr "Vos modifications ont correctement été prises en compte."
|
||||
|
||||
#: cotisations/views.py:996
|
||||
#: cotisations/views.py:998
|
||||
msgid "You are not allowed to credit your balance."
|
||||
msgstr "Vous n'êtes pas autorisé à créditer votre solde."
|
||||
|
||||
#: cotisations/views.py:1027
|
||||
#: cotisations/views.py:1029
|
||||
msgid "Refill your balance"
|
||||
msgstr "Recharger votre solde"
|
||||
|
||||
#: cotisations/views.py:1046
|
||||
#: cotisations/views.py:1048
|
||||
msgid "Could not find a voucher for that invoice."
|
||||
msgstr "Impossible de trouver un reçu pour cette facture."
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
970
cotisations/migrations/0001_model_creation.py
Normal file
970
cotisations/migrations/0001_model_creation.py
Normal file
|
@ -0,0 +1,970 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.core.validators
|
||||
import re2o.mixins
|
||||
import re2o.aes_field
|
||||
import re2o.field_permissions
|
||||
import cotisations.models
|
||||
import cotisations.payment_methods.mixins
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
dependencies = []
|
||||
replaces = [
|
||||
("users", "0001_initial"),
|
||||
("users", "0002_auto_20160630_2301"),
|
||||
("users", "0003_listrights_rights"),
|
||||
("users", "0004_auto_20160701_2312"),
|
||||
("users", "0005_auto_20160702_0006"),
|
||||
("users", "0006_ban"),
|
||||
("users", "0007_auto_20160702_2322"),
|
||||
("users", "0008_user_registered"),
|
||||
("users", "0009_user_room"),
|
||||
("users", "0010_auto_20160703_1226"),
|
||||
("users", "0011_auto_20160703_1227"),
|
||||
("users", "0012_auto_20160703_1230"),
|
||||
("users", "0013_auto_20160704_1547"),
|
||||
("users", "0014_auto_20160704_1548"),
|
||||
("users", "0015_whitelist"),
|
||||
("users", "0016_auto_20160706_1220"),
|
||||
("users", "0017_auto_20160707_0105"),
|
||||
("users", "0018_auto_20160707_0115"),
|
||||
("users", "0019_auto_20160708_1633"),
|
||||
("users", "0020_request"),
|
||||
("users", "0021_ldapuser"),
|
||||
("users", "0022_ldapuser_sambasid"),
|
||||
("users", "0023_auto_20160724_1908"),
|
||||
("users", "0024_remove_ldapuser_mac_list"),
|
||||
("users", "0025_listshell"),
|
||||
("users", "0026_user_shell"),
|
||||
("users", "0027_auto_20160726_0216"),
|
||||
("users", "0028_auto_20160726_0227"),
|
||||
("users", "0029_auto_20160726_0229"),
|
||||
("users", "0030_auto_20160726_0357"),
|
||||
("users", "0031_auto_20160726_0359"),
|
||||
("users", "0032_auto_20160727_2122"),
|
||||
("users", "0033_remove_ldapuser_loginshell"),
|
||||
("users", "0034_auto_20161018_0037"),
|
||||
("users", "0035_auto_20161018_0046"),
|
||||
("users", "0036_auto_20161022_2146"),
|
||||
("users", "0037_auto_20161028_1906"),
|
||||
("users", "0038_auto_20161031_0258"),
|
||||
("users", "0039_auto_20161119_0033"),
|
||||
("users", "0040_auto_20161119_1709"),
|
||||
("users", "0041_listright_details"),
|
||||
("users", "0042_auto_20161126_2028"),
|
||||
("users", "0043_auto_20161224_1156"),
|
||||
("users", "0043_ban_state"),
|
||||
("users", "0044_user_ssh_public_key"),
|
||||
("users", "0045_merge"),
|
||||
("users", "0046_auto_20170617_1433"),
|
||||
("users", "0047_auto_20170618_0156"),
|
||||
("users", "0048_auto_20170618_0210"),
|
||||
("users", "0049_auto_20170618_1424"),
|
||||
("users", "0050_serviceuser_comment"),
|
||||
("users", "0051_user_telephone"),
|
||||
("users", "0052_ldapuser_shadowexpire"),
|
||||
("users", "0053_auto_20170626_2105"),
|
||||
("users", "0054_auto_20170626_2219"),
|
||||
("users", "0055_auto_20171003_0556"),
|
||||
("users", "0056_auto_20171015_2033"),
|
||||
("users", "0057_auto_20171023_0301"),
|
||||
("users", "0058_auto_20171025_0154"),
|
||||
("users", "0059_auto_20171025_1854"),
|
||||
("users", "0060_auto_20171120_0317"),
|
||||
("users", "0061_auto_20171230_2033"),
|
||||
("users", "0062_auto_20171231_0056"),
|
||||
("users", "0063_auto_20171231_0140"),
|
||||
("users", "0064_auto_20171231_0150"),
|
||||
("users", "0065_auto_20171231_2053"),
|
||||
("users", "0066_grouppermissions"),
|
||||
("users", "0067_serveurpermission"),
|
||||
("users", "0068_auto_20180107_2245"),
|
||||
("users", "0069_club_mailing"),
|
||||
("users", "0070_auto_20180324_1906"),
|
||||
("users", "0071_auto_20180415_1252"),
|
||||
("users", "0072_auto_20180426_2021"),
|
||||
("users", "0073_auto_20180629_1614"),
|
||||
("users", "0074_auto_20180810_2104"),
|
||||
("users", "0074_auto_20180814_1059"),
|
||||
("users", "0075_merge_20180815_2202"),
|
||||
("users", "0076_auto_20180818_1321"),
|
||||
("users", "0077_auto_20180824_1750"),
|
||||
("users", "0078_auto_20181011_1405"),
|
||||
("users", "0079_auto_20181228_2039"),
|
||||
("users", "0080_auto_20190108_1726"),
|
||||
("users", "0081_auto_20190317_0302"),
|
||||
("users", "0082_auto_20190908_1338"),
|
||||
("users", "0083_user_shortcuts_enabled"),
|
||||
("users", "0084_auto_20191120_0159"),
|
||||
("users", "0085_user_email_state"),
|
||||
("users", "0086_user_email_change_date"),
|
||||
("users", "0087_request_email"),
|
||||
("users", "0088_auto_20200417_2312"),
|
||||
("users", "0089_auto_20200418_0112"),
|
||||
("users", "0090_auto_20200421_1825"),
|
||||
("users", "0091_auto_20200423_1256"),
|
||||
("users", "0092_auto_20200502_0057"),
|
||||
("users", "0093_user_profile_image"),
|
||||
("users", "0094_remove_user_profile_image"),
|
||||
("users", "0095_user_theme"),
|
||||
("users", "0096_auto_20210110_1811"),
|
||||
("cotisations", "0001_initial"),
|
||||
("cotisations", "0002_remove_facture_article"),
|
||||
("cotisations", "0003_auto_20160702_1448"),
|
||||
("cotisations", "0004_auto_20160702_1528"),
|
||||
("cotisations", "0005_auto_20160702_1532"),
|
||||
("cotisations", "0006_auto_20160702_1534"),
|
||||
("cotisations", "0007_auto_20160702_1543"),
|
||||
("cotisations", "0008_auto_20160702_1614"),
|
||||
("cotisations", "0009_remove_cotisation_user"),
|
||||
("cotisations", "0010_auto_20160702_1840"),
|
||||
("cotisations", "0011_auto_20160702_1911"),
|
||||
("cotisations", "0012_auto_20160704_0118"),
|
||||
("cotisations", "0013_auto_20160711_2240"),
|
||||
("cotisations", "0014_auto_20160712_0245"),
|
||||
("cotisations", "0015_auto_20160714_2142"),
|
||||
("cotisations", "0016_auto_20160715_0110"),
|
||||
("cotisations", "0017_auto_20170718_2329"),
|
||||
("cotisations", "0018_paiement_type_paiement"),
|
||||
("cotisations", "0019_auto_20170819_0055"),
|
||||
("cotisations", "0020_auto_20170819_0057"),
|
||||
("cotisations", "0021_auto_20170819_0104"),
|
||||
("cotisations", "0022_auto_20170824_0128"),
|
||||
("cotisations", "0023_auto_20170902_1303"),
|
||||
("cotisations", "0024_auto_20171015_2033"),
|
||||
("cotisations", "0025_article_type_user"),
|
||||
("cotisations", "0026_auto_20171028_0126"),
|
||||
("cotisations", "0027_auto_20171029_1156"),
|
||||
("cotisations", "0028_auto_20171231_0007"),
|
||||
("cotisations", "0029_auto_20180414_2056"),
|
||||
("cotisations", "0030_custom_payment"),
|
||||
("cotisations", "0031_comnpaypayment_production"),
|
||||
("cotisations", "0032_custom_invoice"),
|
||||
("cotisations", "0033_auto_20180818_1319"),
|
||||
("cotisations", "0034_auto_20180831_1532"),
|
||||
("cotisations", "0035_notepayment"),
|
||||
("cotisations", "0036_custominvoice_remark"),
|
||||
("cotisations", "0037_costestimate"),
|
||||
("cotisations", "0038_auto_20181231_1657"),
|
||||
("cotisations", "0039_freepayment"),
|
||||
("cotisations", "0040_auto_20191002_2335"),
|
||||
("cotisations", "0041_auto_20191103_2131"),
|
||||
("cotisations", "0042_auto_20191120_0159"),
|
||||
("cotisations", "0043_separation_membership_connection_p1"),
|
||||
("cotisations", "0044_separation_membership_connection_p2"),
|
||||
("cotisations", "0045_separation_membership_connection_p3"),
|
||||
("cotisations", "0046_article_need_membership"),
|
||||
("cotisations", "0047_article_need_membership_init"),
|
||||
("cotisations", "0048_auto_20201017_0018"),
|
||||
("cotisations", "0049_auto_20201102_2305"),
|
||||
("cotisations", "0050_auto_20201102_2342"),
|
||||
("cotisations", "0051_auto_20201228_1636"),
|
||||
("machines", "0001_initial"),
|
||||
("machines", "0002_auto_20160703_1444"),
|
||||
("machines", "0003_auto_20160703_1450"),
|
||||
("machines", "0004_auto_20160703_1451"),
|
||||
("machines", "0005_auto_20160703_1523"),
|
||||
("machines", "0006_auto_20160703_1813"),
|
||||
("machines", "0007_auto_20160703_1816"),
|
||||
("machines", "0008_remove_interface_ipv6"),
|
||||
("machines", "0009_auto_20160703_2358"),
|
||||
("machines", "0010_auto_20160704_0104"),
|
||||
("machines", "0011_auto_20160704_0105"),
|
||||
("machines", "0012_auto_20160704_0118"),
|
||||
("machines", "0013_auto_20160705_1014"),
|
||||
("machines", "0014_auto_20160706_1220"),
|
||||
("machines", "0015_auto_20160707_0105"),
|
||||
("machines", "0016_auto_20160708_1633"),
|
||||
("machines", "0017_auto_20160708_1645"),
|
||||
("machines", "0018_auto_20160708_1813"),
|
||||
("machines", "0019_auto_20160718_1141"),
|
||||
("machines", "0020_auto_20160718_1849"),
|
||||
("machines", "0021_auto_20161006_1943"),
|
||||
("machines", "0022_auto_20161011_1829"),
|
||||
("machines", "0023_iplist_ip_type"),
|
||||
("machines", "0024_machinetype_need_infra"),
|
||||
("machines", "0025_auto_20161023_0038"),
|
||||
("machines", "0026_auto_20161026_1348"),
|
||||
("machines", "0027_alias"),
|
||||
("machines", "0028_iptype_domaine_ip"),
|
||||
("machines", "0029_iptype_domaine_range"),
|
||||
("machines", "0030_auto_20161118_1730"),
|
||||
("machines", "0031_auto_20161119_1709"),
|
||||
("machines", "0032_auto_20161119_1850"),
|
||||
("machines", "0033_extension_need_infra"),
|
||||
("machines", "0034_iplist_need_infra"),
|
||||
("machines", "0035_auto_20161224_1201"),
|
||||
("machines", "0036_auto_20161224_1204"),
|
||||
("machines", "0037_domain_cname"),
|
||||
("machines", "0038_auto_20161224_1721"),
|
||||
("machines", "0039_auto_20161224_1732"),
|
||||
("machines", "0040_remove_interface_dns"),
|
||||
("machines", "0041_remove_ns_interface"),
|
||||
("machines", "0042_ns_ns"),
|
||||
("machines", "0043_auto_20170721_0350"),
|
||||
("machines", "0044_auto_20170808_0233"),
|
||||
("machines", "0045_auto_20170808_0348"),
|
||||
("machines", "0046_auto_20170808_1423"),
|
||||
("machines", "0047_auto_20170809_0606"),
|
||||
("machines", "0048_auto_20170823_2315"),
|
||||
("machines", "0049_vlan"),
|
||||
("machines", "0050_auto_20170826_0022"),
|
||||
("machines", "0051_iptype_vlan"),
|
||||
("machines", "0052_auto_20170828_2322"),
|
||||
("machines", "0053_text"),
|
||||
("machines", "0054_text_zone"),
|
||||
("machines", "0055_nas"),
|
||||
("machines", "0056_nas_port_access_mode"),
|
||||
("machines", "0057_nas_autocapture_mac"),
|
||||
("machines", "0058_auto_20171002_0350"),
|
||||
("machines", "0059_iptype_prefix_v6"),
|
||||
("machines", "0060_iptype_ouverture_ports"),
|
||||
("machines", "0061_auto_20171015_2033"),
|
||||
("machines", "0062_extension_origin_v6"),
|
||||
("machines", "0063_auto_20171020_0040"),
|
||||
("machines", "0064_auto_20171115_0253"),
|
||||
("machines", "0065_auto_20171115_1514"),
|
||||
("machines", "0066_srv"),
|
||||
("machines", "0067_auto_20171116_0152"),
|
||||
("machines", "0068_auto_20171116_0252"),
|
||||
("machines", "0069_auto_20171116_0822"),
|
||||
("machines", "0070_auto_20171231_1947"),
|
||||
("machines", "0071_auto_20171231_2100"),
|
||||
("machines", "0072_auto_20180108_1822"),
|
||||
("machines", "0073_auto_20180128_2203"),
|
||||
("machines", "0074_auto_20180129_0352"),
|
||||
("machines", "0075_auto_20180130_0052"),
|
||||
("machines", "0076_auto_20180130_1623"),
|
||||
("machines", "0077_auto_20180409_2243"),
|
||||
("machines", "0078_auto_20180415_1252"),
|
||||
("machines", "0079_auto_20180416_0107"),
|
||||
("machines", "0080_auto_20180502_2334"),
|
||||
("machines", "0081_auto_20180521_1413"),
|
||||
("machines", "0082_auto_20180525_2209"),
|
||||
("machines", "0083_remove_duplicate_rights"),
|
||||
("machines", "0084_dname"),
|
||||
("machines", "0085_sshfingerprint"),
|
||||
("machines", "0086_role"),
|
||||
("machines", "0087_dnssec"),
|
||||
("machines", "0088_iptype_prefix_v6_length"),
|
||||
("machines", "0089_auto_20180805_1148"),
|
||||
("machines", "0090_auto_20180805_1459"),
|
||||
("machines", "0091_auto_20180806_2310"),
|
||||
("machines", "0092_auto_20180807_0926"),
|
||||
("machines", "0093_auto_20180807_1115"),
|
||||
("machines", "0094_auto_20180815_1918"),
|
||||
("machines", "0095_auto_20180919_2225"),
|
||||
("machines", "0096_auto_20181013_1417"),
|
||||
("machines", "0097_extension_dnssec"),
|
||||
("machines", "0098_auto_20190102_1745"),
|
||||
("machines", "0099_role_recursive_dns"),
|
||||
("machines", "0100_auto_20190102_1753"),
|
||||
("machines", "0101_auto_20190108_1623"),
|
||||
("machines", "0102_auto_20190303_1611"),
|
||||
("machines", "0103_auto_20191002_2222"),
|
||||
("machines", "0104_auto_20191002_2231"),
|
||||
("machines", "0105_dname_ttl"),
|
||||
("machines", "0106_auto_20191120_0159"),
|
||||
("machines", "0107_fix_lowercase_domain"),
|
||||
("machines", "0108_ipv6list_active"),
|
||||
("preferences", "0001_initial"),
|
||||
("preferences", "0002_auto_20170625_1923"),
|
||||
("preferences", "0003_optionaluser_solde_negatif"),
|
||||
("preferences", "0004_assooption_services"),
|
||||
("preferences", "0005_auto_20170824_0139"),
|
||||
("preferences", "0006_auto_20170824_0143"),
|
||||
("preferences", "0007_auto_20170824_2056"),
|
||||
("preferences", "0008_auto_20170824_2122"),
|
||||
("preferences", "0009_assooption_utilisateur_asso"),
|
||||
("preferences", "0010_auto_20170825_0459"),
|
||||
("preferences", "0011_auto_20170825_2307"),
|
||||
("preferences", "0012_generaloption_req_expire_hrs"),
|
||||
("preferences", "0013_generaloption_site_name"),
|
||||
("preferences", "0014_generaloption_email_from"),
|
||||
("preferences", "0015_optionaltopologie_radius_general_policy"),
|
||||
("preferences", "0016_auto_20170902_1520"),
|
||||
("preferences", "0017_mailmessageoption"),
|
||||
("preferences", "0018_optionaltopologie_mac_autocapture"),
|
||||
("preferences", "0019_remove_optionaltopologie_mac_autocapture"),
|
||||
("preferences", "0020_optionalmachine_ipv6"),
|
||||
("preferences", "0021_auto_20171015_1741"),
|
||||
("preferences", "0022_auto_20171015_1758"),
|
||||
("preferences", "0023_auto_20171015_2033"),
|
||||
("preferences", "0024_optionaluser_all_can_create"),
|
||||
("preferences", "0025_auto_20171231_2142"),
|
||||
("preferences", "0025_generaloption_general_message"),
|
||||
("preferences", "0026_auto_20171216_0401"),
|
||||
("preferences", "0027_merge_20180106_2019"),
|
||||
("preferences", "0028_assooption_description"),
|
||||
("preferences", "0028_auto_20180111_1129"),
|
||||
("preferences", "0028_auto_20180128_2203"),
|
||||
("preferences", "0029_auto_20180111_1134"),
|
||||
("preferences", "0029_auto_20180318_0213"),
|
||||
("preferences", "0029_auto_20180318_1005"),
|
||||
("preferences", "0030_auto_20180111_2346"),
|
||||
("preferences", "0030_merge_20180320_1419"),
|
||||
("preferences", "0031_auto_20180323_0218"),
|
||||
("preferences", "0031_optionaluser_self_adhesion"),
|
||||
("preferences", "0032_optionaluser_min_online_payment"),
|
||||
("preferences", "0032_optionaluser_shell_default"),
|
||||
("preferences", "0033_accueiloption"),
|
||||
("preferences", "0033_generaloption_gtu_sum_up"),
|
||||
("preferences", "0034_auto_20180114_2025"),
|
||||
("preferences", "0034_auto_20180416_1120"),
|
||||
("preferences", "0035_auto_20180114_2132"),
|
||||
("preferences", "0035_optionaluser_allow_self_subscription"),
|
||||
("preferences", "0036_auto_20180114_2141"),
|
||||
("preferences", "0037_auto_20180114_2156"),
|
||||
("preferences", "0038_auto_20180114_2209"),
|
||||
("preferences", "0039_auto_20180115_0003"),
|
||||
("preferences", "0040_auto_20180129_1745"),
|
||||
("preferences", "0041_merge_20180130_0052"),
|
||||
("preferences", "0042_auto_20180222_1743"),
|
||||
("preferences", "0043_optionalmachine_create_machine"),
|
||||
("preferences", "0044_remove_payment_pass"),
|
||||
("preferences", "0045_remove_unused_payment_fields"),
|
||||
("preferences", "0046_optionaluser_mail_extension"),
|
||||
("preferences", "0047_mailcontact"),
|
||||
("preferences", "0048_auto_20180811_1515"),
|
||||
("preferences", "0049_optionaluser_self_change_shell"),
|
||||
("preferences", "0050_auto_20180818_1329"),
|
||||
("preferences", "0051_auto_20180919_2225"),
|
||||
("preferences", "0052_optionaluser_delete_notyetactive"),
|
||||
("preferences", "0053_optionaluser_self_change_room"),
|
||||
("preferences", "0055_generaloption_main_site_url"),
|
||||
("preferences", "0056_1_radiusoption"),
|
||||
("preferences", "0056_2_radiusoption"),
|
||||
("preferences", "0056_3_radiusoption"),
|
||||
("preferences", "0056_4_radiusoption"),
|
||||
("preferences", "0057_optionaluser_all_users_active"),
|
||||
("preferences", "0058_auto_20190108_1650"),
|
||||
("preferences", "0059_auto_20190120_1739"),
|
||||
("preferences", "0060_auto_20190712_1821"),
|
||||
("preferences", "0061_optionaluser_allow_archived_connexion"),
|
||||
("preferences", "0062_auto_20190910_1909"),
|
||||
("preferences", "0063_mandate"),
|
||||
("preferences", "0064_auto_20191008_1335"),
|
||||
("preferences", "0065_auto_20191010_1227"),
|
||||
("preferences", "0066_optionalmachine_default_dns_ttl"),
|
||||
("preferences", "0067_auto_20191120_0159"),
|
||||
("preferences", "0068_optionaluser_allow_set_password_during_user_creation"),
|
||||
("preferences", "0069_optionaluser_disable_emailnotyetconfirmed"),
|
||||
("preferences", "0070_auto_20200419_0225"),
|
||||
("preferences", "0071_optionaluser_self_change_pseudo"),
|
||||
("topologie", "0001_initial"),
|
||||
("topologie", "0002_auto_20160703_1118"),
|
||||
("topologie", "0003_room"),
|
||||
("topologie", "0004_auto_20160703_1122"),
|
||||
("topologie", "0005_auto_20160703_1123"),
|
||||
("topologie", "0006_auto_20160703_1129"),
|
||||
("topologie", "0007_auto_20160703_1148"),
|
||||
("topologie", "0008_port_room"),
|
||||
("topologie", "0009_auto_20160703_1200"),
|
||||
("topologie", "0010_auto_20160704_2148"),
|
||||
("topologie", "0011_auto_20160704_2153"),
|
||||
("topologie", "0012_port_machine_interface"),
|
||||
("topologie", "0013_port_related"),
|
||||
("topologie", "0014_auto_20160706_1238"),
|
||||
("topologie", "0015_auto_20160706_1452"),
|
||||
("topologie", "0016_auto_20160706_1531"),
|
||||
("topologie", "0017_auto_20160718_1141"),
|
||||
("topologie", "0018_room_details"),
|
||||
("topologie", "0019_auto_20161026_1348"),
|
||||
("topologie", "0020_auto_20161119_0033"),
|
||||
("topologie", "0021_port_radius"),
|
||||
("topologie", "0022_auto_20161211_1622"),
|
||||
("topologie", "0023_auto_20170817_1654"),
|
||||
("topologie", "0023_auto_20170826_1530"),
|
||||
("topologie", "0024_auto_20170818_1021"),
|
||||
("topologie", "0024_auto_20170826_1800"),
|
||||
("topologie", "0025_merge_20170902_1242"),
|
||||
("topologie", "0026_auto_20170902_1245"),
|
||||
("topologie", "0027_auto_20170905_1442"),
|
||||
("topologie", "0028_auto_20170913_1503"),
|
||||
("topologie", "0029_auto_20171002_0334"),
|
||||
("topologie", "0030_auto_20171004_0235"),
|
||||
("topologie", "0031_auto_20171015_2033"),
|
||||
("topologie", "0032_auto_20171026_0338"),
|
||||
("topologie", "0033_auto_20171231_1743"),
|
||||
("topologie", "0034_borne"),
|
||||
("topologie", "0035_auto_20180324_0023"),
|
||||
("topologie", "0036_transferborne"),
|
||||
("topologie", "0037_auto_20180325_0127"),
|
||||
("topologie", "0038_transfersw"),
|
||||
("topologie", "0039_port_new_switch"),
|
||||
("topologie", "0040_transferports"),
|
||||
("topologie", "0041_transferportsw"),
|
||||
("topologie", "0042_transferswitch"),
|
||||
("topologie", "0043_renamenewswitch"),
|
||||
("topologie", "0044_auto_20180326_0002"),
|
||||
("topologie", "0045_auto_20180326_0123"),
|
||||
("topologie", "0046_auto_20180326_0129"),
|
||||
("topologie", "0047_ap_machine"),
|
||||
("topologie", "0048_ap_machine"),
|
||||
("topologie", "0049_switchs_machine"),
|
||||
("topologie", "0050_port_new_switch"),
|
||||
("topologie", "0051_switchs_machine"),
|
||||
("topologie", "0052_transferports"),
|
||||
("topologie", "0053_finalsw"),
|
||||
("topologie", "0054_auto_20180326_1742"),
|
||||
("topologie", "0055_auto_20180329_0431"),
|
||||
("topologie", "0056_building_switchbay"),
|
||||
("topologie", "0057_auto_20180408_0316"),
|
||||
("topologie", "0058_remove_switch_location"),
|
||||
("topologie", "0059_auto_20180415_2249"),
|
||||
("topologie", "0060_server"),
|
||||
("topologie", "0061_portprofile"),
|
||||
("topologie", "0062_auto_20180815_1918"),
|
||||
("topologie", "0063_auto_20180919_2225"),
|
||||
("topologie", "0064_switch_automatic_provision"),
|
||||
("topologie", "0065_auto_20180927_1836"),
|
||||
("topologie", "0066_modelswitch_commercial_name"),
|
||||
("topologie", "0067_auto_20181230_1819"),
|
||||
("topologie", "0068_auto_20190102_1758"),
|
||||
("topologie", "0069_auto_20190108_1439"),
|
||||
("topologie", "0070_auto_20190218_1743"),
|
||||
("topologie", "0071_auto_20190218_1936"),
|
||||
("topologie", "0072_auto_20190720_2318"),
|
||||
("topologie", "0073_auto_20191120_0159"),
|
||||
("topologie", "0074_auto_20200419_1640"),
|
||||
]
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="BaseInvoice",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("date", models.DateTimeField(auto_now_add=True, verbose_name="date")),
|
||||
],
|
||||
bases=(
|
||||
re2o.mixins.RevMixin,
|
||||
re2o.mixins.AclMixin,
|
||||
re2o.field_permissions.FieldPermissionModelMixin,
|
||||
models.Model,
|
||||
),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Facture",
|
||||
fields=[
|
||||
(
|
||||
"baseinvoice_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="cotisations.BaseInvoice",
|
||||
),
|
||||
),
|
||||
(
|
||||
"cheque",
|
||||
models.CharField(
|
||||
max_length=255, blank=True, verbose_name="cheque number"
|
||||
),
|
||||
),
|
||||
("valid", models.BooleanField(default=False, verbose_name="validated")),
|
||||
(
|
||||
"control",
|
||||
models.BooleanField(default=False, verbose_name="controlled"),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"permissions": (
|
||||
("change_facture_control", 'Can edit the "controlled" state'),
|
||||
("view_facture", "Can view an invoice object"),
|
||||
("change_all_facture", "Can edit all the previous invoices"),
|
||||
),
|
||||
"verbose_name": "invoice",
|
||||
"verbose_name_plural": "invoices",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="CustomInvoice",
|
||||
fields=[
|
||||
(
|
||||
"baseinvoice_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="cotisations.BaseInvoice",
|
||||
),
|
||||
),
|
||||
(
|
||||
"recipient",
|
||||
models.CharField(max_length=255, verbose_name="recipient"),
|
||||
),
|
||||
(
|
||||
"payment",
|
||||
models.CharField(max_length=255, verbose_name="payment type"),
|
||||
),
|
||||
("address", models.CharField(max_length=255, verbose_name="address")),
|
||||
("paid", models.BooleanField(default=False, verbose_name="paid")),
|
||||
(
|
||||
"remark",
|
||||
models.TextField(verbose_name="remark", blank=True, null=True),
|
||||
),
|
||||
],
|
||||
bases=("cotisations.baseinvoice",),
|
||||
options={
|
||||
"permissions": (
|
||||
("view_custominvoice", "Can view a custom invoice object"),
|
||||
)
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="CostEstimate",
|
||||
fields=[
|
||||
(
|
||||
"custominvoice_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="cotisations.CustomInvoice",
|
||||
),
|
||||
),
|
||||
(
|
||||
"validity",
|
||||
models.DurationField(
|
||||
verbose_name="period of validity", help_text="DD HH:MM:SS"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"permissions": (
|
||||
("view_costestimate", "Can view a cost estimate object"),
|
||||
)
|
||||
},
|
||||
bases=("cotisations.custominvoice",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Vente",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"number",
|
||||
models.IntegerField(
|
||||
validators=[django.core.validators.MinValueValidator(1)],
|
||||
verbose_name="amount",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=255, verbose_name="article")),
|
||||
(
|
||||
"prix",
|
||||
models.DecimalField(
|
||||
max_digits=5, decimal_places=2, verbose_name="price"
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_connection",
|
||||
models.PositiveIntegerField(
|
||||
default=0, verbose_name="duration of the connection (in months)"
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_days_connection",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name="duration of the connection (in days, will be added to duration in months)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_membership",
|
||||
models.PositiveIntegerField(
|
||||
default=0, verbose_name="duration of the membership (in months)"
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_days_membership",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name="duration of the membership (in days, will be added to duration in months)",
|
||||
),
|
||||
),
|
||||
],
|
||||
bases=(
|
||||
re2o.mixins.RevMixin,
|
||||
re2o.mixins.AclMixin,
|
||||
models.Model,
|
||||
),
|
||||
options={
|
||||
"permissions": (
|
||||
("view_vente", "Can view a purchase object"),
|
||||
("change_all_vente", "Can edit all the previous purchases"),
|
||||
),
|
||||
"verbose_name": "purchase",
|
||||
"verbose_name_plural": "purchases",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Article",
|
||||
bases=(
|
||||
re2o.mixins.RevMixin,
|
||||
re2o.mixins.AclMixin,
|
||||
models.Model,
|
||||
),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"name",
|
||||
models.CharField(max_length=255, verbose_name="designation"),
|
||||
),
|
||||
(
|
||||
"prix",
|
||||
models.DecimalField(
|
||||
max_digits=5, decimal_places=2, verbose_name="unit price"
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_connection",
|
||||
models.PositiveIntegerField(
|
||||
verbose_name="duration of the connection (in months)"
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_days_connection",
|
||||
models.PositiveIntegerField(
|
||||
verbose_name="duration of the connection (in days, will be added to duration in months)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_membership",
|
||||
models.PositiveIntegerField(
|
||||
verbose_name="duration of the membership (in months)"
|
||||
),
|
||||
),
|
||||
(
|
||||
"duration_days_membership",
|
||||
models.PositiveIntegerField(
|
||||
verbose_name="duration of the membership (in days, will be added to duration in months)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"need_membership",
|
||||
models.BooleanField(
|
||||
default=True, verbose_name="need membership to be purchased"
|
||||
),
|
||||
),
|
||||
(
|
||||
"type_user",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("Adherent", "Member"),
|
||||
("Club", "Club"),
|
||||
("All", "Both of them"),
|
||||
],
|
||||
default="All",
|
||||
max_length=255,
|
||||
verbose_name="type of users concerned",
|
||||
),
|
||||
),
|
||||
(
|
||||
"available_for_everyone",
|
||||
models.BooleanField(
|
||||
default=False, verbose_name="is available for every user"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"permissions": (
|
||||
("view_article", "Can view an article object"),
|
||||
("buy_every_article", "Can buy every article"),
|
||||
),
|
||||
"verbose_name": "article",
|
||||
"verbose_name_plural": "articles",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Banque",
|
||||
bases=(
|
||||
re2o.mixins.RevMixin,
|
||||
re2o.mixins.AclMixin,
|
||||
models.Model,
|
||||
),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=255)),
|
||||
],
|
||||
options={
|
||||
"permissions": (("view_banque", "Can view a bank object"),),
|
||||
"verbose_name": "bank",
|
||||
"verbose_name_plural": "banks",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Paiement",
|
||||
bases=(
|
||||
re2o.mixins.RevMixin,
|
||||
re2o.mixins.AclMixin,
|
||||
models.Model,
|
||||
),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("moyen", models.CharField(max_length=255, verbose_name="method")),
|
||||
(
|
||||
"available_for_everyone",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
verbose_name="is available for every user",
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_balance",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
editable=False,
|
||||
verbose_name="is user balance",
|
||||
help_text="There should be only one balance payment method.",
|
||||
validators=[cotisations.models.check_no_balance],
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"permissions": (
|
||||
("view_paiement", "Can view a payment method object"),
|
||||
("use_every_payment", "Can use every payment method"),
|
||||
),
|
||||
"verbose_name": "payment method",
|
||||
"verbose_name_plural": "payment methods",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Cotisation",
|
||||
bases=(
|
||||
re2o.mixins.RevMixin,
|
||||
re2o.mixins.AclMixin,
|
||||
models.Model,
|
||||
),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date_start_con",
|
||||
models.DateTimeField(verbose_name="start date for the connection"),
|
||||
),
|
||||
(
|
||||
"date_end_con",
|
||||
models.DateTimeField(verbose_name="end date for the connection"),
|
||||
),
|
||||
(
|
||||
"date_start_memb",
|
||||
models.DateTimeField(verbose_name="start date for the membership"),
|
||||
),
|
||||
(
|
||||
"date_end_memb",
|
||||
models.DateTimeField(verbose_name="end date for the membership"),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"permissions": (
|
||||
("view_cotisation", "Can view a subscription object"),
|
||||
("change_all_cotisation", "Can edit the previous subscriptions"),
|
||||
),
|
||||
"verbose_name": "subscription",
|
||||
"verbose_name_plural": "subscriptions",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="BalancePayment",
|
||||
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"minimum_balance",
|
||||
models.DecimalField(
|
||||
verbose_name="minimum balance",
|
||||
help_text="The minimal amount of money allowed for the balance at the end of a payment. You can specify a negative amount.",
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"maximum_balance",
|
||||
models.DecimalField(
|
||||
verbose_name="maximum balance",
|
||||
help_text="The maximal amount of money allowed for the balance.",
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
default=50,
|
||||
blank=True,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"credit_balance_allowed",
|
||||
models.BooleanField(
|
||||
verbose_name="allow user to credit their balance", default=False
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "user balance"},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="ChequePayment",
|
||||
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "cheque"},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="ComnpayPayment",
|
||||
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"payment_credential",
|
||||
models.CharField(
|
||||
max_length=255,
|
||||
default="",
|
||||
blank=True,
|
||||
verbose_name="ComNpay VAT Number",
|
||||
),
|
||||
),
|
||||
(
|
||||
"payment_pass",
|
||||
re2o.aes_field.AESEncryptedField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="ComNpay secret key",
|
||||
),
|
||||
),
|
||||
(
|
||||
"minimum_payment",
|
||||
models.DecimalField(
|
||||
verbose_name="minimum payment",
|
||||
help_text="The minimal amount of money you have to use when paying with ComNpay.",
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
default=1,
|
||||
),
|
||||
),
|
||||
(
|
||||
"production",
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
verbose_name="production mode enabled (production URL, instead of homologation)",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "ComNpay"},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="FreePayment",
|
||||
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "Free payment"},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="NotePayment",
|
||||
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("server", models.CharField(max_length=255, verbose_name="server")),
|
||||
("port", models.PositiveIntegerField(blank=True, null=True)),
|
||||
("id_note", models.PositiveIntegerField(blank=True, null=True)),
|
||||
],
|
||||
options={"verbose_name": "NoteKfet"},
|
||||
),
|
||||
]
|
500
cotisations/migrations/0002_foreign_keys.py
Normal file
500
cotisations/migrations/0002_foreign_keys.py
Normal file
|
@ -0,0 +1,500 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-12-30 15:27
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cotisations', '0001_model_creation'),
|
||||
]
|
||||
replaces = [
|
||||
("users", "0001_initial"),
|
||||
("users", "0002_auto_20160630_2301"),
|
||||
("users", "0003_listrights_rights"),
|
||||
("users", "0004_auto_20160701_2312"),
|
||||
("users", "0005_auto_20160702_0006"),
|
||||
("users", "0006_ban"),
|
||||
("users", "0007_auto_20160702_2322"),
|
||||
("users", "0008_user_registered"),
|
||||
("users", "0009_user_room"),
|
||||
("users", "0010_auto_20160703_1226"),
|
||||
("users", "0011_auto_20160703_1227"),
|
||||
("users", "0012_auto_20160703_1230"),
|
||||
("users", "0013_auto_20160704_1547"),
|
||||
("users", "0014_auto_20160704_1548"),
|
||||
("users", "0015_whitelist"),
|
||||
("users", "0016_auto_20160706_1220"),
|
||||
("users", "0017_auto_20160707_0105"),
|
||||
("users", "0018_auto_20160707_0115"),
|
||||
("users", "0019_auto_20160708_1633"),
|
||||
("users", "0020_request"),
|
||||
("users", "0021_ldapuser"),
|
||||
("users", "0022_ldapuser_sambasid"),
|
||||
("users", "0023_auto_20160724_1908"),
|
||||
("users", "0024_remove_ldapuser_mac_list"),
|
||||
("users", "0025_listshell"),
|
||||
("users", "0026_user_shell"),
|
||||
("users", "0027_auto_20160726_0216"),
|
||||
("users", "0028_auto_20160726_0227"),
|
||||
("users", "0029_auto_20160726_0229"),
|
||||
("users", "0030_auto_20160726_0357"),
|
||||
("users", "0031_auto_20160726_0359"),
|
||||
("users", "0032_auto_20160727_2122"),
|
||||
("users", "0033_remove_ldapuser_loginshell"),
|
||||
("users", "0034_auto_20161018_0037"),
|
||||
("users", "0035_auto_20161018_0046"),
|
||||
("users", "0036_auto_20161022_2146"),
|
||||
("users", "0037_auto_20161028_1906"),
|
||||
("users", "0038_auto_20161031_0258"),
|
||||
("users", "0039_auto_20161119_0033"),
|
||||
("users", "0040_auto_20161119_1709"),
|
||||
("users", "0041_listright_details"),
|
||||
("users", "0042_auto_20161126_2028"),
|
||||
("users", "0043_auto_20161224_1156"),
|
||||
("users", "0043_ban_state"),
|
||||
("users", "0044_user_ssh_public_key"),
|
||||
("users", "0045_merge"),
|
||||
("users", "0046_auto_20170617_1433"),
|
||||
("users", "0047_auto_20170618_0156"),
|
||||
("users", "0048_auto_20170618_0210"),
|
||||
("users", "0049_auto_20170618_1424"),
|
||||
("users", "0050_serviceuser_comment"),
|
||||
("users", "0051_user_telephone"),
|
||||
("users", "0052_ldapuser_shadowexpire"),
|
||||
("users", "0053_auto_20170626_2105"),
|
||||
("users", "0054_auto_20170626_2219"),
|
||||
("users", "0055_auto_20171003_0556"),
|
||||
("users", "0056_auto_20171015_2033"),
|
||||
("users", "0057_auto_20171023_0301"),
|
||||
("users", "0058_auto_20171025_0154"),
|
||||
("users", "0059_auto_20171025_1854"),
|
||||
("users", "0060_auto_20171120_0317"),
|
||||
("users", "0061_auto_20171230_2033"),
|
||||
("users", "0062_auto_20171231_0056"),
|
||||
("users", "0063_auto_20171231_0140"),
|
||||
("users", "0064_auto_20171231_0150"),
|
||||
("users", "0065_auto_20171231_2053"),
|
||||
("users", "0066_grouppermissions"),
|
||||
("users", "0067_serveurpermission"),
|
||||
("users", "0068_auto_20180107_2245"),
|
||||
("users", "0069_club_mailing"),
|
||||
("users", "0070_auto_20180324_1906"),
|
||||
("users", "0071_auto_20180415_1252"),
|
||||
("users", "0072_auto_20180426_2021"),
|
||||
("users", "0073_auto_20180629_1614"),
|
||||
("users", "0074_auto_20180810_2104"),
|
||||
("users", "0074_auto_20180814_1059"),
|
||||
("users", "0075_merge_20180815_2202"),
|
||||
("users", "0076_auto_20180818_1321"),
|
||||
("users", "0077_auto_20180824_1750"),
|
||||
("users", "0078_auto_20181011_1405"),
|
||||
("users", "0079_auto_20181228_2039"),
|
||||
("users", "0080_auto_20190108_1726"),
|
||||
("users", "0081_auto_20190317_0302"),
|
||||
("users", "0082_auto_20190908_1338"),
|
||||
("users", "0083_user_shortcuts_enabled"),
|
||||
("users", "0084_auto_20191120_0159"),
|
||||
("users", "0085_user_email_state"),
|
||||
("users", "0086_user_email_change_date"),
|
||||
("users", "0087_request_email"),
|
||||
("users", "0088_auto_20200417_2312"),
|
||||
("users", "0089_auto_20200418_0112"),
|
||||
("users", "0090_auto_20200421_1825"),
|
||||
("users", "0091_auto_20200423_1256"),
|
||||
("users", "0092_auto_20200502_0057"),
|
||||
("users", "0093_user_profile_image"),
|
||||
("users", "0094_remove_user_profile_image"),
|
||||
("users", "0095_user_theme"),
|
||||
("users", "0096_auto_20210110_1811"),
|
||||
("cotisations", "0001_initial"),
|
||||
("cotisations", "0002_remove_facture_article"),
|
||||
("cotisations", "0003_auto_20160702_1448"),
|
||||
("cotisations", "0004_auto_20160702_1528"),
|
||||
("cotisations", "0005_auto_20160702_1532"),
|
||||
("cotisations", "0006_auto_20160702_1534"),
|
||||
("cotisations", "0007_auto_20160702_1543"),
|
||||
("cotisations", "0008_auto_20160702_1614"),
|
||||
("cotisations", "0009_remove_cotisation_user"),
|
||||
("cotisations", "0010_auto_20160702_1840"),
|
||||
("cotisations", "0011_auto_20160702_1911"),
|
||||
("cotisations", "0012_auto_20160704_0118"),
|
||||
("cotisations", "0013_auto_20160711_2240"),
|
||||
("cotisations", "0014_auto_20160712_0245"),
|
||||
("cotisations", "0015_auto_20160714_2142"),
|
||||
("cotisations", "0016_auto_20160715_0110"),
|
||||
("cotisations", "0017_auto_20170718_2329"),
|
||||
("cotisations", "0018_paiement_type_paiement"),
|
||||
("cotisations", "0019_auto_20170819_0055"),
|
||||
("cotisations", "0020_auto_20170819_0057"),
|
||||
("cotisations", "0021_auto_20170819_0104"),
|
||||
("cotisations", "0022_auto_20170824_0128"),
|
||||
("cotisations", "0023_auto_20170902_1303"),
|
||||
("cotisations", "0024_auto_20171015_2033"),
|
||||
("cotisations", "0025_article_type_user"),
|
||||
("cotisations", "0026_auto_20171028_0126"),
|
||||
("cotisations", "0027_auto_20171029_1156"),
|
||||
("cotisations", "0028_auto_20171231_0007"),
|
||||
("cotisations", "0029_auto_20180414_2056"),
|
||||
("cotisations", "0030_custom_payment"),
|
||||
("cotisations", "0031_comnpaypayment_production"),
|
||||
("cotisations", "0032_custom_invoice"),
|
||||
("cotisations", "0033_auto_20180818_1319"),
|
||||
("cotisations", "0034_auto_20180831_1532"),
|
||||
("cotisations", "0035_notepayment"),
|
||||
("cotisations", "0036_custominvoice_remark"),
|
||||
("cotisations", "0037_costestimate"),
|
||||
("cotisations", "0038_auto_20181231_1657"),
|
||||
("cotisations", "0039_freepayment"),
|
||||
("cotisations", "0040_auto_20191002_2335"),
|
||||
("cotisations", "0041_auto_20191103_2131"),
|
||||
("cotisations", "0042_auto_20191120_0159"),
|
||||
("cotisations", "0043_separation_membership_connection_p1"),
|
||||
("cotisations", "0044_separation_membership_connection_p2"),
|
||||
("cotisations", "0045_separation_membership_connection_p3"),
|
||||
("cotisations", "0046_article_need_membership"),
|
||||
("cotisations", "0047_article_need_membership_init"),
|
||||
("cotisations", "0048_auto_20201017_0018"),
|
||||
("cotisations", "0049_auto_20201102_2305"),
|
||||
("cotisations", "0050_auto_20201102_2342"),
|
||||
("cotisations", "0051_auto_20201228_1636"),
|
||||
("machines", "0001_initial"),
|
||||
("machines", "0002_auto_20160703_1444"),
|
||||
("machines", "0003_auto_20160703_1450"),
|
||||
("machines", "0004_auto_20160703_1451"),
|
||||
("machines", "0005_auto_20160703_1523"),
|
||||
("machines", "0006_auto_20160703_1813"),
|
||||
("machines", "0007_auto_20160703_1816"),
|
||||
("machines", "0008_remove_interface_ipv6"),
|
||||
("machines", "0009_auto_20160703_2358"),
|
||||
("machines", "0010_auto_20160704_0104"),
|
||||
("machines", "0011_auto_20160704_0105"),
|
||||
("machines", "0012_auto_20160704_0118"),
|
||||
("machines", "0013_auto_20160705_1014"),
|
||||
("machines", "0014_auto_20160706_1220"),
|
||||
("machines", "0015_auto_20160707_0105"),
|
||||
("machines", "0016_auto_20160708_1633"),
|
||||
("machines", "0017_auto_20160708_1645"),
|
||||
("machines", "0018_auto_20160708_1813"),
|
||||
("machines", "0019_auto_20160718_1141"),
|
||||
("machines", "0020_auto_20160718_1849"),
|
||||
("machines", "0021_auto_20161006_1943"),
|
||||
("machines", "0022_auto_20161011_1829"),
|
||||
("machines", "0023_iplist_ip_type"),
|
||||
("machines", "0024_machinetype_need_infra"),
|
||||
("machines", "0025_auto_20161023_0038"),
|
||||
("machines", "0026_auto_20161026_1348"),
|
||||
("machines", "0027_alias"),
|
||||
("machines", "0028_iptype_domaine_ip"),
|
||||
("machines", "0029_iptype_domaine_range"),
|
||||
("machines", "0030_auto_20161118_1730"),
|
||||
("machines", "0031_auto_20161119_1709"),
|
||||
("machines", "0032_auto_20161119_1850"),
|
||||
("machines", "0033_extension_need_infra"),
|
||||
("machines", "0034_iplist_need_infra"),
|
||||
("machines", "0035_auto_20161224_1201"),
|
||||
("machines", "0036_auto_20161224_1204"),
|
||||
("machines", "0037_domain_cname"),
|
||||
("machines", "0038_auto_20161224_1721"),
|
||||
("machines", "0039_auto_20161224_1732"),
|
||||
("machines", "0040_remove_interface_dns"),
|
||||
("machines", "0041_remove_ns_interface"),
|
||||
("machines", "0042_ns_ns"),
|
||||
("machines", "0043_auto_20170721_0350"),
|
||||
("machines", "0044_auto_20170808_0233"),
|
||||
("machines", "0045_auto_20170808_0348"),
|
||||
("machines", "0046_auto_20170808_1423"),
|
||||
("machines", "0047_auto_20170809_0606"),
|
||||
("machines", "0048_auto_20170823_2315"),
|
||||
("machines", "0049_vlan"),
|
||||
("machines", "0050_auto_20170826_0022"),
|
||||
("machines", "0051_iptype_vlan"),
|
||||
("machines", "0052_auto_20170828_2322"),
|
||||
("machines", "0053_text"),
|
||||
("machines", "0054_text_zone"),
|
||||
("machines", "0055_nas"),
|
||||
("machines", "0056_nas_port_access_mode"),
|
||||
("machines", "0057_nas_autocapture_mac"),
|
||||
("machines", "0058_auto_20171002_0350"),
|
||||
("machines", "0059_iptype_prefix_v6"),
|
||||
("machines", "0060_iptype_ouverture_ports"),
|
||||
("machines", "0061_auto_20171015_2033"),
|
||||
("machines", "0062_extension_origin_v6"),
|
||||
("machines", "0063_auto_20171020_0040"),
|
||||
("machines", "0064_auto_20171115_0253"),
|
||||
("machines", "0065_auto_20171115_1514"),
|
||||
("machines", "0066_srv"),
|
||||
("machines", "0067_auto_20171116_0152"),
|
||||
("machines", "0068_auto_20171116_0252"),
|
||||
("machines", "0069_auto_20171116_0822"),
|
||||
("machines", "0070_auto_20171231_1947"),
|
||||
("machines", "0071_auto_20171231_2100"),
|
||||
("machines", "0072_auto_20180108_1822"),
|
||||
("machines", "0073_auto_20180128_2203"),
|
||||
("machines", "0074_auto_20180129_0352"),
|
||||
("machines", "0075_auto_20180130_0052"),
|
||||
("machines", "0076_auto_20180130_1623"),
|
||||
("machines", "0077_auto_20180409_2243"),
|
||||
("machines", "0078_auto_20180415_1252"),
|
||||
("machines", "0079_auto_20180416_0107"),
|
||||
("machines", "0080_auto_20180502_2334"),
|
||||
("machines", "0081_auto_20180521_1413"),
|
||||
("machines", "0082_auto_20180525_2209"),
|
||||
("machines", "0083_remove_duplicate_rights"),
|
||||
("machines", "0084_dname"),
|
||||
("machines", "0085_sshfingerprint"),
|
||||
("machines", "0086_role"),
|
||||
("machines", "0087_dnssec"),
|
||||
("machines", "0088_iptype_prefix_v6_length"),
|
||||
("machines", "0089_auto_20180805_1148"),
|
||||
("machines", "0090_auto_20180805_1459"),
|
||||
("machines", "0091_auto_20180806_2310"),
|
||||
("machines", "0092_auto_20180807_0926"),
|
||||
("machines", "0093_auto_20180807_1115"),
|
||||
("machines", "0094_auto_20180815_1918"),
|
||||
("machines", "0095_auto_20180919_2225"),
|
||||
("machines", "0096_auto_20181013_1417"),
|
||||
("machines", "0097_extension_dnssec"),
|
||||
("machines", "0098_auto_20190102_1745"),
|
||||
("machines", "0099_role_recursive_dns"),
|
||||
("machines", "0100_auto_20190102_1753"),
|
||||
("machines", "0101_auto_20190108_1623"),
|
||||
("machines", "0102_auto_20190303_1611"),
|
||||
("machines", "0103_auto_20191002_2222"),
|
||||
("machines", "0104_auto_20191002_2231"),
|
||||
("machines", "0105_dname_ttl"),
|
||||
("machines", "0106_auto_20191120_0159"),
|
||||
("machines", "0107_fix_lowercase_domain"),
|
||||
("machines", "0108_ipv6list_active"),
|
||||
("preferences", "0001_initial"),
|
||||
("preferences", "0002_auto_20170625_1923"),
|
||||
("preferences", "0003_optionaluser_solde_negatif"),
|
||||
("preferences", "0004_assooption_services"),
|
||||
("preferences", "0005_auto_20170824_0139"),
|
||||
("preferences", "0006_auto_20170824_0143"),
|
||||
("preferences", "0007_auto_20170824_2056"),
|
||||
("preferences", "0008_auto_20170824_2122"),
|
||||
("preferences", "0009_assooption_utilisateur_asso"),
|
||||
("preferences", "0010_auto_20170825_0459"),
|
||||
("preferences", "0011_auto_20170825_2307"),
|
||||
("preferences", "0012_generaloption_req_expire_hrs"),
|
||||
("preferences", "0013_generaloption_site_name"),
|
||||
("preferences", "0014_generaloption_email_from"),
|
||||
("preferences", "0015_optionaltopologie_radius_general_policy"),
|
||||
("preferences", "0016_auto_20170902_1520"),
|
||||
("preferences", "0017_mailmessageoption"),
|
||||
("preferences", "0018_optionaltopologie_mac_autocapture"),
|
||||
("preferences", "0019_remove_optionaltopologie_mac_autocapture"),
|
||||
("preferences", "0020_optionalmachine_ipv6"),
|
||||
("preferences", "0021_auto_20171015_1741"),
|
||||
("preferences", "0022_auto_20171015_1758"),
|
||||
("preferences", "0023_auto_20171015_2033"),
|
||||
("preferences", "0024_optionaluser_all_can_create"),
|
||||
("preferences", "0025_auto_20171231_2142"),
|
||||
("preferences", "0025_generaloption_general_message"),
|
||||
("preferences", "0026_auto_20171216_0401"),
|
||||
("preferences", "0027_merge_20180106_2019"),
|
||||
("preferences", "0028_assooption_description"),
|
||||
("preferences", "0028_auto_20180111_1129"),
|
||||
("preferences", "0028_auto_20180128_2203"),
|
||||
("preferences", "0029_auto_20180111_1134"),
|
||||
("preferences", "0029_auto_20180318_0213"),
|
||||
("preferences", "0029_auto_20180318_1005"),
|
||||
("preferences", "0030_auto_20180111_2346"),
|
||||
("preferences", "0030_merge_20180320_1419"),
|
||||
("preferences", "0031_auto_20180323_0218"),
|
||||
("preferences", "0031_optionaluser_self_adhesion"),
|
||||
("preferences", "0032_optionaluser_min_online_payment"),
|
||||
("preferences", "0032_optionaluser_shell_default"),
|
||||
("preferences", "0033_accueiloption"),
|
||||
("preferences", "0033_generaloption_gtu_sum_up"),
|
||||
("preferences", "0034_auto_20180114_2025"),
|
||||
("preferences", "0034_auto_20180416_1120"),
|
||||
("preferences", "0035_auto_20180114_2132"),
|
||||
("preferences", "0035_optionaluser_allow_self_subscription"),
|
||||
("preferences", "0036_auto_20180114_2141"),
|
||||
("preferences", "0037_auto_20180114_2156"),
|
||||
("preferences", "0038_auto_20180114_2209"),
|
||||
("preferences", "0039_auto_20180115_0003"),
|
||||
("preferences", "0040_auto_20180129_1745"),
|
||||
("preferences", "0041_merge_20180130_0052"),
|
||||
("preferences", "0042_auto_20180222_1743"),
|
||||
("preferences", "0043_optionalmachine_create_machine"),
|
||||
("preferences", "0044_remove_payment_pass"),
|
||||
("preferences", "0045_remove_unused_payment_fields"),
|
||||
("preferences", "0046_optionaluser_mail_extension"),
|
||||
("preferences", "0047_mailcontact"),
|
||||
("preferences", "0048_auto_20180811_1515"),
|
||||
("preferences", "0049_optionaluser_self_change_shell"),
|
||||
("preferences", "0050_auto_20180818_1329"),
|
||||
("preferences", "0051_auto_20180919_2225"),
|
||||
("preferences", "0052_optionaluser_delete_notyetactive"),
|
||||
("preferences", "0053_optionaluser_self_change_room"),
|
||||
("preferences", "0055_generaloption_main_site_url"),
|
||||
("preferences", "0056_1_radiusoption"),
|
||||
("preferences", "0056_2_radiusoption"),
|
||||
("preferences", "0056_3_radiusoption"),
|
||||
("preferences", "0056_4_radiusoption"),
|
||||
("preferences", "0057_optionaluser_all_users_active"),
|
||||
("preferences", "0058_auto_20190108_1650"),
|
||||
("preferences", "0059_auto_20190120_1739"),
|
||||
("preferences", "0060_auto_20190712_1821"),
|
||||
("preferences", "0061_optionaluser_allow_archived_connexion"),
|
||||
("preferences", "0062_auto_20190910_1909"),
|
||||
("preferences", "0063_mandate"),
|
||||
("preferences", "0064_auto_20191008_1335"),
|
||||
("preferences", "0065_auto_20191010_1227"),
|
||||
("preferences", "0066_optionalmachine_default_dns_ttl"),
|
||||
("preferences", "0067_auto_20191120_0159"),
|
||||
("preferences", "0068_optionaluser_allow_set_password_during_user_creation"),
|
||||
("preferences", "0069_optionaluser_disable_emailnotyetconfirmed"),
|
||||
("preferences", "0070_auto_20200419_0225"),
|
||||
("preferences", "0071_optionaluser_self_change_pseudo"),
|
||||
("topologie", "0001_initial"),
|
||||
("topologie", "0002_auto_20160703_1118"),
|
||||
("topologie", "0003_room"),
|
||||
("topologie", "0004_auto_20160703_1122"),
|
||||
("topologie", "0005_auto_20160703_1123"),
|
||||
("topologie", "0006_auto_20160703_1129"),
|
||||
("topologie", "0007_auto_20160703_1148"),
|
||||
("topologie", "0008_port_room"),
|
||||
("topologie", "0009_auto_20160703_1200"),
|
||||
("topologie", "0010_auto_20160704_2148"),
|
||||
("topologie", "0011_auto_20160704_2153"),
|
||||
("topologie", "0012_port_machine_interface"),
|
||||
("topologie", "0013_port_related"),
|
||||
("topologie", "0014_auto_20160706_1238"),
|
||||
("topologie", "0015_auto_20160706_1452"),
|
||||
("topologie", "0016_auto_20160706_1531"),
|
||||
("topologie", "0017_auto_20160718_1141"),
|
||||
("topologie", "0018_room_details"),
|
||||
("topologie", "0019_auto_20161026_1348"),
|
||||
("topologie", "0020_auto_20161119_0033"),
|
||||
("topologie", "0021_port_radius"),
|
||||
("topologie", "0022_auto_20161211_1622"),
|
||||
("topologie", "0023_auto_20170817_1654"),
|
||||
("topologie", "0023_auto_20170826_1530"),
|
||||
("topologie", "0024_auto_20170818_1021"),
|
||||
("topologie", "0024_auto_20170826_1800"),
|
||||
("topologie", "0025_merge_20170902_1242"),
|
||||
("topologie", "0026_auto_20170902_1245"),
|
||||
("topologie", "0027_auto_20170905_1442"),
|
||||
("topologie", "0028_auto_20170913_1503"),
|
||||
("topologie", "0029_auto_20171002_0334"),
|
||||
("topologie", "0030_auto_20171004_0235"),
|
||||
("topologie", "0031_auto_20171015_2033"),
|
||||
("topologie", "0032_auto_20171026_0338"),
|
||||
("topologie", "0033_auto_20171231_1743"),
|
||||
("topologie", "0034_borne"),
|
||||
("topologie", "0035_auto_20180324_0023"),
|
||||
("topologie", "0036_transferborne"),
|
||||
("topologie", "0037_auto_20180325_0127"),
|
||||
("topologie", "0038_transfersw"),
|
||||
("topologie", "0039_port_new_switch"),
|
||||
("topologie", "0040_transferports"),
|
||||
("topologie", "0041_transferportsw"),
|
||||
("topologie", "0042_transferswitch"),
|
||||
("topologie", "0043_renamenewswitch"),
|
||||
("topologie", "0044_auto_20180326_0002"),
|
||||
("topologie", "0045_auto_20180326_0123"),
|
||||
("topologie", "0046_auto_20180326_0129"),
|
||||
("topologie", "0047_ap_machine"),
|
||||
("topologie", "0048_ap_machine"),
|
||||
("topologie", "0049_switchs_machine"),
|
||||
("topologie", "0050_port_new_switch"),
|
||||
("topologie", "0051_switchs_machine"),
|
||||
("topologie", "0052_transferports"),
|
||||
("topologie", "0053_finalsw"),
|
||||
("topologie", "0054_auto_20180326_1742"),
|
||||
("topologie", "0055_auto_20180329_0431"),
|
||||
("topologie", "0056_building_switchbay"),
|
||||
("topologie", "0057_auto_20180408_0316"),
|
||||
("topologie", "0058_remove_switch_location"),
|
||||
("topologie", "0059_auto_20180415_2249"),
|
||||
("topologie", "0060_server"),
|
||||
("topologie", "0061_portprofile"),
|
||||
("topologie", "0062_auto_20180815_1918"),
|
||||
("topologie", "0063_auto_20180919_2225"),
|
||||
("topologie", "0064_switch_automatic_provision"),
|
||||
("topologie", "0065_auto_20180927_1836"),
|
||||
("topologie", "0066_modelswitch_commercial_name"),
|
||||
("topologie", "0067_auto_20181230_1819"),
|
||||
("topologie", "0068_auto_20190102_1758"),
|
||||
("topologie", "0069_auto_20190108_1439"),
|
||||
("topologie", "0070_auto_20190218_1743"),
|
||||
("topologie", "0071_auto_20190218_1936"),
|
||||
("topologie", "0072_auto_20190720_2318"),
|
||||
("topologie", "0073_auto_20191120_0159"),
|
||||
("topologie", "0074_auto_20200419_1640"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='balancepayment',
|
||||
name='payment',
|
||||
field=models.OneToOneField(default=None, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_balance', to='cotisations.Paiement'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='chequepayment',
|
||||
name='payment',
|
||||
field=models.OneToOneField(default=None, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_cheque', to='cotisations.Paiement'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='comnpaypayment',
|
||||
name='payment',
|
||||
field=models.OneToOneField(default=None, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_comnpay', to='cotisations.Paiement'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='costestimate',
|
||||
name='final_invoice',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='origin_cost_estimate', to='cotisations.CustomInvoice'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cotisation',
|
||||
name='vente',
|
||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='cotisations.Vente', verbose_name='purchase'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='facture',
|
||||
name='banque',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cotisations.Banque'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='facture',
|
||||
name='paiement',
|
||||
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, to='cotisations.Paiement'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='facture',
|
||||
name='user',
|
||||
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='freepayment',
|
||||
name='payment',
|
||||
field=models.OneToOneField(default=None, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_free', to='cotisations.Paiement'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='notepayment',
|
||||
name='payment',
|
||||
field=models.OneToOneField(default=None, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_note', to='cotisations.Paiement'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vente',
|
||||
name='facture',
|
||||
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='cotisations.BaseInvoice', verbose_name='invoice'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
19
cotisations/migrations/0003_auto_20210124_1105.py
Normal file
19
cotisations/migrations/0003_auto_20210124_1105.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2021-01-24 10:05
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0002_foreign_keys'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='baseinvoice',
|
||||
options={'permissions': (('view_baseinvoice', 'Can view an base invoice object'),)},
|
||||
),
|
||||
]
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-09-20 17:19
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0042_auto_20191120_0159'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# migrations.RemoveField(
|
||||
# model_name='article',
|
||||
# name='duration',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='article',
|
||||
# name='duration_days',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='article',
|
||||
# name='type_cotisation',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='cotisation',
|
||||
# name='date_end',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='cotisation',
|
||||
# name='date_start',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='cotisation',
|
||||
# name='type_cotisation',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='vente',
|
||||
# name='duration',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='vente',
|
||||
# name='duration_days',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='vente',
|
||||
# name='type_cotisation',
|
||||
# ),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='duration_connection',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the connection (in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='duration_days_connection',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the connection (in days, will be added to duration in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='duration_days_membership',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the membership (in days, will be added to duration in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='duration_membership',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the membership (in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cotisation',
|
||||
name='date_end_con',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='end date for the connection'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cotisation',
|
||||
name='date_end_memb',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='end date for the membership'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cotisation',
|
||||
name='date_start_con',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='start date for the connection'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cotisation',
|
||||
name='date_start_memb',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='start date for the membership'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vente',
|
||||
name='duration_connection',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='duration of the connection (in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vente',
|
||||
name='duration_days_connection',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the connection (in days, will be added to duration in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vente',
|
||||
name='duration_days_membership',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the membership (in days, will be added to duration in months)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vente',
|
||||
name='duration_membership',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='duration of the membership (in months)'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,140 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-09-20 17:19
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0043_separation_membership_connection_p1'),
|
||||
]
|
||||
|
||||
def split_dates(apps, schema_editor):
|
||||
db_alias = schema_editor.connection.alias
|
||||
cotisation = apps.get_model("cotisations", "Cotisation")
|
||||
cotisations = cotisation.objects.using(db_alias).all()
|
||||
for cotis in cotisations:
|
||||
cotis.date_start_con = cotis.date_start
|
||||
cotis.date_start_memb = cotis.date_start
|
||||
cotis.date_end_con = cotis.date_end
|
||||
cotis.date_end_memb = cotis.date_end
|
||||
if cotis.type_cotisation == 'Connexion':
|
||||
cotis.date_end_memb = cotis.date_start
|
||||
if cotis.type_cotisation == 'Adhesion':
|
||||
cotis.date_end_con = cotis.date_start
|
||||
cotis.save()
|
||||
|
||||
|
||||
|
||||
def split_duration_articles_and_ventes(apps, schema_editor):
|
||||
def split_duration(e):
|
||||
e.duration_membership = e.duration
|
||||
e.duration_connection = e.duration
|
||||
e.duration_days_membership = e.duration_days
|
||||
e.duration_days_connection = e.duration_days
|
||||
if e.type_cotisation == 'Connexion':
|
||||
e.duration_membership = 0
|
||||
e.duration_days_membership = 0
|
||||
if e.type_cotisation == 'Adhesion':
|
||||
e.duration_connection = 0
|
||||
e.duration_days_connection = 0
|
||||
e.save()
|
||||
db_alias = schema_editor.connection.alias
|
||||
article = apps.get_model("cotisations", "Article")
|
||||
vente = apps.get_model("cotisations", "Vente")
|
||||
for a in article.objects.using(db_alias).all():
|
||||
split_duration(a)
|
||||
for v in vente.objects.using(db_alias).all():
|
||||
split_duration(v)
|
||||
|
||||
def unsplit_dates(apps, schema_editor):
|
||||
db_alias = schema_editor.connection.alias
|
||||
cotisation = apps.get_model("cotisations", "Cotisation")
|
||||
cotisations = cotisation.objects.using(db_alias).all()
|
||||
for cotis in cotisations:
|
||||
connection = cotis.date_start_con != cotis.date_end_con
|
||||
adhesion = cotis.date_start_memb != cotis.date_end_memb
|
||||
cotis.date_start = cotis.date_start_con
|
||||
cotis.date_end = max(cotis.date_end_con, cotis.date_end_memb)
|
||||
if connection:
|
||||
cotis.type_cotisation = 'Connexion'
|
||||
if adhesion:
|
||||
cotis.type_cotisation = 'Adhesion'
|
||||
if connection and adhesion:
|
||||
cotis.type_cotisation = 'All'
|
||||
if not (connection or adhesion):
|
||||
cotis.type_cotisation = None
|
||||
cotis.save()
|
||||
|
||||
|
||||
|
||||
def unsplit_duration_articles_and_ventes(apps, schema_editor):
|
||||
def unsplit_duration(e):
|
||||
e.duration = max(e.duration_membership, e.duration_connection)
|
||||
e.duration_days = max(e.duration_days_membership, e.duration_days_connection)
|
||||
connection = not (((e.duration_connection == 0) or (e.duration_connection__isnull)) and \
|
||||
((e.duration_days_connection == 0) or (e.duration_days_connection__isnull)))
|
||||
membership = not (((e.duration_membership == 0) or (e.duration_membership__isnull)) and \
|
||||
((e.duration_days_membership == 0) or (e.duration_days_membership__isnull)))
|
||||
if connection:
|
||||
e.type_cotisation = 'Connection'
|
||||
if membership:
|
||||
e.type_cotisation = 'Adhesion'
|
||||
if connection and membership:
|
||||
e.type_cotisation = 'All'
|
||||
if not (connection or membership):
|
||||
e.type_cotisation = None
|
||||
e.save()
|
||||
db_alias = schema_editor.connection.alias
|
||||
article = apps.get_model("cotisations", "Article")
|
||||
vente = apps.get_model("cotisations", "Vente")
|
||||
for a in article.objects.using(db_alias).all():
|
||||
unsplit_duration(a)
|
||||
for v in vente.objects.using(db_alias).all():
|
||||
unsplit_duration(v)
|
||||
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(split_dates, unsplit_dates),
|
||||
migrations.RunPython(split_duration_articles_and_ventes, unsplit_duration_articles_and_ventes),
|
||||
# migrations.RemoveField(
|
||||
# model_name='article',
|
||||
# name='duration',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='article',
|
||||
# name='duration_days',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='article',
|
||||
# name='type_cotisation',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='cotisation',
|
||||
# name='date_end',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='cotisation',
|
||||
# name='date_start',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='cotisation',
|
||||
# name='type_cotisation',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='vente',
|
||||
# name='duration',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='vente',
|
||||
# name='duration_days',
|
||||
# ),
|
||||
# migrations.RemoveField(
|
||||
# model_name='vente',
|
||||
# name='type_cotisation',
|
||||
# ),
|
||||
]
|
|
@ -0,0 +1,53 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-09-20 17:19
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0044_separation_membership_connection_p2'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='article',
|
||||
name='duration',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='article',
|
||||
name='duration_days',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='article',
|
||||
name='type_cotisation',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cotisation',
|
||||
name='date_end',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cotisation',
|
||||
name='date_start',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cotisation',
|
||||
name='type_cotisation',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='vente',
|
||||
name='duration',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='vente',
|
||||
name='duration_days',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='vente',
|
||||
name='type_cotisation',
|
||||
),
|
||||
]
|
20
cotisations/migrations/0046_article_need_membership.py
Normal file
20
cotisations/migrations/0046_article_need_membership.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-09-25 16:45
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0045_separation_membership_connection_p3'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='need_membership',
|
||||
field=models.BooleanField(default=True, verbose_name='can be purcharsed without membership'),
|
||||
),
|
||||
]
|
28
cotisations/migrations/0047_article_need_membership_init.py
Normal file
28
cotisations/migrations/0047_article_need_membership_init.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-09-25 16:45
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0046_article_need_membership'),
|
||||
]
|
||||
|
||||
def init_need_membership(apps, schema_editor):
|
||||
db_alias = schema_editor.connection.alias
|
||||
article = apps.get_model("cotisations", "Article")
|
||||
articles = article.objects.using(db_alias).all()
|
||||
for art in articles:
|
||||
v = False
|
||||
v = v or bool(art.duration_membership)
|
||||
v = v or bool(art.duration_days_membership)
|
||||
v = v or not (bool(art.duration_connection) or bool(art.duration_days_connection))
|
||||
art.need_membership = v
|
||||
art.save()
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(init_need_membership, lambda *args, **kargs: None),
|
||||
]
|
26
cotisations/migrations/0048_auto_20201017_0018.py
Normal file
26
cotisations/migrations/0048_auto_20201017_0018.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-10-16 22:18
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0047_article_need_membership_init'),
|
||||
]
|
||||
|
||||
|
||||
def set_value_to_zero(apps, schema_editor):
|
||||
db_alias = schema_editor.connection.alias
|
||||
Vente = apps.get_model("cotisations", "Vente")
|
||||
Vente.objects.using(db_alias).filter(duration_connection__isnull=True).update(duration_connection=0)
|
||||
Vente.objects.using(db_alias).filter(duration_days_connection__isnull=True).update(duration_days_connection=0)
|
||||
Vente.objects.using(db_alias).filter(duration_membership__isnull=True).update(duration_membership=0)
|
||||
Vente.objects.using(db_alias).filter(duration_days_membership__isnull=True).update(duration_days_membership=0)
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(set_value_to_zero),
|
||||
]
|
41
cotisations/migrations/0049_auto_20201102_2305.py
Normal file
41
cotisations/migrations/0049_auto_20201102_2305.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-11-02 22:05
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0048_auto_20201017_0018'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='need_membership',
|
||||
field=models.BooleanField(default=True, verbose_name='need membership to be purchased'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vente',
|
||||
name='duration_connection',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='duration of the connection (in months)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vente',
|
||||
name='duration_days_connection',
|
||||
field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the connection (in days, will be added to duration in months)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vente',
|
||||
name='duration_days_membership',
|
||||
field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the membership (in days, will be added to duration in months)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vente',
|
||||
name='duration_membership',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='duration of the membership (in months)'),
|
||||
),
|
||||
]
|
40
cotisations/migrations/0050_auto_20201102_2342.py
Normal file
40
cotisations/migrations/0050_auto_20201102_2342.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-11-02 22:42
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cotisations', '0049_auto_20201102_2305'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='duration_connection',
|
||||
field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the connection (in months)'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='duration_days_connection',
|
||||
field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the connection (in days, will be added to duration in months)'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='duration_days_membership',
|
||||
field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the membership (in days, will be added to duration in months)'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='duration_membership',
|
||||
field=models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration of the membership (in months)'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
59
cotisations/migrations/0051_auto_20201228_1636.py
Normal file
59
cotisations/migrations/0051_auto_20201228_1636.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-12-28 15:36
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("cotisations", "0050_auto_20201102_2342"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="article",
|
||||
name="duration_connection",
|
||||
field=models.PositiveIntegerField(
|
||||
verbose_name="duration of the connection (in months)"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="article",
|
||||
name="duration_days_connection",
|
||||
field=models.PositiveIntegerField(
|
||||
verbose_name="duration of the connection (in days, will be added to duration in months)"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="article",
|
||||
name="duration_days_membership",
|
||||
field=models.PositiveIntegerField(
|
||||
verbose_name="duration of the membership (in days, will be added to duration in months)"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="article",
|
||||
name="duration_membership",
|
||||
field=models.PositiveIntegerField(
|
||||
verbose_name="duration of the membership (in months)"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="vente",
|
||||
name="duration_days_connection",
|
||||
field=models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name="duration of the connection (in days, will be added to duration in months)",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="vente",
|
||||
name="duration_days_membership",
|
||||
field=models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name="duration of the membership (in days, will be added to duration in months)",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,4 +1,4 @@
|
|||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -50,6 +50,8 @@ from preferences.models import CotisationsOption
|
|||
from machines.models import regen
|
||||
from re2o.field_permissions import FieldPermissionModelMixin
|
||||
from re2o.mixins import AclMixin, RevMixin
|
||||
import users.signals
|
||||
import users.models
|
||||
|
||||
from cotisations.utils import find_payment_method, send_mail_invoice, send_mail_voucher
|
||||
from cotisations.validators import check_no_balance
|
||||
|
@ -58,6 +60,12 @@ from cotisations.validators import check_no_balance
|
|||
class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||
date = models.DateTimeField(auto_now_add=True, verbose_name=_("date"))
|
||||
|
||||
class Meta:
|
||||
abstract = False
|
||||
permissions = (
|
||||
("view_baseinvoice", _("Can view an base invoice object")),
|
||||
)
|
||||
|
||||
# TODO : change prix to price
|
||||
def prix(self):
|
||||
"""
|
||||
|
@ -96,6 +104,16 @@ class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
|||
)
|
||||
return name
|
||||
|
||||
def name_detailed(self):
|
||||
"""
|
||||
Return:
|
||||
- a list of strings with the name of all article in the invoice
|
||||
and their quantity.
|
||||
"""
|
||||
ventes = self.vente_set.all()
|
||||
strings = ["{} x {}".format(v.number, v.name) for v in ventes]
|
||||
return strings
|
||||
|
||||
|
||||
# TODO : change facture to invoice
|
||||
class Facture(BaseInvoice):
|
||||
|
@ -138,7 +156,7 @@ class Facture(BaseInvoice):
|
|||
abstract = False
|
||||
permissions = (
|
||||
# TODO : change facture to invoice
|
||||
("change_facture_control", _("Can edit the \"controlled\" state")),
|
||||
("change_facture_control", _('Can edit the "controlled" state')),
|
||||
("view_facture", _("Can view an invoice object")),
|
||||
("change_all_facture", _("Can edit all the previous invoices")),
|
||||
)
|
||||
|
@ -166,7 +184,7 @@ class Facture(BaseInvoice):
|
|||
return (
|
||||
False,
|
||||
_("You don't have the right to edit this user's invoices."),
|
||||
("cotisations.change_all_facture",) + permissions,
|
||||
("cotisations.change_all_facture",) + (permissions or ()),
|
||||
)
|
||||
elif not user_request.has_perm("cotisations.change_all_facture") and (
|
||||
self.control or not self.valid
|
||||
|
@ -198,7 +216,7 @@ class Facture(BaseInvoice):
|
|||
return (
|
||||
False,
|
||||
_("You don't have the right to delete this user's invoices."),
|
||||
("cotisations.change_all_facture",) + permissions,
|
||||
("cotisations.change_all_facture",) + (permissions or ()),
|
||||
)
|
||||
elif not user_request.has_perm("cotisations.change_all_facture") and (
|
||||
self.control or not self.valid
|
||||
|
@ -238,12 +256,12 @@ class Facture(BaseInvoice):
|
|||
|
||||
@staticmethod
|
||||
def can_change_control(user_request, *_args, **_kwargs):
|
||||
""" Returns True if the user can change the 'controlled' status of
|
||||
this invoice """
|
||||
"""Returns True if the user can change the 'controlled' status of
|
||||
this invoice"""
|
||||
can = user_request.has_perm("cotisations.change_facture_control")
|
||||
return (
|
||||
can,
|
||||
_("You don't have the right to edit the \"controlled\" state.")
|
||||
_('You don\'t have the right to edit the "controlled" state.')
|
||||
if not can
|
||||
else None,
|
||||
("cotisations.change_facture_control",),
|
||||
|
@ -283,7 +301,7 @@ class Facture(BaseInvoice):
|
|||
"""Returns every subscription associated with this invoice."""
|
||||
return Cotisation.objects.filter(
|
||||
vente__in=self.vente_set.filter(
|
||||
Q(type_cotisation="All") | Q(type_cotisation="Adhesion")
|
||||
~(Q(duration_membership=0)) | ~(Q(duration_days_membership=0))
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -297,42 +315,33 @@ class Facture(BaseInvoice):
|
|||
for purchase in self.vente_set.all():
|
||||
if hasattr(purchase, "cotisation"):
|
||||
cotisation = purchase.cotisation
|
||||
if cotisation.type_cotisation == 'Connexion':
|
||||
cotisation.date_start = date_con
|
||||
date_con += relativedelta(
|
||||
months=(purchase.duration or 0) * purchase.number,
|
||||
days=(purchase.duration_days or 0) * purchase.number,
|
||||
)
|
||||
cotisation.date_end = date_con
|
||||
elif cotisation.type_cotisation == 'Adhesion':
|
||||
cotisation.date_start = date_adh
|
||||
date_adh += relativedelta(
|
||||
months=(purchase.duration or 0) * purchase.number,
|
||||
days=(purchase.duration_days or 0) * purchase.number,
|
||||
)
|
||||
cotisation.date_end = date_adh
|
||||
else: # it is assumed that adhesion is required for a connexion
|
||||
date = min(date_adh, date_con)
|
||||
cotisation.date_start = date
|
||||
date_adh += relativedelta(
|
||||
months=(purchase.duration or 0) * purchase.number,
|
||||
days=(purchase.duration_days or 0) * purchase.number,
|
||||
)
|
||||
date_con += relativedelta(
|
||||
months=(purchase.duration or 0) * purchase.number,
|
||||
days=(purchase.duration_days or 0) * purchase.number,
|
||||
)
|
||||
date = max(date_adh, date_con)
|
||||
cotisation.date_end = date
|
||||
cotisation.date_start_con = date_con
|
||||
date_con += relativedelta(
|
||||
months=(purchase.duration_connection or 0) * purchase.number,
|
||||
days=(purchase.duration_days_connection or 0) * purchase.number,
|
||||
)
|
||||
cotisation.date_end_con = date_con
|
||||
cotisation.date_start_memb = date_adh
|
||||
date_adh += relativedelta(
|
||||
months=(purchase.duration_membership or 0) * purchase.number,
|
||||
days=(purchase.duration_days_membership or 0) * purchase.number,
|
||||
)
|
||||
cotisation.date_end_memb = date_adh
|
||||
cotisation.save()
|
||||
purchase.facture = self
|
||||
purchase.save()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
try:
|
||||
request = kwargs.pop("request")
|
||||
except:
|
||||
request = None
|
||||
|
||||
super(Facture, self).save(*args, **kwargs)
|
||||
|
||||
if not self.__original_valid and self.valid:
|
||||
self.reorder_purchases()
|
||||
send_mail_invoice(self)
|
||||
send_mail_invoice(self, request)
|
||||
if (
|
||||
self.is_subscription()
|
||||
and not self.__original_control
|
||||
|
@ -340,7 +349,7 @@ class Facture(BaseInvoice):
|
|||
and CotisationsOption.get_cached_value("send_voucher_mail")
|
||||
and self.user.is_adherent()
|
||||
):
|
||||
send_mail_voucher(self)
|
||||
send_mail_voucher(self, request)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.user) + " " + str(self.date)
|
||||
|
@ -355,7 +364,7 @@ def facture_post_save(**kwargs):
|
|||
if facture.valid:
|
||||
user = facture.user
|
||||
user.set_active()
|
||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=True, mac_refresh=False)
|
||||
|
||||
|
||||
@receiver(post_delete, sender=Facture)
|
||||
|
@ -364,7 +373,7 @@ def facture_post_delete(**kwargs):
|
|||
Synchronise the LDAP user after an invoice has been deleted.
|
||||
"""
|
||||
user = kwargs["instance"].user
|
||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=True, mac_refresh=False)
|
||||
|
||||
|
||||
class CustomInvoice(BaseInvoice):
|
||||
|
@ -444,13 +453,6 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
the effect of the purchase on the time agreed for this user)
|
||||
"""
|
||||
|
||||
# TODO : change this to English
|
||||
COTISATION_TYPE = (
|
||||
("Connexion", _("Connection")),
|
||||
("Adhesion", _("Membership")),
|
||||
("All", _("Both of them")),
|
||||
)
|
||||
|
||||
# TODO : change facture to invoice
|
||||
facture = models.ForeignKey(
|
||||
"BaseInvoice", on_delete=models.CASCADE, verbose_name=_("invoice")
|
||||
|
@ -460,27 +462,30 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
validators=[MinValueValidator(1)], verbose_name=_("amount")
|
||||
)
|
||||
# TODO : change this field for a ForeinKey to Article
|
||||
# Note: With a foreign key, modifing an Article modifis the Purchase, wich is bad.
|
||||
# To use a foreign key, you need to make Article read only
|
||||
name = models.CharField(max_length=255, verbose_name=_("article"))
|
||||
# TODO : change prix to price
|
||||
# TODO : this field is not needed if you use Article ForeignKey
|
||||
prix = models.DecimalField(max_digits=5, decimal_places=2, verbose_name=_("price"))
|
||||
# TODO : this field is not needed if you use Article ForeignKey
|
||||
duration = models.PositiveIntegerField(
|
||||
blank=True, null=True, verbose_name=_("duration (in months)")
|
||||
duration_connection = models.PositiveIntegerField(
|
||||
default=0, verbose_name=_("duration of the connection (in months)")
|
||||
)
|
||||
duration_days = models.PositiveIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(0)],
|
||||
verbose_name=_("duration (in days, will be added to duration in months)"),
|
||||
duration_days_connection = models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name=_(
|
||||
"duration of the connection (in days, will be added to duration in months)"
|
||||
),
|
||||
)
|
||||
# TODO : this field is not needed if you use Article ForeignKey
|
||||
type_cotisation = models.CharField(
|
||||
choices=COTISATION_TYPE,
|
||||
blank=True,
|
||||
null=True,
|
||||
max_length=255,
|
||||
verbose_name=_("subscription type"),
|
||||
duration_membership = models.PositiveIntegerField(
|
||||
default=0, verbose_name=_("duration of the membership (in months)")
|
||||
)
|
||||
duration_days_membership = models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name=_(
|
||||
"duration of the membership (in days, will be added to duration in months)"
|
||||
),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -505,34 +510,48 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
"""
|
||||
if hasattr(self, "cotisation"):
|
||||
cotisation = self.cotisation
|
||||
cotisation.date_end = cotisation.date_start + relativedelta(
|
||||
months=(self.duration or 0) * self.number,
|
||||
days=(self.duration_days or 0) * self.number,
|
||||
cotisation.date_end_memb = cotisation.date_start_memb + relativedelta(
|
||||
months=(self.duration_membership or 0) * self.number,
|
||||
days=(self.duration_days_membership or 0) * self.number,
|
||||
)
|
||||
cotisation.date_end_con = cotisation.date_start_con + relativedelta(
|
||||
months=(self.duration_connection or 0) * self.number,
|
||||
days=(self.duration_days_connection or 0) * self.number,
|
||||
)
|
||||
return
|
||||
|
||||
def create_cotis(self, date_start=False):
|
||||
def create_cotis(self, date_start_con=False, date_start_memb=False):
|
||||
"""
|
||||
Creates a cotisation without initializing the dates (start and end ar set to self.facture.facture.date) and without saving it. You should use Facture.reorder_purchases to set the right dates.
|
||||
Creates a cotisation without initializing the dates (start and end ar set to self.facture.facture.date)
|
||||
and without saving it. You should use Facture.reorder_purchases to set the right dates.
|
||||
"""
|
||||
try:
|
||||
invoice = self.facture.facture
|
||||
except Facture.DoesNotExist:
|
||||
return
|
||||
if not hasattr(self, "cotisation") and self.type_cotisation:
|
||||
if not hasattr(self, "cotisation") and self.test_membership_or_connection():
|
||||
cotisation = Cotisation(vente=self)
|
||||
cotisation.type_cotisation = self.type_cotisation
|
||||
if date_start:
|
||||
cotisation.date_start = date_start
|
||||
cotisation.date_end = cotisation.date_start + relativedelta(
|
||||
months=(self.duration or 0) * self.number,
|
||||
days=(self.duration_days or 0) * self.number,
|
||||
if date_start_con:
|
||||
cotisation.date_start_con = date_start_con
|
||||
cotisation.date_end_con = cotisation.date_start_con + relativedelta(
|
||||
months=(self.duration_connection or 0) * self.number,
|
||||
days=(self.duration_days_connection or 0) * self.number,
|
||||
)
|
||||
self.save()
|
||||
cotisation.save()
|
||||
if date_start_memb:
|
||||
cotisation.date_start_memb = date_start_memb
|
||||
cotisation.date_end_memb = cotisation.date_start_memb + relativedelta(
|
||||
months=(self.duration_membership or 0) * self.number,
|
||||
days=(self.duration_days_membership or 0) * self.number,
|
||||
)
|
||||
self.save()
|
||||
cotisation.save()
|
||||
else:
|
||||
cotisation.date_start = invoice.date
|
||||
cotisation.date_end = invoice.date
|
||||
cotisation.date_start_con = invoice.date
|
||||
cotisation.date_start_memb = invoice.date
|
||||
cotisation.date_end_con = invoice.date
|
||||
cotisation.date_end_memb = invoice.date
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
|
@ -540,9 +559,6 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
It also update the associated cotisation in the changes have some
|
||||
effect on the user's cotisation
|
||||
"""
|
||||
# Checking that if a cotisation is specified, there is also a duration
|
||||
if self.type_cotisation and not (self.duration or self.duration_days):
|
||||
raise ValidationError(_("Duration must be specified for a subscription."))
|
||||
self.update_cotisation()
|
||||
super(Vente, self).save(*args, **kwargs)
|
||||
|
||||
|
@ -560,7 +576,7 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
return (
|
||||
False,
|
||||
_("You don't have the right to edit this user's purchases."),
|
||||
("cotisations.change_all_facture",) + permissions,
|
||||
("cotisations.change_all_facture",) + (permissions or ()),
|
||||
)
|
||||
elif not user_request.has_perm("cotisations.change_all_vente") and (
|
||||
self.facture.control or not self.facture.valid
|
||||
|
@ -623,6 +639,15 @@ class Vente(RevMixin, AclMixin, models.Model):
|
|||
def __str__(self):
|
||||
return str(self.name) + " " + str(self.facture)
|
||||
|
||||
def test_membership_or_connection(self):
|
||||
"""Test if the purchase include membership or connecton"""
|
||||
return (
|
||||
self.duration_membership
|
||||
or self.duration_days_membership
|
||||
or self.duration_connection
|
||||
or self.duration_days_connection
|
||||
)
|
||||
|
||||
|
||||
# TODO : change vente to purchase
|
||||
@receiver(post_save, sender=Vente)
|
||||
|
@ -639,12 +664,12 @@ def vente_post_save(**kwargs):
|
|||
if hasattr(purchase, "cotisation"):
|
||||
purchase.cotisation.vente = purchase
|
||||
purchase.cotisation.save()
|
||||
if purchase.type_cotisation:
|
||||
if purchase.test_membership_or_connection():
|
||||
purchase.create_cotis()
|
||||
purchase.cotisation.save()
|
||||
user = purchase.facture.facture.user
|
||||
user.set_active()
|
||||
user.ldap_sync(base=True, access_refresh=True, mac_refresh=False)
|
||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=True, access_refresh=True, mac_refresh=False)
|
||||
|
||||
|
||||
# TODO : change vente to purchase
|
||||
|
@ -660,7 +685,7 @@ def vente_post_delete(**kwargs):
|
|||
return
|
||||
if purchase.type_cotisation:
|
||||
user = invoice.user
|
||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=True, access_refresh=True, mac_refresh=False)
|
||||
|
||||
|
||||
class Article(RevMixin, AclMixin, models.Model):
|
||||
|
@ -671,56 +696,52 @@ class Article(RevMixin, AclMixin, models.Model):
|
|||
It's represented by:
|
||||
* a name
|
||||
* a price
|
||||
* a cotisation type (indicating if this article reprensents a
|
||||
cotisation or not)
|
||||
* a duration (if it is a cotisation)
|
||||
* a duration for the membership
|
||||
* a duration for the connection
|
||||
* if the article can be purchased without membership
|
||||
* a type of user (indicating what kind of user can buy this article)
|
||||
"""
|
||||
|
||||
# TODO : Either use TYPE or TYPES in both choices but not both
|
||||
USER_TYPES = (
|
||||
("Adherent", _("Member")),
|
||||
("Club", _("Club")),
|
||||
("All", _("Both of them")),
|
||||
)
|
||||
|
||||
COTISATION_TYPE = (
|
||||
("Connexion", _("Connection")),
|
||||
("Adhesion", _("Membership")),
|
||||
("All", _("Both of them")),
|
||||
)
|
||||
|
||||
name = models.CharField(max_length=255, verbose_name=_("designation"))
|
||||
# TODO : change prix to price
|
||||
prix = models.DecimalField(
|
||||
max_digits=5, decimal_places=2, verbose_name=_("unit price")
|
||||
)
|
||||
duration = models.PositiveIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(0)],
|
||||
verbose_name=_("duration (in months)"),
|
||||
|
||||
duration_membership = models.PositiveIntegerField(
|
||||
verbose_name=_("duration of the membership (in months)")
|
||||
)
|
||||
duration_days = models.PositiveIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(0)],
|
||||
verbose_name=_("duration (in days, will be added to duration in months)"),
|
||||
duration_days_membership = models.PositiveIntegerField(
|
||||
verbose_name=_(
|
||||
"duration of the membership (in days, will be added to duration in months)"
|
||||
),
|
||||
)
|
||||
duration_connection = models.PositiveIntegerField(
|
||||
verbose_name=_("duration of the connection (in months)")
|
||||
)
|
||||
duration_days_connection = models.PositiveIntegerField(
|
||||
verbose_name=_(
|
||||
"duration of the connection (in days, will be added to duration in months)"
|
||||
),
|
||||
)
|
||||
|
||||
need_membership = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name=_("need membership to be purchased"),
|
||||
)
|
||||
|
||||
type_user = models.CharField(
|
||||
choices=USER_TYPES,
|
||||
default="All",
|
||||
max_length=255,
|
||||
verbose_name=_("type of users concerned"),
|
||||
)
|
||||
type_cotisation = models.CharField(
|
||||
choices=COTISATION_TYPE,
|
||||
default=None,
|
||||
blank=True,
|
||||
null=True,
|
||||
max_length=255,
|
||||
verbose_name=_("subscription type"),
|
||||
)
|
||||
available_for_everyone = models.BooleanField(
|
||||
default=False, verbose_name=_("is available for every user")
|
||||
)
|
||||
|
@ -738,8 +759,6 @@ class Article(RevMixin, AclMixin, models.Model):
|
|||
def clean(self):
|
||||
if self.name.lower() == "solde":
|
||||
raise ValidationError(_("Solde is a reserved article name."))
|
||||
if self.type_cotisation and not (self.duration or self.duration_days):
|
||||
raise ValidationError(_("Duration must be specified for a subscription."))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -772,7 +791,7 @@ class Article(RevMixin, AclMixin, models.Model):
|
|||
|
||||
Args:
|
||||
user: The user requesting articles.
|
||||
target_user: The user to sell articles
|
||||
target_user: The user to sell articles to
|
||||
"""
|
||||
if target_user is None:
|
||||
objects_pool = cls.objects.all()
|
||||
|
@ -784,7 +803,9 @@ class Article(RevMixin, AclMixin, models.Model):
|
|||
)
|
||||
if target_user is not None and not target_user.is_adherent():
|
||||
objects_pool = objects_pool.filter(
|
||||
Q(type_cotisation="All") | Q(type_cotisation="Adhesion")
|
||||
Q(duration_membership__gt=0)
|
||||
| Q(duration_days_membership__gt=0)
|
||||
| Q(need_membership=False)
|
||||
)
|
||||
if user.has_perm("cotisations.buy_every_article"):
|
||||
return objects_pool
|
||||
|
@ -870,11 +891,13 @@ class Paiement(RevMixin, AclMixin, models.Model):
|
|||
|
||||
# So make this invoice valid, trigger send mail
|
||||
invoice.valid = True
|
||||
invoice.save()
|
||||
invoice.save(request=request)
|
||||
|
||||
# In case a cotisation was bought, inform the user, the
|
||||
# cotisation time has been extended too
|
||||
if any(sell.type_cotisation for sell in invoice.vente_set.all()):
|
||||
if any(
|
||||
sell.test_membership_or_connection() for sell in invoice.vente_set.all()
|
||||
):
|
||||
messages.success(
|
||||
request,
|
||||
_(
|
||||
|
@ -935,31 +958,25 @@ class Cotisation(RevMixin, AclMixin, models.Model):
|
|||
The model defining a cotisation. It holds information about the time a user
|
||||
is allowed when he has paid something.
|
||||
It characterised by :
|
||||
* a date_start (the date when the cotisaiton begins/began
|
||||
* a date_end (the date when the cotisation ends/ended
|
||||
* a type of cotisation (which indicates the implication of such
|
||||
cotisation)
|
||||
* a date_start_memb (the date when the membership begins/began
|
||||
* a date_end_memb (the date when the membership ends/ended
|
||||
* a date_start_con (the date when the connection begins/began)
|
||||
* a date_end_con (the date when the connection ends/ended)
|
||||
* a purchase (the related objects this cotisation is linked to)
|
||||
"""
|
||||
|
||||
COTISATION_TYPE = (
|
||||
("Connexion", _("Connection")),
|
||||
("Adhesion", _("Membership")),
|
||||
("All", _("Both of them")),
|
||||
)
|
||||
|
||||
# TODO : change vente to purchase
|
||||
vente = models.OneToOneField(
|
||||
"Vente", on_delete=models.CASCADE, null=True, verbose_name=_("purchase")
|
||||
)
|
||||
type_cotisation = models.CharField(
|
||||
choices=COTISATION_TYPE,
|
||||
max_length=255,
|
||||
default="All",
|
||||
verbose_name=_("subscription type"),
|
||||
date_start_con = models.DateTimeField(
|
||||
verbose_name=_("start date for the connection")
|
||||
)
|
||||
date_start = models.DateTimeField(verbose_name=_("start date"))
|
||||
date_end = models.DateTimeField(verbose_name=_("end date"))
|
||||
date_end_con = models.DateTimeField(verbose_name=_("end date for the connection"))
|
||||
date_start_memb = models.DateTimeField(
|
||||
verbose_name=_("start date for the membership")
|
||||
)
|
||||
date_end_memb = models.DateTimeField(verbose_name=_("end date for the membership"))
|
||||
|
||||
class Meta:
|
||||
permissions = (
|
||||
|
@ -1029,9 +1046,14 @@ class Cotisation(RevMixin, AclMixin, models.Model):
|
|||
return (
|
||||
str(self.vente)
|
||||
+ "from "
|
||||
+ str(self.date_start)
|
||||
+ str(self.date_start_memb)
|
||||
+ " to "
|
||||
+ str(self.date_end)
|
||||
+ str(self.date_end_memb)
|
||||
+ " for membership, "
|
||||
+ str(self.date_start_con)
|
||||
+ " to "
|
||||
+ str(self.date_end_con)
|
||||
+ " for the connection."
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
@ -55,7 +55,7 @@ def accept_payment(request, factureid):
|
|||
)
|
||||
# In case a cotisation was bought, inform the user, the
|
||||
# cotisation time has been extended too
|
||||
if any(purchase.type_cotisation for purchase in invoice.vente_set.all()):
|
||||
if any(purchase.test_membership_or_connection() for purchase in invoice.vente_set.all()):
|
||||
messages.success(
|
||||
request,
|
||||
_(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
@ -32,9 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
<tr>
|
||||
<th>{% trans "Article" %}</th>
|
||||
<th>{% trans "Price" %}</th>
|
||||
<th>{% trans "Subscription type" %}</th>
|
||||
<th>{% trans "Duration (in months)" %}</th>
|
||||
<th>{% trans "Duration (in days)" %}</th>
|
||||
<th>{% trans "Duration membership (in months)" %}</th>
|
||||
<th>{% trans "Duration membership (in days)" %}</th>
|
||||
<th>{% trans "Duration connection (in months)" %}</th>
|
||||
<th>{% trans "Duration connection (in days)" %}</th>
|
||||
<th>{% trans "Concerned users" %}</th>
|
||||
<th>{% trans "Available for everyone" %}</th>
|
||||
<th></th>
|
||||
|
@ -44,9 +45,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
<tr>
|
||||
<td>{{ article.name }}</td>
|
||||
<td>{{ article.prix }}</td>
|
||||
<td>{{ article.type_cotisation }}</td>
|
||||
<td>{{ article.duration }}</td>
|
||||
<td>{{ article.duration_days }}</td>
|
||||
<td>{{ article.duration_membership }}</td>
|
||||
<td>{{ article.duration_days_membership }}</td>
|
||||
<td>{{ article.duration_connection }}</td>
|
||||
<td>{{ article.duration_days_connection }}</td>
|
||||
<td>{{ article.type_user }}</td>
|
||||
<td>{{ article.available_for_everyone | tick }}</td>
|
||||
<td class="text-right">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
@ -73,9 +73,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
<td>{{ estimate.id }}</td>
|
||||
<td>
|
||||
{% if estimate.final_invoice %}
|
||||
<a href="{% url 'cotisations:edit-custom-invoice' estimate.final_invoice.pk %}"><i style="color: #1ECA18;" class="fa fa-check"></i></a>
|
||||
<a href="{% url 'cotisations:edit-custom-invoice' estimate.final_invoice.pk %}"><i class="fa fa-check text-success"></i></a>
|
||||
{% else %}
|
||||
<i style="color: #D10115;" class="fa fa-times"></i>
|
||||
<i class="fa fa-times text-danger"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
@ -59,7 +59,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
{% for facture in facture_list %}
|
||||
<tr>
|
||||
<td><a href="{% url 'users:profil' userid=facture.user.id %}">{{ facture.user }}</a></td>
|
||||
<td>{{ facture.name }}</td>
|
||||
<td>
|
||||
<table class="table-borderless">
|
||||
{% for article in facture.name_detailed %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ article }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td>
|
||||
<td>{{ facture.prix_total }}</td>
|
||||
<td>{{ facture.paiement }}</td>
|
||||
<td>{{ facture.date }}</td>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
61
cotisations/templates/cotisations/aff_profil.html
Normal file
61
cotisations/templates/cotisations/aff_profil.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
Copyright © 2017 Gabriel Détraz
|
||||
Copyright © 2017 Lara 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 %}
|
||||
{% load i18n %}
|
||||
{% load logs_extra %}
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading clearfix profil" data-parent="#accordion" data-toggle="collapse"
|
||||
data-target="#subscriptions">
|
||||
<h3 class="panel-title pull-left">
|
||||
<i class="fa fa-eur"></i>
|
||||
{% trans "Subscriptions" %}
|
||||
</h3>
|
||||
</div>
|
||||
<div id="subscriptions" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% can_create Facture %}
|
||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:new-facture' users.id %}">
|
||||
<i class="fa fa-eur"></i>
|
||||
{% trans "Add a subscription" %}
|
||||
</a>
|
||||
{% if user_solde %}
|
||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:credit-solde' users.id %}">
|
||||
<i class="fa fa-eur"></i>
|
||||
{% trans "Edit the balance" %}
|
||||
</a>
|
||||
{% endif%}
|
||||
{% acl_end %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if facture_list %}
|
||||
{% include 'cotisations/aff_cotisations.html' with facture_list=facture_list %}
|
||||
{% else %}
|
||||
<p>{% trans "No invoice" %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
@ -25,13 +25,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
{% load bootstrap3 %}
|
||||
{% load staticfiles%}
|
||||
{% load massive_bootstrap_form %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Creation and editing of invoices" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% bootstrap_form_errors factureform %}
|
||||
{{ factureform.media }}
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
|
@ -40,7 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
{% else %}
|
||||
<h3>{% trans "Edit invoice" %}</h3>
|
||||
{% endif %}
|
||||
{% massive_bootstrap_form factureform 'user' %}
|
||||
{% bootstrap_form factureform %}
|
||||
{{ venteform.management_form }}
|
||||
<h3>{% trans "Articles" %}</h3>
|
||||
<table class="table table-striped">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'cotisations/sidebar.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
|
@ -27,43 +27,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
{% load i18n %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% can_create CustomInvoice %}
|
||||
<a class="list-group-item list-group-item-success" href="{% url 'cotisations:new-custom-invoice' %}">
|
||||
<i class="fa fa-plus"></i> {% trans "Create an invoice" %}
|
||||
</a>
|
||||
<a class="list-group-item list-group-item-warning" href="{% url 'cotisations:control' %}">
|
||||
<i class="fa fa-eye"></i> {% trans "Control the invoices" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% can_view_all Facture %}
|
||||
<a class="list-group-item list-group-item-info" href="{% url 'cotisations:index' %}">
|
||||
<i class="fa fa-list-ul"></i> {% trans "Invoices" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% can_view_all CustomInvoice %}
|
||||
<a class="list-group-item list-group-item-info" href="{% url 'cotisations:index-custom-invoice' %}">
|
||||
<i class="fa fa-list-ul"></i> {% trans "Custom invoices" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% can_view_all CostEstimate %}
|
||||
<a class="list-group-item list-group-item-info" href="{% url 'cotisations:index-cost-estimate' %}">
|
||||
<i class="fa fa-list-ul"></i> {% trans "Cost estimates" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% can_view_all Article %}
|
||||
<a class="list-group-item list-group-item-info" href="{% url 'cotisations:index-article' %}">
|
||||
<i class="fa fa-list-ul"></i> {% trans "Articles" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% can_view_all Banque %}
|
||||
<a class="list-group-item list-group-item-info" href="{% url 'cotisations:index-banque' %}">
|
||||
<i class="fa fa-list-ul"></i> {% trans "Banks" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% can_view_all Paiement %}
|
||||
<a class="list-group-item list-group-item-info" href="{% url 'cotisations:index-paiement' %}">
|
||||
<i class="fa fa-list-ul"></i> {% trans "Payment methods" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -19,15 +19,17 @@ class VenteModelTests(TestCase):
|
|||
def test_one_day_cotisation(self):
|
||||
"""
|
||||
It should be possible to have one day membership.
|
||||
Add one day of membership and one day of connection.
|
||||
"""
|
||||
date = timezone.now()
|
||||
purchase = Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=0,
|
||||
duration_days=1,
|
||||
type_cotisation="All",
|
||||
duration_connection=0,
|
||||
duration_days_connection=1,
|
||||
duration_membership=0,
|
||||
duration_days_membership=1,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
|
@ -36,48 +38,66 @@ class VenteModelTests(TestCase):
|
|||
datetime.timedelta(days=1),
|
||||
delta=datetime.timedelta(seconds=1),
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
self.user.end_adhesion() - date,
|
||||
datetime.timedelta(days=1),
|
||||
delta=datetime.timedelta(seconds=1),
|
||||
)
|
||||
|
||||
def test_one_month_cotisation(self):
|
||||
"""
|
||||
It should be possible to have one day membership.
|
||||
Add one mounth of membership and one mounth of connection
|
||||
"""
|
||||
date = timezone.now()
|
||||
Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=1,
|
||||
duration_days=0,
|
||||
type_cotisation="All",
|
||||
duration_connection=1,
|
||||
duration_days_connection=0,
|
||||
duration_membership=1,
|
||||
duration_days_membership=0,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
end = self.user.end_connexion()
|
||||
end_con = self.user.end_connexion()
|
||||
end_memb = self.user.end_adhesion()
|
||||
expected_end = date + relativedelta(months=1)
|
||||
self.assertEqual(end.day, expected_end.day)
|
||||
self.assertEqual(end.month, expected_end.month)
|
||||
self.assertEqual(end.year, expected_end.year)
|
||||
self.assertEqual(end_con.day, expected_end.day)
|
||||
self.assertEqual(end_con.month, expected_end.month)
|
||||
self.assertEqual(end_con.year, expected_end.year)
|
||||
self.assertEqual(end_memb.day, expected_end.day)
|
||||
self.assertEqual(end_memb.month, expected_end.month)
|
||||
self.assertEqual(end_memb.year, expected_end.year)
|
||||
|
||||
def test_one_month_and_one_week_cotisation(self):
|
||||
"""
|
||||
It should be possible to have one day membership.
|
||||
Add one mounth and one week of membership and one mounth
|
||||
and one week of connection
|
||||
"""
|
||||
date = timezone.now()
|
||||
Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=1,
|
||||
duration_days=7,
|
||||
type_cotisation="All",
|
||||
duration_connection=1,
|
||||
duration_days_connection=7,
|
||||
duration_membership=1,
|
||||
duration_days_membership=7,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
end = self.user.end_connexion()
|
||||
end_con = self.user.end_connexion()
|
||||
end_memb = self.user.end_adhesion()
|
||||
expected_end = date + relativedelta(months=1, days=7)
|
||||
self.assertEqual(end.day, expected_end.day)
|
||||
self.assertEqual(end.month, expected_end.month)
|
||||
self.assertEqual(end.year, expected_end.year)
|
||||
self.assertEqual(end_con.day, expected_end.day)
|
||||
self.assertEqual(end_con.month, expected_end.month)
|
||||
self.assertEqual(end_con.year, expected_end.year)
|
||||
self.assertEqual(end_memb.day, expected_end.day)
|
||||
self.assertEqual(end_memb.month, expected_end.month)
|
||||
self.assertEqual(end_memb.year, expected_end.year)
|
||||
|
||||
def test_date_start_cotisation(self):
|
||||
"""
|
||||
|
@ -87,15 +107,140 @@ class VenteModelTests(TestCase):
|
|||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=0,
|
||||
duration_days=1,
|
||||
type_cotisation = 'All',
|
||||
duration_connection=0,
|
||||
duration_days_connection=1,
|
||||
duration_membership=0,
|
||||
duration_deys_membership=1,
|
||||
prix=0
|
||||
)
|
||||
v.create_cotis(date_start=timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
||||
v.create_cotis(date_start_con=timezone.make_aware(datetime.datetime(1998, 10, 16)), date_start_memb=timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
||||
v.save()
|
||||
self.assertEqual(v.cotisation.date_end, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
||||
self.assertEqual(v.cotisation.date_end_con, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
||||
self.assertEqual(v.cotisation.date_end_memb, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
||||
|
||||
def test_one_day_cotisation_membership_only(self):
|
||||
"""
|
||||
It should be possible to have one day membership without connection.
|
||||
Add one day of membership and no connection.
|
||||
"""
|
||||
date = timezone.now()
|
||||
purchase = Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration_connection=0,
|
||||
duration_days_connection=0,
|
||||
duration_membership=0,
|
||||
duration_days_membership=1,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
self.assertEqual(
|
||||
self.user.end_connexion(),
|
||||
None,
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
self.user.end_adhesion() - date,
|
||||
datetime.timedelta(days=1),
|
||||
delta=datetime.timedelta(seconds=1),
|
||||
)
|
||||
|
||||
def test_one_month_cotisation_membership_only(self):
|
||||
"""
|
||||
It should be possible to have one month membership.
|
||||
Add one mounth of membership and no connection
|
||||
"""
|
||||
date = timezone.now()
|
||||
Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration_connection=0,
|
||||
duration_days_connection=0,
|
||||
duration_membership=1,
|
||||
duration_days_membership=0,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
end_con = self.user.end_connexion()
|
||||
end_memb = self.user.end_adhesion()
|
||||
expected_end = date + relativedelta(months=1)
|
||||
self.assertEqual(end_con, None)
|
||||
self.assertEqual(end_memb.day, expected_end.day)
|
||||
self.assertEqual(end_memb.month, expected_end.month)
|
||||
self.assertEqual(end_memb.year, expected_end.year)
|
||||
|
||||
def test_one_month_and_one_week_cotisation_membership_only(self):
|
||||
"""
|
||||
It should be possible to have one mounth and one week membership.
|
||||
Add one mounth and one week of membership and no connection.
|
||||
"""
|
||||
date = timezone.now()
|
||||
Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration_connection=0,
|
||||
duration_days_connection=0,
|
||||
duration_membership=1,
|
||||
duration_days_membership=7,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
end_con = self.user.end_connexion()
|
||||
end_memb = self.user.end_adhesion()
|
||||
expected_end = date + relativedelta(months=1, days=7)
|
||||
self.assertEqual(end_con, None)
|
||||
self.assertEqual(end_memb.day, expected_end.day)
|
||||
self.assertEqual(end_memb.month, expected_end.month)
|
||||
self.assertEqual(end_memb.year, expected_end.year)
|
||||
|
||||
def test_date_start_cotisation_membership_only(self):
|
||||
"""
|
||||
It should be possible to add a cotisation with a specific start date
|
||||
"""
|
||||
v = Vente(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration_connection=0,
|
||||
duration_days_connection=0,
|
||||
duration_membership=0,
|
||||
duration_days_membership=1,
|
||||
prix=0
|
||||
)
|
||||
v.create_cotis(date_start_con=timezone.make_aware(datetime.datetime(1998, 10, 16)), date_start_memb=timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
||||
v.save()
|
||||
self.assertEqual(v.cotisation.date_end_con, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
||||
self.assertEqual(v.cotisation.date_end_memb, timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
||||
|
||||
def test_cotisation_membership_diff_connection(self):
|
||||
"""
|
||||
It should be possible to have purchase a membership longer
|
||||
than the connection.
|
||||
"""
|
||||
date = timezone.now()
|
||||
Vente.objects.create(
|
||||
facture=self.f,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration_connection=1,
|
||||
duration_days_connection=0,
|
||||
duration_membership=2,
|
||||
duration_days_membership=0,
|
||||
prix=0,
|
||||
)
|
||||
self.f.reorder_purchases()
|
||||
end_con = self.user.end_connexion()
|
||||
end_memb = self.user.end_adhesion()
|
||||
expected_end_con = date + relativedelta(months=1)
|
||||
expected_end_memb = date + relativedelta(months=2)
|
||||
self.assertEqual(end_con.day, expected_end_con.day)
|
||||
self.assertEqual(end_con.month, expected_end_con.month)
|
||||
self.assertEqual(end_con.year, expected_end_con.year)
|
||||
self.assertEqual(end_memb.day, expected_end_memb.day)
|
||||
self.assertEqual(end_memb.month, expected_end_memb.month)
|
||||
self.assertEqual(end_memb.year, expected_end_memb.year)
|
||||
|
||||
def tearDown(self):
|
||||
self.f.delete()
|
||||
|
@ -121,9 +266,10 @@ class FactureModelTests(TestCase):
|
|||
facture=invoice1,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=1,
|
||||
duration_days=0,
|
||||
type_cotisation="All",
|
||||
duration_connection=1,
|
||||
duration_days_connection=0,
|
||||
duration_membership=1,
|
||||
duration_days_membership=0,
|
||||
prix=0,
|
||||
)
|
||||
invoice1.reorder_purchases()
|
||||
|
@ -134,16 +280,20 @@ class FactureModelTests(TestCase):
|
|||
facture=invoice2,
|
||||
number=1,
|
||||
name="Test purchase",
|
||||
duration=1,
|
||||
duration_days=0,
|
||||
type_cotisation="All",
|
||||
duration_connection=1,
|
||||
duration_days_connection=0,
|
||||
duration_membership=1,
|
||||
duration_days_membership=0,
|
||||
prix=0,
|
||||
)
|
||||
invoice1.reorder_purchases()
|
||||
delta = relativedelta(self.user.end_connexion(), date)
|
||||
delta.microseconds = 0
|
||||
delta_con = relativedelta(self.user.end_connexion(), date)
|
||||
delta_memb = relativedelta(self.user.end_adhesion(), date)
|
||||
delta_con.microseconds = 0
|
||||
delta_memb.microseconds = 0
|
||||
try:
|
||||
self.assertEqual(delta, relativedelta(months=2))
|
||||
self.assertEqual(delta_con, relativedelta(months=2))
|
||||
self.assertEqual(delta_memb, relativedelta(months=2))
|
||||
except Exception as e:
|
||||
invoice1.delete()
|
||||
invoice2.delete()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue