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 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): def superuser_required(view):
""" """
Test if the user is superuser 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): def self_or_has_perm(pkName, perm):
""" """

View file

@ -123,7 +123,7 @@
{% if forloop.counter0|divisibleby:4 %} {% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center"> <tr style="text-align:center">
{% endif %} {% 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 %} {% if forloop.counter|divisibleby:4 %}
</tr> </tr>
{% endif %} {% endif %}
@ -136,7 +136,7 @@
{% if forloop.counter0|divisibleby:4 %} {% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center"> <tr style="text-align:center">
{% endif %} {% 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 %} {% if forloop.counter|divisibleby:4 %}
</tr> </tr>
{% endif %} {% endif %}
@ -146,11 +146,11 @@
{% endif %} {% endif %}
<tr style="text-align:center; font-weight:bold;"><td colspan="4">Bouffe</td></tr> <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 %} {% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center"> <tr style="text-align:center">
{% endif %} {% 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 %} {% if forloop.counter|divisibleby:4 %}
</tr> </tr>
{% endif %} {% endif %}
@ -164,7 +164,7 @@
{% if forloop.counter0|divisibleby:4 %} {% if forloop.counter0|divisibleby:4 %}
<tr style="text-align:center"> <tr style="text-align:center">
{% endif %} {% 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 %} {% if forloop.counter|divisibleby:4 %}
</tr> </tr>
{% endif %} {% 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"> <header class="major">
<h2>Général</h2> <h2>Général</h2>
</header> </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>Nom</strong> : {{ product.name }}<br>
<strong>Prix de vente</strong> : {{ product.amount }}€<br> <strong>Prix de vente</strong> : {{ product.amount }}€<br>
<strong>Stock en soute</strong> : {{ product.stockHold }}<br> <strong>Stock en soute</strong> : {{ product.stockHold }}<br>
<strong>Stock au bar</strong> : {{ product.stockBar }}<br> <strong>Stock au bar</strong> : {{ product.stockBar }}<br>
<strong>Code Barre</strong> : {{ product.barcode }}<br> <strong>Code Barre</strong> : {{ product.barcode }}<br>
<strong>Catégorie</strong> : {{ product.category }}<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>Dégré</strong> : {{ product.deg }}<br>
<strong>Volume</strong> : {{ product.volume }}cl<br> <strong>Volume</strong> : {{ product.volume }}cl<br>
</section> </section>

View file

@ -5,7 +5,6 @@
<li><a href="#first">Produits</a></li> <li><a href="#first">Produits</a></li>
<li><a href="#second">Futs</a></li> <li><a href="#second">Futs</a></li>
<li><a href="#third">Menus</a></li> <li><a href="#third">Menus</a></li>
<li><a href="#fourth">Stocks</a></li>
</ul> </ul>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -39,18 +38,8 @@
Actions possibles : Actions possibles :
<ul> <ul>
<li><a href="{% url 'gestion:addMenu' %}">Créer un menu</a></li> <li><a href="{% url 'gestion:addMenu' %}">Créer un menu</a></li>
<li><a href="">Rechercher un menu</a></li> <li><a href="{% url 'gestion:searchMenu' %}">Rechercher un menu</a></li>
<li><a href="{% url 'users:adminsIndex' %}">Lister les menus</a></li> <li><a href="{% url 'gestion:menusList' %}">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>
</ul> </ul>
</section> </section>
{% endblock %} {% endblock %}

View file

@ -36,10 +36,10 @@
<td>{{ product.stockBar }}</td> <td>{{ product.stockBar }}</td>
<td>{{ product.barcode }}</td> <td>{{ product.barcode }}</td>
<td>{{ product.category }}</td> <td>{{ product.category }}</td>
<td>{{ product.is_active }}</td> <td>{{ product.is_active | yesno:"Oui, Non"}}</td>
<td>{{ product.degree }}</td> <td>{{ product.deg }}</td>
<td>{{ product.volume }}</td> <td>{{ product.volume }} cl</td>
<td></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> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View file

@ -10,6 +10,8 @@ urlpatterns = [
path('productsIndex', views.productsIndex, name="productsIndex"), path('productsIndex', views.productsIndex, name="productsIndex"),
path('productsList', views.productsList, name="productsList"), path('productsList', views.productsList, name="productsList"),
path('addProduct', views.addProduct, name="addProduct"), 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('addKeg', views.addKeg, name="addKeg"),
path('openKeg', views.openKeg, name="openKeg"), path('openKeg', views.openKeg, name="openKeg"),
path('closeKeg', views.closeKeg, name="closeKeg"), path('closeKeg', views.closeKeg, name="closeKeg"),
@ -19,6 +21,10 @@ urlpatterns = [
path('openDirectKeg/<int:pk>', views.openDirectKeg, name="openDirectKeg"), path('openDirectKeg/<int:pk>', views.openDirectKeg, name="openDirectKeg"),
path('closeDirectKeg/<int:pk>', views.closeDirectKeg, name="closeDirectKeg"), path('closeDirectKeg/<int:pk>', views.closeDirectKeg, name="closeDirectKeg"),
path('addMenu', views.addMenu, name="addMenu"), 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('getProduct/<str:barcode>', views.getProduct, name="getProduct"),
path('order', views.order, name="order"), path('order', views.order, name="order"),
path('ranking', views.ranking, name="ranking"), path('ranking', views.ranking, name="ranking"),
@ -28,5 +34,5 @@ urlpatterns = [
path('products-autocomplete', views.ProductsAutocomplete.as_view(), name="products-autocomplete"), path('products-autocomplete', views.ProductsAutocomplete.as_view(), name="products-autocomplete"),
path('kegs-positive-autocomplete', views.KegPositiveAutocomplete.as_view(), name="kegs-positive-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('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()): if(form.is_valid()):
form.save() form.save()
messages.success(request, "Le produit a bien été ajouté") 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"}) 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 @login_required
@permission_required('gestion.view_product') @permission_required('gestion.view_product')
def productsList(request): 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}) data = json.dumps({"pk": product.pk, "barcode" : product.barcode, "name": product.name, "amount" : product.amount})
return HttpResponse(data, content_type='application/json') 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): class ProductsAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self): def get_queryset(self):
qs = Product.objects.all() qs = Product.objects.all()
if self.q: if self.q:
qs = qs.filter(name__istartswith=self.q) qs = qs.filter(name__istartswith=self.q)
return qs return qs
########## Kegs ########## ########## Kegs ##########
@ -325,9 +349,20 @@ def addMenu(request):
if(form.is_valid()): if(form.is_valid()):
menu = form.save() menu = form.save()
messages.success(request, "Le menu " + menu.name + " a bien été ajouté") 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}) 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 @login_required
@permission_required('gestion.view_menu') @permission_required('gestion.view_menu')
@ -352,10 +387,29 @@ def searchMenu(request):
""" """
form = SearchMenuForm(request.POST or None) form = SearchMenuForm(request.POST or None)
if(form.is_valid()): if(form.is_valid()):
menu = form.menu menu = form.cleaned_data['menu']
return redirect(reverse('gestion:changeMenu', kwargs={'pk':menu.pk})) 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"}) 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): class MenusAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self): def get_queryset(self):
qs = Menu.objects.all() 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"> <span class="tabulation2">
<a href="{% url 'gestion:productsIndex' %}">Gestion des produits</a> <a href="{% url 'gestion:productsIndex' %}">Gestion des produits</a>
</span> </span>
<span class="tabulation2">
<a href="{% url 'gestion:annualRanking' %}">Comptabilité</a>
</span>
<span class="tabulation2"> <span class="tabulation2">
<a href="{% url 'gestion:ranking' %}">Classement</a> <a href="{% url 'gestion:ranking' %}">Classement</a>
</span> </span>

View file

@ -81,6 +81,47 @@
</div> </div>
</div> </div>
<section class="row uniform"> <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> </section>
<section id="second" class="main"> <section id="second" class="main">
@ -102,11 +143,14 @@
</tr> </tr>
</thead> </thead>
<tbody id="bodyTransaction"> <tbody id="bodyTransaction">
{% for consumption in consumptions %} {% for c in lastConsumptions %}
<tr> <tr>
{% for part in consumption %} <td>{{c.product}}</td>
<th>{{part}}</th> <td>{{c.quantity}}</td>
{%endfor%} <td>{{c.amount}}</td>
<td>{{c.paymentMethod}}</td>
<td>{{c.date}}</td>
<td></td>
</tr> </tr>
{%endfor%} {%endfor%}
</tbody> </tbody>
@ -119,22 +163,22 @@
<h2>{{self | yesno:"Mes derniers,Derniers"}} rechargements</h2> <h2>{{self | yesno:"Mes derniers,Derniers"}} rechargements</h2>
<p>(Affichage des 5 dernières entrées)</p> <p>(Affichage des 5 dernières entrées)</p>
</header> </header>
<section id="rechargements"> <section>
<div class="table-wrapper"> <div class="table-wrapper">
<table> <table>
<thead id="headRechargement"> <thead>
<tr> <tr>
<th>Montant</th> <th>Montant</th>
<th>Type de Rechargement</th> <th>Type de Rechargement</th>
<th>Date</th> <th>Date</th>
</tr> </tr>
</thead> </thead>
<tbody id="bodyRechargement"> <tbody>
{% for reload in reloads %} {% for reload in reloads %}
<tr> <tr>
<th>{{reload.amount}}€</th> <td>{{reload.amount}}€</td>
<th>{{reload.PaymentMethod}}</th> <td>{{reload.PaymentMethod}}</td>
<th>{{reload.date}}</th> <td>{{reload.date}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </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 coopeV3.acl import admin_required, superuser_required, self_or_has_perm, active_required
from .models import CotisationHistory, WhiteListHistory, School from .models import CotisationHistory, WhiteListHistory, School
from .forms import CreateUserForm, LoginForm, CreateGroupForm, EditGroupForm, SelectUserForm, GroupsEditForm, EditPasswordForm, addCotisationHistoryForm, addCotisationHistoryForm, addWhiteListHistoryForm, SelectNonAdminUserForm, SelectNonSuperUserForm, SchoolForm 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 @active_required
def loginView(request): def loginView(request):
@ -112,7 +112,28 @@ def profile(request, pk):
cotisations = CotisationHistory.objects.filter(user=user) cotisations = CotisationHistory.objects.filter(user=user)
whitelists = WhiteListHistory.objects.filter(user=user) whitelists = WhiteListHistory.objects.filter(user=user)
reloads = Reload.objects.filter(customer=user).order_by('-date') 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 @active_required
@login_required @login_required