3
0
Fork 0
mirror of https://github.com/nanoy42/coope synced 2024-05-02 23:52:24 +00:00

Change stock behavior

This commit is contained in:
Yoann Pétri 2019-08-27 23:21:15 +02:00
parent aa97c26335
commit f17697dd36
10 changed files with 161 additions and 30 deletions

View file

@ -59,8 +59,8 @@ class ProductAdmin(SimpleHistoryAdmin):
"""
The admin class for :class:`Products <gestion.models.Product>`.
"""
list_display = ('name', 'amount', 'is_active', 'category', 'adherentRequired', 'stockHold', 'stockBar', 'volume', 'deg')
ordering = ('name', 'amount', 'stockHold', 'stockBar', 'deg')
list_display = ('name', 'amount', 'is_active', 'category', 'adherentRequired', 'stock', 'volume', 'deg')
ordering = ('name', 'amount', 'stock', 'deg')
search_fields = ('name',)
list_filter = ('is_active', 'adherentRequired', 'category')

View file

@ -0,0 +1,53 @@
# Generated by Django 2.1 on 2019-08-27 19:19
from django.db import migrations, models
def update(apps, schema_editor):
Product = apps.get_model('gestion', 'Product')
for product in Product.objects.all():
product.stock = product.stockBar
product.save()
def reverse(apps, schema_editor):
Product = apps.get_model('gestion', 'Product')
for product in Product.objects.all():
product.stockBar = product.stock
product.save()
class Migration(migrations.Migration):
dependencies = [
('gestion', '0011_auto_20190623_1640'),
]
operations = [
migrations.AddField(
model_name='historicalproduct',
name='stock',
field=models.IntegerField(default=0, verbose_name='Stock'),
),
migrations.AddField(
model_name='product',
name='stock',
field=models.IntegerField(default=0, verbose_name='Stock'),
),
migrations.RunPython(update, reverse),
migrations.RemoveField(
model_name='historicalproduct',
name='stockBar',
),
migrations.RemoveField(
model_name='historicalproduct',
name='stockHold',
),
migrations.RemoveField(
model_name='product',
name='stockBar',
),
migrations.RemoveField(
model_name='product',
name='stockHold',
),
]

View file

