3
0
Fork 0
mirror of https://github.com/nanoy42/coope synced 2024-11-22 03:13:12 +00:00

Docs, permissions

This commit is contained in:
Yoann Pétri 2018-12-02 16:28:40 +01:00
parent c506dde5c2
commit 74b628d831
15 changed files with 1052 additions and 78 deletions

View file

@ -56,6 +56,7 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
'django.contrib.admindocs.middleware.XViewMiddleware',
]
ROOT_URLCONF = 'coopeV3.urls'

View file

@ -0,0 +1,87 @@
# Generated by Django 2.1 on 2018-12-02 15:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('gestion', '0008_auto_20181130_1904'),
]
operations = [
migrations.RemoveField(
model_name='historicalstocking',
name='history_user',
),
migrations.DeleteModel(
name='Stocking',
),
migrations.AlterModelOptions(
name='consumption',
options={'verbose_name': 'Consommation totale'},
),
migrations.AlterModelOptions(
name='consumptionhistory',
options={'verbose_name': 'Consommation'},
),
migrations.AlterModelOptions(
name='historicalconsumption',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Consommation totale'},
),
migrations.AlterModelOptions(
name='historicalconsumptionhistory',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Consommation'},
),
migrations.AlterModelOptions(
name='historicalkeg',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Fût'},
),
migrations.AlterModelOptions(
name='historicalkeghistory',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Historique de fût'},
),
migrations.AlterModelOptions(
name='historicalmenuhistory',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Historique de menu'},
),
migrations.AlterModelOptions(
name='historicalproduct',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Produit'},
),
migrations.AlterModelOptions(
name='historicalrefund',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Remboursement'},
),
migrations.AlterModelOptions(
name='historicalreload',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Rechargement'},
),
migrations.AlterModelOptions(
name='keg',
options={'permissions': (('open_keg', 'Peut percuter les fûts'), ('close_keg', 'Peut fermer les fûts')), 'verbose_name': 'Fût'},
),
migrations.AlterModelOptions(
name='keghistory',
options={'verbose_name': 'Historique de fût'},
),
migrations.AlterModelOptions(
name='menuhistory',
options={'verbose_name': 'Historique de menu'},
),
migrations.AlterModelOptions(
name='product',
options={'verbose_name': 'Produit'},
),
migrations.AlterModelOptions(
name='refund',
options={'verbose_name': 'Remboursement'},
),
migrations.AlterModelOptions(
name='reload',
options={'verbose_name': 'Rechargement'},
),
migrations.DeleteModel(
name='HistoricalStocking',
),
]

View file

@ -1,12 +1,15 @@
from django.db import models
from django.contrib.auth.models import User
from preferences.models import PaymentMethod
from django.core.exceptions import ValidationError
from simple_history.models import HistoricalRecords
from django.core.validators import MinValueValidator
from preferences.models import PaymentMethod
from django.core.exceptions import ValidationError
class Product(models.Model):
"""
Stores a product
"""
P_PRESSION = 'PP'
D_PRESSION = 'DP'
G_PRESSION = 'GP'
@ -23,6 +26,8 @@ class Product(models.Model):
(FOOD, "Bouffe autre que panini"),
(PANINI, "Bouffe pour panini"),
)
class Meta:
verbose_name = "Produit"
name = models.CharField(max_length=40, verbose_name="Nom", unique=True)
amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Prix de vente", validators=[MinValueValidator(0)])
stockHold = models.IntegerField(default=0, verbose_name="Stock en soute")
@ -66,7 +71,11 @@ def isGalopin(id):
)
class Keg(models.Model):
"""
Stores a keg
"""
class Meta:
verbose_name = "Fût"
permissions = (
("open_keg", "Peut percuter les fûts"),
("close_keg", "Peut fermer les fûts")
@ -87,6 +96,12 @@ class Keg(models.Model):
return self.name
class KegHistory(models.Model):
"""
Stores a keg history, related to :model:`gestion.Keg`
"""
class Meta:
verbose_name = "Historique de fût"
keg = models.ForeignKey(Keg, on_delete=models.PROTECT)
openingDate = models.DateTimeField(auto_now_add=True)
quantitySold = models.DecimalField(decimal_places=2, max_digits=5, default=0)
@ -104,6 +119,12 @@ class KegHistory(models.Model):
return res
class Reload(models.Model):
"""
Stores reloads
"""
class Meta:
verbose_name = "Rechargement"
customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="reload_taken", verbose_name="Client")
amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant", validators=[MinValueValidator(0)])
PaymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT, verbose_name="Moyen de paiement")
@ -124,15 +145,13 @@ class Raming(models.Model):
def __str__(self):
return "Percussion d'un {0} effectué par {1} le {2}".format(self.keg, self.coopeman, self.date)
class Stocking(models.Model):
date = models.DateTimeField(auto_now_add=True)
history = HistoricalRecords()
def __str__(self):
return "Inventaire fait le {0}".format(self.date)
class Refund(models.Model):
"""
Stores refunds
"""
class Meta:
verbose_name = "Remboursement"
date = models.DateTimeField(auto_now_add=True)
customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="refund_taken", verbose_name="Client")
amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant", validators=[MinValueValidator(0)])
@ -144,6 +163,9 @@ class Refund(models.Model):
class Menu(models.Model):
"""
Stores menus
"""
name = models.CharField(max_length=255, verbose_name="Nom")
amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant", validators=[MinValueValidator(0)])
barcode = models.CharField(max_length=20, unique=True, verbose_name="Code barre")
@ -162,6 +184,12 @@ class Menu(models.Model):
return res
class MenuHistory(models.Model):
"""
Stores MenuHistory related to :model:`gestion.Menu`
"""
class Meta:
verbose_name = "Historique de menu"
customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="menu_taken")
quantity = models.PositiveIntegerField(default=0)
paymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT)
@ -175,6 +203,12 @@ class MenuHistory(models.Model):
return "{2} a consommé {0} {1}".format(self.quantity, self.menu, self.customer)
class ConsumptionHistory(models.Model):
"""
Stores consumption history related to :model:`gestion.Product`
"""
class Meta:
verbose_name = "Consommation"
customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="consumption_taken")
quantity = models.PositiveIntegerField(default=0)
paymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT)
@ -188,6 +222,12 @@ class ConsumptionHistory(models.Model):
return "{0} {1} consommé par {2} le {3} (encaissé par {4})".format(self.quantity, self.product, self.customer, self.date, self.coopeman)
class Consumption(models.Model):
"""
Stores total consumptions
"""
class Meta:
verbose_name = "Consommation totale"
customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="consumption_global_taken")
product = models.ForeignKey(Product, on_delete=models.PROTECT)
quantity = models.PositiveIntegerField(default=0)

