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
2018-10-05 22:03:02 +00:00
from django . contrib . auth . models import User
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
2018-10-05 22:03:02 +00:00
2019-01-05 23:01:30 +00:00
from django_tex . views import render_to_pdf
from coopeV3 . acl import active_required , acl_or , admin_required
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-01-05 23:01:30 +00:00
import datetime
2018-10-05 22:03:02 +00:00
2019-01-05 23:01:30 +00:00
from . forms import ReloadForm , RefundForm , ProductForm , KegForm , MenuForm , GestionForm , SearchMenuForm , SearchProductForm , SelectPositiveKegForm , SelectActiveKegForm , PinteForm , GenerateReleveForm
from . models import Product , Menu , Keg , ConsumptionHistory , KegHistory , Consumption , MenuHistory , Pinte , Reload , Refund
2018-12-23 17:52:18 +00:00
from preferences . models import PaymentMethod , GeneralPreferences
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
"""
Display the manage page
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` gestion_form ` `
The manage form
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` reload_form ` `
The : model : ` gestion . Reload ` form
` ` refund_form ` `
The : model : ` gestion . Refund ` form
` ` bieresPression ` `
A list of active : model : ` gestion . Product ` corresponding to draft beers
` ` bieresBouteille ` `
A list of active : model : ` gestion . Product ` corresponding to bottle beers
` ` panini ` `
A list of active : model : ` gestion . Product ` corresponding to panini items
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` food ` `
A list of active : model : ` gestion . Product ` corresponding to non - panini items
` ` soft ` `
A list of active : model : ` gestion . Product ` correspond to non alcoholic beverage
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` menus ` `
The list of active : model : ` gestion . Menu `
` ` pay_buttons ` `
List of : model : ` paymentMethod `
* * Template * *
: template : ` gestion / manage . html `
"""
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 = [ ]
bieresBouteille = Product . objects . filter ( category = Product . BOTTLE ) . filter ( is_active = True )
panini = Product . objects . filter ( category = Product . PANINI ) . filter ( is_active = True )
food = Product . objects . filter ( category = Product . FOOD ) . filter ( is_active = True )
soft = Product . objects . filter ( category = Product . SOFT ) . filter ( is_active = True )
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 )
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 ,
" bieresBouteille " : bieresBouteille ,
" panini " : panini ,
" food " : food ,
" soft " : soft ,
" menus " : menus ,
2019-01-06 04:18:31 +00:00
" pay_buttons " : pay_buttons ,
" floating_buttons " : floating_buttons ,
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
"""
Process the given order . Called by a js / JQuery script .
"""
2018-11-22 21:52:15 +00:00
if ( " user " not in request . POST or " paymentMethod " not in request . POST or " amount " not in request . POST or " order " not in request . POST ) :
2018-11-25 12:52:32 +00:00
return HttpResponse ( " Erreur du POST " )
2018-11-22 21:52:15 +00:00
else :
user = get_object_or_404 ( User , pk = request . POST [ ' user ' ] )
paymentMethod = get_object_or_404 ( PaymentMethod , pk = request . POST [ ' paymentMethod ' ] )
amount = Decimal ( request . POST [ ' amount ' ] )
order = json . loads ( request . POST [ " order " ] )
2018-11-27 08:07:12 +00:00
menus = json . loads ( request . POST [ " menus " ] )
2018-12-23 10:53:33 +00:00
listPintes = json . loads ( request . POST [ " listPintes " ] )
2018-12-23 17:52:18 +00:00
gp , _ = GeneralPreferences . objects . get_or_create ( pk = 1 )
2018-11-27 08:07:12 +00:00
if ( not order ) and ( not menus ) :
2018-11-25 12:52:32 +00:00
return HttpResponse ( " Pas de commande " )
adherentRequired = False
for o in order :
product = get_object_or_404 ( Product , pk = o [ " pk " ] )
adherentRequired = adherentRequired or product . adherentRequired
2018-11-27 08:07:12 +00:00
for m in menus :
menu = get_object_or_404 ( Menu , pk = m [ " pk " ] )
adherentRequired = adherentRequired or menu . adherent_required
2018-11-25 12:52:32 +00:00
if ( adherentRequired and not user . profile . is_adherent ) :
return HttpResponse ( " N ' est pas adhérent et devrait l ' être " )
2018-12-23 17:52: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 . 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 )
2018-11-22 21:52:15 +00:00
if ( paymentMethod . affect_balance ) :
if ( user . profile . balance < amount ) :
2018-11-25 12:52:32 +00:00
return HttpResponse ( " Solde inférieur au prix de la commande " )
2018-11-22 21:52:15 +00:00
else :
user . profile . debit + = amount
user . save ( )
for o in order :
product = get_object_or_404 ( Product , pk = o [ " pk " ] )
2018-11-25 12:52:32 +00:00
quantity = int ( o [ " quantity " ] )
if ( product . category == Product . P_PRESSION ) :
keg = get_object_or_404 ( Keg , pinte = product )
if ( not keg . is_active ) :
2018-11-27 08:07:12 +00:00
return HttpResponse ( " Une erreur inconnue s ' est produite. Veuillez contacter le trésorier ou le président " )
2018-11-25 12:52:32 +00:00
kegHistory = get_object_or_404 ( KegHistory , keg = keg , isCurrentKegHistory = True )
kegHistory . quantitySold + = Decimal ( quantity * 0.5 )
kegHistory . amountSold + = Decimal ( quantity * product . amount )
kegHistory . save ( )
elif ( product . category == Product . D_PRESSION ) :
keg = get_object_or_404 ( Keg , demi = product )
if ( not keg . is_active ) :
2018-11-27 08:07:12 +00:00
return HttpResponse ( " Une erreur inconnue s ' est produite. Veuillez contacter le trésorier ou le président " )
2018-11-25 12:52:32 +00:00
kegHistory = get_object_or_404 ( KegHistory , keg = keg , isCurrentKegHistory = True )
kegHistory . quantitySold + = Decimal ( quantity * 0.25 )
kegHistory . amountSold + = Decimal ( quantity * product . amount )
kegHistory . save ( )
elif ( product . category == Product . G_PRESSION ) :
keg = get_object_or_404 ( Keg , galopin = product )
if ( not keg . is_active ) :
2018-11-27 08:07:12 +00:00
return HttpResponse ( " Une erreur inconnue s ' est produite. Veuillez contacter le trésorier ou le président " )
2018-11-25 12:52:32 +00:00
kegHistory = get_object_or_404 ( KegHistory , keg = keg , isCurrentKegHistory = True )
kegHistory . quantitySold + = Decimal ( quantity * 0.125 )
kegHistory . amountSold + = Decimal ( quantity * product . amount )
kegHistory . save ( )
else :
if ( product . stockHold > 0 ) :
product . stockHold - = 1
product . save ( )
consumption , _ = Consumption . objects . get_or_create ( customer = user , product = product )
consumption . quantity + = quantity
consumption . save ( )
2018-12-14 08:01:16 +00:00
ch = ConsumptionHistory ( customer = user , quantity = quantity , paymentMethod = paymentMethod , product = product , amount = Decimal ( quantity * product . amount ) , coopeman = request . user )
2018-11-22 21:52:15 +00:00
ch . save ( )
2018-11-27 08:07:12 +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 ( )
for article in menu . articles . all ( ) :
consumption , _ = Consumption . objects . get_or_create ( customer = user , product = article )
consumption . quantity + = quantity
consumption . save ( )
2018-11-30 18:54:12 +00:00
if ( article . stockHold > 0 ) :
article . stockHold - = 1
article . save ( )
2018-11-22 21:52:15 +00:00
return HttpResponse ( " La commande a bien été effectuée " )
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
"""
Process a reload request
"""
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 ) :
"""
Cancel a reload
"""
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
"""
Process a refund request
"""
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
"""
Cancel a : model : ` gestion . ConsumptionHistory `
` ` pk ` `
The primary key of the : model : ` gestion . ConsumptionHistory ` that have to be cancelled
"""
2018-11-30 18:54:12 +00:00
consumption = get_object_or_404 ( ConsumptionHistory , pk = pk )
user = consumption . customer
2018-12-18 10:38:20 +00:00
if consumption . paymentMethod . affect_balance :
user . profile . debit - = consumption . amount
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 ( )
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
"""
Cancel a : model : ` gestion . MenuHistory `
` ` pk ` `
The primary key of the : model : ` gestion . MenuHistory ` that have to be cancelled
"""
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
user . save ( )
2018-12-13 18:26:58 +00:00
for product in manu_history . menu . articles :
consumptionT = Consumption . objects . get ( customer = user , product = product )
consumptionT - = menu_history . quantity
2019-01-05 23:01:30 +00:00
consumptionT . 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 ##########
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
"""
Display the products manage static page
* * Template * *
: template : ` gestion / products_index . html `
"""
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
"""
Form to add a : model : ` gestion . Product `
* * Context * *
` ` form ` `
The ProductForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the form template
` ` form_button ` `
The text of the button for the form template
* * Template * *
: template : ` form . html `
"""
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 } ) )
2018-10-05 22:03:02 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' un produit " , " form_button " : " Ajouter " } )
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
"""
Form to edit a : model : ` gestion . Product `
` ` pk ` `
The primary key of the requested : model : ` gestion . Product `
* * Context * *
` ` form ` `
The ProductForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the form template
` ` form_button ` `
The text of the button for the form template
* * Template * *
: template : ` form . html `
"""
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 } ) )
2018-11-25 23:15:09 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' un produit " , " form_button " : " Modifier " } )
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
"""
Display the list of : model : ` gestion . Product `
* * Context * *
` ` products ` `
The list of : model : ` gestion . Product `
* * Template * *
: template : ` gestion / products_list . html `
"""
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
"""
Form to search a : model : ` gestion . Product `
* * Context * *
` ` form ` `
The SearchProductForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the form template
` ` form_button ` `
The text of the button for the form template
* * Template * *
: template : ` form . html `
"""
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 } ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Rechercher un produit " , " form_button " : " Rechercher " } )
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
"""
Display the profile of a : model : ` gestion . Product `
` ` pk ` `
The primary key of the requested : model : ` gestion . Product `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` product ` `
The : model : ` gestion . Product ` instance
* * Template * *
: model : ` gestion / product_profile . html `
"""
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
"""
Get : model : ` gestion . Product ` by barcode . Called by a js / JQuery script
2018-12-23 22:55:27 +00:00
` ` pk ` `
The requested pk
2018-12-02 15:28:40 +00:00
"""
2018-12-23 22:55:27 +00:00
product = Product . objects . get ( pk = pk )
2018-12-23 10:53:33 +00:00
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 } )
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 ) :
"""
2018-12-02 15:28:40 +00:00
Switch the active status of the requested : model : ` gestion . Product `
` ` pk ` `
The primary key of the : model : ` gestion . Product `
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
"""
Autocomplete view for all : model : ` gestion . Product `
"""
2018-11-22 21:52:15 +00:00
def get_queryset ( self ) :
qs = Product . objects . all ( )
if self . q :
2018-11-25 23:15:09 +00:00
qs = qs . filter ( name__istartswith = 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 ) :
"""
Autocomplete view for active : model : ` gestion . Product `
"""
def get_queryset ( self ) :
qs = Product . objects . filter ( is_active = True )
if self . q :
qs = qs . filter ( name__istartswith = self . q )
return qs
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
"""
Display a form to add a : model : ` gestion . Keg `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form ` `
The KegForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the : template : ` form . html ` template
` ` form_button ` `
The text for the button in : template : ` form . html ` template
* * Template * *
: template : ` form . html `
"""
2018-10-05 22:03:02 +00:00
form = KegForm ( request . POST or None )
if ( form . is_valid ( ) ) :
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 ' ) )
2018-10-05 22:03:02 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' un fût " , " form_button " : " Ajouter " } )
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
"""
Display a form to edit a : model : ` gestion . Keg `
` ` pk ` `
The primary key of the requested : model : ` gestion . Keg `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form ` `
The KegForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the : template : ` form . html ` template
` ` form_button ` `
The text for the button in : template : ` form . html ` template
* * Template * *
: template : ` form . html `
"""
2018-11-25 12:52:32 +00:00
keg = get_object_or_404 ( Keg , pk = pk )
form = KegForm ( request . POST or None , instance = keg )
if ( form . is_valid ( ) ) :
form . save ( )
messages . success ( request , " Le fût a bien été modifié " )
return redirect ( reverse ( ' gestion:kegsList ' ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' un fût " , " form_button " : " Modifier " } )
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
"""
Display a form to open a : model : ` gestion . Keg `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form ` `
The SelectPositiveKegForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the : template : ` form . html ` template
` ` form_button ` `
The text for the button in : template : ` form . html ` template
* * Template * *
: template : ` form . html `
"""
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 ( )
messages . success ( request , " Le fut a bien été percuté " )
return redirect ( reverse ( ' gestion:kegsList ' ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Percutage d ' un fût " , " form_button " : " Percuter " } )
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
"""
Open the requested : model : ` gestion . Keg `
` ` pk ` `
The primary key of the : model : ` gestion . Keg `
"""
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 ( )
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
"""
Display a form to close a : model : ` gestion . Keg `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form ` `
The SelectActiveKegForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the : template : ` form . html ` template
` ` form_button ` `
The text for the button in : template : ` form . html ` template
* * Template * *
: template : ` form . html `
"""
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 ( )
messages . success ( request , " Le fût a bien été fermé " )
return redirect ( reverse ( ' gestion:kegsList ' ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Fermeture d ' un fût " , " form_button " : " Fermer le fût " } )
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
"""
Close the requested : model : ` gestion . Keg `
` ` pk ` `
The pk of the active : model : ` gestion . Keg `
"""
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 ( )
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
"""
Display the list of : model : ` gestion . Keg `
* * Context * *
` ` kegs_active ` `
List of active : model : ` gestion . Keg `
` ` kegs_inactive ` `
List of inactive : model : ` gestion . Keg `
* * Template * *
: template : ` gestion / kegs_list . html `
"""
2018-11-25 12:52:32 +00:00
kegs_active = KegHistory . objects . filter ( isCurrentKegHistory = True )
ids_actives = kegs_active . values ( ' id ' )
kegs_inactive = Keg . objects . exclude ( id__in = ids_actives )
return render ( request , " gestion/kegs_list.html " , { " kegs_active " : kegs_active , " kegs_inactive " : kegs_inactive } )
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
"""
Display the history of requested : model : ` gestion . Keg `
` ` pk ` `
The primary key of the requested : model : ` gestion . Keg `
* * Context * *
` ` keg ` `
The : model : ` gestion . Keg ` instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` kegHistory ` `
List of : model : ` gestion . KegHistory ` attached to keg
* * Template * *
: template : ` gestion / kegh . html `
"""
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
"""
Autocomplete view for active : model : ` gestion . Keg `
"""
2018-11-25 12:52:32 +00:00
def get_queryset ( self ) :
qs = Keg . objects . filter ( is_active = True )
if self . q :
qs = qs . filter ( name__istartswith = self . q )
return qs
class KegPositiveAutocomplete ( autocomplete . Select2QuerySetView ) :
2018-12-02 15:28:40 +00:00
"""
Autocomplete view for : model : ` gestion . Keg ` with positive stockHold
"""
2018-11-25 12:52:32 +00:00
def get_queryset ( self ) :
qs = Keg . objects . filter ( stockHold__gt = 0 )
if self . q :
qs = qs . filter ( name__istartswith = self . q )
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
"""
Display a form to add a : model : ` gestion . Menu `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form ` `
The MenuForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the : template : ` form . html ` template
` ` form_button ` `
The text for the button in : template : ` form . html ` template
* * Template * *
: template : ` form . html `
"""
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 ' ) )
2018-10-05 22:03:02 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Ajout d ' un menu " , " form_button " : " Ajouter " , " extra_css " : extra_css } )
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
"""
Display a form to edit a : model : ` gestion . Menu `
` ` pk ` `
The primary key of requested : model : ` gestion . Menu `
* * Context * *
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form ` `
The MenuForm instance
2019-01-05 23:01:30 +00:00
2018-12-02 15:28:40 +00:00
` ` form_title ` `
The title for the : template : ` form . html ` template
` ` form_button ` `
The text for the button in : template : ` form . html ` template
* * Template * *
: template : ` form . html `
"""
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 ' ) )
return render ( request , " form.html " , { " form " : form , " form_title " : " Modification d ' un menu " , " form_button " : " Modifier " , " 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 ) :
"""
2018-12-02 15:28:40 +00:00
Search a : model : ` gestion . Menu ` via SearchMenuForm instance
2018-11-22 21:52:15 +00:00
* * Context * *
` ` form_entete ` `
The form title .
` ` form ` `
The SearchMenuForm instance .
` ` form_button ` `
The content of the form button .
* * Template * *
: template : ` form . html `
"""
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 } ) )
2018-11-22 21:52:15 +00:00
return render ( request , " form.html " , { " form " : form , " form_title " : " Recherche d ' un menu " , " form_button " : " Modifier " } )
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
"""
Display the : model : ` gestion . Menu ` list
* * Context * *
` ` menus ` `
The list of : model : ` gestion . Menu ` instances
* * Template * *
: template : ` gestion / menus_list . html `
"""
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 ) :
"""
2018-12-02 15:28:40 +00:00
Switch active status of a : model : ` gestion . Menu `
` ` pk ` `
The pk of the : model : ` gestion . 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
"""
Search : model : ` gestion . Menu ` by barcode
2018-12-23 22:55:27 +00:00
` ` pk ` `
The requested pk
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 :
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 } )
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
"""
Used as autcomplete for all : model : ` gestion . Menu `
"""
2018-11-22 21:52:15 +00:00
def get_queryset ( self ) :
qs = Menu . objects . all ( )
if self . q :
qs = qs . filter ( name__istartswith = self . q )
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
"""
Display the ranking page
* * Context * *
` ` bestBuyers ` `
List of the 25 best buyers
` ` bestDrinkers ` `
List of the 25 best drinkers
* * Template * *
: template : ` gestion / ranking . html `
"""
2018-11-22 21:52:15 +00:00
bestBuyers = User . objects . order_by ( ' -profile__debit ' ) [ : 25 ]
customers = User . objects . all ( )
list = [ ]
for customer in customers :
alcohol = customer . profile . alcohol
list . append ( [ customer , alcohol ] )
bestDrinkers = sorted ( list , key = lambda x : x [ 1 ] , reverse = True ) [ : 25 ]
2018-12-23 10:53:33 +00:00
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 :
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 ) :
"""
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 ' ) )
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 ) :
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 ' ) )
2018-12-23 12:05:41 +00:00
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 ' ) )
2018-12-23 13:36:29 +00:00
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 )
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 ) :
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 } )
@active_required
@login_required
@admin_required
def gen_releve ( request ) :
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
now = datetime . datetime . now ( )
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 :
return render ( request , " form.html " , { " form " : form , " form_title " : " Génération d ' un relevé " , " form_button " : " Générer " } )