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

On avance encore un peu

This commit is contained in:
Yoann Pétri 2018-11-26 00:15:09 +01:00
parent a45d7746f5
commit a78828375c
13 changed files with 214 additions and 49 deletions

View file

@ -1,3 +1,6 @@
{
"python.pythonPath": "/home/nanoy/.virtualenvs/coopeV3/bin/python"
"python.pythonPath": "/home/nanoy/.virtualenvs/coopeV3/bin/python",
"python.linting.pylintArgs": [
"--load-plugins=pylint_django"
],
}

View file

@ -9,13 +9,13 @@ def admin_required(view):
"""
Test if the user is staff
"""
return user_passes_test(view, lambda u:u.is_staff)
return user_passes_test(lambda u: u.is_staff)(view)
def superuser_required(view):
"""
Test if the user is superuser
"""
return user_passes_test(view, lambda u:u.is_superuser)
return user_passes_test(lambda u: u.is_superuser)(view)
def self_or_has_perm(pkName, perm):
"""

View file

@ -123,7 +123,7 @@
{% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center">
{% endif %}
<td><button class="boutonsProduit" disabled target="{{product.codeBarre}}" type="{{product.typeSaisie}}">{{product.nom}}</button></td>
<td><button class="product" target="{{product.barcode}}">{{product.name}}</button></td>
{% if forloop.counter|divisibleby:4 %}
</tr>
{% endif %}
@ -136,7 +136,7 @@
{% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center">
{% endif %}
<td><button class="boutonsProduit" disabled target="{{product.codeBarre}}" type="{{product.typeSaisie}}">{{product.nom}}</button></td>
<td><button class="product" target="{{product.barcode}}">{{product.name}}</button></td>
{% if forloop.counter|divisibleby:4 %}
</tr>
{% endif %}
@ -146,11 +146,11 @@
{% endif %}
<tr style="text-align:center; font-weight:bold;"><td colspan="4">Bouffe</td></tr>
{% for product in autreBouffe %}
{% for product in food %}
{% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center">
{% endif %}
<td><button class="boutonsProduit" disabled target="{{product.codeBarre}}" type="{{product.typeSaisie}}">{{product.nom}}</button></td>
<td><button class="product" target="{{product.barcode}}">{{product.name}}</button></td>
{% if forloop.counter|divisibleby:4 %}
</tr>
{% endif %}
@ -164,7 +164,7 @@
{% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center">
{% endif %}
<td><button class="boutonsProduit" disabled target="{{product.codeBarre}}" type="MN">{{product.nom}}</button></td>
<td><button class="product" target="{{product.barcode}}">{{product.name}}</button></td>
{% if forloop.counter|divisibleby:4 %}
</tr>
{% endif %}

View file

@ -0,0 +1,41 @@
{% extends 'base.html' %}
{% block entete %}<h1>Gestion des produits</h1>{% endblock %}
{% block navbar%}
<ul>
<li><a href="#first">Liste des menus</a></li>
</ul>
{% endblock %}
{% block content %}
<section id="first" class="main">
<header class="major">
<h2>Liste des menus</h2>
</header>
<a class="button" href="{% url 'gestion:addMenu' %}">Créer un menu</a><br><br>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Nom</th>
<th>Prix</th>
<th>Code barre</th>
<th>Produits</th>
<th>Actif</th>
<th>Administrer</th>
</tr>
</thead>
<tbody>
{% for menu in menus %}
<tr>
<td>{{ menu.name }}</td>
<td>{{ menu.amount}} €</td>
<td>{{ menu.barcode }}</td>
<td>{% for art in menu.articles.all %}{{art}},{% endfor %}</td>
<td>{{ menu.is_active | yesno:"Oui, Non"}}</td>
<td><a href="{% url 'gestion:switchActivateMenu' menu.pk %}" class="button small">{% if menu.is_active %}Désa{% else %}A{% endif %}ctiver</a> <a href="{% url 'gestion:editMenu' menu.pk %}" class="button small">Modifier</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
{% endblock %}

View file

@ -10,14 +10,14 @@
<header class="major">
<h2>Général</h2>
</header>
<a class="button small">(Dés)Activer</a> <a class="button small">Modifier</a> <a href="#" class="button small">Supprimer</a><br>
<a href="{% url 'gestion:switchActivate' product.pk %}" class="button small">{% if product.is_active %}Désa{% else %}A{% endif %}ctiver</a> <a href="{% url 'gestion:editProduct' product.pk %}" class="button small">Modifier</a><br>
<strong>Nom</strong> : {{ product.name }}<br>
<strong>Prix de vente</strong> : {{ product.amount }}€<br>
<strong>Stock en soute</strong> : {{ product.stockHold }}<br>
<strong>Stock au bar</strong> : {{ product.stockBar }}<br>
<strong>Code Barre</strong> : {{ product.barcode }}<br>
<strong>Catégorie</strong> : {{ product.category }}<br>
<strong>Actif</strong> : {{ product.active }}<br>
<strong>Actif</strong> : {{ product.is_active | yesno:"Oui, Non"}}<br>
<strong>Dégré</strong> : {{ product.deg }}<br>
<strong>Volume</strong> : {{ product.volume }}cl<br>
</section>

View file

@ -5,7 +5,6 @@
<li><a href="#first">Produits</a></li>
<li><a href="#second">Futs</a></li>
<li><a href="#third">Menus</a></li>
<li><a href="#fourth">Stocks</a></li>
</ul>
{% endblock %}
{% block content %}
@ -39,18 +38,8 @@
Actions possibles :
<ul>
<li><a href="{% url 'gestion:addMenu' %}">Créer un menu</a></li>
<li><a href="">Rechercher un menu</a></li>
<li><a href="{% url 'users:adminsIndex' %}">Lister les menus</a></li>
</ul>
</section>
<section id="fourth" class="main">
<header class="major">
<h2>Stocks</h2>
</header>
Actions possibles :
<ul>
<li><a href="{% url 'users:addSuperuser' %}">Voir les Stocks</a></li>
<li><a href="{% url 'users:superusersIndex' %}">Classement sur un produit</a></li>
<li><a href="{% url 'gestion:searchMenu' %}">Rechercher un menu</a></li>
<li><a href="{% url 'gestion:menusList' %}">Lister les menus</a></li>
</ul>
</section>
{% endblock %}

View file

@ -36,10 +36,10 @@
<td>{{ product.stockBar }}</td>
<td>{{ product.barcode }}</td>
<td>{{ product.category }}</td>
<td>{{ product.is_active }}</td>
<td>{{ product.degree }}</td>
<td>{{ product.volume }}</td>
<td></td>
<td>{{ product.is_active | yesno:"Oui, Non"}}</td>
<td>{{ product.deg }}</td>
<td>{{ product.volume }} cl</td>
<td><a href="{% url 'gestion:productProfile' product.pk %}" class="button small">Profil</a> <a href="{% url 'gestion:switchActivate' product.pk %}" class="button small">{% if product.is_active %}Désa{% else %}A{% endif %}ctiver</a> <a href="{% url 'gestion:editProduct' product.pk %}" class="button small">Modifier</a></td>
</tr>
{% endfor %}
</tbody>

View file

@ -10,6 +10,8 @@ urlpatterns = [
path('productsIndex', views.productsIndex, name="productsIndex"),
path('productsList', views.productsList, name="productsList"),
path('addProduct', views.addProduct, name="addProduct"),
path('editProduct/<int:pk>', views.editProduct, name="editProduct"),
path('switchActivate/<int:pk>', views.switch_activate, name="switchActivate"),
path('addKeg', views.addKeg, name="addKeg"),
path('openKeg', views.openKeg, name="openKeg"),
path('closeKeg', views.closeKeg, name="closeKeg"),
@ -19,6 +21,10 @@ urlpatterns = [
path('openDirectKeg/<int:pk>', views.openDirectKeg, name="openDirectKeg"),
path('closeDirectKeg/<int:pk>', views.closeDirectKeg, name="closeDirectKeg"),
path('addMenu', views.addMenu, name="addMenu"),
path('searchMenu', views.searchMenu, name="searchMenu"),
path('editMenu/<int:pk>', views.edit_menu, name="editMenu"),
path('menusList', views.menus_list, name="menusList"),
path('swicthActivateMenu/<int:pk>', views.switch_activate_menu, name="switchActivateMenu"),
path('getProduct/<str:barcode>', views.getProduct, name="getProduct"),
path('order', views.order, name="order"),
path('ranking', views.ranking, name="ranking"),
@ -28,5 +34,5 @@ urlpatterns = [
path('products-autocomplete', views.ProductsAutocomplete.as_view(), name="products-autocomplete"),
path('kegs-positive-autocomplete', views.KegPositiveAutocomplete.as_view(), name="kegs-positive-autocomplete"),
path('kegs-active-autocomplete', views.KegActiveAutocomplete.as_view(), name="kegs-active-autocomplete"),
path('menus-autcomplete', views.MenusAutocomplete.as_view(), name="menus-autocomplete"),
]

View file

@ -155,9 +155,20 @@ def addProduct(request):
if(form.is_valid()):
form.save()
messages.success(request, "Le produit a bien été ajouté")
return redirect(reverse('gestion:productsIndex'))
return redirect(reverse('gestion:productsList'))
return render(request, "form.html", {"form": form, "form_title": "Ajout d'un produit", "form_button": "Ajouter"})
@login_required
@permission_required('gestion.edit_product')
def editProduct(request, pk):
product = get_object_or_404(Product, pk=pk)
form = ProductForm(request.POST or None, instance=product)
if(form.is_valid()):
form.save()
messages.success(request, "Le produit a bien été modifié")
return redirect(reverse('gestion:productsList'))
return render(request, "form.html", {"form": form, "form_title": "Modification d'un produit", "form_button": "Modifier"})
@login_required
@permission_required('gestion.view_product')
def productsList(request):
@ -184,11 +195,24 @@ def getProduct(request, barcode):
data = json.dumps({"pk": product.pk, "barcode" : product.barcode, "name": product.name, "amount" : product.amount})
return HttpResponse(data, content_type='application/json')
@login_required
@permission_required('gestion.edit_product')
def switch_activate(request, pk):
"""
If the product is active, switch to not active.
If the product is not active, switch to active.
"""
product = get_object_or_404(Product, pk=pk)
product.is_active = 1 - product.is_active
product.save()
messages.success(request, "La disponibilité du produit a bien été changée")
return redirect(reverse('gestion:productsList'))
class ProductsAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Product.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
qs = qs.filter(name__istartswith=self.q)
return qs
########## Kegs ##########
@ -325,9 +349,20 @@ def addMenu(request):
if(form.is_valid()):
menu = form.save()
messages.success(request, "Le menu " + menu.name + " a bien été ajouté")
return redirect(reverse('gestion:productsIndex'))
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})
@login_required
@permission_required('gestion.edit_menu')
def edit_menu(request, pk):
menu = get_object_or_404(Menu, pk=pk)
form = MenuForm(request.POST or None, instance=menu)
extra_css = "#id_articles{height:200px;}"
if form.is_valid():
form.save()
messages.success(request, "Le menu a bien été modifié")
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})
@login_required
@permission_required('gestion.view_menu')
@ -352,10 +387,29 @@ def searchMenu(request):
"""
form = SearchMenuForm(request.POST or None)
if(form.is_valid()):
menu = form.menu
return redirect(reverse('gestion:changeMenu', kwargs={'pk':menu.pk}))
menu = form.cleaned_data['menu']
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"})
@login_required
@permission_required('gestion.view_menu')
def menus_list(request):
menus = Menu.objects.all()
return render(request, "gestion/menus_list.html", {"menus": menus})
@login_required
@permission_required('gestion.edit_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.
"""
menu = get_object_or_404(Menu, pk=pk)
menu.is_active = 1 - menu.is_active
menu.save()
messages.success(request, "La disponibilité du menu a bien été changée")
return redirect(reverse('gestion:menusList'))
class MenusAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Menu.objects.all()

10
staticfiles/chart.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -11,9 +11,6 @@
<span class="tabulation2">
<a href="{% url 'gestion:productsIndex' %}">Gestion des produits</a>
</span>
<span class="tabulation2">
<a href="{% url 'gestion:annualRanking' %}">Comptabilité</a>
</span>
<span class="tabulation2">
<a href="{% url 'gestion:ranking' %}">Classement</a>
</span>

View file

@ -81,6 +81,47 @@
</div>
</div>
<section class="row uniform">
<canvas id="myChart" width="2000px" height="2000px"></canvas>
<script src="{% static 'chart.min.js' %}"></script>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: [{% for p in products %}"{{p}}", {% endfor %}],
datasets: [{
label: '# of Votes',
data: [{% for q in quantities %}{{q}}, {% endfor %}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
</script>
</section>
</section>
<section id="second" class="main">
@ -102,11 +143,14 @@
</tr>
</thead>
<tbody id="bodyTransaction">
{% for consumption in consumptions %}
{% for c in lastConsumptions %}
<tr>
{% for part in consumption %}
<th>{{part}}</th>
{%endfor%}
<td>{{c.product}}</td>
<td>{{c.quantity}}</td>
<td>{{c.amount}}</td>
<td>{{c.paymentMethod}}</td>
<td>{{c.date}}</td>
<td></td>
</tr>
{%endfor%}
</tbody>
@ -119,22 +163,22 @@
<h2>{{self | yesno:"Mes derniers,Derniers"}} rechargements</h2>
<p>(Affichage des 5 dernières entrées)</p>
</header>
<section id="rechargements">
<section>
<div class="table-wrapper">
<table>
<thead id="headRechargement">
<thead>
<tr>
<th>Montant</th>
<th>Type de Rechargement</th>
<th>Date</th>
</tr>
</thead>
<tbody id="bodyRechargement">
<tbody>
{% for reload in reloads %}
<tr>
<th>{{reload.amount}}€</th>
<th>{{reload.PaymentMethod}}</th>
<th>{{reload.date}}</th>
<td>{{reload.amount}}€</td>
<td>{{reload.PaymentMethod}}</td>
<td>{{reload.date}}</td>
</tr>
{% endfor %}
</tbody>

View file

@ -15,7 +15,7 @@ from dal import autocomplete
from coopeV3.acl import admin_required, superuser_required, self_or_has_perm, active_required
from .models import CotisationHistory, WhiteListHistory, School
from .forms import CreateUserForm, LoginForm, CreateGroupForm, EditGroupForm, SelectUserForm, GroupsEditForm, EditPasswordForm, addCotisationHistoryForm, addCotisationHistoryForm, addWhiteListHistoryForm, SelectNonAdminUserForm, SelectNonSuperUserForm, SchoolForm
from gestion.models import Reload
from gestion.models import Reload, Consumption, ConsumptionHistory
@active_required
def loginView(request):
@ -112,7 +112,28 @@ def profile(request, pk):
cotisations = CotisationHistory.objects.filter(user=user)
whitelists = WhiteListHistory.objects.filter(user=user)
reloads = Reload.objects.filter(customer=user).order_by('-date')
return render(request, "users/profile.html", {"user":user, "self":self, "cotisations":cotisations, "whitelists": whitelists, "reloads": reloads})
consumptionsChart = Consumption.objects.filter(customer=user)
products = []
quantities = []
for ch in consumptionsChart:
if ch.product in products:
i = products.index(ch.product)
quantities[i] += ch.quantity
else:
products.append(ch.product)
quantities.append(ch.quantity)
lastConsumptions = ConsumptionHistory.objects.filter(customer=user).order_by('-date')[:10]
return render(request, "users/profile.html",
{
"user":user,
"self":self,
"cotisations":cotisations,
"whitelists": whitelists,
"reloads": reloads,
"products": products,
"quantities": quantities,
"lastConsumptions": lastConsumptions
})
@active_required
@login_required