View file

@ -1,24 +0,0 @@
{% extends "base.html" %}
{%load static %}
{%block entete%}<h1>Classement</h1>{%endblock%}
{% block nav %}
<ul>
<li><a href="#first">Dezo pas Dezo</a></li>
</ul>
{% endblock %}
{% block content %}
<section id="intro" class="main">
<div class="spotlight">
<div class="content">
<header class="major">
<h2>Dezo pas dezo</h2>
</header>
<div class="row">
<div class="12u$">
Dû à des problèmes techniques, cet onglet n'est actuellement pas disponible.
</div>
</div>
</div>
</div>
</section>
{%endblock%}

View file

@ -39,6 +39,7 @@
</header>
<div class="row uniform">
<div class="12u$">
<a class="button small" href="">Annuler</a><br><br>
{{gestion_form}}
</div>
</div>

View file

@ -29,7 +29,6 @@ urlpatterns = [
path('getProduct/<str:barcode>', views.getProduct, name="getProduct"),
path('order', views.order, name="order"),
path('ranking', views.ranking, name="ranking"),
path('annualRanking', views.annualRanking, name="annualRanking"),
path('searchProduct', views.searchProduct, name="searchProduct"),
path('cancelConsumption/<int:pk>', views.cancel_consumption, name="cancelConsumption"),
path('cancelMenu/<int:pk>', views.cancel_menu, name="cancelMenu"),

View file

@ -21,6 +21,45 @@ from preferences.models import PaymentMethod
@login_required
@acl_or('gestion.add_consumptionhistory', 'gestion.add_reload', 'gestion.add_refund')
def manage(request):
"""
Display the manage page
**Context**
``gestion_form``
The manage form
``reload_form``
The :model:`gestion.Reload` form
``refund_form``
The :model:`gestion.Refund` form
``bieresPression``
A list of active :model:`gestion.Product` corresponding to draft beers
``bieresBouteille``
A list of active :model:`gestion.Product` corresponding to bottle beers
``panini``
A list of active :model:`gestion.Product` corresponding to panini items
``food``
A list of active :model:`gestion.Product` corresponding to non-panini items
``soft``
A list of active :model:`gestion.Product` correspond to non alcoholic beverage
``menus``
The list of active :model:`gestion.Menu`
``pay_buttons``
List of :model:`paymentMethod`
**Template**
:template:`gestion/manage.html`
"""
pay_buttons = PaymentMethod.objects.filter(is_active=True)
gestion_form = GestionForm(request.POST or None)
reload_form = ReloadForm(request.POST or None)
@ -39,12 +78,27 @@ def manage(request):
bieresPression.append(keg.demi)
if(keg.galopin):
bieresPression.append(keg.galopin)
return render(request, "gestion/manage.html", {"gestion_form": gestion_form, "reload_form": reload_form, "refund_form": refund_form, "bieresPression": bieresPression, "bieresBouteille": bieresBouteille, "panini": panini, "food": food, "soft": soft, "menus": menus, "pay_buttons": pay_buttons})
return render(request, "gestion/manage.html", {
"gestion_form": gestion_form,
"reload_form": reload_form,
"refund_form": refund_form,
"bieresPression": bieresPression,
"bieresBouteille": bieresBouteille,
"panini": panini,
"food": food,
"soft": soft,
"menus": menus,
"pay_buttons": pay_buttons
})
@active_required
@login_required
@permission_required('gestion.add_consumptionhistory')
@csrf_exempt
def order(request):
"""
Process the given order. Called by a js/JQuery script.
"""
if("user" not in request.POST or "paymentMethod" not in request.POST or "amount" not in request.POST or "order" not in request.POST):
return HttpResponse("Erreur du POST")
else:
@ -120,34 +174,42 @@ def order(request):
article.save()
return HttpResponse("La commande a bien été effectuée")
@active_required
@login_required
@permission_required('gestion.add_reload')
def reload(request):
"""
Process a reload request
"""
reload_form = ReloadForm(request.POST or None)
if(reload_form.is_valid()):
reloadEntry = reload_form.save(commit=False)
reloadEntry.coopeman = request.user
reloadEntry.save()
if reload_form.is_valid():
reload_entry = reload_form.save(commit=False)
reload_entry.coopeman = request.user
reload_entry.save()
user = reload_form.cleaned_data['customer']
amount = reload_form.cleaned_data['amount']
user.profile.credit += amount
user.save()
messages.success(request,"Le compte de " + user.username + " a bien été crédité de " + str(amount) + "")
messages.success(request, "Le compte de " + user.username + " a bien été crédité de " + str(amount) + "")
else:
messages.error(request, "Le rechargement a échoué")
return redirect(reverse('gestion:manage'))
@active_required
@login_required
@permission_required('gestion.add_refund')
def refund(request):
"""
Process a refund request
"""
refund_form = RefundForm(request.POST or None)
if(refund_form.is_valid()):
if refund_form.is_valid():
user = refund_form.cleaned_data['customer']
amount = refund_form.cleaned_data['amount']
if(amount <= user.profile.balance):
refundEntry = refund_form.save(commit = False)
refundEntry.coopeman = request.user
refundEntry.save()
if amount <= user.profile.balance:
refund_entry = refund_form.save(commit = False)
refund_entry.coopeman = request.user
refund_entry.save()
user.profile.credit -= amount
user.save()
messages.success(request, "Le compte de " + user.username + " a bien été remboursé de " + str(amount) + "")
@ -157,9 +219,16 @@ def refund(request):
messages.error(request, "Le remboursement a échoué")
return redirect(reverse('gestion:manage'))
@active_required
@login_required
@permission_required('gestion.delete_consumptionhistory')
def cancel_consumption(request, pk):
"""
Cancel a :model:`gestion.ConsumptionHistory`
``pk``
The primary key of the :model:`gestion.ConsumptionHistory` that have to be cancelled
"""
consumption = get_object_or_404(ConsumptionHistory, pk=pk)
user = consumption.customer
user.profile.debit -= consumption.amount
@ -168,9 +237,16 @@ def cancel_consumption(request, pk):
messages.success(request, "La consommation a bien été annulée")
return redirect(reverse('users:profile', kwargs={'pk': user.pk}))
@active_required
@login_required
@permission_required('gestion.delete_menuhistory')
def cancel_menu(request, pk):
"""
Cancel a :model:`gestion.MenuHistory`
``pk``
The primary key of the :model:`gestion.MenuHistory` that have to be cancelled
"""
menu_history = get_object_or_404(MenuHistory, pk=pk)
user = menu_history.customer
user.profile.debit -= menu_history.amount
@ -180,15 +256,41 @@ def cancel_menu(request, pk):
return redirect(reverse('users:profile', kwargs={'pk': user.pk}))
########## Products ##########
@active_required
@login_required
@acl_or('gestion.add_product', 'gestion.view_product', 'gestion.add_keg', 'gestion.view_keg', 'gestion.change_keg', 'gestion.view_menu', 'gestion.add_menu')
def productsIndex(request):
"""
Display the products manage static page
**Template**
:template:`gestion/products_index.html`
"""
return render(request, "gestion/products_index.html")
@active_required
@login_required
@permission_required('gestion.add_product')
def addProduct(request):
"""
Form to add a :model:`gestion.Product`
**Context**
``form``
The ProductForm instance
``form_title``
The title for the form template
``form_button``
The text of the button for the form template
**Template**
:template:`form.html`
"""
form = ProductForm(request.POST or None)
if(form.is_valid()):
form.save()
@ -196,9 +298,31 @@ def addProduct(request):
return redirect(reverse('gestion:productsList'))
return render(request, "form.html", {"form": form, "form_title": "Ajout d'un produit", "form_button": "Ajouter"})
@active_required
@login_required
@permission_required('gestion.edit_product')
@permission_required('gestion.change_product')
def editProduct(request, pk):
"""
Form to edit a :model:`gestion.Product`
``pk``
The primary key of the requested :model:`gestion.Product`
**Context**
``form``
The ProductForm instance
``form_title``
The title for the form template
``form_button``
The text of the button for the form template
**Template**
:template:`form.html`
"""
product = get_object_or_404(Product, pk=pk)
form = ProductForm(request.POST or None, instance=product)
if(form.is_valid()):
@ -207,38 +331,96 @@ def editProduct(request, pk):
return redirect(reverse('gestion:productsList'))
return render(request, "form.html", {"form": form, "form_title": "Modification d'un produit", "form_button": "Modifier"})
@active_required
@login_required
@permission_required('gestion.view_product')
def productsList(request):
"""
Display the list of :model:`gestion.Product`
**Context**
``products``
The list of :model:`gestion.Product`
**Template**
:template:`gestion/products_list.html`
"""
products = Product.objects.all()
return render(request, "gestion/products_list.html", {"products": products})
@active_required
@login_required
@permission_required('gestion.view_product')
def searchProduct(request):
"""
Form to search a :model:`gestion.Product`
**Context**
``form``
The SearchProductForm instance
``form_title``
The title for the form template
``form_button``
The text of the button for the form template
**Template**
:template:`form.html`
"""
form = SearchProductForm(request.POST or None)
if(form.is_valid()):
return redirect(reverse('gestion:productProfile', kwargs={'pk': form.cleaned_data['product'].pk }))
return render(request, "form.html", {"form": form, "form_title":"Rechercher un produit", "form_button": "Rechercher"})
@active_required
@login_required
@permission_required('gestion.view_product')
def productProfile(request, pk):
"""
Display the profile of a :model:`gestion.Product`
``pk``
The primary key of the requested :model:`gestion.Product`
**Context**
``product``
The :model:`gestion.Product` instance
**Template**
:model:`gestion/product_profile.html`
"""
product = get_object_or_404(Product, pk=pk)
return render(request, "gestion/product_profile.html", {"product": product})
@active_required
@login_required
def getProduct(request, barcode):
"""
Get :model:`gestion.Product` by barcode. Called by a js/JQuery script
``barcode``
The requested barcode
"""
product = Product.objects.get(barcode=barcode)
data = json.dumps({"pk": product.pk, "barcode" : product.barcode, "name": product.name, "amount" : product.amount})
return HttpResponse(data, content_type='application/json')
@active_required
@login_required
@permission_required('gestion.edit_product')
@permission_required('gestion.change_product')
def switch_activate(request, pk):
"""
If the product is active, switch to not active.
If the product is not active, switch to active.
Switch the active status of the requested :model:`gestion.Product`
``pk``
The primary key of the :model:`gestion.Product`
"""
product = get_object_or_404(Product, pk=pk)
product.is_active = 1 - product.is_active
@ -247,6 +429,9 @@ def switch_activate(request, pk):
return redirect(reverse('gestion:productsList'))
class ProductsAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete view for all :model:`gestion.Product`
"""
def get_queryset(self):
qs = Product.objects.all()
if self.q:
@ -255,9 +440,28 @@ class ProductsAutocomplete(autocomplete.Select2QuerySetView):
########## Kegs ##########
@active_required
@login_required
@permission_required('gestion.add_keg')
def addKeg(request):
"""
Display a form to add a :model:`gestion.Keg`
**Context**
``form``
The KegForm instance
``form_title``
The title for the :template:`form.html` template
``form_button``
The text for the button in :template:`form.html` template
**Template**
:template:`form.html`
"""
form = KegForm(request.POST or None)
if(form.is_valid()):
keg = form.save()
@ -265,9 +469,31 @@ def addKeg(request):
return redirect(reverse('gestion:kegsList'))
return render(request, "form.html", {"form":form, "form_title": "Ajout d'un fût", "form_button": "Ajouter"})
@active_required
@login_required
@permission_required('gestion.edit_keg')
@permission_required('gestion.change_keg')
def editKeg(request, pk):
"""
Display a form to edit a :model:`gestion.Keg`
``pk``
The primary key of the requested :model:`gestion.Keg`
**Context**
``form``
The KegForm instance
``form_title``
The title for the :template:`form.html` template
``form_button``
The text for the button in :template:`form.html` template
**Template**
:template:`form.html`
"""
keg = get_object_or_404(Keg, pk=pk)
form = KegForm(request.POST or None, instance=keg)
if(form.is_valid()):
@ -276,9 +502,28 @@ def editKeg(request, pk):
return redirect(reverse('gestion:kegsList'))
return render(request, "form.html", {"form": form, "form_title": "Modification d'un fût", "form_button": "Modifier"})
@active_required
@login_required
@permission_required('gestion.open_keg')
def openKeg(request):
"""
Display a form to open a :model:`gestion.Keg`
**Context**
``form``
The SelectPositiveKegForm instance
``form_title``
The title for the :template:`form.html` template
``form_button``
The text for the button in :template:`form.html` template
**Template**
:template:`form.html`
"""
form = SelectPositiveKegForm(request.POST or None)
if(form.is_valid()):
keg = form.cleaned_data['keg']
@ -296,9 +541,16 @@ def openKeg(request):
return redirect(reverse('gestion:kegsList'))
return render(request, "form.html", {"form": form, "form_title":"Percutage d'un fût", "form_button":"Percuter"})
@active_required
@login_required
@permission_required('gestion.open_keg')
def openDirectKeg(request, pk):
"""
Open the requested :model:`gestion.Keg`
``pk``
The primary key of the :model:`gestion.Keg`
"""
keg = get_object_or_404(Keg, pk=pk)
if(keg.stockHold > 0):
previousKegHistory = KegHistory.objects.filter(keg=keg).filter(isCurrentKegHistory=True)
@ -316,9 +568,28 @@ def openDirectKeg(request, pk):
messages.error(request, "Il n'y a pas de fût en stock")
return redirect(reverse('gestion:kegsList'))
@active_required
@login_required
@permission_required('gestion.close_keg')
def closeKeg(request):
"""
Display a form to close a :model:`gestion.Keg`
**Context**
``form``
The SelectActiveKegForm instance
``form_title``
The title for the :template:`form.html` template
``form_button``
The text for the button in :template:`form.html` template
**Template**
:template:`form.html`
"""
form = SelectActiveKegForm(request.POST or None)
if(form.is_valid()):
keg = form.cleaned_data['keg']
@ -332,11 +603,18 @@ def closeKeg(request):
return redirect(reverse('gestion:kegsList'))
return render(request, "form.html", {"form": form, "form_title":"Fermeture d'un fût", "form_button":"Fermer le fût"})
@active_required
@login_required
@permission_required('gestion:close_keg')
@permission_required('gestion.close_keg')
def closeDirectKeg(request, pk):
"""
Close the requested :model:`gestion.Keg`
``pk``
The pk of the active :model:`gestion.Keg`
"""
keg = get_object_or_404(Keg, pk=pk)
if(keg.is_active):
if keg.is_active:
kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True)
kegHistory.isCurrentKegHistory = False
kegHistory.closingDate = timezone.now()
@ -348,22 +626,60 @@ def closeDirectKeg(request, pk):
messages.error(request, "Le fût n'est pas ouvert")
return redirect(reverse('gestion:kegsList'))
@active_required
@login_required
@permission_required('gestion.view_keg')
def kegsList(request):
"""
Display the list of :model:`gestion.Keg`
**Context**
``kegs_active``
List of active :model:`gestion.Keg`
``kegs_inactive``
List of inactive :model:`gestion.Keg`
**Template**
:template:`gestion/kegs_list.html`
"""
kegs_active = KegHistory.objects.filter(isCurrentKegHistory=True)
ids_actives = kegs_active.values('id')
kegs_inactive = Keg.objects.exclude(id__in = ids_actives)
return render(request, "gestion/kegs_list.html", {"kegs_active": kegs_active, "kegs_inactive": kegs_inactive})
@active_required
@login_required
@permission_required('gestion.view_keghistory')
def kegH(request, pk):
"""
Display the history of requested :model:`gestion.Keg`
``pk``
The primary key of the requested :model:`gestion.Keg`
**Context**
``keg``
The :model:`gestion.Keg` instance
``kegHistory``
List of :model:`gestion.KegHistory` attached to keg
**Template**
:template:`gestion/kegh.html`
"""
keg = get_object_or_404(Keg, pk=pk)
kegHistory = KegHistory.objects.filter(keg=keg).order_by('-openingDate')
return render(request, "gestion/kegh.html", {"keg": keg, "kegHistory": kegHistory})
class KegActiveAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete view for active :model:`gestion.Keg`
"""
def get_queryset(self):
qs = Keg.objects.filter(is_active = True)
if self.q:
@ -371,6 +687,9 @@ class KegActiveAutocomplete(autocomplete.Select2QuerySetView):
return qs
class KegPositiveAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete view for :model:`gestion.Keg` with positive stockHold
"""
def get_queryset(self):
qs = Keg.objects.filter(stockHold__gt = 0)
if self.q:
@ -379,9 +698,28 @@ class KegPositiveAutocomplete(autocomplete.Select2QuerySetView):
########## Menus ##########
@active_required
@login_required
@permission_required('gestion.add_menu')
def addMenu(request):
"""
Display a form to add a :model:`gestion.Menu`
**Context**
``form``
The MenuForm instance
``form_title``
The title for the :template:`form.html` template
``form_button``
The text for the button in :template:`form.html` template
**Template**
:template:`form.html`
"""
form = MenuForm(request.POST or None)
extra_css = "#id_articles{height:200px;}"
if(form.is_valid()):
@ -390,9 +728,31 @@ def addMenu(request):
return redirect(reverse('gestion:menusList'))
return render(request, "form.html", {"form":form, "form_title": "Ajout d'un menu", "form_button": "Ajouter", "extra_css": extra_css})
@active_required
@login_required
@permission_required('gestion.edit_menu')
@permission_required('gestion.change_menu')
def edit_menu(request, pk):
"""
Display a form to edit a :model:`gestion.Menu`
``pk``
The primary key of requested :model:`gestion.Menu`
**Context**
``form``
The MenuForm instance
``form_title``
The title for the :template:`form.html` template
``form_button``
The text for the button in :template:`form.html` template
**Template**
:template:`form.html`
"""
menu = get_object_or_404(Menu, pk=pk)
form = MenuForm(request.POST or None, instance=menu)
extra_css = "#id_articles{height:200px;}"
@ -402,11 +762,12 @@ def edit_menu(request, pk):
return redirect(reverse('gestion:menusList'))
return render(request, "form.html", {"form": form, "form_title": "Modification d'un menu", "form_button": "Modifier", "extra_css": extra_css})
@active_required
@login_required
@permission_required('gestion.view_menu')
def searchMenu(request):
"""
Search a menu via SearchMenuForm instance
Search a :model:`gestion.Menu` via SearchMenuForm instance
**Context**
@ -429,18 +790,34 @@ def searchMenu(request):
return redirect(reverse('gestion:editMenu', kwargs={'pk':menu.pk}))
return render(request, "form.html", {"form": form, "form_title": "Recherche d'un menu", "form_button": "Modifier"})
@active_required
@login_required
@permission_required('gestion.view_menu')
def menus_list(request):
"""
Display the :model:`gestion.Menu` list
**Context**
``menus``
The list of :model:`gestion.Menu` instances
**Template**
:template:`gestion/menus_list.html`
"""
menus = Menu.objects.all()
return render(request, "gestion/menus_list.html", {"menus": menus})
@active_required
@login_required
@permission_required('gestion.edit_menu')
@permission_required('gestion.change_menu')
def switch_activate_menu(request, pk):
"""
If the menu is active, switch to not active.
If the menu is not active, switch to active.
Switch active status of a :model:`gestion.Menu`
``pk``
The pk of the :model:`gestion.Menu`
"""
menu = get_object_or_404(Menu, pk=pk)
menu.is_active = 1 - menu.is_active
@ -448,22 +825,50 @@ def switch_activate_menu(request, pk):
messages.success(request, "La disponibilité du menu a bien été changée")
return redirect(reverse('gestion:menusList'))
@active_required
@login_required
@permission_required('gestion.view_menu')
def get_menu(request, barcode):
"""
Search :model:`gestion.Menu` by barcode
``barcode``
The requested barcode
"""
menu = get_object_or_404(Menu, barcode=barcode)
data = json.dumps({"pk": menu.pk, "barcode" : menu.barcode, "name": menu.name, "amount" : menu.amount})
return HttpResponse(data, content_type='application/json')
class MenusAutocomplete(autocomplete.Select2QuerySetView):
"""
Used as autcomplete for all :model:`gestion.Menu`
"""
def get_queryset(self):
qs = Menu.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
########## Ranking ##########
@active_required
@login_required
def ranking(request):
"""
Display the ranking page
**Context**
``bestBuyers``
List of the 25 best buyers
``bestDrinkers``
List of the 25 best drinkers
**Template**
:template: `gestion/ranking.html`
"""
bestBuyers = User.objects.order_by('-profile__debit')[:25]
customers = User.objects.all()
list = []
@ -471,8 +876,4 @@ def ranking(request):
alcohol = customer.profile.alcohol
list.append([customer, alcohol])
bestDrinkers = sorted(list, key=lambda x: x[1], reverse=True)[:25]
return render(request, "gestion/ranking.html", {"bestBuyers": bestBuyers, "bestDrinkers": bestDrinkers})
@login_required
def annualRanking(request):
return render(request, "gestion/annual_ranking.html")
return render(request, "gestion/ranking.html", {"bestBuyers": bestBuyers, "bestDrinkers": bestDrinkers})

View file

@ -4,17 +4,26 @@ from django.core.exceptions import ValidationError
from .models import Cotisation, PaymentMethod, GeneralPreferences
class CotisationForm(forms.ModelForm):
"""
Form to add and edit cotisations
"""
class Meta:
model = Cotisation
fields = "__all__"
class PaymentMethodForm(forms.ModelForm):
"""
Form to add and edit payment methods
"""
class Meta:
model = PaymentMethod
fields = "__all__"
class GeneralPreferencesForm(forms.ModelForm):
"""
Form to edit the general preferences
"""
class Meta:
model = GeneralPreferences
fields = "__all__"

View file

@ -4,6 +4,9 @@ from django.core.validators import MinValueValidator
class PaymentMethod(models.Model):
"""
Stores payment methods
"""
name = models.CharField(max_length=255, verbose_name="Nom")
is_active = models.BooleanField(default=True, verbose_name="Actif")
is_usable_in_cotisation = models.BooleanField(default=True, verbose_name="Cotisations ?")
@ -15,6 +18,9 @@ class PaymentMethod(models.Model):
return self.name
class GeneralPreferences(models.Model):
"""
Stores a unique line of general preferences
"""
is_active = models.BooleanField(default=True)
active_message = models.TextField(blank=True)
global_message = models.TextField(blank=True)
@ -27,6 +33,9 @@ class GeneralPreferences(models.Model):
history = HistoricalRecords()
class Cotisation(models.Model):
"""
Stores cotisations
"""
amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name="Montant", validators=[MinValueValidator(0)])
duration = models.PositiveIntegerField(verbose_name="Durée de la cotisation (jours)")
history = HistoricalRecords()

