mirror of
https://github.com/nanoy42/coope
synced 2024-11-22 11:23:11 +00:00
commit
cf153f9ed9
17 changed files with 446 additions and 19 deletions
|
@ -60,4 +60,9 @@ 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'))
|
||||
keg = forms.ModelChoiceField(queryset=Keg.objects.filter(is_active = True), required=True, label="Fût", widget=autocomplete.ModelSelect2(url='gestion:kegs-active-autocomplete'))
|
||||
|
||||
class PinteForm(forms.Form):
|
||||
ids = forms.CharField(widget=forms.Textarea, label="Numéros", help_text="Numéros séparés par un espace. Laissez vide pour utiliser le range.", required=False)
|
||||
begin = forms.IntegerField(label="Début", help_text="Début du range", required=False)
|
||||
end = forms.IntegerField(label="Fin", help_text="Fin du range", required=False)
|
25
gestion/migrations/0002_pinte.py
Normal file
25
gestion/migrations/0002_pinte.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 2.1 on 2018-12-21 20:34
|
||||
|
||||
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', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Pinte',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('last_update_date', models.DateTimeField(auto_now=True)),
|
||||
('current_owner', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='pinte_owned_currently', to=settings.AUTH_USER_MODEL)),
|
||||
('previous_owner', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='pinte_owned_previously', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
37
gestion/migrations/0003_historicalpinte.py
Normal file
37
gestion/migrations/0003_historicalpinte.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Generated by Django 2.1 on 2018-12-21 20:51
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import simple_history.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('gestion', '0002_pinte'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='HistoricalPinte',
|
||||
fields=[
|
||||
('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('last_update_date', models.DateTimeField(blank=True, editable=False)),
|
||||
('history_id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
('history_date', models.DateTimeField()),
|
||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
||||
('current_owner', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
('previous_owner', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'historical pinte',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': 'history_date',
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
]
|
25
gestion/migrations/0004_auto_20181223_1830.py
Normal file
25
gestion/migrations/0004_auto_20181223_1830.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 2.1 on 2018-12-23 17:30
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gestion', '0003_historicalpinte'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='pinte',
|
||||
name='current_owner',
|
||||
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='pintes_owned_currently', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='pinte',
|
||||
name='previous_owner',
|
||||
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='pintes_owned_previously', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -225,3 +225,12 @@ class Consumption(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return "Consommation de " + str(self.customer) + " concernant le produit " + str(self.product)
|
||||
|
||||
class Pinte(models.Model):
|
||||
"""
|
||||
Stores a physical pinte
|
||||
"""
|
||||
current_owner = models.ForeignKey(User, on_delete=models.PROTECT, null=True, default=None, related_name="pintes_owned_currently")
|
||||
previous_owner = models.ForeignKey(User, on_delete=models.PROTECT, null=True, default=None, related_name="pintes_owned_previously")
|
||||
last_update_date = models.DateTimeField(auto_now=True)
|
||||
history = HistoricalRecords()
|
||||
|
|
75
gestion/templates/gestion/pintes_list.html
Normal file
75
gestion/templates/gestion/pintes_list.html
Normal file
|
@ -0,0 +1,75 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block entete %}Gestion des produits{% endblock %}
|
||||
{% block navbar%}
|
||||
<ul>
|
||||
<li><a href="#first">Général</a></li>
|
||||
<li><a href="#second">Liste des pintes non rendues</a></li>
|
||||
<li><a href="#third">Liste des pintes rendues</a></li>
|
||||
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<section id="first" class="main">
|
||||
<header class="major">
|
||||
<h2>Général</h2>
|
||||
</header>
|
||||
{% if perms.gestion.add_pinte %}
|
||||
<a class="button" href="{% url 'gestion:addPintes' %}">Créer une ou plusieurs pintes</a><br><br>
|
||||
{% endif %}
|
||||
Il a y actuellement {{ taken_pintes.count|add:free_pintes.count }} pintes, parmis lesquelles <strong>{{ free_pintes.count }} sont rendues</strong> et <strong>{{ taken_pintes.count }} ne sont pas rendues</strong>.
|
||||
</section>
|
||||
<section id="second" class="main">
|
||||
<header class="major">
|
||||
<h2>Liste des pintes non rendues</h2>
|
||||
</header>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Numéro</th>
|
||||
<th>Possesseur actuel</th>
|
||||
<th>Possesseur précédent</th>
|
||||
<th>Date du dernier changement</th>
|
||||
<th>Administrer</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pinte in taken_pintes %}
|
||||
<tr>
|
||||
<td>{{ pinte.pk }}</td>
|
||||
<td>{{ pinte.current_owner }}</td>
|
||||
<td>{{ pinte.previous_owner }}</td>
|
||||
<td>{{ pinte.last_update_date }}</td>
|
||||
<td>{% if perms.gestion.change_pinte %} <a href="{% url 'gestion:release' pinte.pk %}" class="button small">Libérer</a>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<section id="third" class="main">
|
||||
<header class="major">
|
||||
<h2>Liste des pintes rendues</h2>
|
||||
</header>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Numéro</th>
|
||||
<th>Possesseur précédent</th>
|
||||
<th>Date du dernier changement</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pinte in free_pintes %}
|
||||
<tr>
|
||||
<td>{{ pinte.pk }}</td>
|
||||
<td>{{ pinte.previous_owner }}</td>
|
||||
<td>{{ pinte.last_update_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -5,6 +5,7 @@
|
|||
<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">Pintes</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
@ -58,4 +59,21 @@
|
|||
{% endif %}
|
||||
</ul>
|
||||
</section>
|
||||
<section id="fourth" class="main">
|
||||
<header class="major">
|
||||
<h2>Pintes</h2>
|
||||
</header>
|
||||
Actions possibles :
|
||||
<ul>
|
||||
{% if perms.gestion.add_pinte %}
|
||||
<li><a href="{% url 'gestion:addPintes' %}">Créer une ou plusieurs pintes</a></li>
|
||||
{% endif %}
|
||||
{% if perms.gestion.change_pinte %}
|
||||
<li><a href="{% url 'gestion:releasePintes' %}">Libérer des pintes</a></li>
|
||||
{% endif %}
|
||||
{% if perms.gestion.view_pinte %}
|
||||
<li><a href="{% url 'gestion:pintesList' %}">Lister les pintes</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
|
@ -33,6 +33,10 @@ urlpatterns = [
|
|||
path('cancelConsumption/<int:pk>', views.cancel_consumption, name="cancelConsumption"),
|
||||
path('cancelMenu/<int:pk>', views.cancel_menu, name="cancelMenu"),
|
||||
path('productProfile/<int:pk>', views.productProfile, name="productProfile"),
|
||||
path('addPintes', views.add_pintes, name="addPintes"),
|
||||
path('releasePintes', views.release_pintes, name="releasePintes"),
|
||||
path('pintesList', views.pintes_list, name="pintesList"),
|
||||
path('release/<int:pinte_pk>', views.release, name="release"),
|
||||
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"),
|
||||
|
|
107
gestion/views.py
107
gestion/views.py
|
@ -13,9 +13,9 @@ import simplejson as json
|
|||
from dal import autocomplete
|
||||
from decimal import *
|
||||
|
||||
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm
|
||||
from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory
|
||||
from preferences.models import PaymentMethod
|
||||
from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm
|
||||
from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte
|
||||
from preferences.models import PaymentMethod, GeneralPreferences
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
|
@ -107,6 +107,8 @@ def order(request):
|
|||
amount = Decimal(request.POST['amount'])
|
||||
order = json.loads(request.POST["order"])
|
||||
menus = json.loads(request.POST["menus"])
|
||||
listPintes = json.loads(request.POST["listPintes"])
|
||||
gp,_ = GeneralPreferences.objects.get_or_create(pk=1)
|
||||
if (not order) and (not menus):
|
||||
return HttpResponse("Pas de commande")
|
||||
adherentRequired = False
|
||||
|
@ -118,6 +120,14 @@ def order(request):
|
|||
adherentRequired = adherentRequired or menu.adherent_required
|
||||
if(adherentRequired and not user.profile.is_adherent):
|
||||
return HttpResponse("N'est pas adhérent et devrait l'être")
|
||||
# Partie un peu complexe : je libère toutes les pintes de la commande, puis je test
|
||||
# s'il a trop de pintes non rendues, puis je réalloue les pintes
|
||||
for pinte in listPintes:
|
||||
allocate(pinte, None)
|
||||
if(gp.lost_pintes_allowed and user.profile.nb_pintes >= gp.lost_pintes_allowed):
|
||||
return HttpResponse("Impossible de réaliser la commande : l'utilisateur a perdu trop de pintes.")
|
||||
for pinte in listPintes:
|
||||
allocate(pinte, user)
|
||||
if(paymentMethod.affect_balance):
|
||||
if(user.profile.balance < amount):
|
||||
return HttpResponse("Solde inférieur au prix de la commande")
|
||||
|
@ -418,7 +428,11 @@ def getProduct(request, 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})
|
||||
if product.category == Product.P_PRESSION:
|
||||
nb_pintes = 1
|
||||
else:
|
||||
nb_pintes = 0
|
||||
data = json.dumps({"pk": product.pk, "barcode" : product.barcode, "name": product.name, "amount": product.amount, "needQuantityButton": product.needQuantityButton, "nb_pintes": nb_pintes})
|
||||
return HttpResponse(data, content_type='application/json')
|
||||
|
||||
@active_required
|
||||
|
@ -845,7 +859,11 @@ def get_menu(request, 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})
|
||||
nb_pintes = 0
|
||||
for article in menu.articles:
|
||||
if article.category == Product.P_PRESSION:
|
||||
nb_pintes +=1
|
||||
data = json.dumps({"pk": menu.pk, "barcode" : menu.barcode, "name": menu.name, "amount" : menu.amount, needQuantityButton: False, "nb_pintes": nb_pintes})
|
||||
return HttpResponse(data, content_type='application/json')
|
||||
|
||||
class MenusAutocomplete(autocomplete.Select2QuerySetView):
|
||||
|
@ -885,4 +903,81 @@ 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})
|
||||
return render(request, "gestion/ranking.html", {"bestBuyers": bestBuyers, "bestDrinkers": bestDrinkers})
|
||||
|
||||
########## Pinte monitoring ##########
|
||||
|
||||
def allocate(pinte_pk, user):
|
||||
"""
|
||||
Allocate a pinte to a user or release the pinte if user is None
|
||||
"""
|
||||
try:
|
||||
pinte = Pinte.objects.get(pk=pinte_pk)
|
||||
if pinte.current_owner is not None:
|
||||
pinte.previous_owner = pinte.current_owner
|
||||
pinte.current_owner = user
|
||||
pinte.save()
|
||||
return True
|
||||
except Pinte.DoesNotExist:
|
||||
return False
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('gestion.change_pinte')
|
||||
def release(request, pinte_pk):
|
||||
"""
|
||||
View to release a pinte
|
||||
"""
|
||||
if allocate(pinte_pk, None):
|
||||
messages.success(request, "La pinte a bien été libérée")
|
||||
else:
|
||||
messages.error(request, "Impossible de libérer la pinte")
|
||||
return redirect(reverse('gestion:pintesList'))
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('gestion.add_pinte')
|
||||
def add_pintes(request):
|
||||
form = PinteForm(request.POST or None)
|
||||
if form.is_valid():
|
||||
ids = form.cleaned_data['ids']
|
||||
if ids != "":
|
||||
ids = ids.split(" ")
|
||||
else:
|
||||
ids = range(form.cleaned_data['begin'], form.cleaned_data['end'] + 1)
|
||||
i = 0
|
||||
for id in ids:
|
||||
if not Pinte.objects.filter(pk=id).exists():
|
||||
new_pinte = Pinte(pk=int(id))
|
||||
new_pinte.save()
|
||||
i += 1
|
||||
messages.success(request, str(i) + " pinte(s) a(ont) été ajoutée(s)")
|
||||
return redirect(reverse('gestion:productsIndex'))
|
||||
return render(request, "form.html", {"form": form, "form_title": "Ajouter des pintes", "form_button": "Ajouter"})
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('gestion.change_pinte')
|
||||
def release_pintes(request):
|
||||
form = PinteForm(request.POST or None)
|
||||
if form.is_valid():
|
||||
ids = form.cleaned_data['ids']
|
||||
if ids != "":
|
||||
ids = ids.split(" ")
|
||||
else:
|
||||
ids = range(form.cleaned_data['begin'], form.cleaned_data['end'] + 1)
|
||||
i = 0
|
||||
for id in ids:
|
||||
if allocate(id, None):
|
||||
i += 1
|
||||
messages.success(request, str(i) + " pinte(s) a(ont) été libérée(s)")
|
||||
return redirect(reverse('gestion:productsIndex'))
|
||||
return render(request, "form.html", {"form": form, "form_title": "Libérer des pintes", "form_button": "Libérer"})
|
||||
|
||||
@active_required
|
||||
@login_required
|
||||
@permission_required('gestion.view_pinte')
|
||||
def pintes_list(request):
|
||||
free_pintes = Pinte.objects.filter(current_owner=None)
|
||||
taken_pintes = Pinte.objects.exclude(current_owner=None)
|
||||
return render(request, "gestion/pintes_list.html", {"free_pintes": free_pintes, "taken_pintes": taken_pintes})
|
23
preferences/migrations/0002_auto_20181221_2151.py
Normal file
23
preferences/migrations/0002_auto_20181221_2151.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 2.1 on 2018-12-21 20:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('preferences', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='generalpreferences',
|
||||
name='use_pinte_monitoring',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalgeneralpreferences',
|
||||
name='use_pinte_monitoring',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
23
preferences/migrations/0003_auto_20181223_1440.py
Normal file
23
preferences/migrations/0003_auto_20181223_1440.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 2.1 on 2018-12-23 13:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('preferences', '0002_auto_20181221_2151'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='generalpreferences',
|
||||
name='lost_pintes_allowed',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalgeneralpreferences',
|
||||
name='lost_pintes_allowed',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
]
|
|
@ -30,6 +30,8 @@ class GeneralPreferences(models.Model):
|
|||
secretary = models.CharField(max_length=255, blank=True)
|
||||
brewer = models.CharField(max_length=255, blank=True)
|
||||
grocer = models.CharField(max_length=255, blank=True)
|
||||
use_pinte_monitoring = models.BooleanField(default=False)
|
||||
lost_pintes_allowed = models.PositiveIntegerField(default=0)
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Cotisation(models.Model):
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block entete %}Administration{% endblock %}
|
||||
{% block nav %}
|
||||
{% block navbar %}
|
||||
<ul>
|
||||
<li><a href="#first" class="active">Message global</a></li>
|
||||
<li><a href="#first">Message global</a></li>
|
||||
<li><a href="#second">Site actif</a></li>
|
||||
<li><a href="#third">Bureau</a></li>
|
||||
<li><a href="#fourth">Suivi de pintes</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -75,6 +76,27 @@
|
|||
{{form.brewer}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="fourth" class="main">
|
||||
<div class="spotlight">
|
||||
<div class="content">
|
||||
<header class="major">
|
||||
<h2>Suivi de pintes</h2>
|
||||
</header>
|
||||
<div class="row uniform">
|
||||
<div class="12u">
|
||||
{{form.use_pinte_monitoring}}
|
||||
<label for="{{form.use_pinte_monitoring.id_for_label}}">Utiliser le suivi de pinte ?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row uniform">
|
||||
<div class="12u">
|
||||
{{form.lost_pintes_allowed}}
|
||||
<label for="{{form.lost_pintes_allowed.id_for_label}}">Nombre de pintes non rendues avant d'interdire la consommation (0 pour ne jamais l'interdire, nécessite le suivi de pinte actif)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row uniform">
|
||||
<div class="12u">
|
||||
<button type="submit">Enregistrer</button>
|
||||
|
|
|
@ -14,4 +14,5 @@ urlpatterns = [
|
|||
path('editPaymentMethod/<int:pk>', views.editPaymentMethod, name="editPaymentMethod"),
|
||||
path('deletePaymentMethod/<int:pk>', views.deletePaymentMethod, name="deletePaymentMethod"),
|
||||
path('inactive', views.inactive, name="inactive"),
|
||||
path('getConfig', views.get_config, name="getConfig"),
|
||||
]
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import json
|
||||
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib import messages
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.http import HttpResponse
|
||||
from django.forms.models import model_to_dict
|
||||
|
||||
from coopeV3.acl import active_required
|
||||
|
||||
|
@ -238,4 +242,14 @@ def inactive(request):
|
|||
"""
|
||||
gp, _ = GeneralPreferences.objects.get_or_create(pk=1)
|
||||
return render(request, 'preferences/inactive.html', {"message": gp.active_message})
|
||||
|
||||
########## Config ##########
|
||||
|
||||
def get_config(request):
|
||||
"""
|
||||
Load the config and return it in a json format
|
||||
"""
|
||||
gp,_ = GeneralPreferences.objects.get_or_create(pk=1)
|
||||
data = json.dumps(model_to_dict(gp))
|
||||
return HttpResponse(data, content_type='application/json')
|
||||
|
|
@ -5,20 +5,32 @@ paymentMethod = null
|
|||
balance = 0
|
||||
username = ""
|
||||
id = 0
|
||||
listPintes = []
|
||||
nbPintes = 0;
|
||||
use_pinte_monitoring = false;
|
||||
|
||||
function get_config(){
|
||||
res = $.get("../preferences/getConfig", function(data){
|
||||
console.log(data.use_pinte_monitoring)
|
||||
use_pinte_monitoring = data.use_pinte_monitoring;
|
||||
});
|
||||
}
|
||||
|
||||
function get_product(barcode){
|
||||
res = $.get("getProduct/" + barcode, function(data){
|
||||
add_product(data.pk, data.barcode, data.name, data.amount);
|
||||
nbPintes += data.nb_pintes;
|
||||
add_product(data.pk, data.barcode, data.name, data.amount, data.needQuantityButton);
|
||||
});
|
||||
}
|
||||
|
||||
function get_menu(barcode){
|
||||
res = $.get("getMenu/" + barcode, function(data){
|
||||
add_menu(data.pk, data.barcode, data.name, data.amount);
|
||||
nbPintes += data.nb_pintes;
|
||||
add_menu(data.pk, data.barcode, data.name, data.amount, data.needQuantityButton);
|
||||
});
|
||||
}
|
||||
|
||||
function add_product(pk, barcode, name, amount){
|
||||
function add_product(pk, barcode, name, amount, needQuantityButton){
|
||||
exist = false
|
||||
index = -1
|
||||
for(k=0;k < products.length; k++){
|
||||
|
@ -27,10 +39,18 @@ function add_product(pk, barcode, name, amount){
|
|||
index = k
|
||||
}
|
||||
}
|
||||
if(exist){
|
||||
products[index].quantity += 1;
|
||||
if(needQuantityButton){
|
||||
quantity = parseInt(window.prompt("Quantité ?",""));
|
||||
}else{
|
||||
products.push({"pk": pk, "barcode": barcode, "name": name, "amount": amount, "quantity": 1});
|
||||
quantity = 1;
|
||||
}
|
||||
if(quantity == null || !Number.isInteger(quantity)){
|
||||
quantity = 1;
|
||||
}
|
||||
if(exist){
|
||||
products[index].quantity += quantity;
|
||||
}else{
|
||||
products.push({"pk": pk, "barcode": barcode, "name": name, "amount": amount, "quantity": quantity});
|
||||
}
|
||||
generate_html()
|
||||
}
|
||||
|
@ -53,7 +73,7 @@ function add_menu(pk, barcode, name, amount){
|
|||
}
|
||||
|
||||
function generate_html(){
|
||||
html =""
|
||||
html = "";
|
||||
for(k=0;k<products.length;k++){
|
||||
product = products[k]
|
||||
html += '<tr><td>' + product.barcode + '</td><td>' + product.name + '</td><td>' + String(product.amount) + '</td><td><input type="number" data-target="' + String(k) + '" onChange="updateInput(this)" value="' + String(product.quantity) + '"/></td><td>' + String(Number((product.quantity * product.amount).toFixed(2))) + '</td></tr>';
|
||||
|
@ -94,6 +114,7 @@ function updateMenuInput(a){
|
|||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
get_config();
|
||||
$(".product").click(function(){
|
||||
product = get_product($(this).attr('target'));
|
||||
});
|
||||
|
@ -113,7 +134,25 @@ $(document).ready(function(){
|
|||
});
|
||||
});
|
||||
$(".pay_button").click(function(){
|
||||
$.post("order", {"user":id, "paymentMethod": $(this).attr('data-payment'), "order_length": products.length + menus.length, "order": JSON.stringify(products), "amount": total, "menus": JSON.stringify(menus)}, function(data){
|
||||
if(use_pinte_monitoring){
|
||||
message = "Il reste " + nbPintes.toString() + " pintes à renseigner. Numéro de la pinte ?"
|
||||
while(nbPintes > 0){
|
||||
id_pinte = window.prompt(message,"");
|
||||
if(id_pinte == null){
|
||||
return;
|
||||
}else{
|
||||
id_pinte = parseInt(id_pinte);
|
||||
if(!Number.isInteger(id_pinte) || id_pinte < 0){
|
||||
message = "Numéro incorrect. Il reste " + nbPintes.toString() + " pintes à renseigner. Numéro de la pinte ?";
|
||||
}else{
|
||||
listPintes.push(id_pinte)
|
||||
nbPintes -= 1;
|
||||
message = "Il reste " + nbPintes.toString() + " pintes à renseigner. Numéro de la pinte ?"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$.post("order", {"user":id, "paymentMethod": $(this).attr('data-payment'), "order_length": products.length + menus.length, "order": JSON.stringify(products), "amount": total, "menus": JSON.stringify(menus), "listPintes": JSON.stringify(listPintes)}, function(data){
|
||||
alert(data);
|
||||
location.reload();
|
||||
}).fail(function(data){
|
||||
|
|
|
@ -119,6 +119,13 @@ class Profile(models.Model):
|
|||
alcohol += consumption.quantity * float(product.deg) * product.volume * 0.79 /10 /1000
|
||||
return alcohol
|
||||
|
||||
@property
|
||||
def nb_pintes(self):
|
||||
"""
|
||||
Return the number of pintes currently owned
|
||||
"""
|
||||
return self.user.pintes_owned_currently.count()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.user)
|
||||
|
||||
|
@ -128,9 +135,12 @@ class Profile(models.Model):
|
|||
tente de retourner l'attribut de l'user associé à l'instance
|
||||
"""
|
||||
try:
|
||||
r = super().__getattr__(name)
|
||||
r = self.__getattribute__(name)
|
||||
except AttributeError:
|
||||
r = getattr(self.user, name)
|
||||
try:
|
||||
r = super().__getattr__(name)
|
||||
except AttributeError:
|
||||
r = getattr(self.user, name)
|
||||
return r
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue