mirror of
https://github.com/nanoy42/coope
synced 2024-11-22 11:23:11 +00:00
Gestion des f^uts
This commit is contained in:
parent
ca6c938e20
commit
a45d7746f5
16 changed files with 426 additions and 26 deletions
|
@ -1,9 +1,11 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Reload, Refund, Product, Keg, ConsumptionHistory
|
from .models import Reload, Refund, Product, Keg, ConsumptionHistory, KegHistory, Consumption
|
||||||
|
|
||||||
admin.site.register(Reload)
|
admin.site.register(Reload)
|
||||||
admin.site.register(Refund)
|
admin.site.register(Refund)
|
||||||
admin.site.register(Product)
|
admin.site.register(Product)
|
||||||
admin.site.register(Keg)
|
admin.site.register(Keg)
|
||||||
admin.site.register(ConsumptionHistory)
|
admin.site.register(ConsumptionHistory)
|
||||||
|
admin.site.register(KegHistory)
|
||||||
|
admin.site.register(Consumption)
|
|
@ -65,3 +65,9 @@ class SearchMenuForm(forms.Form):
|
||||||
|
|
||||||
class GestionForm(forms.Form):
|
class GestionForm(forms.Form):
|
||||||
client = forms.ModelChoiceField(queryset=User.objects.filter(is_active=True), required=True, label="Client", widget=autocomplete.ModelSelect2(url='users:active-users-autocomplete', attrs={'data-minimum-input-length':2}))
|
client = forms.ModelChoiceField(queryset=User.objects.filter(is_active=True), required=True, label="Client", widget=autocomplete.ModelSelect2(url='users:active-users-autocomplete', attrs={'data-minimum-input-length':2}))
|
||||||
|
|
||||||
|
class SelectPositiveKegForm(forms.Form):
|
||||||
|
keg = forms.ModelChoiceField(queryset=Keg.objects.filter(stockHold__gt = 0), required=True, label="Fût", widget=autocomplete.ModelSelect2(url='gestion:kegs-positive-autocomplete'))
|
||||||
|
|
||||||
|
class SelectActiveKegForm(forms.Form):
|
||||||
|
keg = forms.ModelChoiceField(queryset=Keg.objects.filter(is_active = True), required=True, label="Fût", widget=autocomplete.ModelSelect2(url='gestion:kegs-active-autocomplete'))
|
33
gestion/migrations/0002_auto_20181123_0229.py
Normal file
33
gestion/migrations/0002_auto_20181123_0229.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Generated by Django 2.1 on 2018-11-23 01:29
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('gestion', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='keghistory',
|
||||||
|
old_name='Keg',
|
||||||
|
new_name='keg',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='keghistory',
|
||||||
|
name='amountSold',
|
||||||
|
field=models.DecimalField(decimal_places=2, default=0, max_digits=5),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='keghistory',
|
||||||
|
name='closingDate',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='keghistory',
|
||||||
|
name='quantitySold',
|
||||||
|
field=models.DecimalField(decimal_places=2, default=0, max_digits=5),
|
||||||
|
),
|
||||||
|
]
|
22
gestion/migrations/0003_auto_20181123_0330.py
Normal file
22
gestion/migrations/0003_auto_20181123_0330.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 2.1 on 2018-11-23 02:30
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('gestion', '0002_auto_20181123_0229'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='keg',
|
||||||
|
options={'permissions': (('open_keg', 'Peut percuter les fûts'), ('close_keg', 'Peut fermer les fûts'))},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='product',
|
||||||
|
name='adherentRequired',
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
]
|
25
gestion/migrations/0004_consumption.py
Normal file
25
gestion/migrations/0004_consumption.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 2.1 on 2018-11-23 13:03
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('gestion', '0003_auto_20181123_0330'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Consumption',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('quantity', models.PositiveIntegerField(default=0)),
|
||||||
|
('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='consumption_global_taken', to=settings.AUTH_USER_MODEL)),
|
||||||
|
('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='gestion.Product')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -30,6 +30,7 @@ class Product(models.Model):
|
||||||
is_active = models.BooleanField(default=True, verbose_name="Actif")
|
is_active = models.BooleanField(default=True, verbose_name="Actif")
|
||||||
volume = models.IntegerField(default=0)
|
volume = models.IntegerField(default=0)
|
||||||
deg = models.DecimalField(default=0,max_digits=5, decimal_places=2, verbose_name="Degré")
|
deg = models.DecimalField(default=0,max_digits=5, decimal_places=2, verbose_name="Degré")
|
||||||
|
adherentRequired = models.BooleanField(default=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -61,6 +62,12 @@ def isGalopin(id):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Keg(models.Model):
|
class Keg(models.Model):
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
("open_keg", "Peut percuter les fûts"),
|
||||||
|
("close_keg", "Peut fermer les fûts")
|
||||||
|
)
|
||||||
|
|
||||||
name = models.CharField(max_length=20, unique=True, verbose_name="Nom")
|
name = models.CharField(max_length=20, unique=True, verbose_name="Nom")
|
||||||
stockHold = models.IntegerField(default=0, verbose_name="Stock en soute")
|
stockHold = models.IntegerField(default=0, verbose_name="Stock en soute")
|
||||||
barcode = models.CharField(max_length=20, unique=True, verbose_name="Code barre")
|
barcode = models.CharField(max_length=20, unique=True, verbose_name="Code barre")
|
||||||
|
@ -75,13 +82,21 @@ class Keg(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class KegHistory(models.Model):
|
class KegHistory(models.Model):
|
||||||
Keg = models.ForeignKey(Keg, on_delete=models.PROTECT)
|
keg = models.ForeignKey(Keg, on_delete=models.PROTECT)
|
||||||
openingDate = models.DateTimeField(auto_now_add=True)
|
openingDate = models.DateTimeField(auto_now_add=True)
|
||||||
quantitySold = models.DecimalField(decimal_places=2, max_digits=5)
|
quantitySold = models.DecimalField(decimal_places=2, max_digits=5, default=0)
|
||||||
amountSold = models.DecimalField(decimal_places=2, max_digits=5)
|
amountSold = models.DecimalField(decimal_places=2, max_digits=5, default=0)
|
||||||
closingDate = models.DateTimeField()
|
closingDate = models.DateTimeField(null=True, blank=True)
|
||||||
isCurrentKegHistory = models.BooleanField(default=True)
|
isCurrentKegHistory = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
res = "Fût de " + str(self.keg) + " (" + str(self.openingDate) + " - "
|
||||||
|
if(self.closingDate):
|
||||||
|
res += str(self.closingDate) + ")"
|
||||||
|
else:
|
||||||
|
res += "?)"
|
||||||
|
return res
|
||||||
|
|
||||||
class Reload(models.Model):
|
class Reload(models.Model):
|
||||||
customer = models.ForeignKey(User, on_delete=models.PROTECT, related_name="reload_taken", verbose_name="Client")
|
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")
|
amount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Montant")
|
||||||
|
@ -152,3 +167,11 @@ class ConsumptionHistory(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{0} {1} consommé par {2} le {3} (encaissé par {4})".format(self.quantity, self.product, self.customer, self.date, self.coopeman)
|
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):
|
||||||
|
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)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Consommation de " + str(self.customer) + " concernant le produit " + str(self.product)
|
||||||
|
|
21
gestion/templates/gestion/kegh.html
Normal file
21
gestion/templates/gestion/kegh.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block entete %}<h1>Gestion des produits</h1>{% endblock %}
|
||||||
|
{% block navbar%}
|
||||||
|
<ul>
|
||||||
|
<li><a href="#first">Historique du fût</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<section id="first" class="main">
|
||||||
|
<header class="major">
|
||||||
|
<h2>Historique du fût {{ keg.name }}</h2>
|
||||||
|
</header>
|
||||||
|
<a href="{% url 'gestion:kegsList' %}">Retour à la liste des fûts</a><br><br>
|
||||||
|
{% for kegH in kegHistory %}
|
||||||
|
<h2>Du {{kegH.openingDate}} au {{kegH.closingDate | default:"?"}}</h2>
|
||||||
|
Quantité vendue : {{ kegH.quantitySold }} L<br>
|
||||||
|
Montant vendu : {{ kegH.amountSold }} €(prix fût : {{keg.amount}} €)<br><br>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
89
gestion/templates/gestion/kegs_list.html
Normal file
89
gestion/templates/gestion/kegs_list.html
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block entete %}<h1>Gestion des produits</h1>{% endblock %}
|
||||||
|
{% block navbar%}
|
||||||
|
<ul>
|
||||||
|
<li><a href="#first">Liste des fûts actifs</a></li>
|
||||||
|
<li><a href="#second">Liste des fûts inactifs</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<section id="first" class="main">
|
||||||
|
<header class="major">
|
||||||
|
<h2>Liste des fûts actifs</h2>
|
||||||
|
</header>
|
||||||
|
<a class="button" href="{% url 'gestion:addKeg' %}">Créer un fût</a>
|
||||||
|
<a class="button" href="{% url 'gestion:openKeg' %}">Percuter un fût</a>
|
||||||
|
<a class="button" href="{% url 'gestion:closeKeg' %}">Fermer un fût</a>
|
||||||
|
<br><br>
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Stock en soute</th>
|
||||||
|
<th>Code barre</th>
|
||||||
|
<th>Capacité</th>
|
||||||
|
<th>Quantité vendue</th>
|
||||||
|
<th>Montant vendu</th>
|
||||||
|
<th>Prix du fût</th>
|
||||||
|
<th>Historique</th>
|
||||||
|
<th>Administrer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for kegH in kegs_active %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ kegH.keg.name }}</td>
|
||||||
|
<td>{{ kegH.keg.stockHold}}</td>
|
||||||
|
<td>{{ kegH.keg.barcode }}</td>
|
||||||
|
<td>{{ kegH.keg.capacity }} L</td>
|
||||||
|
<td>{{ kegH.quantitySold }} L</td>
|
||||||
|
<td>{{ kegH.amountSold }} €</td>
|
||||||
|
<td>{{ kegH.keg.amount }} €</td>
|
||||||
|
<td><a href="{% url 'gestion:kegH' kegH.keg.pk %}">Voir</a></td>
|
||||||
|
<td><a href="{% url 'gestion:closeDirectKeg' kegH.keg.pk %}" class="button small">Fermer</a> <a href="{% url 'gestion:editKeg' kegH.keg.pk %}" class="button small">Modifier</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="first" class="main">
|
||||||
|
<header class="major">
|
||||||
|
<h2>Liste des fûts inactifs</h2>
|
||||||
|
</header>
|
||||||
|
<a class="button" href="{% url 'gestion:addKeg' %}">Créer un fût</a>
|
||||||
|
<a class="button" href="{% url 'gestion:openKeg' %}">Percuter un fût</a>
|
||||||
|
<a class="button" href="{% url 'gestion:closeKeg' %}">Fermer un fût</a>
|
||||||
|
<br><br>
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Stock en soute</th>
|
||||||
|
<th>Code barre</th>
|
||||||
|
<th>Capacité</th>
|
||||||
|
<th>Prix du fût</th>
|
||||||
|
<th>Historique</th>
|
||||||
|
<th>Administrer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for keg in kegs_inactive %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ keg.name }}</td>
|
||||||
|
<td>{{ keg.stockHold}}</td>
|
||||||
|
<td>{{ keg.barcode }}</td>
|
||||||
|
<td>{{ keg.capacity }} L</td>
|
||||||
|
<td>{{ keg.amount }} €</td>
|
||||||
|
<td><a href="{% url 'gestion:kegH' keg.pk %}">Voir</a></td>
|
||||||
|
<td>{% if keg.stockHold > 0 %}<a href="{% url 'gestion:openDirectKeg' keg.pk %}" class="button small">Percuter</a>{% endif %} <a href="{% url 'gestion:editKeg' keg.pk %}" class="button small">Modifier</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -27,9 +27,9 @@
|
||||||
Actions possibles :
|
Actions possibles :
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{% url 'gestion:addKeg' %}">Créer un fut</a></li>
|
<li><a href="{% url 'gestion:addKeg' %}">Créer un fut</a></li>
|
||||||
<li><a href="">Percuter un fut</a></li>
|
<li><a href="{% url 'gestion:openKeg' %}">Percuter un fut</a></li>
|
||||||
<li><a href="">Lister les futs</a></li>
|
<li><a href="{% url 'gestion:closeKeg' %}">Fermer un fût</a></li>
|
||||||
<li><a href="">Historique des futs</a></li>
|
<li><a href="{% url 'gestion:kegsList' %}">Lister les futs</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section id="third" class="main">
|
<section id="third" class="main">
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
{% block entete %}<h1>Gestion des produits</h1>{% endblock %}
|
{% block entete %}<h1>Gestion des produits</h1>{% endblock %}
|
||||||
{% block navbar%}
|
{% block navbar%}
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#first">Produits</a></li>
|
<li><a href="#first">Liste des 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>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -11,6 +11,13 @@ urlpatterns = [
|
||||||
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('addKeg', views.addKeg, name="addKeg"),
|
path('addKeg', views.addKeg, name="addKeg"),
|
||||||
|
path('openKeg', views.openKeg, name="openKeg"),
|
||||||
|
path('closeKeg', views.closeKeg, name="closeKeg"),
|
||||||
|
path('kegsList', views.kegsList, name="kegsList"),
|
||||||
|
path('kegH/<int:pk>', views.kegH, name="kegH"),
|
||||||
|
path('editKeg/<int:pk>', views.editKeg, name="editKeg"),
|
||||||
|
path('openDirectKeg/<int:pk>', views.openDirectKeg, name="openDirectKeg"),
|
||||||
|
path('closeDirectKeg/<int:pk>', views.closeDirectKeg, name="closeDirectKeg"),
|
||||||
path('addMenu', views.addMenu, name="addMenu"),
|
path('addMenu', views.addMenu, name="addMenu"),
|
||||||
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"),
|
||||||
|
@ -19,4 +26,7 @@ urlpatterns = [
|
||||||
path('searchProduct', views.searchProduct, name="searchProduct"),
|
path('searchProduct', views.searchProduct, name="searchProduct"),
|
||||||
path('productProfile/<int:pk>', views.productProfile, name="productProfile"),
|
path('productProfile/<int:pk>', views.productProfile, name="productProfile"),
|
||||||
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-active-autocomplete', views.KegActiveAutocomplete.as_view(), name="kegs-active-autocomplete"),
|
||||||
|
|
||||||
]
|
]
|
166
gestion/views.py
166
gestion/views.py
|
@ -5,6 +5,7 @@ from django.http import HttpResponse, Http404
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.contrib.auth.decorators import login_required, permission_required
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from coopeV3.acl import active_required, acl_or
|
from coopeV3.acl import active_required, acl_or
|
||||||
|
|
||||||
|
@ -12,8 +13,8 @@ import simplejson as json
|
||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
from decimal import *
|
from decimal import *
|
||||||
|
|
||||||
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm
|
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm
|
||||||
from .models import Product, Menu, Keg, ConsumptionHistory
|
from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption
|
||||||
from preferences.models import PaymentMethod
|
from preferences.models import PaymentMethod
|
||||||
|
|
||||||
@active_required
|
@active_required
|
||||||
|
@ -44,26 +45,62 @@ def manage(request):
|
||||||
@permission_required('gestion.add_consumptionhistory')
|
@permission_required('gestion.add_consumptionhistory')
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def order(request):
|
def order(request):
|
||||||
print(request.POST)
|
|
||||||
if("user" not in request.POST or "paymentMethod" not in request.POST or "amount" not in request.POST or "order" not in request.POST):
|
if("user" not in request.POST or "paymentMethod" not in request.POST or "amount" not in request.POST or "order" not in request.POST):
|
||||||
raise Http404("Erreur du POST")
|
return HttpResponse("Erreur du POST")
|
||||||
else:
|
else:
|
||||||
user = get_object_or_404(User, pk=request.POST['user'])
|
user = get_object_or_404(User, pk=request.POST['user'])
|
||||||
paymentMethod = get_object_or_404(PaymentMethod, pk=request.POST['paymentMethod'])
|
paymentMethod = get_object_or_404(PaymentMethod, pk=request.POST['paymentMethod'])
|
||||||
amount = Decimal(request.POST['amount'])
|
amount = Decimal(request.POST['amount'])
|
||||||
order = json.loads(request.POST["order"])
|
order = json.loads(request.POST["order"])
|
||||||
if(len(order) == 0 or amount == 0):
|
if(len(order) == 0 or amount == 0):
|
||||||
raise Http404("Pas de commande")
|
return HttpResponse("Pas de commande")
|
||||||
|
adherentRequired = False
|
||||||
|
for o in order:
|
||||||
|
product = get_object_or_404(Product, pk=o["pk"])
|
||||||
|
adherentRequired = adherentRequired or product.adherentRequired
|
||||||
|
if(adherentRequired and not user.profile.is_adherent):
|
||||||
|
return HttpResponse("N'est pas adhérent et devrait l'être")
|
||||||
if(paymentMethod.affect_balance):
|
if(paymentMethod.affect_balance):
|
||||||
if(user.profile.balance < amount):
|
if(user.profile.balance < amount):
|
||||||
raise Http404("Solde inférieur au prix de la commande")
|
return HttpResponse("Solde inférieur au prix de la commande")
|
||||||
else:
|
else:
|
||||||
user.profile.debit += amount
|
user.profile.debit += amount
|
||||||
user.save()
|
user.save()
|
||||||
for o in order:
|
for o in order:
|
||||||
print(o)
|
|
||||||
product = get_object_or_404(Product, pk=o["pk"])
|
product = get_object_or_404(Product, pk=o["pk"])
|
||||||
ch = ConsumptionHistory(customer = user, quantity = int(o["quantity"]), paymentMethod=paymentMethod, product=product, amount=int(o["quantity"])*product.amount, coopeman=request.user)
|
quantity = int(o["quantity"])
|
||||||
|
if(product.category == Product.P_PRESSION):
|
||||||
|
keg = get_object_or_404(Keg, pinte=product)
|
||||||
|
if(not keg.is_active):
|
||||||
|
return HttpResponse("Une erreur inconnue s'est produite")
|
||||||
|
kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True)
|
||||||
|
kegHistory.quantitySold += Decimal(quantity * 0.5)
|
||||||
|
kegHistory.amountSold += Decimal(quantity * product.amount)
|
||||||
|
kegHistory.save()
|
||||||
|
elif(product.category == Product.D_PRESSION):
|
||||||
|
keg = get_object_or_404(Keg, demi=product)
|
||||||
|
if(not keg.is_active):
|
||||||
|
return HttpResponse("Une erreur inconnue s'est produite")
|
||||||
|
kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True)
|
||||||
|
kegHistory.quantitySold += Decimal(quantity * 0.25)
|
||||||
|
kegHistory.amountSold += Decimal(quantity * product.amount)
|
||||||
|
kegHistory.save()
|
||||||
|
elif(product.category == Product.G_PRESSION):
|
||||||
|
keg = get_object_or_404(Keg, galopin=product)
|
||||||
|
if(not keg.is_active):
|
||||||
|
return HttpResponse("Une erreur inconnue s'est produite")
|
||||||
|
kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True)
|
||||||
|
kegHistory.quantitySold += Decimal(quantity * 0.125)
|
||||||
|
kegHistory.amountSold += Decimal(quantity * product.amount)
|
||||||
|
kegHistory.save()
|
||||||
|
else:
|
||||||
|
if(product.stockHold > 0):
|
||||||
|
product.stockHold -= 1
|
||||||
|
product.save()
|
||||||
|
consumption, _ = Consumption.objects.get_or_create(customer=user, product=product)
|
||||||
|
consumption.quantity += quantity
|
||||||
|
consumption.save()
|
||||||
|
ch = ConsumptionHistory(customer = user, quantity = quantity, paymentMethod=paymentMethod, product=product, amount=int(o["quantity"])*product.amount, coopeman=request.user)
|
||||||
ch.save()
|
ch.save()
|
||||||
return HttpResponse("La commande a bien été effectuée")
|
return HttpResponse("La commande a bien été effectuée")
|
||||||
|
|
||||||
|
@ -163,9 +200,120 @@ def addKeg(request):
|
||||||
if(form.is_valid()):
|
if(form.is_valid()):
|
||||||
keg = form.save()
|
keg = form.save()
|
||||||
messages.success(request, "Le fût " + keg.name + " a bien été ajouté")
|
messages.success(request, "Le fût " + keg.name + " a bien été ajouté")
|
||||||
return redirect(reverse('gestion:productsIndex'))
|
return redirect(reverse('gestion:kegsList'))
|
||||||
return render(request, "form.html", {"form":form, "form_title": "Ajout d'un fût", "form_button": "Ajouter"})
|
return render(request, "form.html", {"form":form, "form_title": "Ajout d'un fût", "form_button": "Ajouter"})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion.edit_keg')
|
||||||
|
def editKeg(request, pk):
|
||||||
|
keg = get_object_or_404(Keg, pk=pk)
|
||||||
|
form = KegForm(request.POST or None, instance=keg)
|
||||||
|
if(form.is_valid()):
|
||||||
|
form.save()
|
||||||
|
messages.success(request, "Le fût a bien été modifié")
|
||||||
|
return redirect(reverse('gestion:kegsList'))
|
||||||
|
return render(request, "form.html", {"form": form, "form_title": "Modification d'un fût", "form_button": "Modifier"})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion.open_keg')
|
||||||
|
def openKeg(request):
|
||||||
|
form = SelectPositiveKegForm(request.POST or None)
|
||||||
|
if(form.is_valid()):
|
||||||
|
keg = form.cleaned_data['keg']
|
||||||
|
previousKegHistory = KegHistory.objects.filter(keg=keg).filter(isCurrentKegHistory=True)
|
||||||
|
for pkh in previousKegHistory:
|
||||||
|
pkh.isCurrentKegHistory = False
|
||||||
|
pkh.closingDate = timezone.now()
|
||||||
|
pkh.save()
|
||||||
|
kegHistory = KegHistory(keg = keg)
|
||||||
|
kegHistory.save()
|
||||||
|
keg.stockHold -= 1
|
||||||
|
keg.is_active = True
|
||||||
|
keg.save()
|
||||||
|
messages.success(request, "Le fut a bien été percuté")
|
||||||
|
return redirect(reverse('gestion:kegsList'))
|
||||||
|
return render(request, "form.html", {"form": form, "form_title":"Percutage d'un fût", "form_button":"Percuter"})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion.open_keg')
|
||||||
|
def openDirectKeg(request, pk):
|
||||||
|
keg = get_object_or_404(Keg, pk=pk)
|
||||||
|
if(keg.stockHold > 0):
|
||||||
|
previousKegHistory = KegHistory.objects.filter(keg=keg).filter(isCurrentKegHistory=True)
|
||||||
|
for pkh in previousKegHistory:
|
||||||
|
pkh.isCurrentKegHistory = False
|
||||||
|
pkh.closingDate = timezone.now()
|
||||||
|
pkh.save()
|
||||||
|
kegHistory = KegHistory(keg = keg)
|
||||||
|
kegHistory.save()
|
||||||
|
keg.stockHold -= 1
|
||||||
|
keg.is_active = True
|
||||||
|
keg.save()
|
||||||
|
messages.success(request, "Le fût a bien été percuté")
|
||||||
|
else:
|
||||||
|
messages.error(request, "Il n'y a pas de fût en stock")
|
||||||
|
return redirect(reverse('gestion:kegsList'))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion.close_keg')
|
||||||
|
def closeKeg(request):
|
||||||
|
form = SelectActiveKegForm(request.POST or None)
|
||||||
|
if(form.is_valid()):
|
||||||
|
keg = form.cleaned_data['keg']
|
||||||
|
kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True)
|
||||||
|
kegHistory.isCurrentKegHistory = False
|
||||||
|
kegHistory.closingDate = timezone.now()
|
||||||
|
kegHistory.save()
|
||||||
|
keg.is_active = False
|
||||||
|
keg.save()
|
||||||
|
messages.success(request, "Le fût a bien été fermé")
|
||||||
|
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"})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion:close_keg')
|
||||||
|
def closeDirectKeg(request, pk):
|
||||||
|
keg = get_object_or_404(Keg, pk=pk)
|
||||||
|
if(keg.is_active):
|
||||||
|
kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True)
|
||||||
|
kegHistory.isCurrentKegHistory = False
|
||||||
|
kegHistory.closingDate = timezone.now()
|
||||||
|
kegHistory.save()
|
||||||
|
keg.is_active = False
|
||||||
|
keg.save()
|
||||||
|
messages.success(request, "Le fût a bien été fermé")
|
||||||
|
else:
|
||||||
|
messages.error(request, "Le fût n'est pas ouvert")
|
||||||
|
return redirect(reverse('gestion:kegsList'))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion.view_keg')
|
||||||
|
def kegsList(request):
|
||||||
|
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})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('gestion.view_keghistory')
|
||||||
|
def kegH(request, pk):
|
||||||
|
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):
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = Keg.objects.filter(is_active = True)
|
||||||
|
if self.q:
|
||||||
|
qs = qs.filter(name__istartswith=self.q)
|
||||||
|
return qs
|
||||||
|
|
||||||
|
class KegPositiveAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = Keg.objects.filter(stockHold__gt = 0)
|
||||||
|
if self.q:
|
||||||
|
qs = qs.filter(name__istartswith=self.q)
|
||||||
|
return qs
|
||||||
|
|
||||||
########## Menus ##########
|
########## Menus ##########
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,5 @@ $(document).ready(function(){
|
||||||
alert("Impossible d'effectuer la transaction");
|
alert("Impossible d'effectuer la transaction");
|
||||||
location.reload();
|
location.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
17
users/migrations/0003_auto_20181123_0229.py
Normal file
17
users/migrations/0003_auto_20181123_0229.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 2.1 on 2018-11-23 01:29
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0002_auto_20181009_1119'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='cotisationhistory',
|
||||||
|
options={'permissions': (('validate_consumptionhistory', 'Peut (in)valider les cotisations'),)},
|
||||||
|
),
|
||||||
|
]
|
|
@ -2,6 +2,7 @@ from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from preferences.models import PaymentMethod, Cotisation
|
from preferences.models import PaymentMethod, Cotisation
|
||||||
from gestion.models import ConsumptionHistory
|
from gestion.models import ConsumptionHistory
|
||||||
|
@ -50,6 +51,13 @@ class Profile(models.Model):
|
||||||
school = models.ForeignKey(School, on_delete=models.PROTECT, blank=True, null=True)
|
school = models.ForeignKey(School, on_delete=models.PROTECT, blank=True, null=True)
|
||||||
cotisationEnd = models.DateTimeField(blank=True, null=True)
|
cotisationEnd = models.DateTimeField(blank=True, null=True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_adherent(self):
|
||||||
|
if(self.cotisationEnd and self.cotisationEnd > timezone.now()):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def balance(self):
|
def balance(self):
|
||||||
return self.credit - self.debit
|
return self.credit - self.debit
|
||||||
|
|
|
@ -627,8 +627,8 @@ def addCotisationHistory(request, pk):
|
||||||
if(form.is_valid()):
|
if(form.is_valid()):
|
||||||
cotisation = form.save(commit=False)
|
cotisation = form.save(commit=False)
|
||||||
if(cotisation.paymentMethod.affect_balance):
|
if(cotisation.paymentMethod.affect_balance):
|
||||||
if(user.profile.balance >= cotisation.amount):
|
if(user.profile.balance >= cotisation.cotisation.amount):
|
||||||
user.profile.balance -= cotisation.amount
|
user.profile.debit += cotisation.cotisation.amount
|
||||||
else:
|
else:
|
||||||
cotisation.delete()
|
cotisation.delete()
|
||||||
messages.error(request, "Solde insuffisant")
|
messages.error(request, "Solde insuffisant")
|
||||||
|
|
Loading…
Reference in a new issue