View file

@ -11,8 +11,20 @@ from .forms import CotisationForm, PaymentMethodForm, GeneralPreferencesForm
@active_required
@login_required
@permission_required('preferences.add_generalpreferences')
@permission_required('preferences.change_generalpreferences')
def generalPreferences(request):
"""
Display form to edit the general preferences
**Context**
``form``
The GeneralPreferences form instance
**Template**
:template:`preferences/general_preferences.html`
"""
gp,_ = GeneralPreferences.objects.get_or_create(pk=1)
form = GeneralPreferencesForm(request.POST or None, instance=gp)
if(form.is_valid()):
@ -25,6 +37,18 @@ def generalPreferences(request):
@login_required
@permission_required('preferences.view_cotisation')
def cotisationsIndex(request):
"""
Lists the cotisations
**Context**
``cotisations``
List of cotisations
**Template**
:template:`preferences/cotisations_index.html`
"""
cotisations = Cotisation.objects.all()
return render(request, "preferences/cotisations_index.html", {"cotisations": cotisations})
@ -32,6 +56,24 @@ def cotisationsIndex(request):
@login_required
@permission_required('preferences.add_cotisation')
def addCotisation(request):
"""
Form to add a cotisation
**Context**
``form``
The CotisationForm form instance
``form_title``
The title of the form
``form_button``
The text of the form button
**Template**
:template:`form.html`
"""
form = CotisationForm(request.POST or None)
if(form.is_valid()):
cotisation = form.save()
@ -43,6 +85,27 @@ def addCotisation(request):
@login_required
@permission_required('preferences.change_cotisation')
def editCotisation(request, pk):
"""
Form to edit a cotisation
``pk``
The primary key of the cotisation
**Context**
``form``
The CotisationForm form instance
``form_title``
The title of the form
``form_button``
The text of the form button
**Template**
:template:`form.html`
"""
cotisation = get_object_or_404(Cotisation, pk=pk)
form = CotisationForm(request.POST or None, instance=cotisation)
if(form.is_valid()):
@ -55,6 +118,12 @@ def editCotisation(request, pk):
@login_required
@permission_required('preferences.delete_cotisation')
def deleteCotisation(request,pk):
"""
Delete a cotisation
``pk``
The primary key of the cotisation to delete
"""
cotisation = get_object_or_404(Cotisation, pk=pk)
message = "La cotisation (" + str(cotisation.duration) + " jours, " + str(cotisation.amount) + "€) a bien été supprimée"
cotisation.delete()
@ -68,6 +137,18 @@ def deleteCotisation(request,pk):
@login_required
@permission_required('preferences.view_paymentmethod')
def paymentMethodsIndex(request):
"""
Lists the paymentMethods
**Context**
``paymentMethods``
List of paymentMethods
**Template**
:template:`preferences/payment_methods_index.html`
"""
paymentMethods = PaymentMethod.objects.all()
return render(request, "preferences/payment_methods_index.html", {"paymentMethods": paymentMethods})
@ -75,6 +156,24 @@ def paymentMethodsIndex(request):
@login_required
@permission_required('preferences.add_paymentmethod')
def addPaymentMethod(request):
"""
Form to add a paymentMethod
**Context**
``form``
The CotisationForm form paymentMethod
``form_title``
The title of the form
``form_button``
The text of the form button
**Template**
:template:`form.html`
"""
form = PaymentMethodForm(request.POST or None)
if(form.is_valid()):
paymentMethod = form.save()
@ -86,6 +185,27 @@ def addPaymentMethod(request):
@login_required
@permission_required('preferences.change_paymentmethod')
def editPaymentMethod(request, pk):
"""
Form to edit a paymentMethod
``pk``
The primary key of the paymentMethod
**Context**
``form``
The PaymentMethodForm form instance
``form_title``
The title of the form
``form_button``
The text of the form button
**Template**
:template:`form.html`
"""
paymentMethod = get_object_or_404(PaymentMethod, pk=pk)
form = PaymentMethodForm(request.POST or None, instance=paymentMethod)
if(form.is_valid()):
@ -98,8 +218,14 @@ def editPaymentMethod(request, pk):
@login_required
@permission_required('preferences.delete_paymentmethod')
def deletePaymentMethod(request,pk):
"""
Delete a paymentMethod
``pk``
The primary key of the paymentMethod to delete
"""
paymentMethod = get_object_or_404(PaymentMethod, pk=pk)
message = "Le moyen de paiement " + paymentMethod.name + " a bien été supprimé"
paymentMethod.delete()
messages.success(request, message)
return redirect(reverse('preferences:paymentMethodsIndex'))
return redirect(reverse('preferences:paymentMethodsIndex'))

