diff --git a/CHANGELOG.md b/CHANGELOG.md index 6452260..031d8a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v3.6.4 +* Ajout d'un champ use_stocks +* Séparation des formulaires de fût ## v3.6.3 * Refonte totale du système de stocks * Fix price profile diff --git a/gestion/admin.py b/gestion/admin.py index 95b9471..8097687 100644 --- a/gestion/admin.py +++ b/gestion/admin.py @@ -59,10 +59,10 @@ class ProductAdmin(SimpleHistoryAdmin): """ The admin class for :class:`Products `. """ - list_display = ('name', 'amount', 'is_active', 'category', 'adherentRequired', 'stock', 'volume', 'deg') + list_display = ('name', 'amount', 'is_active', 'category', 'adherentRequired', 'stock', 'volume', 'deg', 'use_stocks') ordering = ('name', 'amount', 'stock', 'deg') search_fields = ('name',) - list_filter = ('is_active', 'adherentRequired', 'category') + list_filter = ('is_active', 'adherentRequired', 'category', 'use_stocks') class ReloadAdmin(SimpleHistoryAdmin): """ diff --git a/gestion/forms.py b/gestion/forms.py index daa8b8c..20822bc 100644 --- a/gestion/forms.py +++ b/gestion/forms.py @@ -42,9 +42,9 @@ class ProductForm(forms.ModelForm): fields = "__all__" widgets = {'amount': forms.TextInput} -class KegForm(forms.ModelForm): +class CreateKegForm(forms.ModelForm): """ - A form to create and edit a :class:`~gestion.models.Keg`. + A form to create a :class:`~gestion.models.Keg`. """ class Meta: @@ -52,9 +52,24 @@ class KegForm(forms.ModelForm): fields = ["name", "stockHold", "amount", "capacity"] widgets = {'amount': forms.TextInput} - category = forms.ModelChoiceField(queryset=Category.objects.all(), label="Catégorie") + category = forms.ModelChoiceField(queryset=Category.objects.all(), label="Catégorie", help_text="Catégorie dans laquelle placer les produits pinte, demi (et galopin si besoin).") deg = forms.DecimalField(max_digits=5, decimal_places=2, label="Degré", validators=[MinValueValidator(0)]) - create_galopin = forms.BooleanField(label="Créer le produit galopin ?") + create_galopin = forms.BooleanField(required=False, label="Créer le produit galopin ?") + + def clean(self): + cleaned_data = super().clean() + if cleaned_data.get("name")[0:4] != "Fût ": + raise ValidationError("Le nom du fût doit être sous la forme 'Fût nom de la bière'") + +class EditKegForm(forms.ModelForm): + """ + A form to edit a :class:`~gestion.models.Keg`. + """ + + class Meta: + model = Keg + fields = ["name", "stockHold", "amount", "capacity", "pinte", "demi", "galopin"] + widgets = {'amount': forms.TextInput} def clean(self): cleaned_data = super().clean() diff --git a/gestion/migrations/0013_auto_20190829_1219.py b/gestion/migrations/0013_auto_20190829_1219.py new file mode 100644 index 0000000..79c38d5 --- /dev/null +++ b/gestion/migrations/0013_auto_20190829_1219.py @@ -0,0 +1,23 @@ +# Generated by Django 2.1 on 2019-08-29 10:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('gestion', '0012_auto_20190827_2119'), + ] + + operations = [ + migrations.AddField( + model_name='historicalproduct', + name='use_stocks', + field=models.BooleanField(default=True, verbose_name='Utiliser les stocks ?'), + ), + migrations.AddField( + model_name='product', + name='use_stocks', + field=models.BooleanField(default=True, verbose_name='Utiliser les stocks ?'), + ), + ] diff --git a/gestion/models.py b/gestion/models.py index 64267d2..627cebf 100644 --- a/gestion/models.py +++ b/gestion/models.py @@ -26,6 +26,13 @@ class Category(models.Model): Return active producs of this category """ return self.product_set.filter(is_active=True) + + @property + def active_stock_products(self): + """ + Return active products that use stocks + """ + return self.product_set.filter(is_active=True).filter(use_stocks=True) class Product(models.Model): """ @@ -87,6 +94,7 @@ class Product(models.Model): On the graphs on :func:`users.views.profile` view, the number of total consumptions is divised by the showingMultiplier """ draft_category = models.IntegerField(choices=DRAFT_TYPES, default=DRAFT_NONE, verbose_name="Type de pression") + use_stocks = models.BooleanField(default=True, verbose_name="Utiliser les stocks ?") history = HistoricalRecords() def __str__(self): diff --git a/gestion/templates/gestion/product_profile.html b/gestion/templates/gestion/product_profile.html index b9dde04..4858c27 100644 --- a/gestion/templates/gestion/product_profile.html +++ b/gestion/templates/gestion/product_profile.html @@ -19,5 +19,6 @@ Actif : {{ product.is_active | yesno:"Oui, Non"}}
Dégré : {{ product.deg }}
Volume : {{ product.volume }}cl
+ Utiliser les stocks : {{product.use_stocks|yesno:"Oui,Non"}}
{% endblock %} diff --git a/gestion/templates/gestion/stocks.html b/gestion/templates/gestion/stocks.html index 82f0671..69ea005 100644 --- a/gestion/templates/gestion/stocks.html +++ b/gestion/templates/gestion/stocks.html @@ -24,7 +24,7 @@ - {% for product in category.active_products %} + {% for product in category.active_stock_products %} {{ product.name }} {{ product.stock }} diff --git a/gestion/views.py b/gestion/views.py index f8e4bed..860eb7c 100644 --- a/gestion/views.py +++ b/gestion/views.py @@ -22,7 +22,7 @@ from decimal import * import os from math import floor, ceil -from .forms import ReloadForm, RefundForm, ProductForm, KegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm, GenerateReleveForm, CategoryForm, SearchCategoryForm, GenerateInvoiceForm, ComputePriceForm +from .forms import ReloadForm, RefundForm, ProductForm, CreateKegForm, EditKegForm, MenuForm, GestionForm, SearchMenuForm, SearchProductForm, SelectPositiveKegForm, SelectActiveKegForm, PinteForm, GenerateReleveForm, CategoryForm, SearchCategoryForm, GenerateInvoiceForm, ComputePriceForm from .models import Product, Menu, Keg, ConsumptionHistory, KegHistory, Consumption, MenuHistory, Pinte, Reload, Refund, Category from users.models import School from preferences.models import PaymentMethod, GeneralPreferences, Cotisation, DivideHistory, PriceProfile @@ -160,7 +160,7 @@ def order(request): kegHistory.quantitySold += Decimal(quantity * 0.125) kegHistory.amountSold += Decimal(quantity * product.amount) kegHistory.save() - else: + if product.use_stocks: if(product.stock > quantity): product.stock -= quantity product.save() @@ -197,11 +197,36 @@ def order(request): consumption, _ = Consumption.objects.get_or_create(customer=user, product=article) consumption.quantity += quantity consumption.save() - if(article.stock > quantity): - article.stock -= quantity - article.save() - else: - raise Exception("Le stock du produit " + article.name + "n'autorise pas l'opération") + if(article.draft_category == Product.DRAFT_PINTE): + keg = get_object_or_404(Keg, pinte=article) + if(not keg.is_active): + raise Exception("Fût non actif") + 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(article.draft_category == Product.DRAFT_DEMI): + keg = get_object_or_404(Keg, demi=article) + if(not keg.is_active): + raise Exception("Fût non actif") + 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(article.draft_category == Product.DRAFT_GALOPIN): + keg = get_object_or_404(Keg, galopin=article) + if(not keg.is_active): + raise Exception("Fût non actif") + kegHistory = get_object_or_404(KegHistory, keg=keg, isCurrentKegHistory=True) + kegHistory.quantitySold += Decimal(quantity * 0.125) + kegHistory.amountSold += Decimal(quantity * product.amount) + kegHistory.save() + if article.use_stocks: + if(article.stock > quantity): + article.stock -= quantity + article.save() + else: + 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") @@ -296,8 +321,9 @@ 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() + if product.use_stocks: + 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})) @@ -467,8 +493,9 @@ class ActiveProductsAutocomplete(autocomplete.Select2QuerySetView): 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() + if product.use_stocks: + product.stock = request.GET.get("stock") + product.save() return HttpResponse("Le stock a bien été mis à jour") @active_required @@ -488,12 +515,16 @@ def stocks(request): @permission_required('gestion.add_keg') def addKeg(request): """ - Displays a :class:`gestion.forms.KegForm` to add a :class:`gestion.models.Keg`. + Displays a :class:`gestion.forms.CreateKegForm` to add a :class:`gestion.models.Keg`. """ - form = KegForm(request.POST or None) + form = CreateKegForm(request.POST or None) if form.is_valid(): + try: + price_profile = PriceProfile.objects.get(use_for_draft=True) + except: + messages.error(request, "Il n'y a pas de profil de prix pour les pressions") + return redirect(reverse('preferences:priceProfilesIndex')) keg = form.save(commit=False) - price_profile = get_object_or_404(PriceProfile, use_for_draft=True) pinte_price = compute_price(form.cleaned_data["amount"]/(2*form.cleaned_data["capacity"]), price_profile.a, price_profile.b, price_profile.c, price_profile.alpha) pinte_price = ceil(10*pinte_price)/10 name = form.cleaned_data["name"][4:] @@ -509,7 +540,8 @@ def addKeg(request): deg = form.cleaned_data["deg"], adherentRequired = True, showingMultiplier = 1, - draft_category = Product.DRAFT_PINTE + draft_category = Product.DRAFT_PINTE, + use_stocks=False, ) pinte.save() keg.pinte = pinte @@ -524,7 +556,8 @@ def addKeg(request): deg = form.cleaned_data["deg"], adherentRequired = True, showingMultiplier = 1, - draft_category = Product.DRAFT_DEMI + draft_category = Product.DRAFT_DEMI, + use_stocks=False, ) demi.save() keg.demi = demi @@ -540,7 +573,8 @@ def addKeg(request): deg = form.cleaned_data["deg"], adherentRequired = True, showingMultiplier = 1, - draft_category = Product.DRAFT_DEMI + draft_category = Product.DRAFT_DEMI, + use_stocks=False, ) galopin.save() keg.galopin = galopin @@ -554,13 +588,13 @@ def addKeg(request): @permission_required('gestion.change_keg') def editKeg(request, pk): """ - Displays a :class:`gestion.forms.KegForm` to edit a :class:`gestion.models.Keg`. + Displays a :class:`gestion.forms.EditKegForm` to edit a :class:`gestion.models.Keg`. pk The primary key of the :class:`gestion.models.Keg` to edit. """ keg = get_object_or_404(Keg, pk=pk) - form = KegForm(request.POST or None, instance=keg) + form = EditKegForm(request.POST or None, instance=keg) if(form.is_valid()): form.save() messages.success(request, "Le fût a bien été modifié") diff --git a/templates/footer.html b/templates/footer.html index c45aa08..ffb1fac 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -42,6 +42,6 @@
  • Facebook
  • - +