2018-11-22 21:52:15 +00:00
from django . shortcuts import render , redirect , get_object_or_404
2018-10-05 22:03:02 +00:00
from django . contrib import messages
from django . urls import reverse
2018-11-22 21:52:15 +00:00
from django . http import HttpResponse , Http404
2019-05-03 21:27:11 +00:00
from django . contrib . auth . models import User , Group
2018-11-22 21:52:15 +00:00
from django . views . decorators . csrf import csrf_exempt
from django . contrib . auth . decorators import login_required , permission_required
2018-11-25 12:52:32 +00:00
from django . utils import timezone
2018-12-24 00:30:00 +00:00
from django . http import HttpResponseRedirect
2019-01-22 19:27:18 +00:00
from django . db import transaction
2019-06-23 11:46:12 +00:00
from django . conf import settings
2018-10-05 22:03:02 +00:00
2019-01-22 19:27:18 +00:00
from datetime import datetime , timedelta
2019-01-05 23:01:30 +00:00
2019-01-22 19:27:18 +00:00
from django_tex . views import render_to_pdf
2019-01-05 23:01:30 +00:00
from coopeV3 . acl import active_required , acl_or , admin_required
2019-06-23 13:31:55 +00:00
from coopeV3 . utils import compute_price
2018-11-22 21:52:15 +00:00
import simplejson as json
2018-10-05 22:03:02 +00:00
from dal import autocomplete
2018-11-22 21:52:15 +00:00
from decimal import *
2019-06-23 11:46:12 +00:00
import os
2019-06-23 13:31:55 +00:00
from math import floor , ceil
2018-10-05 22:03:02 +00:00
2019-08-29 10:45:30 +00:00
from . forms import ReloadForm , RefundForm , ProductForm , CreateKegForm , EditKegForm , MenuForm , GestionForm , SearchMenuForm , SearchProductForm , SelectPositiveKegForm , SelectActiveKegForm , PinteForm , GenerateReleveForm , CategoryForm , SearchCategoryForm , GenerateInvoiceForm , ComputePriceForm
2019-05-03 19:09:32 +00:00
from . models import Product , Menu , Keg , ConsumptionHistory , KegHistory , Consumption , MenuHistory , Pinte , Reload , Refund , Category
2019-05-03 21:27:11 +00:00
from users . models import School
2019-06-23 14:32:38 +00:00
from preferences . models import PaymentMethod , GeneralPreferences , Cotisation , DivideHistory , PriceProfile
2019-01-05 23:01:30 +00:00
from users . models import CotisationHistory
2018-08-31 12:46:35 +00:00
2018-11-22 21:52:15 +00:00
@active_required
@login_required
@acl_or ( ' gestion.add_consumptionhistory ' , ' gestion.add_reload ' , ' gestion.add_refund ' )
2018-09-01 19:57:09 +00:00
def manage ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays the manage view .
2018-12-02 15:28:40 +00:00
"""
2019-05-03 19:09:32 +00:00
categories = Category . objects . exclude ( order = 0 ) . order_by ( ' order ' )
2018-11-22 21:52:15 +00:00
pay_buttons = PaymentMethod . objects . filter ( is_active = True )
2018-10-05 22:03:02 +00:00
gestion_form = GestionForm ( request . POST or None )
reload_form = ReloadForm ( request . POST or None )
refund_form = RefundForm ( request . POST or None )
bieresPression = [ ]
menus = Menu . objects . filter ( is_active = True )
kegs = Keg . objects . filter ( is_active = True )
2019-01-06 04:18:31 +00:00
gp , _ = GeneralPreferences . objects . get_or_create ( pk = 1 )
2019-01-22 19:27:18 +00:00
cotisations = Cotisation . objects . all ( )
2019-01-06 04:18:31 +00:00
floating_buttons = gp . floating_buttons
2018-10-05 22:03:02 +00:00
for keg in kegs :
if ( keg . pinte ) :
bieresPression . append ( keg . pinte )
if ( keg . demi ) :
bieresPression . append ( keg . demi )
if ( keg . galopin ) :
bieresPression . append ( keg . galopin )
2018-12-02 15:28:40 +00:00
return render ( request , " gestion/manage.html " , {
" gestion_form " : gestion_form ,
" reload_form " : reload_form ,
" refund_form " : refund_form ,
" bieresPression " : bieresPression ,
2019-05-03 19:09:32 +00:00
" categories " : categories ,
2019-01-06 04:18:31 +00:00
" pay_buttons " : pay_buttons ,
" floating_buttons " : floating_buttons ,
2019-01-22 19:27:18 +00:00
" cotisations " : cotisations
2018-12-02 15:28:40 +00:00
} )
2018-11-22 21:52:15 +00:00
2018-12-02 18:50:15 +00:00
@csrf_exempt
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.add_consumptionhistory ' )
def order ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Processes the given order . The order is passed through POST .
2018-12-02 15:28:40 +00:00
"""
2019-01-22 19:27:18 +00:00
try :
with transaction . atomic ( ) :
if ( " user " not in request . POST or " paymentMethod " not in request . POST or " amount " not in request . POST or " order " not in request . POST ) :
2019-09-06 16:12:24 +00:00
raise Exception ( " Erreur du post. " )
2018-11-25 12:52:32 +00:00
else :
2019-09-06 16:12:24 +00:00
try :
user = User . objects . get ( pk = request . POST [ ' user ' ] )
except :
raise Exception ( " Impossible de récupérer l ' utilisateur " )
2019-01-22 19:27:18 +00:00
paymentMethod = get_object_or_404 ( PaymentMethod , pk = request . POST [ ' paymentMethod ' ] )
amount = Decimal ( request . POST [ ' amount ' ] )
order = json . loads ( request . POST [ " order " ] )
menus = json . loads ( request . POST [ " menus " ] )
listPintes = json . loads ( request . POST [ " listPintes " ] )
cotisations = json . loads ( request . POST [ ' cotisations ' ] )
2019-09-22 13:32:40 +00:00
reloads = json . loads ( request . POST [ ' reloads ' ] )
2019-01-22 19:27:18 +00:00
gp , _ = GeneralPreferences . objects . get_or_create ( pk = 1 )
if ( not order ) and ( not menus ) and ( not cotisations ) :
2019-09-06 16:12:24 +00:00
raise Exception ( " Pas de commande. " )
2019-09-22 13:32:40 +00:00
if ( reloads ) :
for reload in reloads :
reload_amount = Decimal ( reload [ " value " ] ) * Decimal ( reload [ " quantity " ] )
2019-09-22 18:44:33 +00:00
if ( reload_amount < = 0 ) :
raise Exception ( " Impossible d ' effectuer un rechargement négatif " )
reload_payment_method = get_object_or_404 ( PaymentMethod , pk = reload [ " payment_method " ] )
if not reload_payment_method . is_usable_in_reload :
raise Exception ( " Le moyen de paiement ne peut pas être utilisé pour les rechargements. " )
2019-09-22 13:32:40 +00:00
reload_entry = Reload ( customer = user , amount = reload_amount , PaymentMethod = reload_payment_method , coopeman = request . user )
reload_entry . save ( )
user . profile . credit + = reload_amount
user . save ( )
2019-01-22 19:27:18 +00:00
if ( cotisations ) :
for co in cotisations :
cotisation = Cotisation . objects . get ( pk = co [ ' pk ' ] )
for i in range ( co [ ' quantity ' ] ) :
cotisation_history = CotisationHistory ( cotisation = cotisation )
2019-09-22 18:44:33 +00:00
if not paymentMethod . is_usable_in_cotisation :
raise Exception ( " Le moyen de paiement ne peut pas être utilisé pour les cotisations. " )
2019-01-22 19:27:18 +00:00
if ( paymentMethod . affect_balance ) :
if ( user . profile . balance > = cotisation_history . cotisation . amount ) :
user . profile . debit + = cotisation_history . cotisation . amount
else :
2019-09-06 16:12:24 +00:00
raise Exception ( " Solde insuffisant " )
2019-06-23 15:11:58 +00:00
else :
user . profile . direct_debit + = cotisation_history . cotisation . amount
2019-01-22 19:27:18 +00:00
cotisation_history . user = user
cotisation_history . coopeman = request . user
cotisation_history . amount = cotisation . amount
cotisation_history . duration = cotisation . duration
cotisation_history . paymentMethod = paymentMethod
if ( user . profile . cotisationEnd and user . profile . cotisationEnd > timezone . now ( ) ) :
cotisation_history . endDate = user . profile . cotisationEnd + timedelta ( days = cotisation . duration )
else :
cotisation_history . endDate = timezone . now ( ) + timedelta ( days = cotisation . duration )
user . profile . cotisationEnd = cotisation_history . endDate
user . save ( )
cotisation_history . save ( )
adherentRequired = False
for o in order :
product = get_object_or_404 ( Product , pk = o [ " pk " ] )
adherentRequired = adherentRequired or product . adherentRequired
for m in menus :
menu = get_object_or_404 ( Menu , pk = m [ " pk " ] )
adherentRequired = adherentRequired or menu . adherent_required
if ( adherentRequired and not user . profile . is_adherent ) :
2019-09-06 16:12:24 +00:00
raise Exception ( " N ' est pas adhérent et devrait l ' être. " )
2019-01-22 19:27:18 +00:00
# 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 . use_pinte_monitoring and gp . lost_pintes_allowed and user . profile . nb_pintes > = gp . lost_pintes_allowed ) :
2019-09-06 16:12:24 +00:00
raise Exception ( " Impossible de réaliser la commande : l ' utilisateur a perdu trop de pintes. " )
2019-01-22 19:27:18 +00:00
for pinte in listPintes :
allocate ( pinte , user )
for o in order :
product = get_object_or_404 ( Product , pk = o [ " pk " ] )
quantity = int ( o [ " quantity " ] )
2019-05-06 07:40:40 +00:00
if ( product . draft_category == Product . DRAFT_PINTE ) :
2019-01-22 19:27:18 +00:00
keg = get_object_or_404 ( Keg , pinte = product )
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 ( )
2019-05-06 07:40:40 +00:00
elif ( product . draft_category == Product . DRAFT_DEMI ) :
2019-01-22 19:27:18 +00:00
keg = get_object_or_404 ( Keg , demi = product )
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 ( )
2019-05-06 07:40:40 +00:00
elif ( product . draft_category == Product . DRAFT_GALOPIN ) :
2019-01-22 19:27:18 +00:00
keg = get_object_or_404 ( Keg , galopin = product )
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 ( )
2019-08-29 10:35:47 +00:00
if product . use_stocks :
2019-09-06 16:12:24 +00:00
if ( product . stock > = quantity ) :
2019-08-27 21:21:15 +00:00
product . stock - = quantity
2019-08-27 16:58:55 +00:00
product . save ( )
else :
2019-08-27 21:21:15 +00:00
raise Exception ( " Le stock du produit n ' autorise pas l ' opération " )
2019-01-22 19:27:18 +00:00
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 = Decimal ( quantity * product . amount ) , coopeman = request . user )
ch . save ( )
2019-06-12 21:53:01 +00:00
user . profile . alcohol + = Decimal ( quantity * float ( product . deg ) * product . volume * 0.79 / 10 / 1000 )
2019-01-26 16:02:23 +00:00
if ( paymentMethod . affect_balance ) :
if ( user . profile . balance > = Decimal ( product . amount * quantity ) ) :
user . profile . debit + = Decimal ( product . amount * quantity )
else :
2019-09-06 16:12:24 +00:00
raise Exception ( " Solde insuffisant " )
2019-06-23 15:11:58 +00:00
else :
user . profile . direct_debit + = Decimal ( product . amount * quantity )
2019-01-22 19:27:18 +00:00
for m in menus :
menu = get_object_or_404 ( Menu , pk = m [ " pk " ] )
quantity = int ( m [ " quantity " ] )
mh = MenuHistory ( customer = user , quantity = quantity , paymentMethod = paymentMethod , menu = menu , amount = int ( quantity * menu . amount ) , coopeman = request . user )
mh . save ( )
2019-01-26 16:02:23 +00:00
if ( paymentMethod . affect_balance ) :
if ( user . profile . balance > = Decimal ( product . amount * quantity ) ) :
user . profile . debit + = Decimal ( product . amount * quantity )
else :
2019-09-06 16:12:24 +00:00
raise Exception ( " Solde insuffisant " )
2019-06-23 15:11:58 +00:00
else :
user . profile . direct_debit + = Decimal ( product . amount * quantity )
2019-01-22 19:27:18 +00:00
for article in menu . articles . all ( ) :
consumption , _ = Consumption . objects . get_or_create ( customer = user , product = article )
consumption . quantity + = quantity
consumption . save ( )
2019-08-29 10:35:47 +00:00
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 :
2019-09-06 16:12:24 +00:00
if ( article . stock > = quantity ) :
2019-08-29 10:35:47 +00:00
article . stock - = quantity
article . save ( )
else :
raise Exception ( " Le stock du produit " + article . name + " n ' autorise pas l ' opération " )
2019-06-12 21:53:01 +00:00
user . profile . alcohol + = Decimal ( quantity * float ( product . deg ) * product . volume * 0.79 / 10 / 1000 )
2019-01-24 21:33:48 +00:00
user . save ( )
2019-01-22 19:27:18 +00:00
return HttpResponse ( " La commande a bien été effectuée " )
except Exception as e :
2019-09-06 16:12:24 +00:00
return HttpResponse ( " Impossible d ' effectuer la transaction : " + e . args [ 0 ] )
2018-11-22 21:52:15 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.add_reload ' )
2018-10-05 22:03:02 +00:00
def reload ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` Reload form < gestion . forms . reloadForm > ` .
2018-12-02 15:28:40 +00:00
"""
2018-10-05 22:03:02 +00:00
reload_form = ReloadForm ( request . POST or None )
2018-12-02 15:28:40 +00:00
if reload_form . is_valid ( ) :
reload_entry = reload_form . save ( commit = False )
reload_entry . coopeman = request . user
reload_entry . save ( )
2018-10-05 22:03:02 +00:00
user = reload_form . cleaned_data [ ' customer ' ]
amount = reload_form . cleaned_data [ ' amount ' ]
user . profile . credit + = amount
user . save ( )
2018-12-02 15:28:40 +00:00
messages . success ( request , " Le compte de " + user . username + " a bien été crédité de " + str ( amount ) + " € " )
2018-10-05 22:03:02 +00:00
else :
messages . error ( request , " Le rechargement a échoué " )
return redirect ( reverse ( ' gestion:manage ' ) )
2018-12-24 00:30:00 +00:00
@active_required
@login_required
@permission_required ( ' gestion.delete_reload ' )
def cancel_reload ( request , pk ) :
"""
2019-02-28 12:18:41 +00:00
Delete a : class : ` gestion . models . Reload ` .
pk
The primary key of the reload to delete .
2018-12-24 00:30:00 +00:00
"""
reload_entry = get_object_or_404 ( Reload , pk = pk )
if reload_entry . customer . profile . balance > = reload_entry . amount :
reload_entry . customer . profile . credit - = reload_entry . amount
reload_entry . customer . save ( )
reload_entry . delete ( )
messages . success ( request , " Le rechargement a bien été annulé. " )
else :
messages . error ( request , " Impossible d ' annuler le rechargement. Le solde deviendrait négatif. " )
return HttpResponseRedirect ( request . META . get ( ' HTTP_REFERER ' , ' / ' ) )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.add_refund ' )
2018-10-05 22:03:02 +00:00
def refund ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` Refund form < gestion . forms . RefundForm > ` .
2018-12-02 15:28:40 +00:00
"""
2018-10-05 22:03:02 +00:00
refund_form = RefundForm ( request . POST or None )
2018-12-02 15:28:40 +00:00
if refund_form . is_valid ( ) :
2018-10-05 22:03:02 +00:00
user = refund_form . cleaned_data [ ' customer ' ]
amount = refund_form . cleaned_data [ ' amount ' ]
2018-12-02 15:28:40 +00:00
if amount < = user . profile . balance :
refund_entry = refund_form . save ( commit = False )
refund_entry . coopeman = request . user
refund_entry . save ( )
2018-10-05 22:03:02 +00:00
user . profile . credit - = amount
user . save ( )
messages . success ( request , " Le compte de " + user . username + " a bien été remboursé de " + str ( amount ) + " € " )
else :
messages . error ( request , " Impossible de rembourser l ' utilisateur " + user . username + " de " + str ( amount ) + " € : il n ' a que " + str ( user . profile . balance ) + " € sur son compte. " )
else :
messages . error ( request , " Le remboursement a échoué " )
return redirect ( reverse ( ' gestion:manage ' ) )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-30 18:54:12 +00:00
@login_required
@permission_required ( ' gestion.delete_consumptionhistory ' )
def cancel_consumption ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Delete a : class : ` consumption history < gestion . models . ConsumptionHistory > ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the consumption history to delete .
2018-12-02 15:28:40 +00:00
"""
2018-11-30 18:54:12 +00:00
consumption = get_object_or_404 ( ConsumptionHistory , pk = pk )
user = consumption . customer
2019-08-27 21:21:15 +00:00
product = consumption . product
2018-12-18 10:38:20 +00:00
if consumption . paymentMethod . affect_balance :
user . profile . debit - = consumption . amount
2019-06-23 15:11:58 +00:00
else :
user . profile . direct_debit - = consumption . amount
2019-06-12 21:53:01 +00:00
user . profile . alcohol - = Decimal ( consumption . quantity * float ( consumption . product . deg ) * consumption . product . volume * 0.79 / 10 / 1000 )
user . save ( )
2018-12-13 18:26:58 +00:00
consumptionT = Consumption . objects . get ( customer = user , product = consumption . product )
consumptionT . quantity - = consumption . quantity
consumptionT . save ( )
2019-08-29 10:35:47 +00:00
if product . use_stocks :
product . stock + = consumption . quantity
product . save ( )
2018-11-30 18:54:12 +00:00
consumption . delete ( )
messages . success ( request , " La consommation a bien été annulée " )
return redirect ( reverse ( ' users:profile ' , kwargs = { ' pk ' : user . pk } ) )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-30 18:54:12 +00:00
@login_required
@permission_required ( ' gestion.delete_menuhistory ' )
def cancel_menu ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Delete a : class : ` menu history < gestion . models . MenuHistory > ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the menu history to delete .
2018-12-02 15:28:40 +00:00
"""
2018-11-30 18:54:12 +00:00
menu_history = get_object_or_404 ( MenuHistory , pk = pk )
user = menu_history . customer
2018-12-18 10:38:20 +00:00
if menu_history . paymentMethod . affect_balance :
user . profile . debit - = menu_history . amount
2019-06-23 15:11:58 +00:00
else :
user . profile . direct_debit - = menu_history . amount
2019-08-27 21:21:15 +00:00
for product in menu_history . menu . articles :
product . stock + = menu_history . quantity
product . save ( )
2018-12-13 18:26:58 +00:00
consumptionT = Consumption . objects . get ( customer = user , product = product )
consumptionT - = menu_history . quantity
2019-01-05 23:01:30 +00:00
consumptionT . save ( )
2019-06-12 21:53:01 +00:00
user . profile . alcohol - = Decimal ( menu_history . quantity * float ( menu_history . product . deg ) * menu_history . product . volume * 0.79 / 10 / 1000 )
2019-06-23 15:11:58 +00:00
user . save ( )
2018-11-30 18:54:12 +00:00
menu_history . delete ( )
messages . success ( request , " La consommation du menu a bien été annulée " )
return redirect ( reverse ( ' users:profile ' , kwargs = { ' pk ' : user . pk } ) )
2018-11-22 21:52:15 +00:00
########## Products ##########
2019-08-27 21:21:15 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@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 ' )
2018-10-05 22:03:02 +00:00
def productsIndex ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays the products manage static page .
2018-12-02 15:28:40 +00:00
"""
2018-10-05 22:03:02 +00:00
return render ( request , " gestion/products_index.html " )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.add_product ' )
2018-10-05 22:03:02 +00:00
def addProduct ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . ProductForm ` to add a product .
2018-12-02 15:28:40 +00:00
"""
2018-10-05 22:03:02 +00:00
form = ProductForm ( request . POST or None )
if ( form . is_valid ( ) ) :
2018-12-16 08:33:44 +00:00
product = form . save ( )
2018-10-05 22:03:02 +00:00
messages . success ( request , " Le produit a bien été ajouté " )
2018-12-16 08:33:44 +00:00
return redirect ( reverse ( ' gestion:productProfile ' , kwargs = { ' pk ' : product . pk } ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' un produit " , " form_button " : " Ajouter " , " form_button_icon " : " plus-square " } )
2018-10-05 22:03:02 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 23:15:09 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.change_product ' )
2018-11-25 23:15:09 +00:00
def editProduct ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . ProductForm ` to edit a product .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the the : class : ` gestion . models . Product ` to edit .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 23:15:09 +00:00
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é " )
2018-12-16 08:33:44 +00:00
return redirect ( reverse ( ' gestion:productProfile ' , kwargs = { ' pk ' : product . pk } ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' un produit " , " form_button " : " Modifier " , " form_button_icon " : " pencil-alt " } )
2018-11-25 23:15:09 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.view_product ' )
2018-10-05 22:03:02 +00:00
def productsList ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Display the list of : class : ` products < gestion . models . Product > ` .
2018-12-02 15:28:40 +00:00
"""
2018-10-05 22:03:02 +00:00
products = Product . objects . all ( )
return render ( request , " gestion/products_list.html " , { " products " : products } )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.view_product ' )
def searchProduct ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . SearchProduct ` to search a : class : ` gestion . models . Product ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-22 21:52:15 +00:00
form = SearchProductForm ( request . POST or None )
if ( form . is_valid ( ) ) :
return redirect ( reverse ( ' gestion:productProfile ' , kwargs = { ' pk ' : form . cleaned_data [ ' product ' ] . pk } ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Rechercher un produit " , " form_button " : " Rechercher " , " form_button_icon " : " search " } )
2018-11-22 21:52:15 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.view_product ' )
def productProfile ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays the profile of a : class : ` gestion . models . Product ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the : class : ` gestion . models . Product ` to display profile .
2018-12-02 15:28:40 +00:00
"""
2018-11-22 21:52:15 +00:00
product = get_object_or_404 ( Product , pk = pk )
return render ( request , " gestion/product_profile.html " , { " product " : product } )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
2018-12-23 22:55:27 +00:00
def getProduct ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-06-23 14:43:23 +00:00
Get a : class : ` gestion . models . Product ` by pk and return it in JSON format .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the : class : ` gestion . models . Product ` to get infos .
2018-12-02 15:28:40 +00:00
"""
2018-12-23 22:55:27 +00:00
product = Product . objects . get ( pk = pk )
2019-05-06 07:40:40 +00:00
if product . category == Product . DRAFT_PINTE :
2018-12-23 10:53:33 +00:00
nb_pintes = 1
else :
nb_pintes = 0
2019-06-23 14:43:23 +00:00
data = json . dumps ( { " pk " : product . pk , " name " : product . name , " amount " : product . amount , " needQuantityButton " : product . needQuantityButton , " nb_pintes " : nb_pintes } )
2018-10-05 22:03:02 +00:00
return HttpResponse ( data , content_type = ' application/json ' )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 23:15:09 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.change_product ' )
2018-11-25 23:15:09 +00:00
def switch_activate ( request , pk ) :
"""
2019-02-28 12:18:41 +00:00
Switch the active status of the requested : class : ` gestion . models . Product ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the : class : ` gestion . models . Product ` to display profile .
2018-11-25 23:15:09 +00:00
"""
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 " )
2018-12-16 08:33:44 +00:00
return redirect ( reverse ( ' gestion:productProfile ' , kwargs = { ' pk ' : product . pk } ) )
2018-11-25 23:15:09 +00:00
2018-11-22 21:52:15 +00:00
class ProductsAutocomplete ( autocomplete . Select2QuerySetView ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Autocomplete view for all : class : ` products < gestion . models . Product > ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-22 21:52:15 +00:00
def get_queryset ( self ) :
qs = Product . objects . all ( )
if self . q :
2019-01-23 11:31:33 +00:00
qs = qs . filter ( name__icontains = self . q )
2018-11-22 21:52:15 +00:00
return qs
2018-10-05 22:03:02 +00:00
2018-12-23 22:55:27 +00:00
class ActiveProductsAutocomplete ( autocomplete . Select2QuerySetView ) :
"""
2019-02-28 12:18:41 +00:00
Autocomplete view for active : class : ` products < gestion . models . Product > ` .
2018-12-23 22:55:27 +00:00
"""
def get_queryset ( self ) :
qs = Product . objects . filter ( is_active = True )
if self . q :
2019-01-23 11:31:33 +00:00
qs = qs . filter ( name__icontains = self . q )
2018-12-23 22:55:27 +00:00
return qs
2019-08-27 21:21:15 +00:00
@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 ) :
2019-08-29 10:35:47 +00:00
if product . use_stocks :
product . stock = request . GET . get ( " stock " )
product . save ( )
2019-08-27 21:21:15 +00:00
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 } )
2018-10-05 22:03:02 +00:00
########## Kegs ##########
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.add_keg ' )
2018-10-05 22:03:02 +00:00
def addKeg ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-08-29 10:45:30 +00:00
Displays a : class : ` gestion . forms . CreateKegForm ` to add a : class : ` gestion . models . Keg ` .
2018-12-02 15:28:40 +00:00
"""
2019-08-29 10:45:30 +00:00
form = CreateKegForm ( request . POST or None )
2019-06-23 14:32:38 +00:00
if form . is_valid ( ) :
2019-08-29 10:35:47 +00:00
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 ' ) )
2019-06-23 14:32:38 +00:00
keg = form . save ( commit = False )
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 : ]
create_galopin = form . cleaned_data [ " create_galopin " ]
pinte = Product (
name = " Pinte " + name ,
amount = pinte_price ,
2019-08-27 21:21:15 +00:00
stock = 0 ,
2019-06-23 14:32:38 +00:00
category = form . cleaned_data [ " category " ] ,
needQuantityButton = False ,
is_active = True ,
volume = 50 ,
deg = form . cleaned_data [ " deg " ] ,
adherentRequired = True ,
showingMultiplier = 1 ,
2019-08-29 10:35:47 +00:00
draft_category = Product . DRAFT_PINTE ,
use_stocks = False ,
2019-06-23 14:32:38 +00:00
)
pinte . save ( )
keg . pinte = pinte
demi = Product (
name = " Demi " + name ,
amount = ceil ( 5 * pinte_price ) / 10 ,
2019-08-27 21:21:15 +00:00
stock = 0 ,
2019-06-23 14:32:38 +00:00
category = form . cleaned_data [ " category " ] ,
needQuantityButton = False ,
is_active = True ,
volume = 25 ,
deg = form . cleaned_data [ " deg " ] ,
adherentRequired = True ,
showingMultiplier = 1 ,
2019-08-29 10:35:47 +00:00
draft_category = Product . DRAFT_DEMI ,
use_stocks = False ,
2019-06-23 14:32:38 +00:00
)
demi . save ( )
keg . demi = demi
if create_galopin :
galopin = Product (
name = " Galopin " + name ,
amount = ceil ( 2.5 * pinte_price ) / 10 ,
2019-08-27 21:21:15 +00:00
stock = 0 ,
2019-06-23 14:32:38 +00:00
category = form . cleaned_data [ " category " ] ,
needQuantityButton = False ,
is_active = True ,
volume = 13 ,
deg = form . cleaned_data [ " deg " ] ,
adherentRequired = True ,
showingMultiplier = 1 ,
2019-08-29 10:35:47 +00:00
draft_category = Product . DRAFT_DEMI ,
use_stocks = False ,
2019-06-23 14:32:38 +00:00
)
galopin . save ( )
keg . galopin = galopin
2018-10-05 22:03:02 +00:00
keg = form . save ( )
messages . success ( request , " Le fût " + keg . name + " a bien été ajouté " )
2018-11-25 12:52:32 +00:00
return redirect ( reverse ( ' gestion:kegsList ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' un fût " , " form_button " : " Ajouter " , " form_button_icon " : " plus-square " } )
2018-10-05 22:03:02 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.change_keg ' )
2018-11-25 12:52:32 +00:00
def editKeg ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-08-29 10:45:30 +00:00
Displays a : class : ` gestion . forms . EditKegForm ` to edit a : class : ` gestion . models . Keg ` .
2019-01-05 23:01:30 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the : class : ` gestion . models . Keg ` to edit .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
keg = get_object_or_404 ( Keg , pk = pk )
2019-08-29 10:45:30 +00:00
form = EditKegForm ( request . POST or None , instance = keg )
2018-11-25 12:52:32 +00:00
if ( form . is_valid ( ) ) :
2019-09-20 20:01:51 +00:00
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 ( )
# Update produtcs
name = form . cleaned_data [ " name " ] [ 4 : ]
pinte_price = compute_price ( keg . amount / ( 2 * keg . capacity ) , price_profile . a , price_profile . b , price_profile . c , price_profile . alpha )
pinte_price = ceil ( 10 * pinte_price ) / 10
keg . pinte . deg = keg . deg
keg . pinte . amount = pinte_price
keg . pinte . name = " Pinte " + name
keg . pinte . save ( )
keg . demi . deg = keg . deg
keg . demi . amount = ceil ( 5 * pinte_price ) / 10
keg . demi . name = " Demi " + name
keg . demi . save ( )
if ( keg . galopin ) :
2019-10-05 17:26:56 +00:00
keg . galopin . deg = keg . deg
2019-09-20 20:01:51 +00:00
keg . galopin . amount = ceil ( 2.5 * pinte_price ) / 10
keg . galopin . name = " Galopin " + name
keg . galopin . save ( )
2018-11-25 12:52:32 +00:00
messages . success ( request , " Le fût a bien été modifié " )
return redirect ( reverse ( ' gestion:kegsList ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' un fût " , " form_button " : " Modifier " , " form_button_icon " : " pencil-alt " } )
2018-11-25 12:52:32 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
@permission_required ( ' gestion.open_keg ' )
def openKeg ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . SelectPositiveKegForm ` to open a : class : ` gestion . models . Keg ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
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 ( )
2019-09-22 13:32:40 +00:00
if keg . pinte :
keg . pinte . is_active = True
keg . pinte . save ( )
if keg . demi :
keg . demi . is_active = True
keg . demi . save ( )
if keg . galopin :
keg . galopin . is_active = True
keg . galopin . save ( )
2018-11-25 12:52:32 +00:00
messages . success ( request , " Le fut a bien été percuté " )
return redirect ( reverse ( ' gestion:kegsList ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Percutage d ' un fût " , " form_button " : " Percuter " , " form_button_icon " : " fill-drip " } )
2018-11-25 12:52:32 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
@permission_required ( ' gestion.open_keg ' )
def openDirectKeg ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Opens a class : ` gestion . models . Keg ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the class : ` gestion . models . Keg ` to open .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
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 ( )
2019-09-22 13:32:40 +00:00
if keg . pinte :
keg . pinte . is_active = True
keg . pinte . save ( )
if keg . demi :
keg . demi . is_active = True
keg . demi . save ( )
if keg . galopin :
keg . galopin . is_active = True
keg . galopin . save ( )
2018-11-25 12:52:32 +00:00
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 ' ) )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
@permission_required ( ' gestion.close_keg ' )
def closeKeg ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . SelectPositiveKegForm ` to open a : class : ` gestion . models . Keg ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
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 ( )
2019-09-22 13:32:40 +00:00
if keg . pinte :
keg . pinte . is_active = False
keg . pinte . save ( )
if keg . demi :
keg . demi . is_active = False
keg . demi . save ( )
if keg . galopin :
keg . galopin . is_active = False
keg . galopin . save ( )
2018-11-25 12:52:32 +00:00
messages . success ( request , " Le fût a bien été fermé " )
return redirect ( reverse ( ' gestion:kegsList ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Fermeture d ' un fût " , " form_button " : " Fermer le fût " , " form_button_icon " : " fill " } )
2018-11-25 12:52:32 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.close_keg ' )
2018-11-25 12:52:32 +00:00
def closeDirectKeg ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Closes a class : ` gestion . models . Keg ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the class : ` gestion . models . Keg ` to open .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
keg = get_object_or_404 ( Keg , pk = pk )
2018-12-02 15:28:40 +00:00
if keg . is_active :
2018-11-25 12:52:32 +00:00
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 ( )
2019-09-22 13:32:40 +00:00
if keg . pinte :
keg . pinte . is_active = False
keg . pinte . save ( )
if keg . demi :
keg . demi . is_active = False
keg . demi . save ( )
if keg . galopin :
keg . galopin . is_active = False
keg . galopin . save ( )
2018-11-25 12:52:32 +00:00
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 ' ) )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
@permission_required ( ' gestion.view_keg ' )
def kegsList ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Display the list of : class : ` kegs < gestion . models . Keg > ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
kegs_active = KegHistory . objects . filter ( isCurrentKegHistory = True )
2019-01-24 21:26:38 +00:00
ids_actives = kegs_active . values ( ' keg__id ' )
2018-11-25 12:52:32 +00:00
kegs_inactive = Keg . objects . exclude ( id__in = ids_actives )
return render ( request , " gestion/kegs_list.html " , { " kegs_active " : kegs_active , " kegs_inactive " : kegs_inactive } )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 12:52:32 +00:00
@login_required
@permission_required ( ' gestion.view_keghistory ' )
def kegH ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Display the : class : ` history < gestion . models . KegHistory > ` of requested : class : ` gestion . models . Keg ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
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 ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Autocomplete view for active : class : ` kegs < gestion . models . Keg > ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
def get_queryset ( self ) :
qs = Keg . objects . filter ( is_active = True )
if self . q :
2019-01-23 11:31:33 +00:00
qs = qs . filter ( name__icontains = self . q )
2018-11-25 12:52:32 +00:00
return qs
class KegPositiveAutocomplete ( autocomplete . Select2QuerySetView ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Autocomplete view for : class : ` kegs < gestion . models . Keg > ` with positive stockHold .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 12:52:32 +00:00
def get_queryset ( self ) :
qs = Keg . objects . filter ( stockHold__gt = 0 )
if self . q :
2019-01-23 11:31:33 +00:00
qs = qs . filter ( name__icontains = self . q )
2018-11-25 12:52:32 +00:00
return qs
2018-10-05 22:03:02 +00:00
########## Menus ##########
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.add_menu ' )
2018-10-05 22:03:02 +00:00
def addMenu ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Display a : class : ` gestion . forms . MenuForm ` to add a : class : ` gestion . models . Menu ` .
2018-12-02 15:28:40 +00:00
"""
2018-10-05 22:03:02 +00:00
form = MenuForm ( request . POST or None )
extra_css = " #id_articles { height:200px;} "
if ( form . is_valid ( ) ) :
menu = form . save ( )
messages . success ( request , " Le menu " + menu . name + " a bien été ajouté " )
2018-11-25 23:15:09 +00:00
return redirect ( reverse ( ' gestion:menusList ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' un menu " , " form_button " : " Ajouter " , " form_button_icon " : " plus-square " , " extra_css " : extra_css } )
2018-10-05 22:03:02 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 23:15:09 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.change_menu ' )
2018-11-25 23:15:09 +00:00
def edit_menu ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . MenuForm ` to edit a : class : ` gestion . models . Menu ` .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the : class : ` gestion . models . Menu ` to edit .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 23:15:09 +00:00
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 ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' un menu " , " form_button " : " Modifier " , " form_button_icon " : " pencil-alt " , " extra_css " : extra_css } )
2018-11-22 21:52:15 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
@permission_required ( ' gestion.view_menu ' )
def searchMenu ( request ) :
"""
2019-02-28 12:18:41 +00:00
Displays a : class : ` gestion . forms . SearchMenuForm ` to search a : class : ` gestion . models . Menu ` .
2018-11-22 21:52:15 +00:00
"""
form = SearchMenuForm ( request . POST or None )
if ( form . is_valid ( ) ) :
2018-11-25 23:15:09 +00:00
menu = form . cleaned_data [ ' menu ' ]
return redirect ( reverse ( ' gestion:editMenu ' , kwargs = { ' pk ' : menu . pk } ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Recherche d ' un menu " , " form_button " : " Modifier " , " form_button_icon " : " search " } )
2018-11-22 21:52:15 +00:00
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 23:15:09 +00:00
@login_required
@permission_required ( ' gestion.view_menu ' )
def menus_list ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Display the list of : class : ` menus < gestion . models . Menu > ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-25 23:15:09 +00:00
menus = Menu . objects . all ( )
return render ( request , " gestion/menus_list.html " , { " menus " : menus } )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-25 23:15:09 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.change_menu ' )
2018-11-25 23:15:09 +00:00
def switch_activate_menu ( request , pk ) :
"""
2019-02-28 12:18:41 +00:00
Switch active status of a : class : ` gestion . models . Menu ` .
2018-11-25 23:15:09 +00:00
"""
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 ' ) )
2018-12-02 15:28:40 +00:00
@active_required
2018-11-27 08:07:12 +00:00
@login_required
2018-12-02 15:28:40 +00:00
@permission_required ( ' gestion.view_menu ' )
2018-12-23 22:55:27 +00:00
def get_menu ( request , pk ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Get a : class : ` gestion . models . Menu ` by pk and return it in JSON format .
2018-12-02 15:28:40 +00:00
2019-02-28 12:18:41 +00:00
pk
The primary key of the : class : ` gestion . models . Menu ` .
2018-12-02 15:28:40 +00:00
"""
2018-12-23 22:55:27 +00:00
menu = get_object_or_404 ( Menu , pk = pk )
2018-12-23 10:53:33 +00:00
nb_pintes = 0
for article in menu . articles :
2019-05-06 07:40:40 +00:00
if article . category == Product . DRAFT_PINTE :
2018-12-23 10:53:33 +00:00
nb_pintes + = 1
2019-06-23 14:43:23 +00:00
data = json . dumps ( { " pk " : menu . pk , " name " : menu . name , " amount " : menu . amount , " needQuantityButton " : False , " nb_pintes " : nb_pintes } )
2018-11-27 08:07:12 +00:00
return HttpResponse ( data , content_type = ' application/json ' )
2018-11-22 21:52:15 +00:00
class MenusAutocomplete ( autocomplete . Select2QuerySetView ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Autocomplete view for active : class : ` menus < gestion . models . Menu > ` .
2018-12-02 15:28:40 +00:00
"""
2018-11-22 21:52:15 +00:00
def get_queryset ( self ) :
qs = Menu . objects . all ( )
if self . q :
2019-01-23 11:31:33 +00:00
qs = qs . filter ( name__icontains = self . q )
2018-11-22 21:52:15 +00:00
return qs
2018-12-02 15:28:40 +00:00
2018-11-22 21:52:15 +00:00
########## Ranking ##########
2018-12-02 15:28:40 +00:00
@active_required
2018-11-22 21:52:15 +00:00
@login_required
def ranking ( request ) :
2018-12-02 15:28:40 +00:00
"""
2019-02-28 12:18:41 +00:00
Displays the ranking page .
2018-12-02 15:28:40 +00:00
"""
2018-11-22 21:52:15 +00:00
bestBuyers = User . objects . order_by ( ' -profile__debit ' ) [ : 25 ]
2019-06-10 23:28:22 +00:00
bestDrinkers = User . objects . order_by ( ' -profile__alcohol ' ) [ : 25 ]
2019-01-18 14:38:48 +00:00
form = SearchProductForm ( request . POST or None )
if ( form . is_valid ( ) ) :
product_ranking = form . cleaned_data [ ' product ' ] . ranking
else :
product_ranking = None
return render ( request , " gestion/ranking.html " , { " bestBuyers " : bestBuyers , " bestDrinkers " : bestDrinkers , " product_ranking " : product_ranking , " form " : form } )
2018-12-23 10:53:33 +00:00
########## Pinte monitoring ##########
def allocate ( pinte_pk , user ) :
"""
2019-02-28 12:18:41 +00:00
Allocate a : class : ` gestion . models . Pinte ` to a user ( : class : ` django . contrib . auth . models . User ` ) or release the pinte if user is None
2018-12-23 10:53:33 +00:00
"""
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 :
2018-12-23 11:54:37 +00:00
return False
2018-12-23 13:36:29 +00:00
@active_required
@login_required
@permission_required ( ' gestion.change_pinte ' )
def release ( request , pinte_pk ) :
"""
2019-02-28 12:18:41 +00:00
View to release a : class : ` gestion . models . Pinte ` .
pinte_pk
The primary key of the : class : ` gestion . models . Pinte ` to release .
2018-12-23 13:36:29 +00:00
"""
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 ' ) )
2019-01-05 23:01:30 +00:00
2018-12-23 11:54:37 +00:00
@active_required
@login_required
@permission_required ( ' gestion.add_pinte ' )
2018-12-23 13:36:29 +00:00
def add_pintes ( request ) :
2019-02-28 12:18:41 +00:00
"""
Displays a : class : ` gestion . forms . PinteForm ` to add one or more : class : ` gestion . models . Pinte ` .
"""
2018-12-23 12:05:41 +00:00
form = PinteForm ( request . POST or None )
2018-12-23 11:54:37 +00:00
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 ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajouter des pintes " , " form_button " : " Ajouter " , " form_button_icon " : " plus-square " } )
2018-12-23 12:05:41 +00:00
@active_required
@login_required
@permission_required ( ' gestion.change_pinte ' )
def release_pintes ( request ) :
2019-02-28 12:18:41 +00:00
"""
Displays a : class : ` gestion . forms . PinteForm ` to release one or more : class : ` gestion . models . Pinte ` .
"""
2018-12-23 12:05:41 +00:00
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 ' ) )
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Libérer des pintes " , " form_button " : " Libérer " , " form_button_icon " : " glass-whiskey " } )
2018-12-23 13:36:29 +00:00
@active_required
@login_required
@permission_required ( ' gestion.view_pinte ' )
def pintes_list ( request ) :
2019-02-28 12:18:41 +00:00
"""
Displays the list of : class : ` gestion . models . Pinte `
"""
2018-12-23 13:36:29 +00:00
free_pintes = Pinte . objects . filter ( current_owner = None )
taken_pintes = Pinte . objects . exclude ( current_owner = None )
2018-12-23 20:21:30 +00:00
return render ( request , " gestion/pintes_list.html " , { " free_pintes " : free_pintes , " taken_pintes " : taken_pintes } )
@active_required
@login_required
@permission_required ( ' auth.view_user ' )
def pintes_user_list ( request ) :
2019-02-28 12:18:41 +00:00
"""
Displays the list of user , who have unreturned : class : ` Pinte ( s ) < gestion . models . Pinte > ` .
"""
2018-12-23 20:21:30 +00:00
pks = [ x . pk for x in User . objects . all ( ) if x . profile . nb_pintes > 0 ]
users = User . objects . filter ( pk__in = pks )
2019-01-05 23:01:30 +00:00
return render ( request , " gestion/pintes_user_list.html " , { " users " : users } )
2019-06-23 11:46:12 +00:00
@active_required
@login_required
@permission_required ( ' users.can_generate_invoices ' )
def gen_invoice ( request ) :
"""
Displays a form to generate an invoice .
"""
form = GenerateInvoiceForm ( request . POST or None )
if form . is_valid ( ) :
products = [ x . split ( " ; " ) for x in form . cleaned_data [ " products " ] . split ( " \n " ) ]
total = 0
for product in products :
sub_total = Decimal ( product [ 1 ] ) * Decimal ( product [ 2 ] )
product . append ( sub_total )
total + = sub_total
return render_to_pdf (
request ,
' gestion/invoice.tex ' ,
{
" invoice_date " : form . cleaned_data [ " invoice_date " ] ,
" invoice_number " : form . cleaned_data [ " invoice_number " ] ,
" invoice_place " : form . cleaned_data [ " invoice_place " ] ,
" invoice_object " : form . cleaned_data [ " invoice_object " ] ,
" invoice_description " : form . cleaned_data [ " invoice_description " ] ,
" client_name " : form . cleaned_data [ " client_name " ] ,
" client_address_first_line " : form . cleaned_data [ " client_address_fisrt_line " ] ,
" client_address_second_line " : form . cleaned_data [ " client_address_second_line " ] ,
" products " : products ,
" total " : total ,
" path " : os . path . join ( settings . BASE_DIR , " templates/coope.png " ) ,
} ,
filename = " FE " + form . cleaned_data [ " invoice_number " ] + " .pdf " )
else :
return render ( request , " form.html " , { " form " : form , " form_title " : " Génération d ' une facture " , " form_button " : " Générer " , " form_button_icon " : " file-pdf " } )
2019-01-05 23:01:30 +00:00
@active_required
@login_required
@admin_required
def gen_releve ( request ) :
2019-02-28 12:18:41 +00:00
"""
Displays a : class : ` forms . gestion . GenerateReleveForm ` to generate a releve .
"""
2019-01-05 23:01:30 +00:00
form = GenerateReleveForm ( request . POST or None )
if form . is_valid ( ) :
begin , end = form . cleaned_data [ ' begin ' ] , form . cleaned_data [ ' end ' ]
consumptions = ConsumptionHistory . objects . filter ( date__gte = begin ) . filter ( date__lte = end ) . order_by ( ' -date ' )
reloads = Reload . objects . filter ( date__gt = begin ) . filter ( date__lt = end ) . order_by ( ' -date ' )
refunds = Refund . objects . filter ( date__gt = begin ) . filter ( date__lt = end ) . order_by ( ' -date ' )
cotisations = CotisationHistory . objects . filter ( paymentDate__gt = begin ) . filter ( paymentDate__lt = end ) . order_by ( ' -paymentDate ' )
especes = PaymentMethod . objects . get ( name = " Espèces " )
lydia = PaymentMethod . objects . get ( name = " Lydia " )
cheque = PaymentMethod . objects . get ( name = " Chèque " )
value_especes = 0
value_lydia = 0
value_cheque = 0
for consumption in consumptions :
pm = consumption . paymentMethod
if pm == especes :
value_especes + = consumption . amount
elif pm == lydia :
value_lydia + = consumption . amount
elif pm == cheque :
value_cheque + = consumption . amount
for reload in reloads :
pm = reload . PaymentMethod
if pm == especes :
value_especes + = reload . amount
elif pm == lydia :
value_lydia + = reload . amount
elif pm == cheque :
value_cheque + = reload . amount
for refund in refunds :
value_especes - = refund . amount
for cot in cotisations :
pm = cot . paymentMethod
if pm == especes :
value_especes + = cot . amount
elif pm == lydia :
value_lydia + = cot . amount
elif pm == cheque :
value_cheque + = cot . amount
2019-01-22 19:27:18 +00:00
now = datetime . now ( )
2019-01-05 23:01:30 +00:00
return render_to_pdf ( request , ' gestion/releve.tex ' , { " consumptions " : consumptions , " reloads " : reloads , " refunds " : refunds , " cotisations " : cotisations , " begin " : begin , " end " : end , " now " : now , " value_especes " : value_especes , " value_lydia " : value_lydia , " value_cheque " : value_cheque } , filename = " releve.pdf " )
else :
2019-01-17 22:16:43 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Génération d ' un relevé " , " form_button " : " Générer " , " form_button_icon " : " file-pdf " } )
2019-05-03 19:09:32 +00:00
2019-06-23 08:54:21 +00:00
@active_required
@login_required
@permission_required ( ' preferences.can_divide ' )
def divide ( request ) :
"""
Divide all non - divided cotisation
"""
if request . POST :
non_divided_cotisations = CotisationHistory . objects . filter ( divided = False )
for cotisation_history in non_divided_cotisations :
cotisation_history . divided = True
cotisation_history . save ( )
divide_history = DivideHistory (
total_cotisations = non_divided_cotisations . count ( ) ,
2019-06-27 21:03:19 +00:00
total_cotisations_amount = sum ( [ x . amount or 0 for x in non_divided_cotisations ] ) ,
total_ptm_amount = sum ( [ x . amount_ptm or 0 for x in non_divided_cotisations ] ) ,
2019-06-23 08:54:21 +00:00
coopeman = request . user
)
divide_history . save ( )
non_divided_cotisations = CotisationHistory . objects . filter ( divided = False )
2019-06-27 21:03:19 +00:00
total_amount = sum ( [ x . amount or 0 for x in non_divided_cotisations ] )
total_amount_ptm = sum ( [ x . amount_ptm or 0 for x in non_divided_cotisations ] )
2019-06-23 08:54:21 +00:00
divide_histories = DivideHistory . objects . all ( ) . order_by ( ' -date ' )
return render (
request ,
" gestion/divide.html " ,
{
" total_cotisations " : non_divided_cotisations . count ( ) ,
" total_amount " : total_amount ,
" total_amount_ptm " : total_amount_ptm ,
" divide_histories " : divide_histories ,
}
)
2019-08-27 16:25:53 +00:00
2019-05-03 19:09:32 +00:00
########## categories ##########
2019-08-27 16:25:53 +00:00
2019-05-03 19:09:32 +00:00
@active_required
@login_required
@permission_required ( ' gestion.add_category ' )
def addCategory ( request ) :
"""
Displays a : class : ` gestion . forms . CategoryForm ` to add a category .
"""
form = CategoryForm ( request . POST or None )
if ( form . is_valid ( ) ) :
category = form . save ( )
messages . success ( request , " La catégorie a bien été ajoutée " )
return redirect ( reverse ( ' gestion:categoryProfile ' , kwargs = { ' pk ' : category . pk } ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' une catégorie " , " form_button " : " Ajouter " , " form_button_icon " : " plus-square " } )
@active_required
@login_required
@permission_required ( ' gestion.change_category ' )
def editCategory ( request , pk ) :
"""
Displays a : class : ` gestion . forms . CategoryForm ` to edit a category .
pk
The primary key of the the : class : ` gestion . models . Category ` to edit .
"""
category = get_object_or_404 ( Category , pk = pk )
form = CategoryForm ( request . POST or None , instance = category )
if ( form . is_valid ( ) ) :
form . save ( )
messages . success ( request , " La catégorie a bien été modifiée " )
return redirect ( reverse ( ' gestion:categoryProfile ' , kwargs = { ' pk ' : category . pk } ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' une catégorie " , " form_button " : " Modifier " , " form_button_icon " : " pencil-alt " } )
@active_required
@login_required
@permission_required ( ' gestion.view_category ' )
def categoriesList ( request ) :
"""
Display the list of : class : ` categories < gestion . models . Category > ` .
"""
categories = Category . objects . all ( ) . order_by ( ' order ' )
return render ( request , " gestion/categories_list.html " , { " categories " : categories } )
@active_required
@login_required
@permission_required ( ' gestion.view_category ' )
def searchCategory ( request ) :
"""
Displays a : class : ` gestion . forms . SearchCategory ` to search a : class : ` gestion . models . Category ` .
"""
form = SearchCategoryForm ( request . POST or None )
if ( form . is_valid ( ) ) :
return redirect ( reverse ( ' gestion:categoryProfile ' , kwargs = { ' pk ' : form . cleaned_data [ ' category ' ] . pk } ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Rechercher une catégorie " , " form_button " : " Rechercher " , " form_button_icon " : " search " } )
@active_required
@login_required
@permission_required ( ' gestion.view_category ' )
def categoryProfile ( request , pk ) :
"""
Displays the profile of a : class : ` gestion . models . Category ` .
pk
The primary key of the : class : ` gestion . models . Category ` to display profile .
"""
category = get_object_or_404 ( Category , pk = pk )
return render ( request , " gestion/category_profile.html " , { " category " : category } )
class CategoriesAutocomplete ( autocomplete . Select2QuerySetView ) :
"""
Autocomplete view for active : class : ` categories < gestion . models . Category > ` .
"""
def get_queryset ( self ) :
qs = Category . objects . all ( )
if self . q :
qs = qs . filter ( name__icontains = self . q )
2019-05-03 21:27:11 +00:00
return qs
2019-06-23 13:31:55 +00:00
########## Compute price ##########
def compute_price_view ( request ) :
form = ComputePriceForm ( request . POST or None )
if form . is_valid ( ) :
price_profile = form . cleaned_data [ " price_profile " ]
price = compute_price ( form . cleaned_data [ " price " ] , price_profile . a , price_profile . b , price_profile . c , price_profile . alpha )
form_p = " Le prix est " + str ( ceil ( 100 * price ) / 100 ) + " € (arrondi au centième) ou " + str ( ceil ( 10 * price ) / 10 ) + " € (arrondi au dixième). "
else :
form_p = " "
2019-09-06 16:12:24 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Calcul d ' un prix " , " form_button " : " Calculer " , " form_icon " : " search_dollar " , " form_p " : form_p } )