View file

@ -14,9 +14,6 @@
<span class="tabulation2">
<a href="{% url 'gestion:ranking' %}">Classement</a>
</span>
<span class="tabulation2">
<a href="{% url 'gestion:annualRanking' %}">Classement sur l'année</a>
</span>
<span class="tabulation2">
<a href="{% url 'preferences:generalPreferences' %}">Admin</a>
</span>

View file

@ -4,10 +4,16 @@ from dal import autocomplete
from .models import School, CotisationHistory, WhiteListHistory
class LoginForm(forms.Form):
"""
Form to log in
"""
username = forms.CharField(max_length=255, label="Nom d'utitisateur")
password = forms.CharField(max_length=255, widget=forms.PasswordInput, label="Mot de passe")
class CreateUserForm(forms.ModelForm):
"""
Form to create a new user
"""
class Meta:
model = User
fields = ("username", "last_name", "first_name", "email")
@ -15,35 +21,59 @@ class CreateUserForm(forms.ModelForm):
school = forms.ModelChoiceField(queryset=School.objects.all(), label="École")
class CreateGroupForm(forms.ModelForm):
"""
Form to create a new group
"""
class Meta:
model = Group
fields = ("name", )
class EditGroupForm(forms.ModelForm):
"""
Form to edit a group
"""
class Meta:
model = Group
fields = "__all__"
class SelectUserForm(forms.Form):
"""
Form to select a user from all users
"""
user = forms.ModelChoiceField(queryset=User.objects.all(), required=True, label="Utilisateur", widget=autocomplete.ModelSelect2(url='users:all-users-autocomplete', attrs={'data-minimum-input-length':2}))
class SelectNonSuperUserForm(forms.Form):
"""
Form to select a user from all non-superuser users
"""
user = forms.ModelChoiceField(queryset=User.objects.filter(is_active=True), required=True, label="Utilisateur", widget=autocomplete.ModelSelect2(url='users:non-super-users-autocomplete', attrs={'data-minimum-input-length':2}))
class SelectNonAdminUserForm(forms.Form):
"""
Form to select a user from all non-staff users
"""
user = forms.ModelChoiceField(queryset=User.objects.filter(is_active=True), required=True, label="Utilisateur", widget=autocomplete.ModelSelect2(url='users:non-admin-users-autocomplete', attrs={'data-minimum-input-length':2}))
class GroupsEditForm(forms.ModelForm):
"""
Form to edit a user's list of groups
"""
class Meta:
model = User
fields = ("groups", )
class EditPasswordForm(forms.Form):
"""
Form to change the password of a user
"""
password = forms.CharField(max_length=255, widget=forms.PasswordInput, label="Mot de passe actuel")
password1 = forms.CharField(max_length=255, widget=forms.PasswordInput, label="Nouveau mot de passe")
password2 = forms.CharField(max_length=255, widget=forms.PasswordInput, label="Nouveau mot de passe (répétez)")
def clean_password2(self):
"""
Verify if the two new passwords are identical
"""
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
@ -51,16 +81,25 @@ class EditPasswordForm(forms.Form):
return password2
class addCotisationHistoryForm(forms.ModelForm):
"""
Form to add a cotisation to user
"""
class Meta:
model = CotisationHistory
fields = ("cotisation", "paymentMethod")
class addWhiteListHistoryForm(forms.ModelForm):
"""
Form to add a whitelist to user
"""
class Meta:
model = WhiteListHistory
fields = ("duration", )
class SchoolForm(forms.ModelForm):
"""
Form to add and edit a school
"""
class Meta:
model = School
fields = "__all__"