@ -54,13 +54,9 @@ class Product(models.Model):
"""
The price of the product.
"""
stockHold = models.IntegerField(default=0, verbose_name="Stock en soute")
stock = models.IntegerField(default=0, verbose_name="Stock")
"""
Number of product in the hold.
"""
stockBar = models.IntegerField(default=0, verbose_name="Stock en bar")
"""
Number of product at the bar.
Number of product
"""
category = models.ForeignKey('Category', on_delete=models.PROTECT, verbose_name="Catégorie")
"""

View file

@ -14,8 +14,7 @@
{% if perms.gestion.change_product %}<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>{% endif %}<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>Stock en soute</strong> : {{ product.stock }}<br>
<strong>Catégorie</strong> : <a href="{% url 'gestion:categoryProfile' product.category.pk %}">{{ product.category }}</a><br>
<strong>Actif</strong> : {{ product.is_active | yesno:"Oui, Non"}}<br>
<strong>Dégré</strong> : {{ product.deg }}<br>

View file

@ -19,8 +19,7 @@
<tr>
<th>Nom</th>
<th>Prix</th>
<th>Stock (soute)</th>
<th>Stock (bar)</th>
<th>Stock</th>
<th>Catégorie</th>
<th>Actif</th>
<th>Degré</th>
@ -33,8 +32,7 @@
<tr>
<td><a href="{% url 'gestion:productProfile' product.pk %}">{{ product.name }}</a></td>
<td>{{ product.amount}}</td>
<td>{{ product.stockHold }}</td>
<td>{{ product.stockBar }}</td>
<td>{{ product.stock }}</td>
<td>{{ product.category }}</td>
<td>{{ product.is_active | yesno:"Oui, Non"}}</td>
<td>{{ product.deg }}</td>

View file

@ -0,0 +1,41 @@
{% extends 'base.html' %}
{% load static %}
{% block entete %}Gestion des produits{% endblock %}
{% block navbar%}
<ul>
{% for category in categories %}
<li><a href="#{{category}}">Stocks {{category}}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% block content %}
{% for category in categories %}
<section id="{{category}}" class="main">
<header class="major">
<h2>Stocks {{category}}</h2>
</header>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Nom</th>
<th>Stock</th>
<th>Mettre à jour</th>
</tr>
</thead>
<tbody>
{% for product in category.active_products %}
<tr id="tr-{{product.pk}}">
<td><a href="{% url 'gestion:productProfile' product.pk %}">{{ product.name }}</a></td>
<td id="stock-{{product.pk}}">{{ product.stock }}</td>
<td><button class="update-stock" data-pk="{{product.pk}}" data-stock="{{product.stock}}" ><i class="fa fa-marker"></i></button></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
{% endfor %}
<script src="{% static 'jquery.js' %}"></script>
<script src="{% static 'stocks.js' %}"></script>
{% endblock %}

View file

@ -55,4 +55,6 @@ urlpatterns = [
path('divide', views.divide, name="divide"),
path('gen_invoice', views.gen_invoice, name="gen_invoice"),
path('compute-price', views.compute_price_view, name="compute-price"),
path('stocks', views.stocks, name="stocks"),
path('updateStock/<int:pk>', views.update_stock, name="updateStock"),
]

View file

@ -161,12 +161,11 @@ def order(request):
kegHistory.amountSold += Decimal(quantity * product.amount)
kegHistory.save()
else:
if(product.stockBar > quantity):
product.stockBar -= quantity
if(product.stock > quantity):
product.stock -= quantity
product.save()
else:
product.stockBar = 0
product.save()
raise Exception("Le stock du produit n'autorise pas l'opération")
consumption, _ = Consumption.objects.get_or_create(customer=user, product=product)
consumption.quantity += quantity
consumption.save()
@ -198,12 +197,11 @@ def order(request):
consumption, _ = Consumption.objects.get_or_create(customer=user, product=article)
consumption.quantity += quantity
consumption.save()
if(article.stockBar > quantity):
article.stockBar -= quantity
if(article.stock > quantity):
article.stock -= quantity
article.save()
else:
article.stockBar = 0
article.save()
raise Exception("Le stock du produit " + article.name + "n'autorise pas l'opération")
user.profile.alcohol += Decimal(quantity * float(product.deg) * product.volume * 0.79 /10 /1000)
user.save()
return HttpResponse("La commande a bien été effectuée")
@ -288,6 +286,7 @@ def cancel_consumption(request, pk):
"""
consumption = get_object_or_404(ConsumptionHistory, pk=pk)
user = consumption.customer
product = consumption.product
if consumption.paymentMethod.affect_balance:
user.profile.debit -= consumption.amount
else:
@ -297,6 +296,8 @@ def cancel_consumption(request, pk):
consumptionT = Consumption.objects.get(customer=user, product=consumption.product)
consumptionT.quantity -= consumption.quantity
consumptionT.save()
product.stock += consumption.quantity
product.save()
consumption.delete()
messages.success(request, "La consommation a bien été annulée")
return redirect(reverse('users:profile', kwargs={'pk': user.pk}))
@ -317,7 +318,9 @@ def cancel_menu(request, pk):
user.profile.debit -= menu_history.amount
else:
user.profile.direct_debit -= menu_history.amount
for product in manu_history.menu.articles:
for product in menu_history.menu.articles:
product.stock += menu_history.quantity
product.save()
consumptionT = Consumption.objects.get(customer=user, product=product)
consumptionT -= menu_history.quantity
consumptionT.save()
@ -328,6 +331,7 @@ 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')
@ -457,6 +461,26 @@ class ActiveProductsAutocomplete(autocomplete.Select2QuerySetView):
qs = qs.filter(name__icontains=self.q)
return qs
@active_required
@login_required
@permission_required('gestion.change_product')
def update_stock(request, pk):
product = get_object_or_404(Product, pk=pk)
if("stock" in request.GET):
product.stock = request.GET.get("stock")
product.save()
return HttpResponse("Le stock a bien été mis à jour")
@active_required
@login_required
@permission_required('gestion.change_product')
def stocks(request):
"""
View to update stocks of active products
"""
categories = Category.objects.exclude(order=0).order_by("order")
return render(request, "gestion/stocks.html", {"categories": categories})
########## Kegs ##########
@active_required
@ -477,8 +501,7 @@ def addKeg(request):
pinte = Product(
name = "Pinte " + name,
amount = pinte_price,
stockHold = 0,
stockBar = 0,
stock = 0,
category = form.cleaned_data["category"],
needQuantityButton = False,
is_active = True,
@ -493,8 +516,7 @@ def addKeg(request):
demi = Product(
name = "Demi " + name,
amount = ceil(5*pinte_price)/10,
stockHold = 0,
stockBar = 0,
stock = 0,
category = form.cleaned_data["category"],
needQuantityButton = False,
is_active = True,
@ -510,8 +532,7 @@ def addKeg(request):
galopin = Product(
name = "Galopin " + name,
amount = ceil(2.5 * pinte_price)/10,
stockHold = 0,
stockBar = 0,
stock = 0,
category = form.cleaned_data["category"],
needQuantityButton = False,
is_active = True,

16
staticfiles/stocks.js Normal file
View file

@ -0,0 +1,16 @@
$(document).ready(function(){
$(".update-stock").click(function(){
var pk = $(this).attr('data-pk');
var current_value = $(this).attr('data-stock');
var ok = false;
while(!ok){
var new_stock = prompt("Nouveau stock ? (entier attendu)", current_value);
ok = new_stock == null || !(isNaN(parseInt(new_stock)));
}
if(new_stock != null){
$.get("/gestion/updateStock/" + pk, {"stock": new_stock}, function(data){
$("#stock-"+pk).html(new_stock);
});
}
});
});

View file

@ -20,8 +20,13 @@
<i class="fa fa-dolly-flatbed"></i> <a href="{% url 'gestion:productsIndex' %}">Gestion des produits</a>
</span>
{% endif %}
{% if perms.gestion.change_product %}
<span class="tabulation2">
<br>
<i class="fa fa-boxes"></i> <a href="{% url 'gestion:stocks' %}">Stocks</a>
</span>
{% endif %}
<span class="tabulation2">
<br>
<i class="fa fa-list-ol"></i> <a href="{% url 'gestion:ranking' %}">Classement</a>
</span>
{% if perms.preferences.change_generalpreferences %}