View file

@ -0,0 +1,45 @@
# Generated by Django 2.1 on 2018-12-02 15:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0004_historicalcotisationhistory_historicalprofile_historicalschool_historicalwhitelisthistory'),
]
operations = [
migrations.AlterModelOptions(
name='cotisationhistory',
options={'permissions': (('validate_cotisationhistory', 'Peut (in)valider les cotisations'),), 'verbose_name': 'Historique cotisation'},
),
migrations.AlterModelOptions(
name='historicalcotisationhistory',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Historique cotisation'},
),
migrations.AlterModelOptions(
name='historicalprofile',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Profil'},
),
migrations.AlterModelOptions(
name='historicalschool',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical École'},
),
migrations.AlterModelOptions(
name='historicalwhitelisthistory',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Historique accès gracieux'},
),
migrations.AlterModelOptions(
name='profile',
options={'verbose_name': 'Profil'},
),
migrations.AlterModelOptions(
name='school',
options={'verbose_name': 'École'},
),
migrations.AlterModelOptions(
name='whitelisthistory',
options={'verbose_name': 'Historique accès gracieux'},
),
]

View file

@ -8,6 +8,12 @@ from preferences.models import PaymentMethod, Cotisation
from gestion.models import ConsumptionHistory
class School(models.Model):
"""
Stores school
"""
class Meta:
verbose_name = "École"
name = models.CharField(max_length=255, verbose_name="Nom")
history = HistoricalRecords()
@ -15,9 +21,13 @@ class School(models.Model):
return self.name
class CotisationHistory(models.Model):
"""
Stores cotisations history, related to :model:`preferences.Cotisation`
"""
class Meta:
verbose_name = "Historique cotisation"
permissions = (
("validate_consumptionhistory", "Peut (in)valider les cotisations"),
("validate_cotisationhistory", "Peut (in)valider les cotisations"),
)
WAITING = 0
@ -40,6 +50,12 @@ class CotisationHistory(models.Model):
history = HistoricalRecords()
class WhiteListHistory(models.Model):
"""
Stores whitelist history
"""
class Meta:
verbose_name = "Historique accès gracieux"
user = models.ForeignKey(User, on_delete=models.PROTECT)
paymentDate = models.DateTimeField(auto_now_add=True)
endDate = models.DateTimeField()
@ -48,6 +64,12 @@ class WhiteListHistory(models.Model):
history = HistoricalRecords()
class Profile(models.Model):
"""
Stores user profile
"""
class Meta:
verbose_name = "Profil"
user = models.OneToOneField(User, on_delete=models.CASCADE)
credit = models.DecimalField(max_digits=5, decimal_places=2, default=0)
debit = models.DecimalField(max_digits=5, decimal_places=2, default=0)
@ -57,6 +79,9 @@ class Profile(models.Model):
@property
def is_adherent(self):
"""
Test if a user is adherent
"""
if(self.cotisationEnd and self.cotisationEnd > timezone.now()):
return True
else:
@ -64,17 +89,29 @@ class Profile(models.Model):
@property
def balance(self):
"""
Computes user balance
"""
return self.credit - self.debit
def positiveBalance(self):
"""
Test if the user balance is positive or null
"""
return self.balance >= 0
@property
def rank(self):
"""
Computes the rank (by debit) of the user
"""
return Profile.objects.filter(debit__gte=self.debit).count()
@property
def alcohol(self):
"""
Computes ingerated alcohol
"""
consumptions = ConsumptionHistory.objects.filter(customer=self.user).select_related('product')
alcohol = 0
for consumption in consumptions:
@ -87,18 +124,27 @@ class Profile(models.Model):
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
"""
Create profile when user is created
"""
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
"""
Save profile when user is saved
"""
instance.profile.save()
def str_user(self):
if(self.profile.is_adherent):
"""
Rewrite str method for user
"""
if self.profile.is_adherent:
fin = "Adhérent"
else:
fin = "Non adhérent"
return self.username + " (" + self.first_name + " " + self.last_name + ", " + str(self.profile.balance) + "€, " + fin + ")"
User.add_to_class("__str__", str_user)
User.add_to_class("__str__", str_user)

View file

@ -623,6 +623,18 @@ def removeUser(request, groupPk, userPk):
@login_required
@admin_required
def adminsIndex(request):
"""
Lists the staff
**Context**
``admins``
List of staff
**Template**
:template:`users/admins_index.html`
"""
admins = User.objects.filter(is_staff=True)
return render(request, "users/admins_index.html", {"admins": admins})
@ -630,6 +642,24 @@ def adminsIndex(request):
@login_required
@admin_required
def addAdmin(request):
"""
Form to add a member to staff
**Context**
``form``
The SelectNonAdminUserForm form instance
``form_title``
The title of the form
``form_button``
The text of the button
**Template**
:template:`form.html`
"""
form = SelectNonAdminUserForm(request.POST or None)
if(form.is_valid()):
user = form.cleaned_data['user']
@ -637,12 +667,18 @@ def addAdmin(request):
user.save()
messages.success(request, "L'utilisateur " + user.username + " a bien été rajouté aux admins")
return redirect(reverse('users:adminsIndex'))
return render(request, "form.html", {"form_entete": "Gestion des admins", "form": form, "form_title": "Ajout d'un admin", "form_button":"Ajouter l'utilisateur aux admins"})
return render(request, "form.html", {"form": form, "form_title": "Ajout d'un admin", "form_button":"Ajouter l'utilisateur aux admins"})
@active_required
@login_required
@admin_required
def removeAdmin(request, pk):
"""
Remove an user form staff
``pk``
The primary key of the user
"""
user = get_object_or_404(User, pk=pk)
if user.is_staff:
if user.is_superuser:
@ -664,6 +700,18 @@ def removeAdmin(request, pk):
@login_required
@superuser_required
def superusersIndex(request):
"""
Lists the superusers
**Context**
``superusers``
List of superusers
**Template**
:template:`users/superusers_index.html`
"""
superusers = User.objects.filter(is_superuser=True)
return render(request, "users/superusers_index.html", {"superusers": superusers})
@ -671,8 +719,26 @@ def superusersIndex(request):
@login_required
@superuser_required
def addSuperuser(request):
"""
Displays a form to add a superuser
**Context**
``form``
The SelectNonSuperUserForm form instance
``form_title``
The title of the form
``form_button``
The text of the button
**Template**
:template:`form.html`
"""
form = SelectNonSuperUserForm(request.POST or None)
if(form.is_valid()):
if form.is_valid():
user = form.cleaned_data['user']
user.is_admin = True
user.is_superuser = True
@ -685,6 +751,12 @@ def addSuperuser(request):
@login_required
@superuser_required
def removeSuperuser(request, pk):
"""
Removes a user from superusers
``pk``
The primary key of the user
"""
user = get_object_or_404(User, pk=pk)
if user.is_superuser:
if User.objects.filter(is_superuser=True).count() > 1:
@ -703,6 +775,27 @@ def removeSuperuser(request, pk):
@login_required
@permission_required('users.add_cotisationhistory')
def addCotisationHistory(request, pk):
"""
Add a cotisation to the requested user
``pk``
The primary key of the user
**Context**
``form``
The addCotisationHistoryForm form instance
``form_title``
The title of the form
``form_button``
The text of the button
**Template**
:template:`form.html`
"""
user = get_object_or_404(User, pk=pk)
form = addCotisationHistoryForm(request.POST or None)
if(form.is_valid()):
@ -730,8 +823,14 @@ def addCotisationHistory(request, pk):
@active_required
@login_required
@permission_required('users.validate_consumptionhistory')
@permission_required('users.validate_cotisationhistory')
def validateCotisationHistory(request, pk):
"""
Validate the requested :model:`users.CotisationHistory`
``pk``
The primary key of the :model:`users.CotisationHistory`
"""
cotisationHistory = get_object_or_404(CotisationHistory, pk=pk)
cotisationHistory.valid = CotisationHistory.VALID
cotisationHistory.save()
@ -740,8 +839,14 @@ def validateCotisationHistory(request, pk):
@active_required
@login_required
@permission_required('users.validate_consumptionhistory')
@permission_required('users.validate_cotisationhistory')
def invalidateCotisationHistory(request, pk):
"""
Invalidate the requested :model:`users.CotisationHistory`
``pk``
The primary key of the :model:`users.CotisationHistory`
"""
cotisationHistory = get_object_or_404(CotisationHistory, pk=pk)
cotisationHistory.valid = CotisationHistory.INVALID
cotisationHistory.save()
@ -759,6 +864,27 @@ def invalidateCotisationHistory(request, pk):
@login_required
@permission_required('users.add_whitelisthistory')
def addWhiteListHistory(request, pk):
"""
Add a :model:`users.WhitelistHistory` to the requested user
``pk``
The primary key of the user
**Context**
``form``
The addWhiteListHistoryForm form instance
``form_title``
The title of the form
``form_button``
The text of the button
**Template**
:template:`form.html`
"""
user = get_object_or_404(User, pk=pk)
form = addWhiteListHistoryForm(request.POST or None)
if(form.is_valid()):
@ -782,6 +908,18 @@ def addWhiteListHistory(request, pk):
@login_required
@permission_required('users.view_school')
def schoolsIndex(request):
"""
Lists the :model:`users.School`
**Context**
``schools``
List of the :model:`users.School`
**Template**
:template:`users/schools_index.html`
"""
schools = School.objects.all()
return render(request, "users/schools_index.html", {"schools": schools})
@ -789,8 +927,26 @@ def schoolsIndex(request):
@login_required
@permission_required('users.add_school')
def createSchool(request):
"""
Displays form to create :model:`users.School`
**Context**
``form``
The SchoolForm form instance
``form_title``
The title of the form
``form_button``
The text of the button
**Template**
:template:`form.html`
"""
form = SchoolForm(request.POST or None)
if(form.is_valid()):
if form.is_valid():
form.save()
messages.success(request, "L'école a bien été créée")
return redirect(reverse('users:schoolsIndex'))
@ -800,6 +956,27 @@ def createSchool(request):
@login_required
@permission_required('users.change_school')
def editSchool(request, pk):
"""
Displays form to create :model:`users.School`
``pk``
The primary key of :model:`users.School`
**Context**
``form``
The SchoolForm form instance
``form_title``
The title of the form
``form_button``
The text of the button
**Template**
:template:`form.html`
"""
school = get_object_or_404(School, pk=pk)
form = SchoolForm(request.POST or None, instance=school)
if(form.is_valid()):
@ -812,6 +989,12 @@ def editSchool(request, pk):
@login_required
@permission_required('users.delete_school')
def deleteSchool(request, pk):
"""
Delete a :model:`users.School`
``pk``
The primary key of the school to delete
"""
school = get_object_or_404(School, pk=pk)
message = "L'école " + str(school) + " a bien été supprimée"
school.delete()
@ -821,6 +1004,9 @@ def deleteSchool(request, pk):
########## Autocomplete searchs ##########
class AllUsersAutocomplete(autocomplete.Select2QuerySetView):
"""
Autcomplete for all users
"""
def get_queryset(self):
qs = User.objects.all()
if self.q:
@ -828,6 +1014,9 @@ class AllUsersAutocomplete(autocomplete.Select2QuerySetView):
return qs
class ActiveUsersAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete for active users
"""
def get_queryset(self):
qs = User.objects.filter(is_active=True)
if self.q:
@ -835,11 +1024,17 @@ class ActiveUsersAutocomplete(autocomplete.Select2QuerySetView):
return qs
class AdherentAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete for adherents
"""
def get_queryset(self):
qs = User.objects.all()
return qs
class NonSuperUserAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete for non-superuser users
"""
def get_queryset(self):
qs = User.objects.filter(is_superuser=False)
if self.q:
@ -847,6 +1042,9 @@ class NonSuperUserAutocomplete(autocomplete.Select2QuerySetView):
return qs
class NonAdminUserAutocomplete(autocomplete.Select2QuerySetView):
"""
Autocomplete for non-admin users
"""
def get_queryset(self):
qs = User.objects.filter(is_staff=False)
if self.q: