Compare commits

..

No commits in common. "main" and "0.1" have entirely different histories.
main ... 0.1

61 changed files with 1803 additions and 3417 deletions

View file

@ -1,28 +1,31 @@
# Module de gestion de matériels pour Paheko
Ce module permet de gérer les matériels de l'association: stock,
entrées, sorties, classés par catégorie.
Ce module permet de gérer les matériels de l'association: stock, entrées, sorties.
Un matériel peut entrer temporairement (location, emprunt, ...) ou
définitivement dans l'association (achat, ...).
## Configuration
- Il y a plusieurs types d'entrée et de sorties prédéfinies (Achat,
Location, Vente, ...) mais il est possible d'en ajouter d'autres.
Un matériel appartenant à l'association peut sortir :
- temporairement (prêt, ...) : il est possible de lui associer un lieu
de stockage ainsi qu'un membre dépositaire du matériel ; il peut
ensuite revenir dans l'association.
- définitivement (vente, ...) : il est possible de lui associer un
membre bénéficiaire du matériel.
## Démarrage
- Il faut commencer par créer des catégories de matériel (ex:
Audiovisuel, Informatique, Mobilier, ...).
- On peut ensuite ajouter des entrées puis des sorties.
Un matériel présent temporairement dans l'association peut être
retourné à son propriétaire.
### Entrées
Il y a trois boutons pour ajouter une entrée :
- Matériel répertorié : ajouter une entrée pour du matériel déjà
répertorié dans l'inventaire
- Matériel non répertorié : ajouter une entrée pour du matériel qui
n'est pas encore répertorié dans l'inventaire
- Retour de sortie temporaire : ajouter une entrée pour du matériel
qui revient après une sortie temporaire (location, prêt)
Un matériel dont il n'existe plus d'exemplaire en stock peut être archivé.
On peut lister l'ensemble des mouvements des matériels ou seulement
ceux d'un matériel donné.
Il est possible de créer des catégories de matériels, des types
d'entrées et sorties, des lieux de stockage.
### Sorties
Il y a deux boutons pour ajouter une sortie :
- Matériel en stock disponible : ajouter une sortie pour du matériel
propriété de l'association
- Matériel emprunté : ajouter une sortie pour du matériel qui n'est
pas propriété de l'association, suite à un emprunt ou une location
## Droits d'accès
Le module est accessible uniquement pour les membres ayant au moins le

112
_calcul_dispo.html Normal file
View file

@ -0,0 +1,112 @@
{{*
Calcul des entrées/sorties de matériels à une date donnée
paramètres :
- liste de clés de catégories
- date
résultat : cumul_mvt
*}}
{{* liste des catégories *}}
{{if $category_keys === null}}
{{#load type="category"}}
{{:assign var="cumul_mvt.%s.name"|args:$key value=$name}}
{{/load}}
{{else}}
{{#load type="category" where="key"|sql_where:'IN':$category_keys}}
{{:assign var="cumul_mvt.%s.name"|args:$key value=$name}}
{{/load}}
{{/if}}
{{#foreach from=$cumul_mvt key="cat_key" item="elem"}}
{{:assign var="in_categories." value="'%s'"|args:$cat_key}}
{{/foreach}}
{{:assign in_categories=$in_categories|implode:","}}
{{:assign in_categories="("|cat:$in_categories|cat:")"}}
{{* liste des matériels dans les catégories passées en paramètre *}}
{{#load type="equipment" where="$$.category IN %s"|args:$in_categories}}
{{:assign var="equipments.%s.category"|args:$key value=$category}}
{{:assign var="equipments.%s.designation"|args:$key value=$designation}}
{{:assign var="in_equipments." value="'%s'"|args:$key}}
{{/load}}
{{:assign in_equipments=$in_equipments|implode:","}}
{{:assign in_equipments="("|cat:$in_equipments|cat:")"}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="./_get_config.html" keep="config"}}
{{* parcourir les mouvements et cumuler les entrées/sorties *}}
{{#load type="movement" where="$$.equipment IN %s"|args:$in_equipments assign="mvt"}}
{{* matériel propriété de l'asso en stock *}}
{{:assign
var="stock"
from="equipments.%s.stock"|args:$mvt.equipment}}
{{if $stock == null}}
{{:assign stock=0}}
{{/if}}
{{* matériel propriété de l'asso à l'extérieur *}}
{{:assign
var="exterieur"
from="equipments.%s.exterieur"|args:$mvt.equipment}}
{{if $exterieur == null}}
{{:assign exterieur=0}}
{{/if}}
{{* matériel non propriété de l'asso *}}
{{:assign
var="nonproprio"
from="equipments.%s.nonproprio"|args:$mvt.equipment}}
{{if $nonproprio == null}}
{{:assign nonproprio=0}}
{{/if}}
{{* déterminer le type de mouvement *}}
{{:assign var="mvt_nature" from="mvt.%s_nature"|args:$mvt.direction}}
{{:assign var="type_mvt" from="config.%s_nature.%s"|args:$mvt.direction:$mvt_nature}}
{{if $mvt.direction === 'input'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d+%d"|math:$stock:$mvt.amount}}
{{:assign
var="equipments.%s.stock"|args:$mvt.equipment
from=stock}}
{{elseif $type_mvt == 'retour'}}
{{:assign exterieur="%d-%d"|math:$exterieur:$mvt.amount}}
{{:assign
var="equipments.%s.exterieur"|args:$mvt.equipment
from=exterieur}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign nonproprio="%d+%d"|math:$nonproprio:$mvt.amount}}
{{:assign
var="equipments.%s.nonproprio"|args:$mvt.equipment
from=nonproprio}}
{{/if}}
{{elseif $mvt.direction === 'output'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$mvt.amount}}
{{:assign
var="equipments.%s.stock"|args:$mvt.equipment
from=stock}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$mvt.amount}}
{{:assign
var="equipments.%s.exterieur"|args:$mvt.equipment
from=exterieur}}
{{elseif $type_mvt == 'retour'}}
{{:assign nonproprio="%d-%d"|math:$nonproprio:$mvt.amount}}
{{:assign
var="equipments.%s.nonproprio"|args:$mvt.equipment
from=nonproprio}}
{{/if}}
{{/if}}
{{/load}}
{{* grouper les résultats par catégorie *}}
{{#foreach from=$equipments key="eqpmt_key" item="eqpmt"}}
{{:assign
var="cumul_mvt.%s.eqpmt.%s"|args:$eqpmt.category:$eqpmt_key
value=$eqpmt}}
{{/foreach}}

View file

@ -1,30 +1,35 @@
{{* -*- brindille -*- *}}
{{*
Récupérer soit la config enregistrée, soit la config par défaut
résultat : config.input_nature et config.output_nature
*}}
{{* config par défaut *}}
{{:read file="./default.json" assign="config_defaut"}}
{{:read file="./defaut.json" assign="config_defaut"}}
{{:assign config_defaut=$config_defaut|json_decode}}
{{:assign var="directions.input" value="entrée"}}
{{:assign var="directions.output" value="sortie"}}
{{#foreach from=$directions key="direction"}}
{{:assign var="nature" from="module.config.%s_nature"|args:$direction}}
{{if $nature != null}}
{{#foreach from=$nature item="elem"}}
{{:assign var="item" label=$label type=$type}}
{{:assign var="config.%s_nature.%s"|args:$direction:$key value=$item}}
{{if $module.config.input_nature != null}}
{{#foreach from=$module.config.input_nature item="elem"}}
{{:assign var="config.input_nature.%s"|args:$elem.label value=$elem.type}}
{{/foreach}}
{{else}}
{{* pas de config enregistrée : utiliser la config par défaut *}}
{{:assign var="nature" from="config_defaut.%ss"|args:$direction}}
{{#foreach from=$nature item="elem"}}
{{:assign var="item" label=$label type=$type}}
{{:assign var="config.%s_nature.%s"|args:$direction:$key value=$item}}
{{#foreach from=$config_defaut.inputs item="elem"}}
{{#foreach from=$elem key=label item=value}}
{{:assign var="config.input_nature.%s"|args:$label value=$value}}
{{/foreach}}
{{/foreach}}
{{/if}}
{{if $module.config.output_nature != null}}
{{#foreach from=$module.config.output_nature item="elem"}}
{{:assign var="config.output_nature.%s"|args:$elem.label value=$elem.type}}
{{/foreach}}
{{* :assign var=config.output_nature value=$module.config.output_nature *}}
{{else}}
{{* pas de config enregistrée : utiliser la config par défaut *}}
{{#foreach from=$config_defaut.outputs item="elem"}}
{{#foreach from=$elem key=label item=value}}
{{:assign var="config.output_nature.%s"|args:$label value=$value}}
{{/foreach}}
{{/foreach}}
{{/if}}

View file

@ -1,94 +0,0 @@
{{* -*- brindille -*- *}}
{{*
inventaire des entrées/sorties des matériels permanents
*}}
{{* Sélecteur catégories *}}
{{:assign var="options." value="" label="Toutes les catégories" href="?prop=1"}}
{{#load type="category" order="$$.name"}}
{{:assign var="categories.%s"|args:$key value=$name}}
{{:assign
var="options."
value=$key
label=$name
href="?cat_key=%s&prop=1"|args:$key
}}
{{/load}}
<fieldset class="shortFormRight">
<legend>Filtrer par catégorie</legend>
{{:dropdown
title="Filtrer par catégorie"
options=$options
value="%s"|args:$_GET.cat_key
}}
</fieldset>
<div class="shortFormLeft">
<p class="help">Inventaire des matériels propriété de l'association</p>
</div>
{{* filtrer selon la catégorie *}}
{{if $_GET.cat_key == null}}
{{:assign condition="1"}}
{{else}}
{{:assign cat_key=$_GET.cat_key|quote_sql}}
{{:assign condition="$$.category = %s"|args:$cat_key}}
{{/if}}
{{#list
select="
$$.name AS 'Matériel' ;
(SELECT $$.name
FROM @TABLE as cat
WHERE cat.key = @TABLE.$$.category) AS 'Catégorie' ;
$$.stock AS 'Stock' ;
$$.out AS 'Sorti' ;
(SELECT $$.stock - $$.out) AS 'Disponible'
"
type="equipment"
where="$$.status <> 'archived' AND $$.stock NOT NULL AND %s"|args:$condition
order=1
}}
{{:assign var=cat_name from=categories.%s|args:$category}}
<tr>
<td>{{$name}}</td>
<td>{{$cat_name}}</td>
<td class="num">{{$stock}}</td>
<td class="num">{{$out}}</td>
<td class="num">{{$col5}}</td>
<td class="actions">
{{if $col5 > 0}}
{{:linkbutton
label="Sortie"
shape="minus"
href="movements/output_equipment.html?key=%s"|args:$key
target="_dialog"}}
{{/if}}
{{:linkbutton
label="Entrée"
shape="plus"
href="movements/input_equipment.html?key=%s"|args:$key
target="_dialog"}}
{{:linkbutton
label="Historique"
href="equipment_history.html?key=%s&prop=1"|args:$key
shape="table"}}
{{:linkbutton
label="Modifier"
href="modify_equipment.html?key=%s&prop=1"|args:$key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{else}}
<p class="block alert">Aucun matériel.</p>
{{/list}}
<script type="text/javascript" src="scripts.js"></script>
<script type="text/javascript">
(function () {
disableColumSort(document.querySelector("table[class=list]"));
})();
</script>

View file

@ -1,59 +1,9 @@
{{* -*- brindille -*- *}}
<nav class="tabs">
{{if $current == 'inventaire'}}
<aside>
{{if $subsubcurrent == null && $cat == 0}}
{{:linkbutton label="Ajouter une catégorie" shape="plus" href="categories/add_category.html" target="_dialog"}}
{{else}}
{{:linkbutton label="Ajouter un nouveau matériel" shape="plus" href="movements/add_new_equipment.html" target="_dialog"}}
{{/if}}
</aside>
{{/if}}
<ul>
<li {{if $current == 'inventaire'}} class="current"{{/if}}><a href="{{$module.url}}index.html?prop=1">Inventaire</a></li>
<li {{if $current == 'historique'}} class="current"{{/if}}><a href="{{$module.url}}global_history.html">Historique</a></li>
<li {{if $current == 'archives'}} class="current"{{/if}}><a href="{{$module.url}}archives.html">Archives</a></li>
<li {{if $current == 'config'}} class="current"{{/if}}><a href="{{$module.url}}categories/index.html">Configuration</a></li>
<li {{if $current == 'index'}} class="current"{{/if}}><a href="{{$module.url}}index.html">Inventaire</a></li>
<li {{if $current == 'categories'}} class="current"{{/if}}><a href="{{$module.url}}categories/index.html">Catégories</a></li>
<li {{if $current == 'entrees'}} class="current"{{/if}}><a href="{{$module.url}}mouvements/entrees/index.html">Entrées</a></li>
<li {{if $current == 'sorties'}} class="current"{{/if}}><a href="{{$module.url}}mouvements/sorties/index.html">Sorties</a></li>
<li {{if $current == 'config'}} class="current"{{/if}}><a href="{{$module.url}}config.html">Configuration</a></li>
</ul>
{{if $current == 'inventaire'}}
<ul class="sub">
<li {{if $subcurrent == 'proprio'}} class="current"{{/if}}><a href="{{$module.url}}index.html?prop=1">Matériels permanents</a></li>
<li {{if $subcurrent == 'nonproprio'}} class="current"{{/if}}><a href="{{$module.url}}index.html?prop=0">Matériels temporaires</a></li>
</ul>
{{if $subsubcurrent == 'historique'}}
<ul class="sub">
<li class="title"><strong>Historique — {{$eqpmt}} ({{$category}})</strong></li>
</ul>
{{/if}}
{{elseif $current == 'archives'}}
{{if $subsubcurrent == 'historique'}}
<ul class="sub">
<li class="title"><strong>Historique — {{$eqpmt}} ({{$category}})</strong></li>
</ul>
{{/if}}
{{elseif $current == 'config'}}
{{if $subcurrent == 'categories'}}
<aside>
{{:linkbutton label="Ajouter une catégorie" shape="plus" href="add_category.html" target="_dialog"}}
</aside>
{{elseif $subcurrent == 'storage'}}
<aside>
{{:linkbutton label="Ajouter un lieu de stockage" shape="plus" href="add_storage.html" target="_dialog"}}
</aside>
{{elseif $subcurrent == 'typesES'}}
<aside>
{{:linkbutton label="Ajouter un type d'entrée" shape="plus" href="config/add_movement_type.html?dir=input" target="_dialog"}}
{{:linkbutton label="Ajouter un type de sortie" shape="plus" href="config/add_movement_type.html?dir=output" target="_dialog"}}
</aside>
{{/if}}
<ul class="sub">
<li {{if $subcurrent == 'categories'}} class="current"{{/if}}><a href="{{$module.url}}categories/index.html">Catégories</a></li>
<li {{if $subcurrent == 'storage'}} class="current"{{/if}}><a href="{{$module.url}}storage/index.html">Lieux de stockage</a></li>
<li {{if $subcurrent == 'typesES'}} class="current"{{/if}}><a href="{{$module.url}}config.html">Types d'entrées/sorties</a></li>
</ul>
{{/if}}
</nav>

View file

@ -1,76 +0,0 @@
{{* -*- brindille -*- *}}
{{*
inventaire des entrées/sorties des matériels temporaires
*}}
{{* Sélecteur catégories *}}
{{:assign var="options." value="" label="Toutes les catégories" href="?prop=0"}}
{{#load type="category" order="$$.name"}}
{{:assign var="categories.%s"|args:$key value=$name}}
{{:assign
var="options."
value=$key
label=$name
href="?cat_key=%s&prop=0"|args:$key
}}
{{/load}}
<fieldset class="shortFormRight">
<legend>Filtrer par catégorie</legend>
{{:dropdown
title="Filtrer par catégorie"
options=$options
value="%s"|args:$_GET.cat_key
}}
</fieldset>
<div class="shortFormLeft">
<p class="help">Inventaire des matériels empruntés ou loués</p>
</div>
{{* filtrer selon la catégorie *}}
{{if $_GET.cat_key == null}}
{{:assign condition="1"}}
{{else}}
{{:assign cat_key=$_GET.cat_key|quote_sql}}
{{:assign condition="$$.category = %s"|args:$cat_key}}
{{/if}}
{{#list
select="
$$.name AS 'Matériel' ;
(SELECT $$.name
FROM @TABLE as cat
WHERE cat.key = @TABLE.$$.category) AS 'Catégorie' ;
$$.notowned AS 'Quantité'
"
type="equipment"
where="$$.status <> 'archived' AND $$.notowned != 0 AND %s"|args:$condition
order=1
}}
{{:assign var=cat_name from=categories.%s|args:$category}}
<tr>
<td>{{$name}}</td>
<td>{{$cat_name}}</td>
<td class="num">{{$col3}}</td>
<td class="actions">
{{:linkbutton
label="Entrée"
shape="plus"
href="movements/input_equipment.html?key=%s"|args:$key
target="_dialog"}}
{{:linkbutton
label="Historique"
href="equipment_history.html?key=%s&prop=0"|args:$key
shape="table"}}
{{:linkbutton
label="Modifier"
href="modify_equipment.html?key=%s&prop=0"|args:$key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{else}}
<p class="block alert">Aucun matériel.</p>
{{/list}}

View file

@ -1,68 +0,0 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Matériels archivés" current="module_equipment"}}
{{:include file="_nav.html" current="archives"}}
{{if $_GET.ok}}
<p class="block confirm">Matériel remis en service</p>
{{/if}}
{{* Sélecteur catégories *}}
{{:assign var="options." value="" label="Toutes les catégories" href="?prop=1"}}
{{#load type="category" order="$$.name"}}
{{:assign
var="options."
value=$key
label=$name
href="?cat_key=%s"|args:$key
}}
{{/load}}
<fieldset class="shortFormRight">
<legend>Filtrer par catégorie</legend>
{{:dropdown
title="Filtrer par catégorie"
options=$options
value="%s"|args:$_GET.cat_key
}}
</fieldset>
{{* filtrer selon la catégorie *}}
{{if $_GET.cat_key == null}}
{{:assign condition="1"}}
{{else}}
{{:assign cat_key=$_GET.cat_key|quote_sql}}
{{:assign condition="$$.category == %s"|args:$cat_key}}
{{/if}}
{{* Liste des matériels archivés *}}
{{#list
select="
$$.name AS "Matériel" ;
(SELECT $$.name
FROM @TABLE as cat
WHERE cat.key = @TABLE.$$.category) AS "Catégorie"
"
type="equipment"
where="$$.status='archived' AND %s"|args:$condition
order=1
}}
<tr>
<td>{{$name}}</td>
<td>{{$col2}}</td>
<td class="actions">
{{:linkbutton
label="Historique"
href="equipment_history.html?key=%s&prop=1&current=archives"|args:$key
shape="table"}}
{{:linkbutton
label="Modifier"
href="unarchive_equipment.html?key=%s"|args:$key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{else}}
<p class="block alert">Aucun matériel.</p>
{{/list}}

View file

@ -1,43 +0,0 @@
{{* -*- brindille -*- *}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="config" subcurrent="categories"}}
{{/if}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* Vérifier s'il existe déjà une catégorie avec le même nom *}}
{{#load type="category" where="$$.name = :name COLLATE U_NOCASE" :name=$_POST.name|trim limit=1}}
{{:error message="Impossible d'ajouter la catégorie « %s » car elle existe déjà !"|args:$name|trim}}
{{/load}}
{{:assign key=""|uuid}}
{{:assign cat_name=$_POST.name|trim}}
{{:save
key=$key
validate_schema="./category.schema.json"
type="category"
name=$cat_name
}}
{{:redirect force="./index.html?ok=1&msg=ajout"}}
{{/form}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{:form_errors}}
{{* formulaire d'ajout de catégorie *}}
<form method="post" action="{{$self_url}}" data-focus="1">
<fieldset class="ajout_categorie">
<legend>Ajouter une catégorie</legend>
<dl>
{{:input type="text" name="name" label="Nom" autofocus=true required=true maxlength="100"}}
</dl>
<p class="submit">
{{:button type="submit" name="save" label="Ajouter" shape="right" class="main"}}
</p>
</fieldset>
</form>
{{:admin_footer}}

View file

@ -1,4 +1,4 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Supprimer une catégorie" current="module_equipment"}}
{{#load key=$_GET.key assign="category"}}
{{else}}
@ -12,13 +12,10 @@
{{else}}
{{* supprimer la catégorie sélectionnée*}}
{{:delete where="key = :key" :key=$category.key}}
{{:redirect force="./index.html?ok=1&msg=suppression"|args:$msg}}
{{:redirect force="./index.html?ok=1&msg=suppression"}}
{{/load}}
{{/form}}
{{:admin_header title="Supprimer une catégorie" current="module_equipment"}}
{{:form_errors}}
{{:delete_form
legend="Supprimer une catégorie"
warning="Supprimer la catégorie « %s » ?"|args:$category.name

View file

@ -1,20 +1,18 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Configuration" current="module_equipment"}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="../_nav.html" current="config" subcurrent="categories"}}
{{:include file="../_nav.html" current="categories"}}
{{if $_GET.ok}}
{{if $_GET.msg == "modification"}}
<p class="block confirm">Modification enregistrée</p>
{{elseif $_GET.msg == "suppression"}}
<p class="block confirm">Catégorie supprimée</p>
{{elseif $_GET.msg == "ajout"}}
<p class="block confirm">Catégorie ajoutée</p>
{{/if}}
{{elseif $_GET.err}}
{{if $_GET.msg == "suppression"}}
{{if $_GET.msg == "modification"}}
<p class="block error">{{$_GET.msg}}</p>
{{elseif $_GET.msg == "suppression"}}
<p class="block error">
Cette catégorie ne peut être supprimée car elle contient encore des matériels
</p>
@ -24,16 +22,10 @@
{{* afficher les catégories déjà enregistrées *}}
<section class="categories">
{{#list select="$$.name AS 'Catégorie'" order="1" where="$$.type = 'category'"}}
{{:assign category_key=$key}}
{{* voir s'il y a des matériels dans cette catégorie *}}
{{:assign materiel_present=true}}
{{#load type="equipment" where="$$.category = :category_key" :category_key=$category_key}}
{{else}}
{{:assign materiel_present=false}}
{{/load}}
<tr>
<th>{{$name}}</th>
<td class="actions">
{{:linkbutton label="Liste des matériels" href="list_equipment.html?key=%s&dialog"|args:$key shape="search" target="_dialog"}}
{{:linkbutton label="Modifier" href="modify_category.html?key=%s"|args:$key shape="edit" target="_dialog"}}
{{:linkbutton label="Supprimer" href="delete_category.html?key=%s"|args:$key shape="delete" target="_dialog"}}
</td>
@ -43,4 +35,37 @@
{{/list}}
</section>
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* Vérifier s'il existe déjà une catégorie avec le même nom *}}
{{#load type="category" where="lower($$.name) = :name" :name=$_POST.name|trim|tolower}}
{{:error message="Impossible d'ajouter la catégorie « %s » car elle existe déjà !"|args:$name|trim}}
{{/load}}
{{:assign key=""|uuid}}
{{:save
key=$key
validate_schema="./category.schema.json"
type="category"
name=$_POST.name|trim
}}
{{:redirect to="./index.html?ok=1&msg=Catégorie enregistrée"}}
{{/form}}
{{:form_errors}}
{{* formulaire d'ajout de catégorie *}}
<form method="post" action="{{$self_url}}">
<fieldset class="ajout_categorie">
<legend>Ajouter une catégorie</legend>
<dl>
{{:input type="text" name="name" label="Nom" autofocus=true required=true maxlength="100"}}
</dl>
<p class="submit">
{{:button type="submit" name="save" label="Ajouter" shape="right" class="main"}}
</p>
</fieldset>
</form>
{{:admin_footer}}

View file

@ -0,0 +1,15 @@
{{#load key=$_GET.key}}
{{:assign cat_name=$name}}
{{/load}}
{{:admin_header title="Matériels de la catégorie « %s »"|args:$cat_name current="module_equipment"}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="entrees"}}
{{/if}}
{{:assign var="category_keys." value=$_GET.key}}
{{:include file="../inventaire.html"}}
{{:admin_footer}}

View file

@ -1,4 +1,4 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Modifier une catégorie" current="module_equipment"}}
{{#load key=$_GET.key assign="category"}}
{{else}}
@ -7,11 +7,6 @@
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* Vérifier s'il existe déjà une catégorie avec le même nom *}}
{{#load type="category" where="$$.name = :name COLLATE U_NOCASE" :name=$_POST.name|trim limit=1}}
{{:error message="Modification impossible car ce nom de catégorie (« %s ») existe déjà !"|args:$name|trim}}
{{/load}}
{{:save
key=$category.key
validate_schema="./category.schema.json"
@ -21,11 +16,10 @@
{{:redirect force="./index.html?ok=1&msg=modification"}}
{{/form}}
{{:admin_header title="Modifier une catégorie" current="module_equipment"}}
{{:form_errors}}
{{* formulaire de modification de catégorie *}}
<form method="post" action="" data-focus="1">
<form method="post" action="">
<fieldset class="modif_categorie">
<legend>Modifier la catégorie « {{$category.name}} »</legend>
<dl>

View file

@ -1,52 +1,162 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Configuration" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="_nav.html" current="config" subcurrent="typesES"}}
{{:include file="_nav.html" current="config"}}
{{if $_GET.ok}}
<p class="block confirm">Configuration enregistrée.</p>
{{/if}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{:save key="config"
validate_schema="./config.schema.json"
input_nature=$_POST.input_fields|array_transpose
output_nature=$_POST.output_fields|array_transpose
}}
{{:redirect to="./config.html?ok=1"}}
{{/form}}
{{* lecture config (défaut ou enregistrée) *}}
{{:include file="./_get_config.html" keep="config, directions"}}
{{:include file="./_get_config.html" keep="config"}}
{{#foreach from=$directions key="direction" item="item"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{:assign var='input_types.%s'|args:$type value=$type}}
{{/foreach}}
{{* types de mouvements qui ne peuvent être supprimés *}}
{{#load type="movement" where="$$.direction='%s'"|args:$direction group="$$.operation"}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
{{:assign var="locked_%ss."|args:$direction value=$op_label}}
{{* Natures d'entrées qui ne peuvent être supprimées *}}
{{#load type="movement" where="$$.direction='input'" group="$$.input_nature"}}
{{:assign var="locked_inputs." value=$input_nature}}
{{/load}}
<h2 class="ruler">{{$item|ucfirst}}s</h2>
<table class="list">
{{* types de sorties *}}
{{#foreach from=$config.output_nature key="label" item="type"}}
{{:assign var='output_types.%s'|args:$type value=$type}}
{{/foreach}}
{{* Natures de sorties qui ne peuvent être supprimées *}}
{{#load type="movement" where="$$.direction='output'" group="$$.output_nature"}}
{{:assign var="locked_outputs." value=$output_nature}}
{{/load}}
<form method="post" action="">
<fieldset>
<legend>Entrées</legend>
<table class="list input_fields">
<thead>
<tr>
<th>Libellé</th>
<th>Nature de l'entrée</th>
<th>Type</th>
<th></th>
<th>Action</th>
</tr>
</thead>
<tbody>
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key=key}}
<tbody id="input_body">
{{#foreach from=$config.input_nature key="label" item="type"}}
<tr>
<td>{{$label}}</td>
<td>{{$type}}</td>
<td class="actions">
{{:assign var="locked" from="locked_%ss"|args:$direction}}
{{if ! $locked|has:$label}}
{{:linkbutton label="Supprimer" shape="delete" href="config/delete_movement_type.html?dir=%s&op_key=%s"|args:$direction:$key target="_dialog"}}
{{/if}}
{{:linkbutton label="Modifier" shape="edit" href="config/modify_movement_type.html?dir=%s&op_key=%s"|args:$direction:$key target="_dialog"}}
<td>{{:input type="text" name="input_fields[label][]" default=$label}}</td>
<td>{{:input type="select"
name="input_fields[type][]"
options=$input_types
default=$type
required=true
default_empty="— Choisir un type —"}}
</td>
<td class="action">
{{:button
label="Supprimer" shape="minus"
disabled=$locked_inputs|has:$label
onclick="this.parentNode.parentNode.remove();"}}
</td>
</tr>
{{/foreach}}
</tbody>
</table>
<p class="actions">
{{:button shape="plus" label="Ajouter un champ" onclick="addLine('#input_body')"}}
</p>
<div class="help block">
<h3>Signification du type d'entrée</h3>
<ul>
<li><b>définitif</b> : l'asso devient propriétaire du matériel (ex : achat, don)</li>
<li><b>temporaire</b> : l'asso ne devient <strong>pas</strong> propriétaire du matériel (ex : location, emprunt)</li>
<li><b>retour</b> : matériel qui revient après une sortie temporaire (ex : retour de location ou de prêt)</li>
</ul>
</div>
</fieldset>
<fieldset>
<legend>Sorties</legend>
<table class="list output_fields">
<thead>
<tr>
<th>Nature de la sortie</th>
<th>Type</th>
<th>Action</th>
</tr>
</thead>
<tbody id="output_body">
{{#foreach from=$config.output_nature key="label" item="type"}}
<tr>
<td>{{:input type="text" name="output_fields[label][]" default=$label}}</td>
<td>{{:input
type="select"
name="output_fields[type][]"
options=$output_types
default=$type
required=true
default_empty="— Choisir un type —"}}
</td>
<td class="action">
{{:button
label="Supprimer" shape="minus"
disabled=$locked_outputs|has:$label
onclick="this.parentNode.parentNode.remove();"}}
</td>
</tr>
{{/foreach}}
</tbody>
</table>
<p class="actions">
{{:button shape="plus"
label="Ajouter un champ"
onclick="addLine('#output_body')"}}
</p>
<div class="help block">
<h3>Signification du type de sortie</h3>
<ul>
<li><b>définitif</b> : le matériel n'appartient plus à l'asso (ex : vente, casse, perte, vol, ...)</li>
<li><b>temporaire</b> : le matériel sort temporairement de l'asso qui en reste propriétaire (ex : location, prêt)</li>
<li><b>retour</b> : le matériel <strong>non propriété de l'asso</strong> est rendu à son propriétaire (ex : retour de location ou d'emprunt)</li>
</dl>
</div>
</fieldset>
<p class="submit">
{{:button
type="submit"
name="save"
label="Enregistrer"
shape="right"
class="main"
}}
</p>
</form>
<script type="text/javascript">
// dupliquer la dernière ligne d'une table
function addLine(id_body) {
var ligne = document.querySelector(id_body).lastElementChild;
var nelle = ligne.cloneNode(true);
let text = nelle.querySelector('input[type="text"]');
text.value = null;
let menu = nelle.querySelector('select')
if (menu != null) {
menu[0].selected = 'selected';
}
ligne.parentNode.appendChild(nelle);
text.focus();
}
</script>
{{:admin_footer}}

View file

@ -8,9 +8,6 @@
"items": {
"type": "object",
"properties": {
"key" : {
"type" : "string"
},
"label" : {
"type" : "string"
},
@ -27,9 +24,6 @@
"items": {
"type": "object",
"properties": {
"key" : {
"type" : "string"
},
"label" : {
"type" : "string"
},

View file

@ -1,136 +0,0 @@
{{* -*- brindille -*- *}}
{{*
paramètres :
- dir : input ou output
*}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="config" subcurrent="typesES"}}
{{/if}}
{{* Traiter l'envoi du formulaire *}}
{{* lecture config (défaut ou enregistrée) *}}
{{:include file="../_get_config.html" keep="config, directions"}}
{{#form on="save"}}
{{* vérifier s'il existe un type de mouvement de même nom *}}
{{#foreach from=$directions key="direction"}}
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key="key"}}
{{:assign var="fields" from="_POST.%s_fields"|args:$_GET.dir}}
{{if $label|trim|tolower == $fields.label|trim|tolower}}
{{:error message="Ce libellé est déjà présent"}}
{{/if}}
{{:assign var="%s_nature.key"|args:$direction value=$key}}
{{:assign var="%s_nature.label"|args:$direction value=$label}}
{{:assign var="%s_nature.type"|args:$direction value=$type}}
{{:assign var="%s_natures."|args:$direction from="%s_nature"|args:$direction}}
{{/foreach}}
{{* ajouter le nouveau type de mouvement *}}
{{if $_GET.dir == $direction}}
{{:assign var="newlabel" from="_POST.%s_fields.label"|args:$direction}}
{{:assign newlabel=$newlabel|trim}}
{{:assign var="%s_nature.key"|args:$direction value=""|uuid}}
{{:assign var="%s_nature.label"|args:$direction value=$newlabel}}
{{:assign var="%s_nature.type"|args:$direction from="_POST.%s_fields.type"|args:$direction}}
{{:assign var="%s_natures."|args:$direction from="%s_nature"|args:$direction}}
{{/if}}
{{/foreach}}
{{:save
key="config"
validate_schema="../config.schema.json"
input_nature=$input_natures
output_nature=$output_natures
}}
{{:redirect to="./config.html?ok=1"}}
{{/form}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{:form_errors}}
{{if $_GET.dir == 'input'}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature}}
{{:assign var='input_types.%s'|args:$type value=$type}}
{{/foreach}}
<form method="post" action="">
<fieldset>
<legend>Type d'entrée</legend>
<dl>
<td>
{{:input type="select"
label="Type d'entrée"
name="input_fields[type]"
options=$input_types
default=$type
required=true
default_empty="— Choisir un type —"}}
</td>
<td>
{{:input
type="text"
label="Libellé de l'entrée"
name="input_fields[label]"
required=true}}
</td>
</dl>
<div class="help block">
<h3>Signification du type d'entrée</h3>
<ul>
<li><b>définitif</b> : l'asso devient propriétaire du matériel (ex : achat, don)</li>
<li><b>temporaire</b> : l'asso ne devient <strong>pas</strong> propriétaire du matériel (ex : location, emprunt)</li>
<li><b>retour</b> : matériel qui revient après une sortie temporaire (ex : retour de location ou de prêt)</li>
</ul>
</div>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
{{* types de sorties *}}
{{#foreach from=$config.output_nature}}
{{:assign var='output_types.%s'|args:$type value=$type}}
{{/foreach}}
<form method="post" action="">
<fieldset>
<legend>Type de sortie</legend>
<dl>
<td>
{{:input type="select"
label="Type de sortie"
name="output_fields[type]"
options=$output_types
default=$type
required=true
default_empty="— Choisir un type —"}}
</td>
<td>
{{:input
type="text"
label="Libellé de la sortie"
name="output_fields[label]"
required=true}}
</td>
</dl>
<div class="help block">
<h3>Signification du type de sortie</h3>
<ul>
<li><b>définitif</b> : le matériel n'appartient plus à l'asso (ex : vente, casse, perte, vol, ...)</li>
<li><b>temporaire</b> : le matériel sort temporairement de l'asso qui en reste propriétaire (ex : location, prêt)</li>
<li><b>retour</b> : le matériel <strong>non propriété de l'asso</strong> est rendu à son propriétaire (ex : retour de location ou d'emprunt)</li>
</ul>
</div>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{/if}}

View file

@ -1,49 +0,0 @@
{{* -*- brindille -*- *}}
{{*
paramètres :
- dir : input ou output
- op_key : clé du type de mouvement à supprimer
*}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="config" subcurrent="typesES"}}
{{/if}}
{{* lecture config (défaut ou enregistrée) *}}
{{:include file="../_get_config.html" keep="config, directions"}}
{{#form on="delete"}}
{{#foreach from=$directions key="direction"}}
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key="key"}}
{{if $_GET.dir == $direction && $key != $_GET.op_key || $_GET.dir != $direction}}
{{:assign var="%s_nature.key"|args:$direction value=$key}}
{{:assign var="%s_nature.label"|args:$direction value=$label}}
{{:assign var="%s_nature.type"|args:$direction value=$type}}
{{:assign var="%s_natures."|args:$direction from="%s_nature"|args:$direction}}
{{/if}}
{{/foreach}}
{{/foreach}}
{{:save
key="config"
validate_schema="../config.schema.json"
input_nature=$input_natures
output_nature=$output_natures
}}
{{:redirect to="./config.html?ok=1"}}
{{/form}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{:form_errors}}
{{:assign var="mvt_label" from="config.%s_nature.%s.label"|args:$_GET.dir:$_GET.op_key}}
{{:assign var="dir_label" from="directions.%s"|args:$_GET.dir}}
{{:delete_form
legend="Supprimer cette %s ?"|args:$dir_label
warning="Supprimer « %s » ?"|args:$mvt_label
}}
{{:admin_footer}}

View file

@ -1,58 +0,0 @@
{{* -*- brindille -*- *}}
{{*
paramètres :
- dir : input ou output
- op_key : clé du type de mouvement dont on veut modifier le libellé
*}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="config" subcurrent="typesES"}}
{{/if}}
{{* lecture config (défaut ou enregistrée) *}}
{{:include file="../_get_config.html" keep="config, directions"}}
{{#form on="save"}}
{{#foreach from=$directions key="direction"}}
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key="key"}}
{{:assign var="%s_nature.key"|args:$direction value=$key}}
{{if $_GET.dir == $direction}}
{{if $key == $_GET.op_key}}
{{:assign var="%s_nature.label"|args:$direction value=$_POST.name|trim}}
{{else}}
{{:assign var="%s_nature.label"|args:$direction value=$label}}
{{/if}}
{{else}}
{{:assign var="%s_nature.label"|args:$direction value=$label}}
{{/if}}
{{:assign var="%s_nature.type"|args:$direction value=$type}}
{{:assign var="%s_natures."|args:$direction from="%s_nature"|args:$direction}}
{{/foreach}}
{{/foreach}}
{{:save
key="config"
validate_schema="../config.schema.json"
input_nature=$input_natures
output_nature=$output_natures
}}
{{:redirect to="./config.html?ok=1"}}
{{/form}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{:form_errors}}
{{:assign var="default_label" from="config.%s_nature.%s.label"|args:$_GET.dir:$_GET.op_key}}
<form method="post" action="" data-focus="1">
<fieldset>
<legend>Modifier le libellé</legend>
<dl>
{{:input type="text" name="name" label="Libellé" default=$default_label required=true maxlength="100"}}
</dl>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</fieldset>
</form>

View file

@ -1,37 +0,0 @@
{
"inputs": [
{
"key": "c3a955e3-4e6e-414e-90f4-ede7ac3e9e33",
"label": "Achat",
"type": "définitif"
},
{
"key": "9e909c25-14dc-4e02-b97e-73c34ab2ee9b",
"label" : "Location",
"type": "temporaire"
},
{
"key": "30eb854c-f89a-4c19-85e4-baa5e34a0317",
"label" : "Retour de Location/Prêt",
"type" : "retour"
}
],
"outputs": [
{
"key": "f0eb189b-0b72-46c7-8b48-c23eed7e9672",
"label" : "Vente",
"type" : "définitif"
},
{
"key" : "c9ba00d9-26ee-448b-9f02-73e479ec2980",
"label" : "Prêt",
"type" : "temporaire"
},
{
"key" : "fefefa51-1a85-46ca-ab78-b594b10390ff",
"label" : "Retour de Location/Emprunt",
"type" : "retour"
}
]
}

12
defaut.json Normal file
View file

@ -0,0 +1,12 @@
{
"inputs" : [
{ "Achat" : "définitif" },
{ "Location" : "temporaire" },
{ "Retour de Location/Prêt" : "retour" }
],
"outputs" : [
{ "Vente" : "définitif" },
{ "Prêt" : "temporaire" },
{ "Retour de Location/Emprunt" : "retour" }
]
}

View file

@ -10,30 +10,10 @@
"description": "Clé de la catégorie",
"type": "string"
},
"name": {
"designation": {
"description": "Désignation du matériel",
"type": "string"
},
"status": {
"description": "État du matériel",
"type": "string",
"enum": ["available", "archived"]
},
"stock": {
"description": "Quantité en stock",
"type" : ["integer", "null"],
"minimum": 0
},
"out": {
"description": "Quantité sortie temporairement",
"type" : ["integer", "null"],
"minimum": 0
},
"notowned": {
"description": "Quantité présente temporairement",
"type" : ["integer", "null"],
"minimum": 0
}
},
"required": ["type", "category", "name", "status", "stock", "out", "notowned"]
"required": ["type", "category", "designation"]
}

View file

@ -1,341 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Afficher l'historique des mouvements d'un matériel
paramètres
- key : clé du matériel
- prop : = 1 si matériel appartient à l'asso
- ok : vrai si opération terminée avec succès
- err : vrai si opération terminée en erreur (ça fait doublon avec ok, non ?)
- msg : message de retour
*}}
{{* barre de navigation *}}
{{if $_GET.prop == 1}}
{{:assign proprio="proprio"}}
{{else}}
{{:assign proprio="nonproprio"}}
{{/if}}
{{:assign equipment_key=$_GET.key|trim}}
{{#load key=$equipment_key assign="equipment"}}
{{else}}
{{:error message="Pas de matériel avec la clé %s"|args:$equipment_key}}
{{/load}}
{{#load type="category" where="key = :cle" :cle=$equipment.category assign="category"}}
{{else}}
{{:error message="Le matériel %s n'appartient à aucune catégorie"|args:$equipment.name}}
{{/load}}
{{:admin_header title="Gestion des matériels" custom_css="./style.css" current="module_equipment"}}
{{if $_GET.current != null}}
{{:assign current=$_GET.current}}
{{else}}
{{:assign current="inventaire"}}
{{/if}}
{{:include file="./_nav.html" current=$current subcurrent=$proprio subsubcurrent="historique" eqpmt=$equipment.name category=$category.name}}
{{if $_GET.ok}}
{{if $_GET.msg == "modification"}}
<p class="block confirm">Modification enregistrée</p>
{{elseif $_GET.msg == "copie"}}
<p class="block confirm">Mouvement copié</p>
{{elseif $_GET.msg == "retour"}}
<p class="block confirm">Retour enregistré</p>
{{elseif $_GET.msg == "suppression"}}
<p class="block confirm">Mouvement supprimé</p>
{{else}}
<p class="block confirm">Mouvement enregistré</p>
{{/if}}
{{elseif $_GET.err}}
{{if $_GET.msg == "suppression"}}
<p class="block error">Ce mouvement ne peut être supprimé</p>
{{/if}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="./_get_config.html" keep="config"}}
{{* déterminer les types de mouvements selon l'affection du matériel *}}
{{#foreach from=$config.input_nature}}
{{if $_GET.prop}}
{{* matériel propriété de l'asso *}}
{{if $type != 'temporaire'}}
{{:assign var="input_types." value=$label}}
{{/if}}
{{else}}
{{* matériel non propriété de l'asso *}}
{{if $type == 'temporaire'}}
{{:assign var="input_types." value=$label}}
{{/if}}
{{/if}}
{{/foreach}}
{{#foreach from=$config.output_nature}}
{{if $_GET.prop}}
{{* matériel propriété de l'asso *}}
{{if $type != 'retour'}}
{{:assign var="output_types." value=$label}}
{{/if}}
{{else}}
{{* matériel non propriété de l'asso *}}
{{if $type == 'retour'}}
{{:assign var="output_types." value=$label}}
{{/if}}
{{/if}}
{{/foreach}}
{{* calculer et mémoriser les quantités pour que le tri de la liste affiche les valeurs correctes *}}
{{:assign stock=0}}
{{:assign exterieur=0}}
{{:assign nonproprio=0}}
{{#load type="movement" where="$$.equipment = :key" :key=$equipment_key order="$$.date"}}
{{if $direction == 'input'}}
{{:assign var="type_mvt" from="config.input_nature.%s.type"|args:$operation}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d+%d"|math:$stock:$amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign exterieur="%d-%d"|math:$exterieur:$amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign nonproprio="%d+%d"|math:$nonproprio:$amount}}
{{/if}}
{{else}}
{{:assign var="type_mvt" from="config.output_nature.%s.type"|args:$operation}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign nonproprio="%d-%d"|math:$nonproprio:$amount}}
{{/if}}
{{/if}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{:assign var="quantites.%s.stock"|args:$id value=$stock}}
{{:assign var="quantites.%s.exterieur"|args:$id value=$exterieur}}
{{:assign var="quantites.%s.dispo"|args:$id value=$dispo}}
{{:assign var="quantites.%s.nonproprio"|args:$id value=$nonproprio}}
{{/load}}
{{if $current != "archives"}}
<nav class="tabs">
<aside>
{{if $_GET.prop}}
{{if $equipment.stock > 0}}
{{:linkbutton label="Sortie" shape="minus" href="movements/output_equipment.html?key=%s"|args:$_GET.key target="_dialog"}}
{{/if}}
{{:linkbutton label="Entrée" shape="plus" href="movements/input_equipment.html?key=%s"|args:$_GET.key target="_dialog"}}
{{else}}
{{:linkbutton label="Entrée" shape="plus" href="movements/input_equipment.html?key=%s"|args:$_GET.key target="_dialog"}}
{{/if}}
</aside>
</nav>
{{/if}}
{{* lister tous les mouvements du matériel passé en paramètre *}}
{{if $_GET.prop}}
{{* calculer la quantité temporairement l'extérieur de chaque matériel *}}
{{#foreach from=$config.output_nature key=key}}
{{if $type == "temporaire"}}
{{:assign var="temp_outputs." value=$key|quote_sql}}
{{/if}}
{{/foreach}}
{{:assign operations=$temp_outputs|implode:","}}
{{:assign operations="("|cat:$operations|cat:")"}}
{{#select
mvt.key AS mvt_key,
json_extract(mvt.document, '$.amount') - IFNULL(SUM(json_extract(mvt2.document, '$.amount')), 0) AS reste
FROM module_data_equipment AS mvt
LEFT JOIN module_data_equipment AS link ON mvt.key = json_extract(link.document, '$.temp_key')
LEFT JOIN module_data_equipment AS mvt2 ON mvt2.key = json_extract(link.document, '$.return')
WHERE
json_extract(mvt.document, '$.operation') IN !op
AND json_extract(mvt.document, '$.equipment') = :eqpmt_key
GROUP by mvt.key
;
!op = $operations
:eqpmt_key = $_GET.key
}}
{{:assign var="reste.%s"|args:$mvt_key value=$reste}}
{{/select}}
{{#list
type="movement"
select="
($$.date || '_' || substr('000000' || id, -6, 6)) AS 'Date';
CASE $$.direction WHEN 'input' THEN 'Entrée' WHEN 'output' THEN 'Sortie' END AS 'Mouvement';
$$.operation AS 'Opération';
$$.amount AS 'Quantité';
'' AS 'Stock';
'' AS 'Sorti';
'' AS 'Disponible';
CASE WHEN $$.user NOT NULL
THEN (SELECT %s AS nom FROM users WHERE id = $$.user)
ELSE ''
END AS 'Dépositaire';
CASE WHEN $$.storage NOT NULL
THEN (SELECT $$.name FROM @TABLE as storage WHERE storage.key = @TABLE.$$.storage)
ELSE ''
END AS 'Stockage';
$$.comment AS 'Commentaire'
"|args:$config.user_fields.name_sql
equipment=$equipment_key
order=1
}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$direction:$operation}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
{{if $direction === "input" && $op_label|in:$input_types ||
$direction === "output"&& $op_label|in:$output_types
}}
{{:assign var="stock" from="quantites.%s.stock"|args:$id}}
{{:assign var="exterieur" from="quantites.%s.exterieur"|args:$id}}
{{:assign var="dispo" from="quantites.%s.dispo"|args:$id}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$col2}}</td>
<td>{{$op_label}}</td>
<td class="num">{{$amount}}</td>
<td class="num nosort">{{$stock}}</td>
<td class="num nosort">{{$exterieur}}</td>
<td class="num nosort">{{$dispo}}</td>
<td>{{:link href="/admin/users/details.php?id=%s"|args:$user label="%s"|args:$col8}}</td>
<td>{{$col9}}</td>
<td>{{$comment}}</td>
<td class="actions">
{{if $current != "archives"}}
{{if $direction == "output" && $type_mvt == "temporaire"}}
{{:assign var="temp_ext" from="reste.%s"|args:$key}}
{{if $temp_ext != null && $temp_ext > 0}}
{{:linkbutton
label="Retour"
href="movements/output_return.html?key=%s&prop=%s"|args:$key:$_GET.prop
shape="reset"
target="_dialog"}}
{{/if}}
{{/if}}
{{if $direction == "input" && $type_mvt == "retour"}}
{{* interdire dupliquer *}}
{{else}}
{{:linkbutton
label="Dupliquer"
href="movements/copy_movement.html?key=%s&prop=%s"|args:$key:$_GET.prop
shape="plus"
target="_dialog"}}
{{/if}}
{{:linkbutton
label="Modifier"
href="movements/modify_movement.html?key=%s"|args:$key
shape="edit"
target="_dialog"}}
{{:linkbutton
label="Supprimer"
href="movements/delete_movement.html?key=%s&prop=%s"|args:$key:$_GET.prop
shape="delete"
target="_dialog"}}
{{/if}}
</td>
</tr>
{{/if}}
{{/list}}
{{else}}
{{* calculer la quantité présente temporairement de chaque matériel *}}
{{#foreach from=$config.input_nature key=key}}
{{if $type == "temporaire"}}
{{:assign var="temp_inputs." value=$key|quote_sql}}
{{/if}}
{{/foreach}}
{{:assign operations=$temp_inputs|implode:","}}
{{:assign operations="("|cat:$operations|cat:")"}}
{{#select
mvt.key AS mvt_key,
json_extract(mvt.document, '$.amount') - IFNULL(SUM(json_extract(mvt2.document, '$.amount')), 0) AS present
FROM module_data_equipment AS mvt
LEFT JOIN module_data_equipment AS link ON mvt.key = json_extract(link.document, '$.temp_key')
LEFT JOIN module_data_equipment AS mvt2 ON mvt2.key = json_extract(link.document, '$.return')
WHERE
json_extract(mvt.document, '$.operation') IN !op
AND json_extract(mvt.document, '$.equipment') = :eqpmt_key
GROUP by mvt.key
;
!op = $operations
:eqpmt_key = $_GET.key
}}
{{:assign var="present.%s"|args:$mvt_key value=$present}}
{{/select}}
{{#list
type="movement"
select="($$.date || '_' || substr('000000' || id, -6, 6)) AS 'Date';
CASE $$.direction WHEN 'input' THEN 'Entrée' WHEN 'output' THEN 'Sortie' END AS 'Mouvement';
$$.operation AS 'Opération';
$$.amount AS 'Quantité';
"" as 'Présent';
CASE WHEN $$.storage NOT NULL
THEN (SELECT $$.name FROM @TABLE as storage WHERE storage.key = @TABLE.$$.storage)
ELSE ''
END as 'Stockage';
$$.comment AS 'Commentaire'"
equipment=$equipment_key
order=1
}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$direction:$col3}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
{{if $direction === "input" && $op_label|in:$input_types ||
$direction === "output"&& $op_label|in:$output_types
}}
{{:assign var="stock" from="quantites.%s.nonproprio"|args:$id}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$col2}}</td>
<td>{{$op_label}}</td>
<td class="num">{{$amount}}</td>
<td class="num nosort">{{$stock}}</td>
<td>{{$col6}}</td>
<td>{{$comment}}</td>
<td class="actions">
{{if $direction == "input" && $type_mvt == "temporaire"}}
{{:assign var="temp_in" from="present.%s"|args:$key}}
{{if $temp_in != null && $temp_in > 0}}
{{:linkbutton
label="Retour"
href="movements/input_return.html?key=%s&prop=%s"|args:$key:$_GET.prop
shape="reset"
target="_dialog"}}
{{/if}}
{{/if}}
{{:linkbutton
label="Dupliquer"
href="movements/copy_movement.html?key=%s&prop=%s"|args:$key:$_GET.prop
shape="plus"
target="_dialog"}}
{{:linkbutton
label="Modifier"
href="movements/modify_movement.html?key=%s"|args:$key
shape="edit"
target="_dialog"}}
{{:linkbutton
label="Supprimer"
href="movements/delete_movement.html?key=%s&prop=%s"|args:$key:$_GET.prop
shape="delete"
target="_dialog"}}
</td>
</tr>
{{/if}}
{{/list}}
{{/if}}
{{:admin_footer}}
<script type="text/javascript" src="scripts.js"></script>
<script type="text/javascript">
(function () {
disableColumSort(document.querySelector("table[class=list]"));
})();
</script>

View file

@ -1,94 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Afficher l'historique de tous les mouvements
*}}
{{:admin_header title="Historique des mouvements" custom_css="./style.css" current="module_equipment"}}
{{:include file="./_nav.html" current="historique"}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="./_get_config.html" keep="config"}}
{{* Sélecteur catégories *}}
{{:assign var="options." value="" label="Toutes les catégories" href="?"}}
{{#load type="category" order="$$.name"}}
{{:assign var="categories.%s"|args:$key value=$name}}
{{:assign
var="options."
value=$key
label=$name
href="?cat_key=%s"|args:$key
}}
{{/load}}
<fieldset class="shortFormRight">
<legend>Filtrer par catégorie</legend>
{{:dropdown
title="Filtrer par catégorie"
options=$options
value="%s"|args:$_GET.cat_key
}}
</fieldset>
{{* condition de filtrage *}}
{{if $_GET.cat_key != null}}
{{:assign condition="(SELECT key
FROM @TABLE AS cat
WHERE cat.key = (SELECT $$.category
FROM @TABLE AS mat
WHERE mat.key = @TABLE.$$.equipment)) = '%s'"|args:$_GET.cat_key}}
{{else}}
{{:assign condition=1}}
{{/if}}
{{* lister tous les mouvements *}}
{{#list
type="movement"
select="($$.date || '_' || substr('000000' || id, -6, 6)) AS 'Date';
CASE $$.direction WHEN 'input' THEN 'Entrée' WHEN 'output' THEN 'Sortie' END AS 'Mouvement';
$$.operation AS 'Opération';
(SELECT $$.name
FROM @TABLE AS mat
WHERE mat.key = @TABLE.$$.equipment) AS 'Matériel' ;
$$.amount AS 'Quantité';
CASE WHEN $$.user NOT NULL
THEN (SELECT %s AS nom FROM users WHERE id = $$.user)
ELSE ''
END as 'Dépositaire';
CASE WHEN $$.storage NOT NULL
THEN (SELECT $$.name FROM @TABLE as storage WHERE storage.key = @TABLE.$$.storage)
ELSE ''
END as 'Stockage';
$$.comment AS 'Commentaire'
"|args:$config.user_fields.name_sql
where="%s"|args:$condition
order=1
max=50
desc=true
}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$col2}}</td>
<td class="nosort">{{$op_label}}</td>
<td>{{$col4}}</td>
<td class="num">{{$amount}}</td>
<td>{{:link href="/admin/users/details.php?id=%s"|args:$user label="%s"|args:$col6}}</td>
<td>{{$col7}}</td>
<td>{{$comment}}</td>
<td></td>
</tr>
{{else}}
<p class="block alert">Aucun mouvement.</p>
{{/list}}
{{:admin_footer}}
<script type="text/javascript" src="scripts.js"></script>
<script type="text/javascript">
(function () {
disableColumSort(document.querySelector("table[class=list]"));
})();
</script>

34
historique.html Normal file
View file

@ -0,0 +1,34 @@
{{:assign equipment_key=$_GET.key|trim}}
{{#load key=$_GET.key assign="equipment"}}
{{else}}
{{:error message="Pas de matériel avec la clé %s"|args:$equipment_key}}
{{/load}}
{{#load type="category" where="key = :cle" :cle=$equipment.category assign="category"}}
{{else}}
{{:error message="Le matériel %s n'appartient à aucune catégorie"|args:$equipment.designation}}
{{/load}}
{{:admin_header title="Historique des mouvements de %s (%s)"|args:$equipment.designation:$category.name current="module_equipment"}}
{{* lister tous les mouvements du matériel passé en paramètre *}}
{{#list
type="movement"
select="$$.date AS 'Date';
CASE $$.direction WHEN 'input' THEN 'Entrée' WHEN 'output' THEN 'Sortie' END AS 'Mvt';
CASE $$.direction WHEN 'input' THEN $$.input_nature WHEN 'output' THEN $$.output_nature END AS 'Type';
$$.amount AS 'Nombre';
$$.comment AS 'Commentaire'"
equipment=$equipment_key
order=1
}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$col2}}</td>
<td>{{$col3}}</td>
<td>{{$amount}}</td>
<td>{{$comment}}</td>
<td></td>
</tr>
{{/list}}
{{:admin_footer}}

View file

@ -1,39 +1,22 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{:admin_header title="Gestion des matériels" custom_css=$custom_css current="module_equipment"}}
{{* barre de navigation *}}
{{if $_GET.prop == null || $_GET.prop}}
{{:assign proprio="proprio"}}
{{else}}
{{:assign proprio="nonproprio"}}
{{/if}}
{{#load type="category" count=true assign="result"}}{{/load}}
{{:include file="_nav.html" current="inventaire" cat="%d"|args:$result.count subcurrent="%s"|args:$proprio}}
{{:include file="_nav.html" current="index"}}
{{if $_GET.ok}}
{{if $_GET.msg == "ajout" }}
<p class="block confirm">Ajout effectué</p>
{{elseif $_GET.msg == "modification" }}
<p class="block confirm">Modification effectuée</p>
{{elseif $_GET.msg == "suppression" }}
<p class="block confirm">Suppression effectuée</p>
{{elseif $_GET.msg == "supprmvtmat" }}
<p class="block confirm">Mouvement supprimé - Matériel supprimé</p>
{{/if}}
{{elseif $_GET.err}}
<p class="block error">Modification refusée</p>
{{/if}}
{{if $result.count == 0}}
{{#load type="category"}}
{{:assign var="category_keys." value=$key}}
{{/load}}
{{if $category_keys|count == 0}}
<p class="block alert">Il n'y a aucune catégorie : vous devez en ajouter.</p>
{{else}}
{{if $_GET.prop == null || $_GET.prop == "1"}}
{{:include file="./_inventory.html"}}
{{else}}
{{:include file="./_temp_inventory.html"}}
{{/if}}
{{:include file="./inventaire.html" print_cat_name=true}}
{{/if}}
{{:admin_footer}}

150
inventaire.html Normal file
View file

@ -0,0 +1,150 @@
{{* inventaire des entrées/sorties des matériels des catégories de la variable category_keys *}}
{{* Extraire et compiler les infos de la base *}}
{{:include file="./_calcul_dispo.html" keep="cumul_mvt,category_keys"}}
{{* Afficher les résultats *}}
{{if $cumul_mvt === null}}
{{if $category_keys|count == 1}}
<p class="block alert">Il n'y a aucun matériel dans cette catégorie.</p>
{{else}}
<p class="block alert">Il n'y a aucun matériel dans ces catégories.</p>
{{/if}}
{{else}}
<section class="inventaire">
<h2 class="ruler">Matériels dont l'association est propriétaire</h2>
{{* itérer sur les catégories *}}
{{#foreach from=$cumul_mvt key="cat_key" item="cat_elem"}}
{{if $print_cat_name}}
<h3>{{$cat_elem.name}}</h3>
{{/if}}
{{* vérifier s'il y a des matériels dans cette catégorie *}}
{{:assign present=false}}
{{if $cat_elem|keys|has:"eqpmt"}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{if $eqpmt.stock !== null && $eqpmt.stock !== 0}}
{{:assign present=true}}
{{:break}}
{{/if}}
{{/foreach}}
{{/if}}
{{if $present}}
<table class="list">
<thead>
<tr>
<th>Désignation</th>
<th>Stock</th>
<th>Sortie</th>
<th>Disponible</th>
<th class="actions"></th>
</tr>
</thead>
<tbody>
{{* itérer sur les matériels de la catégorie *}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{:assign keys=$eqpmt|keys}}
{{if "stock"|in:$keys && $eqpmt.stock !== 0}}
{{if "exterieur"|in:$keys}}
{{:assign dispo="%d-%d"|math:$eqpmt.stock:$eqpmt.exterieur}}
{{:assign exterieur=$eqpmt.exterieur}}
{{else}}
{{:assign dispo=$eqpmt.stock}}
{{:assign exterieur=0}}
{{/if}}
<tr>
<td>{{$eqpmt.designation}}</td>
<td>{{$eqpmt.stock}}</td>
<td>{{$exterieur}}</td>
<td>{{$dispo}}</td>
<td class="actions">
{{:linkbutton
label="Historique des mouvements"
href="%shistorique.html?key=%s"|args:$module.url:$eqpmt_key
shape="table"
target="_dialog"}}
{{:linkbutton
label="Modifier"
href="%smodifier_materiel.html?key=%s"|args:$module.url:$eqpmt_key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{/if}}
{{else}}
<p class="block alert">Il n'y a aucun matériel dans cette catégorie.</p>
{{/foreach}}
</tbody>
</table>
{{else}}
<p class="block alert">Il n'y a aucun matériel dans cette catégorie.</p>
{{/if}}
{{/foreach}}
<h2 class="ruler">Matériels dont l'association n'est pas propriétaire</h2>
{{* itérer sur les catégories *}}
{{#foreach from=$cumul_mvt key="cat_key" item="cat_elem"}}
{{if $print_cat_name}}
<h3>{{$cat_elem.name}}</h3>
{{/if}}
{{* vérifier s'il y a des matériels dans cette catégorie *}}
{{:assign present=false}}
{{if $cat_elem|keys|has:"eqpmt"}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{if $eqpmt.nonproprio !== null && $eqpmt.nonproprio !== 0}}
{{:assign present=true}}
{{:break}}
{{/if}}
{{/foreach}}
{{/if}}
{{if $present}}
<table class="list">
<thead>
<tr>
<th>Désignation</th>
<th>Quantité</th>
<th class="actions"></th>
</tr>
</thead>
<tbody>
{{* itérer sur les matériels de la catégorie *}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{:assign keys=$eqpmt|keys}}
{{if "nonproprio"|in:$keys && $eqpmt.nonproprio !== 0}}
{{:assign dispo="%d-%d"|math:$eqpmt.stock:$eqpmt.exterieur}}
<tr>
<td>{{$eqpmt.designation}}</td>
<td>{{$eqpmt.nonproprio}}</td>
<td class="actions">
{{:linkbutton
label="Historique des mouvements"
href="%shistorique.html?key=%s"|args:$module.url:$eqpmt_key
shape="table"
target="_dialog"}}
{{:linkbutton
label="Modifier"
href="%smodifier_materiel.html?key=%s"|args:$module.url:$eqpmt_key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{/if}}
{{else}}
<p class="block alert">Il n'y a aucun matériel dans cette catégorie.</p>
{{/foreach}}
</tbody>
</table>
{{else}}
<p class="block alert">Il n'y a aucun matériel dans cette catégorie.</p>
{{/if}}
{{/foreach}}
</section>
{{/if}}

73
modifier_materiel.html Normal file
View file

@ -0,0 +1,73 @@
{{:admin_header title="Modifier matériel" current="module_equipment"}}
{{:assign equipment_key=$_GET.key|trim}}
{{#load key=$_GET.key assign="equipment"}}
{{:assign default_category=$equipment.category}}
{{else}}
{{:error message="Pas de matériel avec la clé %s"|args:$equipment_key}}
{{/load}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* récupérer les infos de la catégorie *}}
{{#load type="category" key=$_POST.category assign="category"}}
{{/load}}
{{* vérifier la validité des changements demandés *}}
{{:assign chgt_ok=true}}
{{if $_POST.category != $default_category}}
{{* catégorie change : vérifier le nom *}}
{{#load key=$equipment_key}}
{{if $designation|trim|tolower != $_POST.designation|trim|tolower}}
{{* le nom change => vérifier l'existence d'un matériel du même nom *}}
{{#load type="equipment" where="lower($$.designation) = :name" :name=$_POST.designation|trim|tolower}}
{{:assign chgt_ok=false}}
{{/load}}
{{else}}
{* le nom ne change pas : ok *}}
{{/if}}
{{/load}}
{{else}}
{{* catégorie ne change pas => vérifier le nom*}}
{{#load type="equipment" where="lower($$.designation) = :name" :name=$_POST.designation|trim|tolower}}
{{:assign chgt_ok=false}}
{{/load}}
{{/if}}
{{if !$chgt_ok}}
{{:error message="Erreur : il existe déjà un matériel avec cette désignation"}}
{{/if}}
{{* enregistrer les modifications *}}
{{:save
key=$equipment_key
category=$category.key
designation=$_POST.designation|trim
}}
{{:redirect force="index.html?ok=1"}}
{{else}}
{{:form_errors}}
{{/form}}
{{* lister les catégories disponibles *}}
{{#load type="category" assign="category" order="$$.name"}}
{{:assign var="categories.%s"|args:$category.key value=$category.name}}
{{/load}}
<form method="post" action="">
<fieldset class="modification">
<legend>Modifier un matériel</legend>
<dl>
{{:input type="select" name="category" label="Catégorie" default=$default_category required=true options=$categories}}
{{:input type="text" name="designation" label="Désignation" default=$equipment.designation required=true}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>

View file

@ -1,95 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Paramètres :
- key : clé du matériel à modifier
- prop : =1 si matériel propriété de l'association, 0 sinon
*}}
{{:assign equipment_key=$_GET.key|trim}}
{{#load key=$_GET.key assign="equipment"}}
{{else}}
{{:error message="Pas de matériel avec la clé %s"|args:$equipment_key}}
{{/load}}
{{:assign default_category=$equipment.category}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{if $_POST.archive == 1}}
{{* vérifier les qunatités *}}
{{if $_GET.prop == 1 && $equipment.stock != 0}}
{{:error message="L'archivage n'est possible que si le stock est nul !"}}
{{elseif $_GET.prop == 0 && $equipment.notowned != 0}}
{{:error message="L'archivage n'est possible que s'il n'y a plus de matériel présent temporairement"}}
{{/if}}
{{* archiver le matériel *}}
{{:save
key=$equipment_key
status="archived"
}}
{{else}}
{{* récupérer les infos de la catégorie *}}
{{#load type="category" key=$_POST.category assign="category"}}{{/load}}
{{* vérifier la validité des changements demandés *}}
{{:assign chgt_ok=true}}
{{if $_POST.category != $default_category}}
{{* catégorie change : vérifier le nom *}}
{{#load key=$equipment_key}}
{{if $name|trim|tolower != $_POST.name|trim|tolower}}
{{* le nom change => vérifier l'existence d'un matériel du même nom *}}
{{#load type="equipment" where="$$.name = :name COLLATE U_NOCASE" :name=$_POST.name|trim limit=1}}
{{:assign chgt_ok=false}}
{{/load}}
{{else}}
{* le nom ne change pas : ok *}}
{{/if}}
{{/load}}
{{else}}
{{* catégorie ne change pas => vérifier le nom *}}
{{#load type="equipment" where="$$.name = :name COLLATE U_NOCASE" :name=$_POST.name|trim limit=1}}
{{:assign chgt_ok=false}}
{{/load}}
{{/if}}
{{if !$chgt_ok}}
{{:error message="Erreur : il existe déjà un matériel avec cette désignation"}}
{{/if}}
{{* enregistrer les modifications *}}
{{:save
key=$equipment_key
category=$category.key
name=$_POST.name|trim
}}
{{/if}}
{{:redirect force="index.html?ok=1&msg=modification&prop=%s"|args:$_GET.prop}}
{{/form}}
{{:admin_header title="Modifier matériel" current="module_equipment"}}
{{:form_errors}}
{{* lister les catégories disponibles *}}
{{#load type="category" assign="category" order="$$.name"}}
{{:assign var="categories.%s"|args:$category.key value=$category.name}}
{{/load}}
<form method="post" action="">
<fieldset class="modification">
<legend>Modifier un matériel</legend>
<dl>
{{:input type="select" name="category" label="Catégorie" default=$default_category required=true options=$categories}}
{{:input type="text" name="name" label="Désignation" default=$equipment.name required=true}}
{{:input type="checkbox" value=1 name="archive" label="Archiver" help="cocher pour archiver le matériel ; possible uniquement si la quantité en stock est nulle"}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>

View file

@ -1,7 +1,7 @@
name="Gestion des matériels"
description="Permet de gérer un inventaire de matériels, ainsi que de suivre les prêts (en test)."
description="Gestion des matériels: stock, entrées, sorties."
author="Jean-Christophe Engel"
author_url="https://gitea.zaclys.com/lesanges"
author_url="https://git.roflcopter.fr/lesanges"
home_button=false
menu=true
restrict_section="accounting"

View file

@ -0,0 +1,12 @@
{{* déterminer la quantité des matériels sortis temporairement *}}
{{#foreach from=$cumul_mvt key="cat_key" item="cat_elem"}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{:assign quantite=$eqpmt.exterieur}}
{{if $quantite != 0}}
{{:assign
var="temporaire.%s.%s"|args:$cat_elem.name:$eqpmt_key
value="%s (quantité : %d)"|args:$eqpmt.designation:$quantite
}}
{{/if}}
{{/foreach}}
{{/foreach}}

View file

@ -0,0 +1,85 @@
{{:admin_header title="Supprimer une entrée" current="module_equipment"}}
{{* récupérer les infos du mouvement à supprimer et du matériel associé *}}
{{#load key=$_GET.key assign="mvt_suppr"}}
{{else}}
{{:error message="Aucune entrée avec la clé « %s »"|args:$_GET.key}}
{{/load}}
{{:assign amount_suppr=$mvt_suppr.amount}}
{{:assign date_suppr=$mvt_suppr.date|date_short}}
{{:assign key_eqpmt_suppr=$mvt_suppr.equipment}}
{{#load key=$key_eqpmt_suppr assign="eqpmt_suppr"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$key_eqpmt_suppr}}
{{/load}}
{{#form on="delete"}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* vérifier s'il est possible de supprimer l'entrée *}}
{{:assign dispo=0}}
{{:assign nonprop=0}}
{{* parcourir la liste des mouvements du matériel *}}
{{#load
type="movement"
where="$$.equipment = :key" :key=$key_eqpmt_suppr
assign="mvt"
order="$$.date"}}
{{* déterminer le type de mouvement *}}
{{:assign var="mvt_nature" from="mvt.%s_nature"|args:$mvt.direction}}
{{:assign var="type_mvt" from="config.%s_nature.%s"|args:$mvt.direction:$mvt_nature}}
{{if $key != $_GET.key}}
{{* ce n'est pas le mouvement à supprimer : cumuler les entrées/sorties *}}
{{if $mvt.direction == 'input'}}
{{if $type_mvt == 'temporaire'}}
{{:assign nonprop="%d+%d"|math:$nonprop:$mvt.amount}}
{{else}}
{{:assign dispo="%d+%d"|math:$dispo:$mvt.amount}}
{{/if}}
{{elseif $mvt.direction == 'output'}}
{{if $type_mvt == 'retour'}}
{{:assign nonprop="%d-%d"|math:$nonprop:$mvt.amount}}
{{else}}
{{:assign dispo="%d-%d"|math:$dispo:$mvt.amount}}
{{/if}}
{{/if}}
{{* problème ? *}}
{{if $dispo < 0 || $nonprop < 0}}
{{:redirect force="./index.html?err=1&msg=suppression"}}
{{/if}}
{{/if}}
{{/load}}
{{* vérification réussie : supprimer l'entrée *}}
{{:delete key=$_GET.key}}
{{:assign var="msg" value="suppression"}}
{{* voir s'il reste des mouvements pour le matériel concerné par le mouvement supprimé *}}
{{#load type="movement" where="$$.equipment = :eqpmt_key" :eqpmt_key=$key_eqpmt_suppr}}
{{else}}
{{* supprimer le matériel *}}
{{:delete key=$key_eqpmt_suppr}}
{{:assign var="msg" value="%s - matériel"|args:$msg}}
{{/load}}
{{:redirect force="./index.html?ok=1&msg=%s"|args:$msg}}
{{/form}}
{{:delete_form
legend="Supprimer cette entrée ?"
warning="Supprimer l'entrée « %s %s (%d) en date du %s » ?"|args:$mvt_suppr.input_nature:$eqpmt_suppr.designation:$amount_suppr:$date_suppr
info="S'il ne reste aucun mouvement pour ce matériel, le matériel sera supprimé"
}}
{{:form_errors}}
{{:admin_footer}}

View file

@ -0,0 +1,103 @@
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="../../_nav.html" current="entrees"}}
{{if $_GET.ok}}
{{if $_GET.msg|match:"suppression"}}
{{:assign msg="Entrée supprimée"}}
{{if $_GET.msg|match:"matériel"}}
{{:assign var="msg" value="%s - Matériel supprimé"|args:$msg}}
{{/if}}
{{elseif $_GET.msg == "entrée"}}
{{:assign msg="Entrée enregistrée"}}
{{elseif $_GET.msg == "modification"}}
{{:assign msg="Entrée modifiée"}}
{{/if}}
<p class="block confirm">{{$msg}}</p>
{{elseif $_GET.err}}
{{if $_GET.msg == "suppression"}}
<p class="block error">Impossible de supprimer l'entrée</p>
{{/if}}
{{/if}}
{{* vérifier s'il existe des catégories *}}
{{#load type="category"}}
{{:assign categories_exist=true}}
{{else}}
<p class="block alert">Il n'y a aucune catégorie : vous devez en ajouter.</p>
{{/load}}
{{if $categories_exist}}
{{#load type="equipment"}}
{{:assign disabled=false}}
{{else}}
{{:assign disabled=true}}
{{/load}}
{{* vérifier s'il y a des sorties temporaires *}}
{{if ! $disabled}}
{{:include file="../../_calcul_dispo.html" keep="cumul_mvt"}}
{{:include file="_temporaire.html" keep="temporaire"}}
{{/if}}
<form method="post" action="">
<fieldset class="entree">
<legend>Ajouter une entrée</legend>
<dl>
{{if ! $disabled}}
{{:linkbutton label="Matériel répertorié" shape="plus" href="repertorie.html" target="_dialog"}}
{{/if}}
{{:linkbutton label="Matériel non répertorié" shape="plus" href="non_repertorie.html" target="_dialog"}}
{{if ! $disabled && $temporaire != null}}
{{:linkbutton label="Retour de sortie temporaire" shape="plus" href="retour.html" target="_dialog"}}
{{/if}}
</dl>
</fieldset>
</form>
{{* lister les entrées *}}
<section class="liste_entrees">
<h2>Liste des entrées</h2>
{{#list
select="
$$.date AS 'Date' ;
$$.input_nature AS 'Type' ;
$$.amount AS 'Nombre' ;
(SELECT $$.designation
FROM @TABLE AS b
WHERE b.key = @TABLE.$$.equipment) AS 'Matériel' ;
$$.comment AS 'Remarques'"
type="movement"
direction="input"
order=1}}
{{:assign var='mvt_key' value=$key}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$input_nature}}</td>
<td>{{$amount}}</td>
<td>{{$col4}}</td>
<td>{{$comment}}</td>
<td class="actions">
{{:linkbutton
label="Supprimer"
href="delete_entree.html?key=%s"|args:$mvt_key
shape="delete"
target="_dialog"}}
{{:linkbutton
label="Modifier"
href="../modifier_mouvement.html?key=%s&direction=input"|args:$mvt_key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{else}}
<p class="block alert">Il n'y a aucune entrée.</p>
{{/list}}
</section>
{{/if}}
{{:admin_footer}}

View file

@ -0,0 +1,99 @@
{{:admin_header title="Entrée de matériel" current="module_equipment"}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../../_nav.html" current="entrees"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{if $type != 'retour'}}
{{:assign var='input_labels.' value="%s"|args:$label}}
{{/if}}
{{/foreach}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* récupérer les infos de la catégorie *}}
{{#load type="category" key=$_POST.category assign="category"}}
{{/load}}
{{* vérifier l'existence d'un matériel du même nom *}}
{{#load type="equipment" where="lower($$.designation) = :name" :name=$_POST.designation|trim|tolower}}
{{* utiliser la clé du matériel trouvé *}}
{{:assign equipment_key=$key}}
{{else}}
{{* nouveau matériel => nouvelle clé *}}
{{:assign equipment_key=""|uuid}}
{{* enregistrer un nouveau matériel *}}
{{:save
key=$equipment_key
validate_schema="../../equipment.schema.json"
type="equipment"
category=$category.key
designation=$_POST.designation|trim
}}
{{/load}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:assign var="operation" from="input_labels.%d"|args:$_POST.type_operation}}
{{:save
key=$mvt_key
validate_schema="../movement.schema.json"
type="movement"
direction="input"
input_nature=$operation
amount=$_POST.quantite|intval
equipment=$equipment_key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
}}
{{:redirect force="index.html?ok=1&msg=entrée"}}
{{else}}
{{:form_errors}}
{{/form}}
{{* lister les catégories disponibles *}}
{{#load type="category" assign="category" order="$$.name"}}
{{:assign var="categories.%s"|args:$category.key value=$category.name}}
{{/load}}
{{if $categories != null}}
{{* formulaire d'ajout de matériel *}}
<form method="post" action="">
<fieldset class="entree">
<legend>Ajouter une entrée d'un matériel non répertorié</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$input_labels}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="quantite" label="Quantité" required=true default=1}}
</dl>
</fieldset>
<fieldset>
<legend>Matériel</legend>
<dl>
{{:input type="select" name="category" label="Catégorie" required=true options=$categories}}
{{:input type="text" name="designation" label="Désignation" required=true}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40", rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucune catégorie, il faut en créer au moins une</p>
{{/if}}
{{:admin_footer}}

View file

@ -0,0 +1,83 @@
{{:admin_header title="Entrée de matériel" current="module_equipment"}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../../_nav.html" current="entrees"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{if $type != 'retour'}}
{{:assign var='input_labels.' value="%s"|args:$label}}
{{/if}}
{{/foreach}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* récupérer les infos du matériel *}}
{{#load type="equipment" key=$_POST.equipment assign="equipment"}}
{{/load}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:assign var="operation" from="input_labels.%d|args:$_POST.type_operation}}
{{:save
key=$mvt_key
validate_schema="../movement.schema.json"
type="movement"
direction="input"
input_nature=$operation
amount=$_POST.quantite|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
}}
{{:redirect force="index.html?ok=1&msg=entrée"}}
{{else}}
{{:form_errors}}
{{/form}}
{{* lister les catégories et matériels associés *}}
{{#load type="category" assign="category" order="$$.name"}}
{{:assign nom_cat=$category.name}}
{{#load type="equipment" where="$$.category = :key" :key=$category.key assign="equipment"}}
{{:assign var="equipments.%s.%s"|args:$nom_cat:$equipment.key value=$equipment.designation}}
{{/load}}
{{/load}}
{{* Vérifier s'il y a au moins un matériel enregistré *}}
{{if $equipments != null}}
{{* formulaire d'entrée de matériel *}}
<form method="post" action="">
<fieldset class="entree">
<legend>Ajouter une entrée d'un matériel répertorié</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$input_labels}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="quantite" label="Quantité" required=true default=1}}
</dl>
</fieldset>
<fieldset>
<legend>Matériel</legend>
<dl>
{{:input type="select_groups" name="equipment" label="Matériel" required=true options=$equipments}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40" rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucun matériel déjà répertorié</p>
{{/if}}
{{:admin_footer}}

View file

@ -0,0 +1,99 @@
{{:admin_header title="Entrée de matériel" current="module_equipment"}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../../_nav.html" current="entrees"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{if $type == 'retour'}}
{{:assign var='input_labels.' value="%s"|args:$label}}
{{/if}}
{{/foreach}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* récupérer les infos du matériel *}}
{{#load type="equipment" key=$_POST.equipment assign="equipment"}}
{{:assign designation=$equipment.designation}}
{{:assign var="categories." value=$equipment.category}}
{{/load}}
{{* Extraire et compiler les infos de la base *}}
{{:include
file="../../_calcul_dispo.html"
keep="cumul_mvt"
date=$_POST.date|parse_date
}}
{{* déterminer la quantité sortie temporairement de ce matriel à la date donnée *}}
{{:assign var=sorti from="cumul_mvt.%s.eqpmt.%s.exterieur"|args:$equipment.category:$_POST.equipment}}
{{if $_POST.quantite|intval > $sorti}}
{{:error message="Erreur : la quantité indiquée (%s) est supérieure à celle sortie (%d) à la date du %s"|args:$_POST.quantite:$sorti:$_POST.date}}
{{/if}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:assign var="operation" from="input_labels.%d|args:$_POST.type_operation}}
{{:save
key=$mvt_key
validate_schema="../movement.schema.json"
type="movement"
direction="input"
input_nature=$operation
amount=$_POST.quantite|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
}}
{{:redirect force="index.html?ok=1&msg=entrée"}}
{{else}}
{{:form_errors}}
{{/form}}
{{* Extraire et compiler les infos de la base *}}
{{:include file="../../_calcul_dispo.html" keep="cumul_mvt"}}
{{if $cumul_mvt !== null}}
{{* déterminer la quantité des matériels sortis temporairement *}}
{{:include file="_temporaire.html" keep="temporaire"}}
{{if $temporaire != null}}
{{* formulaire d'entrée de matériel *}}
<form method="post" action="">
<fieldset class="entree">
<legend>Ajouter une entrée pour un retour de matériel</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$input_labels}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="quantite" label="Quantité" required=true default=1}}
</dl>
</fieldset>
<fieldset>
<legend>Matériel</legend>
<dl>
{{:input type="select_groups" name="equipment" label="Matériel" required=true options=$temporaire}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40", rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucun matériel sorti temporairement</p>
{{/if}}
{{else}}
<p class="block error">Il n'y a aucun matériel</p>
{{/if}}
{{:admin_footer}}

View file

@ -0,0 +1,185 @@
{{:admin_header title="Modifier une %s"|args:$_GET.direction current="module_equipment"}}
{{:assign direction=$_GET.direction}}
{{:assign key_mvt=$_GET.key}}
{{* récupérer les infos du mouvement à modifier *}}
{{#load key=$key_mvt assign="mvt_modif"}}
{{else}}
{{:error message="Aucune %s avec la clé %s"|args:$_GET.direction:$key_mvt}}
{{/load}}
{{if $direction == "input"}}
{{:assign input_init=$mvt_modif.input_nature}}
{{:assign url="entrees/index.html"}}
{{else}}
{{:assign output_init=$mvt_modif.output_nature}}
{{:assign url="sorties/index.html"}}
{{/if}}
{{:assign amount_init=$mvt_modif.amount}}
{{:assign date_init=$mvt_modif.date|date_short}}
{{:assign key_eqpmt_init=$mvt_modif.equipment}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{if $direction == "input"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{:assign var="input_labels.%s"|args:$label value="%s"|args:$label}}
{{if $label == $mvt_modif.input_nature}}
{{:assign type_defaut=$label}}
{{/if}}
{{/foreach}}
{{else}}
{{* types de sorties *}}
{{#foreach from=$config.output_nature key="label" item="type"}}
{{:assign var="output_labels.%s"|args:$label value="%s"|args:$label}}
{{if $label == $mvt_modif.output_nature}}
{{:assign type_defaut=$label}}
{{/if}}
{{/foreach}}
{{/if}}
{{* récupérer les infos du matériel associé *}}
{{#load key=$key_eqpmt_init assign="eqpmt_init"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$key_eqpmt_init}}
{{/load}}
{{*
-------------------- Traiter la saisie --------------------
*}}
{{#form on="change"}}
{{* préparer le mouvement modifié *}}
{{if $direction == "input"}}
{{:assign var="mvt_modif.input_nature" from="input_labels.%s"|args:$_POST.type_operation}}
{{else}}
{{:assign var="mvt_modif.output_nature" from="output_labels.%s"|args:$_POST.type_operation}}
{{/if}}
{{:assign var="mvt_modif.amount" value=$_POST.amount}}
{{:assign var="mvt_modif.equipment" value=$_POST.equipment}}
{{:assign var="mvt_modif.date" value=$_POST.date|parse_date}}
{{:assign var="mvt_modif.comment" value=$_POST.comment}}
{{*
lister les mouvements et remplacer le mouvement sélectionné par sa version modifiée
en l'insérant à sa place par date croissante
*}}
{{:assign insere=false}}
{{#load
where="
$$.type = 'movement'
AND
($$.equipment = :old_eqpmt_key OR $$.equipment = :new_eqpmt_key)"
:old_eqpmt_key=$key_eqpmt_init
:new_eqpmt_key=$_POST.equipment
order="$$.date"
assign="movement"
}}
{{if $key != $key_mvt}}
{{if $date > $mvt_modif.date && ! $insere}}
{{:assign var=movements_modif." from=mvt_modif}}
{{:assign insere=true}}
{{/if}}
{{:assign var=movements_modif." from=movement}}
{{/if}}
{{/load}}
{{if ! $insere}}
{{:assign var=movements_modif." from=mvt_modif}}
{{/if}}
{{* Vérifier la cohérence des opérations de l'ancien matériel *}}
{{:include
file="./valider_modification.html"
keep="erreur"
movements=$movements_modif
eqpmt_key=$key_eqpmt_init
}}
{{* Si le matériel a changé, vérifier la cohérence des opérations du nouveau matériel *}}
{{if ! $erreur && $key_eqpmt_init != $_POST.equipment}}
{{:include
file="./valider_modification.html"
keep="erreur"
movements=$movements_modif
eqpmt_key=$_POST.equipment
}}
{{/if}}
{{#load key=$mvt_modif.equipment assign="eqpmt"}}{{/load}}
{{if $erreur}}
<p class="block error">
Modification demandée impossible :
{{if $direction == "input"}}
« {{$input_init}} de {{$eqpmt_init.designation}} (qté : {{$amount_init}}) en date du {{$date_init}} » vers
« {{$mvt_modif.input_nature}} de {{$eqpmt.designation}} (qté : {{$mvt_modif.amount}}) à la date du {{$mvt_modif.date|date_short}} »
{{else}}
« {{$output_init}} de {{$eqpmt_init.designation}} (qté : {{$amount_init}}) en date du {{$date_init}} » vers
« {{$mvt_modif.output_nature}} de {{$eqpmt.designation}} (qté : {{$mvt_modif.amount}}) à la date du {{$mvt_modif.date|date_short}} »
{{/if}}
</p>
{{else}}
{{* vérification réussie : modifier le mouvement *}}
{{:save
key=$key_mvt
validate_schema="./movement.schema.json"
type="movement"
direction=$direction
input_nature=$mvt_modif.input_nature
output_nature=$mvt_modif.output_nature
amount=$mvt_modif.amount|intval
equipment=$mvt_modif.equipment
date=$mvt_modif.date
comment=$mvt_modif.comment
}}
{{:redirect force="%s?ok=1&msg=modification"|args:$url}}
{{/if}}
{{/form}}
{{*
-------------------- Préparer la saisie --------------------
*}}
{{* lister les catégories et matériels associés *}}
{{#load type="category" assign="category" order="$$.name"}}
{{:assign nom_cat=$category.name}}
{{#load type="equipment" where="$$.category = :key" :key=$category.key assign="equipment"}}
{{:assign var="equipments.%s.%s"|args:$nom_cat:$equipment.key value=$equipment.designation}}
{{/load}}
{{/load}}
{{* formulaire de modification du mouvement *}}
<form method="post" action="">
<fieldset class="entree">
{{if $direction == "input"}}
<legend>Modifier l'entrée « {{$input_init}} {{$eqpmt_init.designation}} ({{$amount_init}}) en date du {{$date_init}} »</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$input_labels default=$type_defaut}}
{{else}}
<legend>Modifier la sortie « {{$output_init}} {{$eqpmt_init.designation}} ({{$amount_init}}) en date du {{$date_init}} »</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$output_labels default=$type_defaut}}
{{/if}}
{{:input type="date" name="date" label="Date" required=true default=$mvt_modif.date}}
{{:input type="number" name="amount" label="Quantité" required=true default=$mvt_modif.amount}}
</dl>
</fieldset>
<fieldset>
<legend>Matériel</legend>
<dl>
{{:input type="select_groups" name="equipment" label="Matériel" required=true options=$equipments default=$key_eqpmt_init}}
{{:input type="textarea" name="comment" label="Remarques" cols="40", rows="3" required=false default=$mvt_modif.comment}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="change" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{:admin_footer}}

View file

@ -11,9 +11,13 @@
"type": "string",
"enum": ["input", "output"]
},
"operation": {
"description": "clé de l'opération",
"type": "string"
"input_nature": {
"description": "Nature de l'entrée",
"type": ["null", "string"]
},
"output_nature": {
"description": "Nature de la sortie",
"type": ["null", "string"]
},
"amount": {
"description": "Quantité ajoutée ou retirée",
@ -32,15 +36,7 @@
"comment": {
"description": "Commentaire additionnel",
"type": ["null", "string"]
},
"user": {
"description": "identifiant membre dépositaire",
"type": ["integer", "null"]
},
"storage": {
"description": "clé du lieu de stockage",
"type": ["string", "null"]
}
},
"required": ["type", "direction", "operation", "amount", "equipment", "date", "comment"]
"required": ["type", "direction", "amount", "equipment", "date", "comment"]
}

View file

@ -0,0 +1,12 @@
{{* calculer les quantité de matériels dont l'asso n'est pas propriétaire *}}
{{#foreach from=$cumul_mvt key="cat_key" item="cat_elem"}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{:assign quantite="%d-%d"|math:$eqpmt.nonproprio:$eqpmt.retour}}
{{if $quantite != 0}}
{{:assign
var="temporaire.%s.%s"|args:$cat_elem.name:$eqpmt_key
value="%s (quantité : %d)"|args:$eqpmt.designation:$quantite
}}
{{/if}}
{{/foreach}}
{{/foreach}}

View file

@ -0,0 +1,87 @@
{{:admin_header title="Supprimer une sortie" current="module_equipment"}}
{{* récupérer les infos du mouvement à supprimer et du matériel associé *}}
{{#load key=$_GET.key assign="mvt_suppr"}}
{{else}}
{{:error message="Aucune sortie avec la clé « %s »"|args:$_GET.key}}
{{/load}}
{{:assign amount_suppr=$mvt_suppr.amount}}
{{:assign date_suppr=$mvt_suppr.date|date_short}}
{{:assign key_eqpmt_suppr=$mvt_suppr.equipment}}
{{#load key=$key_eqpmt_suppr assign="eqpmt_suppr"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$key_eqpmt_suppr}}
{{/load}}
{{#form on="delete"}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* déterminer s'il s'agit d'une sortie temporaire *}}
{{:assign temporaire=false}}
{{:assign var="output_nature" from="config.output_nature.%s"|args:$mvt_suppr.output_nature}}
{{if $output_nature == 'temporaire'}}
{{:assign temporaire=true}}
{{/if}}
{{* dans le cas d'une sortie temporaire, vérifier s'il est possible de la supprimer *}}
{{if $temporaire}}
{{:assign exterieur=0}}
{{#load
type="movement"
where="$$.equipment = :key" :key=$key_eqpmt_suppr
assign="mvt"
order="$$.date"}}
{{* déterminer le type de mouvement *}}
{{:assign var="mvt_nature" from="mvt.%s_nature"|args:$mvt.direction}}
{{:assign var="type_mvt" from="config.%s_nature.%s"|args:$mvt.direction:$mvt_nature}}
{{if $key != $_GET.key}}
{{* ce n'est pas le mouvement à supprimer : cumuler les entrées/sorties *}}
{{if $mvt.direction == 'input'}}
{{if $type_mvt == 'retour'}}
{{:assign exterieur="%d-%d"|math:$exterieur:$mvt.amount}}
{{/if}}
{{elseif $mvt.direction == 'output'}}
{{if $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$mvt.amount}}
{{/if}}
{{/if}}
{{* problème ? *}}
{{if $exterieur < 0}}
{{:redirect force="./index.html?err=1&msg=suppression"}}
{{/if}}
{{/if}}
{{/load}}
{{/if}}
{{* vérification réussie : supprimer la sortie *}}
{{:delete key=$_GET.key}}
{{:assign var="msg" value="suppression"}}
{{* voir s'il reste des mouvements pour le matériel concerné par le mouvement supprimé *}}
{{#load type="movement" where="$$.equipment = :eqpmt_key" :eqpmt_key=$key_eqpmt_suppr}}
{{else}}
{{* supprimer le matériel *}}
{{:delete key=$key_eqpmt_suppr}}
{{:assign var="msg" value="%s - matériel"|args:$msg}}
{{/load}}
{{:redirect force="./index.html?ok=1&msg=%s"|args:$msg}}
{{/form}}
{{:delete_form
legend="Supprimer cette sortie ?"
warning="Supprimer la sortie « %s %s (%d) en date du %s » ?"|args:$mvt_suppr.output_nature:$eqpmt_suppr.designation:$amount_suppr:$date_suppr
info="S'il ne reste aucun mouvement pour ce matériel, le matériel sera supprimé"
}}
{{:form_errors}}
{{:admin_footer}}

View file

@ -0,0 +1,110 @@
{{:admin_header title="Sortie de matériel" current="module_equipment"}}
{{if ! $dialog}}
{{* barre de navigation *}}
{{:include file="../../_nav.html" current="sorties"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* types de sorties *}}
{{#foreach from=$config.output_nature key="label" item="type"}}
{{if $type == 'retour'}}
{{:assign var='output_labels.' value="%s"|args:$label}}
{{/if}}
{{/foreach}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* récupérer les infos du matériel *}}
{{#load type="equipment" key=$_POST.equipment assign="equipment"}}
{{:assign designation=$equipment.designation}}
{{:assign var="category_keys." value=$equipment.category}}
{{/load}}
{{* Extraire et compiler les infos de la base *}}
{{:include
file="../../_calcul_dispo.html"
keep="cumul_mvt"
date=$_POST.date|parse_date
}}
{{* déterminer la quantité présente de ce matériel à la date donnée *}}
{{:assign var=present from="cumul_mvt.%s.eqpmt.%s.nonproprio"|args:$equipment.category:$_POST.equipment}}
{{if $_POST.quantite|intval > $present}}
{{:error message="Erreur : la quantité indiquée (%s) est supérieure à celle présente (%d) à la date du %s"|args:$_POST.quantite:$present:$_POST.date}}
{{/if}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:assign var="operation" from="output_labels.%d|args:$_POST.type_operation}}
{{:save
key=$mvt_key
validate_schema="../movement.schema.json"
type="movement"
direction="output"
output_nature=$operation
amount=$_POST.quantite|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
}}
{{:redirect force="index.html?ok=1&msg=sortie"}}
{{else}}
{{:form_errors}}
{{/form}}
{{* Extraire et compiler les infos de la base *}}
{{:include file="../../_calcul_dispo.html" keep="cumul_mvt"}}
{{if $cumul_mvt !== null}}
{{* calculer les quantité de matériels dont l'asso n'est pas propriétaire *}}
{{:include file="_temporaire.html" keep="temporaire"}}
{{if $temporaire != null}}
{{* formulaire de sortie de matériel *}}
<form method="post" action="">
<fieldset class="sortie">
<legend>Ajouter une sortie d'un matériel disponible en stock</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$output_labels}}
{{:input type="date" name="date" label="Date de sortie" required=true default=$now|date_short}}
{{:input type="number" name="quantite" label="Quantité" required=true default=1 min=1}}
</dl>
</fieldset>
<fieldset>
<legend>Matériel</legend>
<p><span class="alert">La quantité disponible est celle à la date du jour</span></p>
<dl>
{{:input type="select_groups" name="equipment" label="Matériel" required=true options=$temporaire onchange="fixerValeurMax('f_equipment', 'f_quantite')"}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40" rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucun matériel présent temporairement</p>
{{/if}}
{{else}}
<p class="block error">Il n'y a aucun matériel en stock</p>
{{/if}}
<script type="text/javascript">
// fixer la valeur maximale du champ de saisie de la quantité
function fixerValeurMax(idSelect, idNumber) {
let option = document.getElementById(idSelect).selectedOptions[0];
let max = parseInt(option.label.match(/\(quantité : ([0-9]+)\)/)[1]);
let val = parseInt(document.getElementById(idNumber).value);
document.getElementById(idNumber).setAttribute("max", max);
if (val > max) {
document.getElementById(idNumber).value = max;
}
}
</script>
{{:admin_footer}}

View file

@ -0,0 +1,101 @@
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="../../_nav.html" current="sorties"}}
{{if $_GET.ok}}
{{if $_GET.msg|match:"suppression"}}
{{:assign msg="Sortie supprimée"}}
{{if $_GET.msg|match:"matériel"}}
{{:assign var="msg" value="%s - Matériel supprimé"|args:$msg}}
{{/if}}
{{elseif $_GET.msg == "sortie"}}
{{:assign msg="Sortie enregistrée"}}
{{elseif $_GET.msg == "modification"}}
{{:assign msg="Sortie modifiée"}}
{{/if}}
<p class="block confirm">{{$msg}}</p>
{{elseif $_GET.err}}
{{if $_GET.msg == "suppression"}}
<p class="block error">Impossible de supprimer la sortie</p>
{{/if}}
{{/if}}
{{* vérifier s'il existe des catégories *}}
{{#load type="category"}}
{{:assign categories_exist=true}}
{{else}}
<p class="block alert">Il n'y a aucune catégorie : vous devez en ajouter.</p>
{{/load}}
{{if $categories_exist}}
{{* vérifier s'il y a eu des entrées de matériel *}}
{{#load type="equipment"}}
{{:assign disabled=false}}
{{else}}
{{:assign disabled=true}}
{{/load}}
{{* vérifier s'il y a des entrées temporaires *}}
{{if ! $disabled}}
{{:include file="../../_calcul_dispo.html" keep="cumul_mvt"}}
{{:include file="_temporaire.html" keep="temporaire"}}
<form method="post" action="">
<fieldset class="sortie">
<legend>Ajouter une sortie </legend>
<dl>
{{:linkbutton label="Matériel en stock disponible" shape="plus" href="stock_disponible.html" target="_dialog"}}
{{if $temporaire != null}}
{{:linkbutton label="Matériel emprunté" shape="plus" href="emprunte.html" target="_dialog"}}
{{/if}}
</dl>
</fieldset>
</form>
{{/if}}
{{* lister les sorties *}}
<section class="liste_sorties">
<h2>Liste des sorties</h2>
{{#list
select="
$$.date AS 'Date' ;
$$.output_nature AS 'Type' ;
$$.amount AS 'Nombre' ;
(SELECT $$.designation
FROM @TABLE AS b
WHERE b.key = @TABLE.$$.equipment) AS 'Matériel' ;
$$.comment AS 'Remarques'"
type="movement"
direction="output"
order=1}}
{{:assign var='mvt_key' value=$key}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$output_nature}}</td>
<td>{{$amount}}</td>
<td>{{$col4}}</td>
<td>{{$comment}}</td>
<td class="actions">
{{:linkbutton
label="Supprimer"
href="delete_sortie.html?key=%s"|args:$mvt_key
shape="delete"
target="_dialog"}}
{{:linkbutton
label="Modifier"
href="../modifier_mouvement.html?key=%s&direction=output"|args:$mvt_key
shape="edit"
target="_dialog"}}
</td>
</tr>
{{else}}
<p class="block alert">Il n'y a aucune sortie.</p>
{{/list}}
</section>
{{/if}}
{{:admin_footer}}

View file

@ -0,0 +1,121 @@
{{:admin_header title="Sortie de matériel" current="module_equipment"}}
{{if ! $dialog}}
{{* barre de navigation *}}
{{:include file="../../_nav.html" current="sorties"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../../_get_config.html" keep="config"}}
{{* types de sorties *}}
{{#foreach from=$config.output_nature key="label" item="type"}}
{{if $type != 'retour'}}
{{:assign var='output_labels.' value="%s"|args:$label}}
{{/if}}
{{/foreach}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* récupérer les infos du matériel *}}
{{#load type="equipment" key=$_POST.equipment assign="equipment"}}
{{:assign designation=$equipment.designation}}
{{:assign var="category_keys." value=$equipment.category}}
{{/load}}
{{* Extraire et compiler les infos de la base *}}
{{:include
file="../../_calcul_dispo.html"
keep="cumul_mvt"
date=$_POST.date|parse_date
}}
{{* déterminer la quantité disponible de ce matériel à la date donnée *}}
{{:assign var=stock from="cumul_mvt.%s.eqpmt.%s.stock"|args:$equipment.category:$_POST.equipment}}
{{:assign var=exterieur from="cumul_mvt.%s.eqpmt.%s.exterieur"|args:$equipment.category:$_POST.equipment}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{if $_POST.quantite|intval > $dispo}}
{{:error message="Erreur : la quantité indiquée (%s) est supérieure à celle disponible (%d) à la date du %s"|args:$_POST.quantite:$dispo:$_POST.date}}
{{/if}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:assign var="operation" from="output_labels.%d|args:$_POST.type_operation}}
{{:save
key=$mvt_key
validate_schema="../movement.schema.json"
type="movement"
direction="output"
output_nature=$operation
amount=$_POST.quantite|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
}}
{{:redirect force="index.html?ok=1&msg=sortie"}}
{{else}}
{{:form_errors}}
{{/form}}
{{* Extraire et compiler les infos de la base *}}
{{:include file="../../_calcul_dispo.html" keep="cumul_mvt"}}
{{if $cumul_mvt !== null}}
{{* calculer les disponibilités *}}
{{#foreach from=$cumul_mvt key="cat_key" item="cat_elem"}}
{{#foreach from=$cat_elem.eqpmt key="eqpmt_key" item="eqpmt"}}
{{:assign dispo="%d-%d"|math:$eqpmt.stock:$eqpmt.exterieur}}
{{if $dispo != 0}}
{{:assign
var="disponibilites.%s.%s"|args:$cat_elem.name:$eqpmt_key
value="%s (dispo : %d)"|args:$eqpmt.designation:$dispo
}}
{{/if}}
{{/foreach}}
{{/foreach}}
{{if $disponibilites === null}}
{{:error message="Le matériel choisi (%s) n'est pas présent à la date du %s"|args:$designation:$_POST.date}}
{{/if}}
{{* formulaire de sortie de matériel *}}
<form method="post" action="">
<fieldset class="sortie">
<legend>Ajouter une sortie d'un matériel disponible en stock</legend>
<dl>
{{:input type="select" name="type_operation" label="Type" required=true options=$output_labels}}
{{:input type="date" name="date" label="Date de sortie" required=true default=$now|date_short}}
{{:input type="number" name="quantite" label="Quantité" required=true default=1 min=1}}
</dl>
</fieldset>
<fieldset>
<legend>Matériel</legend>
<p><span class="alert">La quantité disponible est celle à la date du jour</span></p>
<dl>
{{:input type="select_groups" name="equipment" label="Matériel" required=true options=$disponibilites onchange="fixerValeurMax('f_equipment', 'f_quantite')"}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40" rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucun matériel en stock</p>
{{/if}}
<script type="text/javascript">
// fixer la valeur maximale du champ de saisie de la quantité
function fixerValeurMax(idSelect, idNumber) {
let option = document.getElementById(idSelect).selectedOptions[0];
let max = parseInt(option.label.match(/\(dispo : ([0-9]+)\)/)[1]);
let val = parseInt(document.getElementById(idNumber).value);
document.getElementById(idNumber).setAttribute("max", max);
if (val > max) {
document.getElementById(idNumber).value = max;
}
}
</script>
{{:admin_footer}}

View file

@ -0,0 +1,44 @@
{{*
Vérifier la cohérence des E/S d'un matériel
- paramètres :
- movements : liste de mouvements
- eqpmt_key : clé du matériel à vérifier
*}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{:assign erreur = false}}
{{:assign stock=0}}
{{:assign exterieur=0}}
{{:assign nonprop=0}}
{{#foreach from=$movements item="mvt"}}
{{* déterminer le type de mouvement *}}
{{:assign var="mvt_nature" from="mvt.%s_nature"|args:$mvt.direction}}
{{:assign var="type_mvt" from="config.%s_nature.%s"|args:$mvt.direction:$mvt_nature}}
{{if $mvt.equipment == $eqpmt_key}}
{{if $mvt.direction == 'input'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d+%d"|math:$stock:$mvt.amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign exterieur="%d-%d"|math:$exterieur:$mvt.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign nonprop="%d+%d"|math:$nonprop:$mvt.amount}}
{{/if}}
{{elseif $mvt.direction == 'output'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$mvt.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$mvt.amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign nonprop="%d-%d"|math:$nonprop:$mvt.amount}}
{{/if}}
{{/if}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{if $dispo < 0 || $stock < 0 || $exterieur < 0 || $nonprop < 0}}
{{:assign erreur=true}}
{{:break}}
{{/if}}
{{/if}}
{{/foreach}}

View file

@ -1,44 +0,0 @@
{{* -*- brindille -*-
Vérifier la cohérence des E/S d'un matériel
- paramètres :
- movements : liste de mouvements d'un matériel
*}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{:assign erreur=false}}
{{:assign stock=0}}
{{:assign exterieur=0}}
{{:assign nonprop=0}}
{{#foreach from=$movements item="mvt"}}
{{* déterminer le type de mouvement *}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt.direction:$mvt.operation}}
{{if $mvt.direction == 'input'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d+%d"|math:$stock:$mvt.amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign exterieur="%d-%d"|math:$exterieur:$mvt.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign nonprop="%d+%d"|math:$nonprop:$mvt.amount}}
{{/if}}
{{elseif $mvt.direction == 'output'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$mvt.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$mvt.amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign nonprop="%d-%d"|math:$nonprop:$mvt.amount}}
{{/if}}
{{/if}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{if $dispo < 0 || $stock < 0 || $exterieur < 0 || $nonprop < 0}}
{{:assign erreur=true}}
{{:assign var="pb.mvt" value=$mvt}}
{{:break}}
{{/if}}
{{/foreach}}

View file

@ -1,155 +0,0 @@
{{* -*- brindille -*- *}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="entrees"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key=key}}
{{if $type != 'retour'}}
{{:assign var="input_labels.%s"|args:$key value=$label}}
{{/if}}
{{/foreach}}
{{* lister les catégories et les matériels disponibles *}}
{{#load type="category" assign="category" order="$$.name"}}
{{*:assign nom_cat=$category.name*}}
{{:assign var="categories.%s"|args:$category.key value=$category.name}}
{{/load}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* vérifier la quantité saisie *}}
{{if $_POST.amount <= 0}}
{{:error message="La quantité (%s) doit être strictement positive !!"|args:$_POST.amount}}
{{/if}}
{{* interdire date dans le futur *}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{* vérifier l'existence d'un matériel de même nom *}}
{{#load type="equipment" where="$$.name = :name COLLATE U_NOCASE" :name=$_POST.name|trim limit=1 assign="equipment"}}
{{:assign present=true}}
{{/load}}
{{:assign var=nom_cat from="categories.%s"|args:$equipment.category}}
{{:assign var=post_cat from="categories.%s"|args:$_POST.category}}
{{:assign post_mat=$_POST.name|trim}}
{{:assign var="type_mvt" from="config.input_nature.%s.type"|args:$_POST.operation}}
{{if $present}}
{{* voir si le matériel existe dans une autre catégorie *}}
{{if $nom_cat != $post_cat}}
{{:error message="Le matériel « %s » est déjà présent dans la catégorie « %s » ..."|args:$post_mat:$nom_cat}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{if $type_mvt == 'définitif'}}
{{:assign var="equipment.stock" value="%d+%d"|math:$equipment.stock:$_POST.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="equipment.notowned" value="%d+%d"|math:$equipment.notowned:$_POST.amount|intval}}
{{/if}}
{{:assign equipment_key=$equipment.key}}
{{:save
key=$equipment_key
validate_schema="../equipment.schema.json"
type="equipment"
category=$_POST.category
name=$post_mat
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{else}}
{{* enregistrer un nouveau matériel *}}
{{:assign equipment_key=""|uuid}}
{{if $type_mvt == 'définitif'}}
{{:assign stock=$_POST.amount|intval}}
{{:assign notowned=null}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign notowned=$_POST.amount|intval}}
{{:assign stock=null}}
{{/if}}
{{:save
key=$equipment_key
validate_schema="../equipment.schema.json"
type="equipment"
category=$_POST.category
name=$post_mat
status="available"
stock=$stock
out=0
notowned=$notowned
}}
{{/if}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:assign var="operation" from="input_labels.%d"|args:$_POST.type_operation}}
{{:save
key=$mvt_key
validate_schema="./movement.schema.json"
type="movement"
direction="input"
operation=$_POST.operation
amount=$_POST.amount|intval
equipment=$equipment_key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
storage=$_POST.storage
}}
{{if $type_mvt == "temporaire"}}
{{:assign prop=0}}
{{else}}
{{:assign prop=1}}
{{/if}}
{{:redirect force="../index.html?prop=%s&ok=1&msg=ajout"|args:$prop}}
{{/form}}
{{:admin_header title="Entrée de matériel" current="module_equipment"}}
{{:form_errors}}
{{if $categories != null}}
{{#load type="storage" order="$$.name"}}
{{:assign var="storage.%s"|args:$key value=$name}}
{{/load}}
{{* formulaire ajout matériel *}}
<form method="post" action="">
<fieldset class="entree">
<legend>Enregistrer une entrée de matériel</legend>
<dl>
{{:input type="select" name="operation" label="Type" required=true default_empty="— Aucun —" options=$input_labels|sort}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="amount" label="Quantité" min=1 required=true default=1}}
</dl>
</fieldset>
<fieldset>
<legend>Sélectionner une catégorie et indiquer le nom du nouveau matériel</legend>
<dl>
{{:input type="select" name="category" label="Catégorie" default_empty="— Aucune —" options=$categories required=true}}
{{:input type="text" name="name" label="Désignation" required=true}}
{{if $storage != null}}
{{:input type="select" name="storage" label="Lieu de stockage" default_empty="— Aucun —" options=$storage required=false}}
{{/if}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40", rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucune catégorie, il faut en créer au moins une</p>
{{/if}}
{{:admin_footer}}

View file

@ -1,257 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Dupliquer un mouvement
paramètres :
- key : clé du mouvement à dupliquer
- prop = 1 si matériel appartient à l'asso
*}}
{{* récupérer les infos du mouvement à dupliquer *}}
{{#load key=$_GET.key assign="mvt_new"}}
{{else}}
{{:error message="Aucun mouvement avec la clé %s"|args:$_GET.key}}
{{/load}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config, directions"}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt_new.direction:$mvt_new.operation}}
{{if $mvt_new.direction == "input"}}
{{if $type_mvt == "temporaire"}}
{{:assign prop=0}}
{{else}}
{{:assign prop=1}}
{{/if}}
{{else}}
{{if $type_mvt == "retour"}}
{{:assign prop=0}}
{{else}}
{{:assign prop=1}}
{{/if}}
{{/if}}
{{* infos pour affichage *}}
{{:assign amount_init=$mvt_new.amount}}
{{:assign date_init=$mvt_new.date|date_short}}
{{:assign eqpmt_key=$mvt_new.equipment}}
{{* récupérer les infos du matériel associé *}}
{{#load key=$eqpmt_key assign="equipment"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$eqpmt_key}}
{{/load}}
{{* limiter les opérations possibles *}}
{{if $mvt_new.direction == "input"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key=key}}
{{if $_GET.prop && $type != "temporaire" ||
! $_GET.prop && $type == "temporaire"
}}
{{:assign var="input_labels.%s"|args:$key value=$label}}
{{/if}}
{{/foreach}}
{{else}}
{{* types de sorties *}}
{{#foreach from=$config.output_nature key=key}}
{{if $_GET.prop && $type != "retour" ||
! $_GET.prop && $type == "retour"
}}
{{:assign var="output_labels.%s"|args:$key value=$label}}
{{/if}}
{{/foreach}}
{{/if}}
{{*
-------------------- Traiter la saisie --------------------
*}}
{{#form on="save"}}
{{* vérifier la validité de la saisie *}}
{{if $_POST.amount <= 0}}
{{:error message="La quantité (%s) doit être strictement positive !!"|args:$_POST.amount}}
{{/if}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{if $mvt_new.direction == "input" && $_POST.user != null}}
{{:error message="Un membre ne peut être associé qu'à une sortie"}}
{{/if}}
{{if $_POST.user|count > 1}}
{{:error message="Un membre au plus peut être associé à une sortie"}}
{{/if}}
{{#foreach from=$_POST.user key="id" item="name"}}
{{:assign var="user.id" value=$id}}
{{:assign var="user.name" value=$name}}
{{/foreach}}
{{* préparer le mouvement copié *}}
{{:assign var="mvt_new.operation" value=$_POST.operation}}
{{:assign var="mvt_new.amount" value=$_POST.amount}}
{{:assign var="mvt_new.date" value=$_POST.date|parse_date}}
{{:assign var="mvt_new.comment" value=$_POST.comment}}
{{*
lister les mouvements
- insérer le mvt copié à sa place par date croissante
*}}
{{:assign insere=false}}
{{#load
where="
$$.type = 'movement'
AND
$$.equipment = :eqpmt_key"
:eqpmt_key=$eqpmt_key
order="$$.date"
assign="movement"
}}
{{if ! $insere}}
{{if $mvt_new.date < $date}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.date == $date}}
{{if $mvt_new.direction == "input" && $type_mvt != "retour"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.direction == "output" && $type_mvt == "temporaire"}}
{{if $movement.direction == "input"}}
{{:assign var="type_mvt_crt" from="config.input_nature.%s.type"|args::$movement.operation}}
{{if $type_mvt_crt == "retour"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{:assign var="movements_new." from=movement}}
{{/load}}
{{if ! $insere}}
{{:assign var="movements_new." from=mvt_new}}
{{/if}}
{{* Vérifier la cohérence des mouvements du matériel *}}
{{:include
file="./_validate_modification.html"
keep="erreur"
movements=$movements_new
}}
{{if $erreur}}
{{:assign var="mvt_label" from="%s_labels.%s"|args:$mvt_new.direction:$mvt_new.operation}}
{{:assign new_date=$mvt_new.date|date_short}}
{{:error message="Impossible d'enregistrer ce mouvement : « %s de %s (qté : %s) à la date du %s »"|args:$mvt_label:$equipment.name:$mvt_new.amount:$new_date}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{if $mvt_new.direction == "input"}}
{{:assign var="type_mvt" from="config.input_nature.%s.type"|args:$_POST.operation}}
{{if $type_mvt == 'définitif'}}
{{:assign var="equipment.stock" value="%d+%d"|math:$equipment.stock:$_POST.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="equipment.notowned" value="%d+%d"|math:$equipment.notowned:$_POST.amount|intval}}
{{elseif $type_mvt == 'retour'}}
{{:assign var="equipment.out" value="%d-%d"|math:$equipment.out:$_POST.amount|intval}}
{{/if}}
{{else}}
{{:assign var="type_mvt" from="config.output_nature.%s.type"|args:$_POST.operation}}
{{if $type_mvt == 'définitif'}}
{{:assign var="equipment.stock" value="%d-%d"|math:$equipment.stock:$_POST.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="equipment.out" value="%d+%d"|math:$equipment.out:$_POST.amount|intval}}
{{elseif $type_mvt == 'retour'}}
{{:assign var="equipment.notowned" value="%d-%d"|math:$equipment.notowned:$_POST.amount|intval}}
{{/if}}
{{/if}}
{{:save
key=$equipment.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$equipment.category
name=$equipment.name
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{* vérification réussie : enregistrer le nouveau mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:save
key=$mvt_key
validate_schema="movement.schema.json"
type="movement"
direction=$mvt_new.direction
operation=$_POST.operation
amount=$mvt_new.amount|intval
equipment=$eqpmt_key
date=$mvt_new.date
comment=$mvt_new.comment
user=$user.id
storage=$_POST.storage
}}
{{:redirect force="../equipment_history.html?ok=1&key=%s&prop=%s&msg=copie"|args:$eqpmt_key:$prop}}
{{/form}}
{{:admin_header title="Dupliquer un mouvement" current="module_equipment"}}
{{:form_errors}}
{{*
-------------------- Préparer la saisie --------------------
*}}
{{* récupérer les infos de la catégorie *}}
{{#load key=$equipment.category assign="category"}}{{/load}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$mvt_new.direction:$mvt_new.operation}}
{{if $mvt_new.user != null}}
{{#select id, !name as nom FROM users WHERE id=:id; !name=$config.user_fields.name_sql :id=$mvt_new.user}}
{{:assign var="user.%s"|args:$id value=$nom}}
{{/select}}
{{/if}}
{{#load type="storage" order="$$.name"}}
{{:assign var="storage.%s"|args:$key value=$name}}
{{/load}}
{{* formulaire de copie du mouvement *}}
<form method="post" action="">
<fieldset>
<legend>Créer une copie de « {{$op_label}} {{$equipment.name}} (Catégorie : {{$category.name}}) »</legend>
<dl>
{{if $mvt_new.direction == "input"}}
{{:input type="select" name="operation" label="Type" required=true options=$input_labels|sort default=$mvt_new.operation}}
{{else}}
{{:input type="select" name="operation" label="Type" required=true options=$output_labels|sort default=$mvt_new.operation}}
{{/if}}
{{:input type="date" name="date" label="Date" required=true default=$mvt_new.date}}
{{:input type="number" name="amount" label="Quantité" min=1 required=true default=$mvt_new.amount}}
{{if $prop == 1 && $mvt_new.direction == "output"}}
{{:input
type="list"
name="user"
label="Membre destinataire"
default=$user
target="!users/selector.php"
multiple=true
max=1
}}
{{/if}}
{{if $mvt_new.direction == "input"}}
{{if $storage != null}}
{{:input type="select" name="storage" label="Lieu de stockage" default_empty="— Aucun —" options=$storage required=false}}
{{/if}}
{{/if}}
{{:input type="textarea" name="comment" label="Remarques" cols="40", rows="3" required=false default=$mvt_new.comment}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{:admin_footer}}

View file

@ -1,171 +0,0 @@
{{* -*- brindille -*-}}
{{*
paramètres GET :
- key : clé du mouvement à supprimer
- prop : = 1 si matériel propriété de l'asso
*}}
{{#load key=$_GET.key assign="mvt_suppr"}}
{{else}}
{{:error message="Aucun mouvement avec la clé « %s »"|args:$_GET.key}}
{{/load}}
{{* trouver le matériel concerné par ce mouvement *}}
{{#load type="equipment" where="key = :key" :key=$mvt_suppr.equipment assign="curr_eqpmt"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$mvt_suppr.equipment}}
{{/load}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{#form on="delete"}}
{{* vérifier s'il est possible de supprimer le mouvement *}}
{{if $mvt_suppr.direction == 'input'}}
{{:assign var="type_operation" from="config.input_nature.%s.type"|args:$mvt_suppr.operation}}
{{if $type_operation == 'temporaire'}}
{{#load type="link" where="$$.temp_key = :key" :key=$_GET.key}}
{{:assign link_key=$key}}
{{/load}}
{{if $link_key != null}}
{{:redirect force="../equipment_history.html?key=%s&prop=%s&err=1&msg=suppression"|args:$mvt_suppr.equipment:$_GET.prop}}
{{/if}}
{{else}}
{{:assign dispo=0}}
{{:assign nonprop=0}}
{{#load
type="movement"
where="$$.equipment = :key" :key=$mvt_suppr.equipment
assign="mvt"
order="$$.date"}}
{{* déterminer le type de mouvement *}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt.direction:$mvt.operation}}
{{if $key != $_GET.key}}
{{* ce n'est pas le mouvement à supprimer : cumuler les entrées/sorties *}}
{{if $mvt.direction == 'input'}}
{{if $type_mvt == 'temporaire'}}
{{:assign nonprop="%d+%d"|math:$nonprop:$mvt.amount}}
{{else}}
{{:assign dispo="%d+%d"|math:$dispo:$mvt.amount}}
{{/if}}
{{elseif $mvt.direction == 'output'}}
{{if $type_mvt == 'retour'}}
{{:assign nonprop="%d-%d"|math:$nonprop:$mvt.amount}}
{{else}}
{{:assign dispo="%d-%d"|math:$dispo:$mvt.amount}}
{{/if}}
{{/if}}
{{* problème ? *}}
{{if $dispo < 0 || $nonprop < 0}}
{{:redirect force="../equipment_history.html?key=%s&prop=%s&err=1&msg=suppression"|args:$mvt_suppr.equipment:$_GET.prop}}
{{/if}}
{{/if}}
{{/load}}
{{* suppression possible *}}
{{if $type_operation == 'retour'}}
{{#load type="link" where="$$.return = :key" :key=$_GET.key}}
{{:assign link_key=$key}}
{{/load}}
{{/if}}
{{/if}}
{{else}}
{{* sortie *}}
{{:assign var="type_operation" from="config.output_nature.%s.type"|args:$mvt_suppr.operation}}
{{if $type_operation == 'temporaire'}}
{{#load type="link" where="$$.temp_key = :key OR $$.return = :key" :key=$_GET.key}}
{{:assign link_key=$key}}
{{/load}}
{{if $link_key != null}}
{{:redirect force="../equipment_history.html?key=%s&prop=%s&err=1&msg=suppression"|args:$mvt_suppr.equipment:$_GET.prop}}
{{/if}}
{{elseif $type_operation == 'retour'}}
{{#load type="link" where="$$.return = :key" :key=$_GET.key}}
{{:assign link_key=$key}}
{{/load}}
{{/if}}
{{/if}}
{{* vérification réussie : supprimer le mouvement *}}
{{:delete key=$_GET.key}}
{{if $link_key != null}}
{{:delete key=$link_key}}
{{/if}}
{{* voir s'il reste des mouvements pour le matériel concerné par le mouvement supprimé *}}
{{#foreach from=$config.input_nature key=key}}
{{if $type == 'définitif'}}
{{:assign var="input_types." value=$key}}
{{/if}}
{{/foreach}}
{{#load type="movement" where="$$.equipment = :eqpmt_key" :eqpmt_key=$curr_eqpmt.key}}
{{:assign mvt_ok=true}}
{{if $operation|in:$input_types}}
{{:assign entree_def=true}}
{{:break}}
{{/if}}
{{/load}}
{{if $mvt_ok}}
{{* calculer et mettre à jour la nouvelle quantité du matériel *}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt_suppr.direction:$mvt_suppr.operation}}
{{if $mvt_suppr.direction == 'input'}}
{{if $type_mvt == 'définitif'}}
{{:assign var="curr_eqpmt.stock" value="%d-%d"|math:$curr_eqpmt.stock:$mvt_suppr.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="curr_eqpmt.notowned" value="%d-%d"|math:$curr_eqpmt.notowned:$mvt_suppr.amount|intval}}
{{elseif $type_mvt == 'retour'}}
{{:assign var="curr_eqpmt.out" value="%d+%d"|math:$curr_eqpmt.out:$mvt_suppr.amount|intval}}
{{/if}}
{{else}}
{{if $type_mvt == 'définitif'}}
{{:assign var="curr_eqpmt.stock" value="%d+%d"|math:$curr_eqpmt.stock:$mvt_suppr.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="curr_eqpmt.out" value="%d-%d"|math:$curr_eqpmt.out:$mvt_suppr.amount|intval}}
{{elseif $type_mvt == 'retour'}}
{{:assign var="curr_eqpmt.notowned" value="%d+%d"|math:$curr_eqpmt.notowned:$mvt_suppr.amount|intval}}
{{/if}}
{{/if}}
{{if $curr_eqpmt.stock == 0 && ! $entree_def}}
{{:assign var="curr_eqpmt.stock" value=null}}
{{/if}}
{{:save
key=$curr_eqpmt.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$curr_eqpmt.category
name=$curr_eqpmt.name
status="available"
stock=$curr_eqpmt.stock
out=$curr_eqpmt.out
notowned=$curr_eqpmt.notowned
}}
{{:redirect force="../equipment_history.html?ok=1&key=%s&prop=%s&msg=suppression"|args:$mvt_suppr.equipment:$_GET.prop}}
{{else}}
{{* supprimer le matériel *}}
{{:delete key=$curr_eqpmt.key}}
{{:redirect force="../index.html?ok=1&msg=supprmvtmat"}}
{{/if}}
{{/form}}
{{:admin_header title="Supprimer un mouvement" current="module_equipment"}}
{{:form_errors}}
{{:assign var="date_suppr" value="%s"|args:$mvt_suppr.date|date_short}}
{{:assign var="mvt_label" from="config.%s_nature.%s.label"|args:$mvt_suppr.direction:$mvt_suppr.operation}}
{{:delete_form
legend="Supprimer ?"
warning="Supprimer le mouvement « %s de %s (quantité : %d) en date du %s » ?"|args:$mvt_label:$curr_eqpmt.name:$mvt_suppr.amount:$date_suppr
}}
{{:admin_footer}}

View file

@ -1,120 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Enregistrer une entrée de matériel
paramètres :
- key : clé du matériel à ajouter
*}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="entrees"}}
{{/if}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key=key}}
{{if $type != 'retour'}}
{{:assign var="input_labels.%s"|args:$key value=$label}}
{{/if}}
{{/foreach}}
{{* récupérer les informations du matériel et de sa catégorie *}}
{{#load key=$_GET.key assign="equipment"}}
{{/load}}
{{#load where="key = :key" :key=$equipment.category assign="category"}}
{{/load}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* vérifier la quantité saisie *}}
{{if $_POST.amount <= 0}}
{{:error message="La quantité (%s) doit être strictement positive !!"|args:$_POST.amount}}
{{/if}}
{{* interdire date dans le futur *}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{:assign var="type_mvt" from="config.input_nature.%s.type"|args:$_POST.operation}}
{{if $type_mvt == 'définitif'}}
{{:assign var="equipment.stock" value="%d+%d"|math:$equipment.stock:$_POST.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="equipment.notowned" value="%d+%d"|math:$equipment.notowned:$_POST.amount|intval}}
{{/if}}
{{:save
key=$equipment.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$equipment.category
name=$equipment.name
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:save
key=$mvt_key
validate_schema="./movement.schema.json"
type="movement"
direction="input"
operation=$_POST.operation
amount=$_POST.amount|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
storage=$_POST.storage
}}
{{:assign var=type_entree from="config.input_nature.%s.type"|args:$_POST.operation}}
{{if $type_entree == "temporaire"}}
{{:assign prop=0}}
{{else}}
{{:assign prop=1}}
{{/if}}
{{:redirect force="../equipment_history.html?key=%s&ok=1&msg=entrée&prop=%s"|args:$equipment.key:$prop}}
{{/form}}
{{:admin_header title="Entrée de matériel" custom_css="./../style.css" current="module_equipment"}}
{{:form_errors}}
{{* formulaire de saisie d'une entrée de matériel *}}
{{#load type="storage" order="$$.name"}}
{{:assign var="storage.%s"|args:$key value=$name}}
{{/load}}
<form method="post" action="">
<fieldset class="informations">
<legend>Informations matériel</legend>
<dl class="describe">
<dt>Matériel</dt>
<dd>{{$equipment.name}}</dd>
<dt>Catégorie</dt>
<dd>{{$category.name}}</dd>
</dl>
</fieldset>
<fieldset class="entree">
<legend>Enregistrer une entrée de matériel</legend>
<dl>
{{:input type="select" name="operation" label="Type" required=true default_empty="— Aucun —" options=$input_labels|sort}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="amount" label="Quantité" required=true min=1 default=1}}
{{if $storage != null}}
{{:input type="select" name="storage" label="Lieu de stockage" default_empty="— Aucun —" options=$storage required=false}}
{{/if}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40" rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{:admin_footer}}

View file

@ -1,205 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Enregistrer un retour d'entrée temporaire
paramètres :
- key : clé de l'entrée temporaire
*}}
{{* infos du mouvement *}}
{{#load key=$_GET.key assign="mvt_new"}}
{{else}}
{{:error message="Aucun mouvement avec la clé %s"|args:$_GET.key}}
{{/load}}
{{* infos du matériel associé *}}
{{#load key=$mvt_new.equipment assign="equipment"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$key}}
{{/load}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{* calculer la quantité entrée temporairement *}}
{{#foreach from=$config.input_nature key=key}}
{{if $type == "temporaire"}}
{{:assign var="temp_inputs." value=$key|quote_sql}}
{{/if}}
{{/foreach}}
{{:assign operations=$temp_inputs|implode:","}}
{{:assign operations="("|cat:$operations|cat:")"}}
{{#select
json_extract(mvt.document, '$.amount') - IFNULL(SUM(json_extract(mvt2.document, '$.amount')), 0) AS present
FROM module_data_equipment AS mvt
LEFT JOIN module_data_equipment AS link ON mvt.key = json_extract(link.document, '$.temp_key')
LEFT JOIN module_data_equipment AS mvt2 ON mvt2.key = json_extract(link.document, '$.return')
WHERE
json_extract(mvt.document, '$.operation') IN !op
AND mvt.key = :mvt_key
GROUP by mvt.key
;
!op = $operations
:mvt_key = $_GET.key
}}
{{:assign present=$present}}
{{/select}}
{{*
-------------------- Traiter la saisie --------------------
*}}
{{#form on="save"}}
{{* vérifier validité des données *}}
{{if $_POST.amount <= 0}}
{{:error message="La quantité (%s) doit être strictement positive !!"|args:$_POST.amount}}
{{/if}}
{{if $_POST.amount > $present}}
{{:error message="La quantité (%s) doit être inférieure à la quantité présente (%s) !!"|args:$_POST.amount:$present}}
{{/if}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{* préparer le nouveau mouvement *}}
{{:assign var="mvt_new.key" value=""|uuid}}
{{:assign var="mvt_new.direction" value="output"}}
{{:assign var="mvt_new.date" value=$_POST.date|parse_date}}
{{:assign var="mvt_new.operation" value=$_POST.operation}}
{{:assign var="mvt_new.amount" value=$_POST.amount}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt_new.direction:$mvt_new.operation}}
{{*
lister les mouvements
- insérer le nouveau mvt à sa place par date croissante
*}}
{{:assign insere=false}}
{{#load
where="
$$.type = 'movement'
AND
$$.equipment = :eqpmt_key"
:eqpmt_key=$equipment.key
order="$$.date"
assign="movement"
}}
{{if ! $insere}}
{{if $mvt_new.date < $date}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.date == $date}}
{{if $mvt_new.direction == "input" && $type_mvt != "retour"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.direction == "output" && $type_mvt == "temporaire"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{/if}}
{{/if}}
{{/if}}
{{:assign var="movements_new." from=movement}}
{{/load}}
{{if ! $insere}}
{{:assign var="movements_new." from=mvt_new}}
{{/if}}
{{* Vérifier la cohérence des mouvements du matériel *}}
{{:include
file="./_validate_modification.html"
keep="erreur, pb"
movements=$movements_new
}}
{{if $erreur}}
{{:assign message="Impossible d'enregistrer ce mouvement."}}
{{if $pb.mvt.key != $mvt_new.key}}
{{:assign var="err_mvt_label" from="config.output_nature.%s.label"|args:$pb.mvt.operation}}
{{:assign date_pb=$pb.mvt.date|date_short}}
{{:assign var=message2 value=" Mouvement incompatible avec « %s » : « %s (qté : %s) en date du %s »."|args:$err_mvt_label:$equipment.name:$pb.mvt.amount:$date_pb}}
{{:assign message=$message|cat:$message2}}
{{/if}}
{{:error message=$message}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{:assign var="type_mvt" from="config.output_nature.%s.type"|args:$_POST.operation}}
{{:assign var="equipment.notowned" value="%d-%d"|math:$equipment.notowned:$_POST.amount|intval}}
{{:save
key=$equipment.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$equipment.category
name=$equipment.name
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{* vérification réussie : enregistrer le mouvement modifié *}}
{{:assign mvt_key=""|uuid}}
{{:save
key=$mvt_key
validate_schema="movement.schema.json"
type="movement"
direction="output"
operation=$_POST.operation
amount=$_POST.amount|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.comment|trim
}}
{{* enregistrer la liaison entre le retour et la sortie temporaire *}}
{{:save
key=""|uuid
validate_schema="link.schema.json"
type="link"
direction="input"
temp_key=$_GET.key
return=$mvt_key
}}
{{:redirect force="../equipment_history.html?ok=1&key=%s&prop=0&msg=retour"|args:$mvt_new.equipment}}
{{/form}}
{{:admin_header title="Retour de matériel" custom_css="../style.css" current="module_equipment"}}
{{:form_errors}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="entrees"}}
{{/if}}
{{*
-------------------- Préparer la saisie --------------------
*}}
{{#foreach from=$config.output_nature key=key}}
{{if $type == "retour"}}
{{:assign var="return_label.%s"|args:$key value=$label}}
{{:break}}
{{/if}}
{{/foreach}}
{{* infos de la catégorie *}}
{{#load key=$equipment.category assign="category"}}{{/load}}
<form method="post" action="">
<fieldset>
<legend>Retour de « {{$equipment.name}} (Catégorie : {{$category.name}}) »</legend>
<dl>
{{:input type="select" name="operation" label="Type" required=true options=$return_label}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="amount" label="Quantité" min=1 max=$present required=true default=$present}}
{{:input type="textarea" name="comment" label="Remarques" cols="40", rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{:admin_footer}}

View file

@ -1,23 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["link"]
},
"direction" : {
"type" : "string",
"enum" : ["input", "output"]
},
"temp_key" : {
"description": "clé d'une entrée ou sortie temporaire",
"type": "string"
},
"return": {
"description": "clé du retour associé",
"type": "string"
}
},
"required": ["type", "direction", "temp_key", "return"]
}

View file

@ -1,275 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Modifier un mouvement
paramètres :
- key : clé du mouvement à modifier
*}}
{{* récupérer les infos du mouvement à modifier *}}
{{#load key=$_GET.key assign="mvt_new"}}
{{else}}
{{:error message="Aucun mouvement avec la clé %s"|args:$_GET.key}}
{{/load}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config, directions"}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt_new.direction:$mvt_new.operation}}
{{if $mvt_new.direction == "input"}}
{{if $type_mvt == "temporaire"}}
{{:assign prop=0}}
{{else}}
{{:assign prop=1}}
{{/if}}
{{else}}
{{if $type_mvt == "retour"}}
{{:assign prop=0}}
{{else}}
{{:assign prop=1}}
{{/if}}
{{/if}}
{{* infos pour affichage *}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$mvt_new.direction:$mvt_new.operation}}
{{:assign amount_init=$mvt_new.amount}}
{{:assign operation_init=$mvt_new.operation}}
{{:assign date_init=$mvt_new.date|date_short}}
{{:assign eqpmt_key=$mvt_new.equipment}}
{{* récupérer les infos du matériel associé *}}
{{#load key=$eqpmt_key assign="equipment"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$eqpmt_key}}
{{/load}}
{{#foreach from=$directions key="direction"}}
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key="key"}}
{{:assign var="%s_labels.%s"|args:$direction:$key value=$label}}
{{/foreach}}
{{/foreach}}
{{*
-------------------- Traiter la saisie --------------------
*}}
{{#form on="save"}}
{{if $_POST.amount <= 0}}
{{:error message="La quantité (%s) doit être strictement positive !!"|args:$_POST.amount}}
{{/if}}
{{* vérifier validité des données *}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{if $mvt_new.direction == "input" && $_POST.user != null}}
{{:error message="Un membre ne peut être associé qu'à une sortie"}}
{{/if}}
{{if $_POST.user|count > 1}}
{{:error message="Un membre au plus peut être associé à une sortie"}}
{{/if}}
{{#foreach from=$_POST.user key="id" item="name"}}
{{:assign var="user.id" value=$id}}
{{:assign var="user.name" value=$name}}
{{/foreach}}
{{* préparer le mouvement modifié *}}
{{:assign var="mvt_new.operation" value=$_POST.operation}}
{{:assign var="mvt_new.amount" value=$_POST.amount}}
{{:assign var="mvt_new.date" value=$_POST.date|parse_date}}
{{:assign var="mvt_new.comment" value=$_POST.comment}}
{{*
lister les mouvements
- ignorer le mouvement à modifier
- insérer le mvt modifié à sa place par date croissante
*}}
{{:assign insere=false}}
{{#load
where="
$$.type = 'movement'
AND
$$.equipment = :eqpmt_key"
:eqpmt_key=$eqpmt_key
order="$$.date"
assign="movement"
}}
{{if $key != $_GET.key}}
{{if ! $insere}}
{{if $mvt_new.date < $date}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.date == $date}}
{{if $mvt_new.direction == "input" && $type_mvt != "retour"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.direction == "output" && $type_mvt == "temporaire"}}
{{if $movement.direction == "input"}}
{{:assign var="type_mvt_crt" from="config.input_nature.%s.type"|args::$movement.operation}}
{{if $type_mvt_crt == "retour"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{/if}}
{{:assign var="movements_new." from=movement}}
{{/if}}
{{/load}}
{{if ! $insere}}
{{:assign var="movements_new." from=mvt_new}}
{{/if}}
{{* Vérifier la cohérence des mouvements du matériel *}}
{{:include
file="./_validate_modification.html"
keep="erreur"
movements=$movements_new
}}
{{if $erreur}}
{{:assign var="new_op_label" from="config.%s_nature.%s.label"|args:$mvt_new.direction:$mvt_new.operation}}
{{:assign new_date=$mvt_new.date|date_short}}
{{:error message="Modification impossible : « %s de %s (qté : %s) en date du %s » vers « %s de %s (qté : %s) à la date du %s »"|args:$op_label:$equipment.name:$amount_init:$date_init:$new_op_label:$equipment.name:$mvt_new.amount:$new_date}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{:assign var="type_mvt_init" from="config.%s_nature.%s.type"|args:$mvt_new.direction:$operation_init}}
{{:assign var="type_mvt_final" from="config.%s_nature.%s.type"|args:$mvt_new.direction:$mvt_new.operation}}
{{if $mvt_new.direction == 'input'}}
{{if $type_mvt_init == 'définitif'}}
{{:assign var="equipment.stock" value="%d-%d"|math:$equipment.stock:$amount_init}}
{{elseif $type_mvt_init == 'temporaire'}}
{{:assign var="equipment.notowned" value="%d-%d"|math:$equipment.notowned:$amount_init}}
{{elseif $type_mvt_init == 'retour'}}
{{:assign var="equipment.out" value="%d+%d"|math:$equipment.out:$amount_init}}
{{/if}}
{{if $type_mvt_final == 'définitif'}}
{{:assign var="equipment.stock" value="%d+%d"|math:$equipment.stock:$mvt_new.amount|intval}}
{{elseif $type_mvt_final == 'temporaire'}}
{{:assign var="equipment.notowned" value="%d+%d"|math:$equipment.notowned:$mvt_new.amount|intval}}
{{elseif $type_mvt_final == 'retour'}}
{{:assign var="equipment.out" value="%d-%d"|math:$equipment.out:$mvt_new.amount|intval}}
{{/if}}
{{else}}
{{if $type_mvt_init == 'définitif'}}
{{:assign var="equipment.stock" value="%d+%d"|math:$equipment.stock:$amount_init}}
{{elseif $type_mvt_init == 'temporaire'}}
{{:assign var="equipment.out" value="%d-%d"|math:$equipment.out:$amount_init}}
{{elseif $type_mvt_init == 'retour'}}
{{:assign var="equipment.notowned" value="%d+%d"|math:$equipment.notowned:$amount_init}}
{{/if}}
{{if $type_mvt_final == 'définitif'}}
{{:assign var="equipment.stock" value="%d-%d"|math:$equipment.stock:$mvt_new.amount|intval}}
{{elseif $type_mvt_final == 'temporaire'}}
{{:assign var="equipment.out" value="%d+%d"|math:$equipment.out:$mvt_new.amount|intval}}
{{elseif $type_mvt_final == 'retour'}}
{{:assign var="equipment.notowned" value="%d-%d"|math:$equipment.notowned:$mvt_new.amount|intval}}
{{/if}}
{{/if}}
{{:save
key=$equipment.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$equipment.category
name=$equipment.name
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{* enregistrer le mouvement modifié *}}
{{if $user == null}}
{{:assign user_id=$mvt_new.user}}
{{else}}
{{:assign user_id=$user.id}}
{{/if}}
{{:save
key=$_GET.key
validate_schema="movement.schema.json"
type="movement"
direction=$mvt_new.direction
operation=$_POST.operation
amount=$mvt_new.amount|intval
equipment=$eqpmt_key
date=$mvt_new.date
comment=$mvt_new.comment
user=$user_id
storage=$_POST.storage
}}
{{:redirect force="../equipment_history.html?ok=1&key=%s&prop=%s&msg=modification"|args:$eqpmt_key:$prop}}
{{/form}}
{{:admin_header title="Modifier un mouvement" current="module_equipment"}}
{{:form_errors}}
{{*
-------------------- Préparer la saisie --------------------
*}}
{{#load key=$equipment.category assign="category"}}{{/load}}
{{if $mvt_new.user != null}}
{{#select id, !name as nom FROM users WHERE id=:id; !name=$config.user_fields.name_sql :id=$mvt_new.user}}
{{:assign var="user.%s"|args:$id value=$nom}}
{{/select}}
{{#load type="link" where="$$.direction="output" AND $$.temp_key = :mvt_key" :mvt_key=$mvt_new.key limit=1}}
{{:assign retour=true}}
{{else}}
{{:assign retour=false}}
{{/load}}
{{/if}}
{{#load type="storage" order="$$.name"}}
{{:assign var="storage.%s"|args:$key value=$name}}
{{/load}}
{{* formulaire de modification du mouvement *}}
<form method="post" action="">
<fieldset>
<legend>Modifier « {{$op_label}} {{$equipment.name}} (Catégorie : {{$category.name}}) »</legend>
<dl>
{{if $mvt_new.direction == "input"}}
{{:input type="select" name="operation" label="Type" required=true options=$input_labels|sort default=$mvt_new.operation}}
{{else}}
{{:input type="select" name="operation" label="Type" required=true options=$output_labels|sort default=$mvt_new.operation}}
{{/if}}
{{:input type="date" name="date" label="Date" required=true default=$mvt_new.date}}
{{:input type="number" name="amount" label="Quantité" min=1 required=true default=$mvt_new.amount}}
{{if $prop == 1 && $mvt_new.direction == "output" && ! $retour}}
{{:input
type="list"
name="user"
label="Membre destinataire"
default=$user
target="!users/selector.php"
multiple=true
max=1
}}
{{/if}}
{{if $mvt_new.direction == "input"}}
{{if $storage != null}}
{{:input type="select" name="storage" label="Lieu de stockage" default=$mvt_new.storage default_empty="— Aucun —" options=$storage required=false}}
{{/if}}
{{/if}}
{{:input type="textarea" name="comment" label="Remarques" cols="40", rows="3" required=false default=$mvt_new.comment}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{:admin_footer}}

View file

@ -1,199 +0,0 @@
{{* -*- brindille -*- *}}
{{*
paramètres :
- key : clé du matériel à sortir
*}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{* types de sorties *}}
{{#foreach from=$config.output_nature key=key}}
{{if $type != 'retour'}}
{{:assign var="output_labels.%s"|args:$key value=$label}}
{{/if}}
{{/foreach}}
{{* récupérer les infos du matériel *}}
{{#load key=$_GET.key assign="equipment"}}{{/load}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* interdire date dans le futur *}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{* vérifier les infos saisies *}}
{{if $_POST.operation == ""}}
{{:error message="Vous devez choisir un type de sortie"}}
{{/if}}
{{:assign var="type_mvt" from="config.output_nature.%s.type"|args:$_POST.operation}}
{{if $_POST.user|count > 1}}
{{:error message="Un membre au plus peut être associé à une sortie"}}
{{/if}}
{{#foreach from=$_POST.user key="id" item="name"}}
{{:assign var="user.id" value=$id}}
{{:assign var="user.name" value=$name}}
{{/foreach}}
{{:assign stock=0}}
{{:assign exterieur=0}}
{{:assign nonproprio=0}}
{{:assign insere=false}}
{{* lister tous les mouvements du matériel *}}
{{#load type="movement" where="$$.equipment = '%s'"|args:$_GET.key assign="mvt" order="$$.date ASC"}}
{{* traiter le nouveau mouvement *}}
{{if ! $insere && $mvt.date > $_POST.date|parse_date}}
{{:assign insere=true}}
{{:assign dispo_old="%d-%d"|math:$stock:$exterieur}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$_POST.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$_POST.amount}}
{{/if}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{if $dispo < 0 || $stock < 0 || $exterieur < 0}}
{{:assign date_err=$_POST.date|date:"d/m/Y"}}
{{:error message="Erreur : la quantité indiquée (%s) est supérieure à celle disponible (%d) à la date du %s"|args:$_POST.amount:$dispo_old:$date_err}}
{{/if}}
{{/if}}
{{* traiter le mouvement courant *}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt.direction:$mvt.operation}}
{{if $mvt.direction === 'input'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d+%d"|math:$stock:$mvt.amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign exterieur="%d-%d"|math:$exterieur:$mvt.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign nonproprio="%d+%d"|math:$nonproprio:$mvt.amount}}
{{/if}}
{{elseif $mvt.direction === 'output'}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$mvt.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$mvt.amount}}
{{elseif $type_mvt == 'retour'}}
{{:assign nonproprio="%d-%d"|math:$nonproprio:$mvt.amount}}
{{/if}}
{{/if}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{if $dispo < 0 || $stock < 0 || $exterieur < 0 || $nonproprio < 0}}
{{:assign date_err=$mvt.date|date:"d/m/Y"}}
{{:error message="Erreur : la quantité indiquée (%s) est incompatible avec la sortie de %s unités à la date du %s"|args:$_POST.amount:$mvt.amount:$date_err}}
{{/if}}
{{/load}}
{{if ! $insere}}
{{:assign dispo_old="%d-%d"|math:$stock:$exterieur}}
{{:assign var="type_mvt" from="config.output_nature.%s.type"|args:$_POST.operation}}
{{if $type_mvt == 'définitif'}}
{{:assign stock="%d-%d"|math:$stock:$_POST.amount}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign exterieur="%d+%d"|math:$exterieur:$_POST.amount}}
{{/if}}
{{:assign dispo="%d-%d"|math:$stock:$exterieur}}
{{if $dispo < 0 || $stock < 0 || $exterieur < 0}}
{{:assign date_err=$_POST.date|date:"d/m/Y"}}
{{:error message="Erreur : la quantité indiquée (%s) est supérieure à celle disponible (%d) à la date du %s"|args:$_POST.amount:$dispo_old:$date_err}}
{{/if}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{:assign var="type_mvt" from="config.output_nature.%s.type"|args:$_POST.operation}}
{{if $type_mvt == 'définitif'}}
{{:assign var="equipment.stock" value="%d-%d"|math:$equipment.stock:$_POST.amount|intval}}
{{elseif $type_mvt == 'temporaire'}}
{{:assign var="equipment.out" value="%d+%d"|math:$equipment.out:$_POST.amount|intval}}
{{/if}}
{{:save
key=$equipment.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$equipment.category
name=$equipment.name
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{* Enregistrer le mouvement *}}
{{:assign mvt_key=""|uuid}}
{{:save
key=$mvt_key
validate_schema="./movement.schema.json"
type="movement"
direction="output"
operation=$_POST.operation
amount=$_POST.amount|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.remarques|trim
user=$user.id
}}
{{:redirect force="../equipment_history.html?ok=1&key=%s&prop=1&msg=sortie"|args:$_GET.key}}
{{/form}}
{{:admin_header title="Sortie de matériel" custom_css="./../style.css" current="module_equipment"}}
{{if ! $dialog}}
{{* barre de navigation *}}
{{:include file="../_nav.html" current="sorties"}}
{{/if}}
{{#load key=$equipment.category assign="category"}}{{/load}}
{{:assign dispo="%d-%d"|math:$equipment.stock:$equipment.out}}
{{if $dispo > 0}}
{{* formulaire de sortie de matériel *}}
<form method="post" action="">
<fieldset class="informations">
<legend>Informations matériel</legend>
<dl class="describe">
<dt>Matériel</dt>
<dd>{{$equipment.name}}</dd>
<dt>Catégorie</dt>
<dd>{{$category.name}}</dd>
<dt>Quantité disponible</dt>
<dd class="num">{{$dispo}}</dd>
</dl>
</fieldset>
<fieldset class="sortie">
<legend>Enregistrer une sortie</legend>
<dl>
{{:input type="select" name="operation" label="Type" required=true default_empty="— Aucun —" options=$output_labels|sort}}
{{:input type="date" name="date" label="Date de sortie" required=true default=$now|date_short}}
{{:input type="number" name="amount" label="Quantité" required=true default=$dispo min=1 max=$dispo}}
{{:input
type="list"
name="user"
label="Membre destinataire"
target="!users/selector.php"
multiple=true
max=1
}}
{{:input type="textarea" name="remarques" label="Remarques" cols="40" rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{else}}
<p class="block error">Il n'y a aucune unité de ce matériel disponible à la date du {{$now|date_short}}</p>
{{/if}}
{{:form_errors}}
{{:admin_footer}}

View file

@ -1,209 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Enregistrer un retour de sortie temporaire
paramètres :
- key : clé de la sortie temporaire
*}}
{{* infos du mouvement *}}
{{#load key=$_GET.key assign="mvt_new"}}
{{else}}
{{:error message="Aucun mouvement avec la clé %s"|args:$_GET.key}}
{{/load}}
{{* infos du matériel associé *}}
{{#load key=$mvt_new.equipment assign="equipment"}}
{{else}}
{{:error message="Aucun matériel avec la clé « %s »"|args:$key}}
{{/load}}
{{* récupérer la config des entrées/sorties *}}
{{:include file="../_get_config.html" keep="config"}}
{{* calculer la quantité sortie temporairement *}}
{{#foreach from=$config.output_nature key=key}}
{{if $type == "temporaire"}}
{{:assign var="temp_outputs." value=$key|quote_sql}}
{{/if}}
{{/foreach}}
{{:assign operations=$temp_outputs|implode:","}}
{{:assign operations="("|cat:$operations|cat:")"}}
{{#select
json_extract(mvt.document, '$.amount') - IFNULL(SUM(json_extract(mvt2.document, '$.amount')), 0) AS exterieur
FROM module_data_equipment AS mvt
LEFT JOIN module_data_equipment AS link ON mvt.key = json_extract(link.document, '$.temp_key')
LEFT JOIN module_data_equipment AS mvt2 ON mvt2.key = json_extract(link.document, '$.return')
WHERE
json_extract(mvt.document, '$.operation') IN !op
AND mvt.key = :mvt_key
GROUP by mvt.key
;
!op = $operations
:mvt_key = $_GET.key
}}
{{:assign exterieur=$exterieur}}
{{/select}}
{{*
-------------------- Traiter la saisie --------------------
*}}
{{#form on="save"}}
{{* vérifier validité des données *}}
{{if $_POST.amount <= 0}}
{{:error message="La quantité (%s) doit être strictement positive !!"|args:$_POST.amount}}
{{/if}}
{{if $_POST.amount > $exterieur}}
{{:error message="La quantité (%s) doit être inférieure à la quantité sortie (%s) !!"|args:$_POST.amount:$exterieur}}
{{/if}}
{{if $_POST.date|parse_date|strtotime > $now}}
{{:error message="Impossible de saisir une date dans le futur (%s)"|args:$_POST.date}}
{{/if}}
{{* préparer le nouveau mouvement *}}
{{:assign var="mvt_new.key" value=""|uuid}}
{{:assign var="mvt_new.direction" value="input"}}
{{:assign var="mvt_new.date" value=$_POST.date|parse_date}}
{{:assign var="mvt_new.operation" value=$_POST.operation}}
{{:assign var="mvt_new.amount" value=$_POST.amount}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$mvt_new.direction:$mvt_new.operation}}
{{*
lister les mouvements
- insérer le nouveau mvt à sa place par date croissante
*}}
{{:assign insere=false}}
{{#load
where="
$$.type = 'movement'
AND
$$.equipment = :eqpmt_key"
:eqpmt_key=$equipment.key
order="$$.date"
assign="movement"
}}
{{if ! $insere}}
{{if $mvt_new.date < $date}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.date == $date}}
{{if $mvt_new.direction == "input" && $type_mvt != "retour"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{elseif $mvt_new.direction == "output" && $type_mvt == "temporaire"}}
{{:assign var="movements_new." from=mvt_new}}
{{:assign insere=true}}
{{/if}}
{{/if}}
{{/if}}
{{:assign var="movements_new." from=movement}}
{{/load}}
{{if ! $insere}}
{{:assign var="movements_new." from=mvt_new}}
{{/if}}
{{* Vérifier la cohérence des mouvements du matériel *}}
{{:include
file="./_validate_modification.html"
keep="erreur, pb"
movements=$movements_new
}}
{{if $erreur}}
{{:assign message="Impossible d'enregistrer ce mouvement."}}
{{if $pb.mvt.key != $mvt_new.key}}
{{:assign var="err_mvt_label" from="config.input_nature.%s.label"|args:$pb.mvt.operation}}
{{:assign date_pb=$pb.mvt.date|date_short}}
{{:assign var=message2 value=" Mouvement incompatible avec « %s » : « %s (qté : %s) en date du %s »."|args:$err_mvt_label:$equipment.name:$pb.mvt.amount:$date_pb}}
{{:assign message=$message|cat:$message2}}
{{/if}}
{{:error message=$message}}
{{/if}}
{{* calculer la nouvelle quantité du matériel *}}
{{:assign var="type_mvt" from="config.input_nature.%s.type"|args:$_POST.operation}}
{{:assign var="equipment.out" value="%d-%d"|math:$equipment.out:$_POST.amount|intval}}
{{:save
key=$equipment.key
validate_schema="../equipment.schema.json"
type="equipment"
category=$equipment.category
name=$equipment.name
status="available"
stock=$equipment.stock
out=$equipment.out
notowned=$equipment.notowned
}}
{{* enregistrer le mouvement modifié *}}
{{:assign mvt_key=""|uuid}}
{{:save
key=$mvt_key
validate_schema="movement.schema.json"
type="movement"
direction="input"
operation=$_POST.operation
amount=$_POST.amount|intval
equipment=$equipment.key
date=$_POST.date|parse_date
comment=$_POST.comment|trim
user=$mvt_new.user
}}
{{* enregistrer la liaison entre le retour et la sortie temporaire *}}
{{:save
key=""|uuid
validate_schema="link.schema.json"
type="link"
direction="output"
temp_key=$_GET.key
return=$mvt_key
}}
{{if $_GET.user == null}}
{{:redirect force="../equipment_history.html?ok=1&key=%s&prop=1&msg=retour"|args:$mvt_new.equipment}}
{{else}}
{{:redirect force="/admin/users/details.php?id=%s"|args:$_GET.user}}
{{/if}}
{{/form}}
{{:admin_header title="Retour de matériel" custom_css="../style.css" current="module_equipment"}}
{{:form_errors}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="entrees"}}
{{/if}}
{{*
-------------------- Préparer la saisie --------------------
*}}
{{#foreach from=$config.input_nature key=key}}
{{if $type == "retour"}}
{{:assign var="return_label.%s"|args:$key value=$label}}
{{:break}}
{{/if}}
{{/foreach}}
{{* infos de la catégorie *}}
{{#load key=$equipment.category assign="category"}}{{/load}}
<form method="post" action="">
<fieldset>
<legend>Retour de « {{$equipment.name}} (Catégorie : {{$category.name}}) »</legend>
<dl>
{{:input type="select" name="operation" label="Type" required=true options=$return_label}}
{{:input type="date" name="date" label="Date" required=true default=$now|date_short}}
{{:input type="number" name="amount" label="Quantité" min=1 max=$exterieur required=true default=$exterieur}}
{{:input type="textarea" name="comment" label="Remarques" cols="40", rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>
{{:admin_footer}}

View file

@ -1,27 +0,0 @@
/**
* désactiver le tri des colonnes ayant la classe nosort dans une liste triable
* @param {Node} liste - liste triable
*/
function disableColumSort(liste) {
// chercher la première ligne du corps de la table
let columns = liste.querySelectorAll("tbody > tr > td");
// chercher la ligne de titres
let titles = liste.querySelectorAll("thead > tr > td");
// désactiver le tri
for (let i = 0; i < titles.length; ++i) {
let anchor = titles[i].querySelector("a");
const classAttr = columns[i].getAttribute("class");
if (anchor != null && classAttr != null && classAttr.includes("nosort")) {
anchor.removeAttribute("href");
anchor.removeAttribute("title");
anchor.removeChild(anchor.firstElementChild);
let headerClass = titles[i].getAttribute("class");
if (headerClass == null) { headerClass = ""; }
headerClass += "nosort";
titles[i].setAttribute("class", headerClass);
}
}
}

View file

@ -1,149 +0,0 @@
{{* -*- brindille -*- *}}
{{#restrict section="users" level="read"}}{{/restrict}}
{{* lecture config (défaut ou enregistrée) *}}
{{:include file="../_get_config.html" keep="config, directions"}}
{{#foreach from=$directions key="direction"}}
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key=key}}
{{:assign var="types.%s.%s."|args:$direction:$type value=$key|quote_sql}}
{{/foreach}}
{{:assign var="io_types" from="types.%s"|args:$direction}}
{{#foreach from=$io_types key=key}}
{{:assign var=elem from="io_types.%s"|args:$key}}
{{:assign elem=$elem|implode:","}}
{{:assign elem="("|cat:$elem|cat:")"}}
{{:assign var="%s_types.%s"|args:$direction:$key value=$elem}}
{{/foreach}}
{{/foreach}}
{{#select
eqpmt.key as eqpmt_key,
json_extract(eqpmt.document, '$.name') as eqpmt_name,
mvt.key AS mvt_key,
json_extract(mvt.document, '$.direction') as direction,
json_extract(mvt.document, '$.operation') as operation,
json_extract(mvt.document, '$.date') as date,
json_extract(mvt.document, '$.amount') as amount
FROM module_data_equipment AS mvt
INNER JOIN users ON json_extract(mvt.document, '$.user') = users.id
INNER JOIN module_data_equipment AS eqpmt
ON json_extract(mvt.document, '$.equipment') = eqpmt.key
WHERE users.id = :user
AND (json_extract(mvt.document, '$.operation') IN !output_types
OR json_extract(mvt.document, '$.operation') IN !input_types)
ORDER BY date
;
:user = $user.id
!output_types=$output_types.temporaire
!input_types=$input_types.retour
assign="temp_mat."
}}
{{/select}}
{{if $temp_mat|count != 0}}
<h3 class="ruler">Matériels attribués temporairement</h3>
<table class="list">
<thead>
<tr>
<td>Date</td>
<td>Opération</td>
<td>Matériel</td>
<td>Quantité</td>
<td>Total</td>
<td class="actions"></td>
</tr>
</thead>
<tbody>
{{#foreach from=$temp_mat}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$direction:$operation}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
{{:assign var="total" from="reste.%s"|args:$eqpmt_key}}
{{if $total == null}}
{{:assign total=0}}
{{/if}}
{{if $direction == 'input' && $type_mvt == 'retour'}}
{{:assign var="reste.%s"|args:$eqpmt_key value="%d-%d"|math:$total:$amount}}
{{elseif $direction == 'output' && $type_mvt == 'temporaire'}}
{{:assign var="reste.%s"|args:$eqpmt_key value="%d+%d"|math:$total:$amount}}
{{/if}}
{{:assign var="total" from="reste.%s"|args:$eqpmt_key}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$op_label}}</td>
<td>{{$eqpmt_name}}</td>
<td>{{$amount}}</td>
<td>{{$total}}</td>
<td class="actions">
{{if $direction == "output" && $type_mvt == "temporaire"}}
{{:linkbutton
label="Retour"
href="%smovements/output_return.html?key=%s&prop=0&user=%s"|args:$module.url:$mvt_key:$user.id
shape="history"
target="_dialog"}}
{{/if}}
</td>
</tr>
{{/foreach}}
</tbody>
</table>
{{/if}}
{{#select
eqpmt.key as eqpmt_key,
json_extract(eqpmt.document, '$.name') as eqpmt_name,
json_extract(mvt.document, '$.direction') as direction,
json_extract(mvt.document, '$.operation') as operation,
json_extract(mvt.document, '$.date') as date,
json_extract(mvt.document, '$.amount') as amount
FROM module_data_equipment AS mvt
INNER JOIN users ON json_extract(mvt.document, '$.user') = users.id
INNER JOIN module_data_equipment AS eqpmt
ON json_extract(mvt.document, '$.equipment') = eqpmt.key
WHERE users.id = :user
AND json_extract(mvt.document, '$.operation') IN !output_types
ORDER BY date DESC
;
:user = $user.id
!output_types=$output_types.définitif
assign="def_mat."
}}
{{/select}}
{{if $def_mat|count != 0}}
<h3 class="ruler">Matériels attribués définitivement</h3>
<table class="list">
<thead>
<tr>
<td>Date</td>
<td>Opération</td>
<td>Matériel</td>
<td>Quantité</td>
<td>Total</td>
</tr>
</thead>
<tbody>
{{#foreach from=$def_mat}}
{{:assign var="type_mvt" from="config.%s_nature.%s.type"|args:$direction:$operation}}
{{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
{{:assign var="total" from="reste.%s"|args:$eqpmt_key}}
{{if $total == null}}
{{:assign total=0}}
{{/if}}
{{if $direction == 'output' && $type_mvt == 'définitif'}}
{{:assign var="reste.%s"|args:$eqpmt_key value="%d+%d"|math:$total:$amount}}
{{/if}}
{{:assign var="total" from="reste.%s"|args:$eqpmt_key}}
<tr>
<td>{{$date|date_short}}</td>
<td>{{$op_label}}</td>
<td>{{$eqpmt_name}}</td>
<td>{{$amount}}</td>
<td>{{$total}}</td>
</tr>
{{/foreach}}
</tbody>
</table>
{{/if}}

View file

@ -1,43 +0,0 @@
{{* -*- brindille -*- *}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* vérification *}}
{{if $_POST.name == null}}
{{:error message="Le nom du lieu de stockage est obligatoire"}}
{{/if}}
{{#load type="storage" where="$$.name = :name" :name=$_POST.name|trim limit=1}}
{{:error message="Ce nom est déjà utilisé"}}
{{/load}}
{{:save
key=""|uuid
validate_schema="storage.schema.json"
type="storage"
name=$_POST.name|trim
location=$_POST.location|trim
}}
{{:redirect force="index.html?ok=1&msg=ajout"}}
{{/form}}
{{:admin_header title="Lieu de stockage" current="module_equipment"}}
{{* barre de navigation *}}
{{if ! $dialog}}
{{:include file="../_nav.html" current="storage"}}
{{/if}}
{{:form_errors}}
<form method="post" action="" data-focus="1">
<fieldset class="storage">
<legend>Ajouter un lieu de stockage</legend>
<dl>
{{:input type="text" name="name" label="Nom" required=true}}
{{:input type="textarea" name="location" label="Emplacement" cols="40", rows="3" required=false}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>

View file

@ -1,27 +0,0 @@
{{* -*- brindille -*- *}}
{{*
paramètres :
- key : clé du stockage à supprimer
*}}
{{#form on="delete"}}
{{* vérifier s'il est possible de supprimer le lieu de stockage *}}
{{#load type="movement" where="$$.storage = :storage_key" :storage_key=$_GET.key limit=1}}
{{:redirect force="index.html?err=1&msg=suppression"}}
{{/load}}
{{:delete where="key = :key" :key=$_GET.key}}
{{:redirect force="index.html?ok=1&msg=suppression"}}
{{/form}}
{{:admin_header title="Lieux de stockage" custom_css="../style.css" current="module_equipment"}}
{{:form_errors}}
{{#load key=$_GET.key limit="1" assign="store"}}{{/load}}
{{:delete_form
legend="Supprimer %s ?"|args:$store.name
warning="Confirmer la suppression de « %s »"|args:$store.name
}}

View file

@ -1,44 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Afficher les lieux de stockage
*}}
{{:admin_header title="Configuration" current="module_equipment"}}
{{:include file="../_nav.html" current="config" subcurrent="storage"}}
{{if $_GET.ok}}
{{if $_GET.msg == "ajout"}}
<p class="block confirm">Ajout effectué</p>
{{elseif $_GET.msg == "suppression"}}
<p class="block confirm">Suppression effectuée</p>
{{/if}}
{{elseif $_GET.err}}
{{if $_GET.msg == "suppression"}}
<p class="block error">Impossible de supprimer ce lieu de stockage car il est utilisé !</p>
{{else}}
<p class="block error">Opération refusée</p>
{{/if}}
{{/if}}
{{#list
type="storage"
select="
$$.name AS 'Nom';
$$.location AS 'Emplacement'
"
}}
<tr>
<td>{{$name}}</td>
<td>{{$location}}</td>
<td class="actions">
{{:linkbutton label="Modifier" shape="edit" href="modify_storage.html?key=%s"|args:$key target="_dialog"}}
{{:linkbutton label="Supprimer" shape="delete" href="delete_storage.html?key=%s"|args:$key target="_dialog"}}
</td>
</tr>
{{else}}
<p class="block alert">Aucun lieu de stockage.</p>
{{/list}}
{{:admin_footer}}

View file

@ -1,53 +0,0 @@
{{* -*- brindille -*- *}}
{{* récupérer les infos du lieu de stockage *}}
{{#load key=$_GET.key assign="storage"}}
{{else}}
{{:error message="Lieu de stockage introuvable"}}
{{/load}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{* voir si le nom a changé *}}
{{if $_POST.name|trim == $storage.name}}
{{* voir si l'emplacement a changé *}}
{{if $_POST.location|trim != $storage.location}}
{{:assign modif=true}}
{{/if}}
{{else}}
{{* voir s'il existe un lieu de stockage de même nom *}}
{{#load type="storage" where="$$.name = :name" :name=$_POST.name|trim limit=1}}
{{:error message="Modification impossible car ce nom (« %s ») est déjà utilisé !"|args:$name|trim}}
{{else}}
{{:assign modif=true}}
{{/load}}
{{/if}}
{{if $modif}}
{{:save
key=$storage.key
validate_schema="storage.schema.json"
type="storage"
name=$_POST.name|trim
location=$_POST.location|trim
}}
{{/if}}
{{:redirect force="./index.html?ok=1&msg=modification"}}
{{/form}}
{{:admin_header title="Modifier un lieu de stockage" current="module_equipment"}}
{{:form_errors}}
{{* formulaire de modification d'un lieu de stockage *}}
<form method="post" action="" data-focus="1">
<fieldset class="modif_storage">
<legend>Modifier le lieu de stockage « {{$storage.name}} »</legend>
<dl>
{{:input type="text" name="name" label="Nom" default=$storage.name required=true maxlength="100"}}
{{:input type="textarea" name="location" label="Emplacement" default=$storage.location cols="40", rows="3" required=false}}
</dl>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</fieldset>
</form>

View file

@ -1,19 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["storage"]
},
"name" : {
"description": "Nom du lieu de stockage",
"type": "string"
},
"location": {
"description": "Emplacement du lieu de stockage",
"type": "string"
}
},
"required": ["type", "name"]
}

View file

@ -1,26 +0,0 @@
.informations {
margin-top : 0.5em;
}
.informations dt::after {
content: ' :';
}
.informations dl.describe {
margin : 0;
}
.informations dl.describe > dt {
flex: 0 0 10rem;
margin-right: 0;
}
.informations dl.describe > dd {
margin-top : 0;
margin-left : 0;
}
/* désactiver rétroaction pour colonnes non triables */
table.list > thead td[class~=nosort] a:hover {
background-color : rgba(var(--gSecondColor), 0.);
}

View file

@ -1,51 +0,0 @@
{{* -*- brindille -*- *}}
{{*
Remettre le matériel en service
Paramètres :
- key : clé du matériel à modifier
*}}
{{:assign equipment_key=$_GET.key|trim}}
{{#load key=$_GET.key assign="equipment"}}
{{else}}
{{:error message="Pas de matériel avec la clé %s"|args:$equipment_key}}
{{/load}}
{{* Traiter l'envoi du formulaire *}}
{{#form on="save"}}
{{if $_POST.unarchive != 1}}
{{:save
key=$equipment.key
status="available"
}}
{{:redirect force="archives.html?ok=1&msg=modification"}}
{{/if}}
{{:redirect force="archives.html"}}
{{/form}}
{{:admin_header title="Modifier matériel" custom_css="./style.css" current="module_equipment"}}
{{:form_errors}}
{{#load key=$equipment.category}}
{{:assign cat_name=$name}}
{{/load}}
<form method="post" action="">
<fieldset class="informations">
<legend>Désarchiver un matériel</legend>
<dl class="describe">
<dt>Matériel</dt>
<dd>{{$equipment.name}}</dd>
<dt>Catégorie</dt>
<dd>{{$cat_name}}</dd>
</dl>
<dl>
{{:input type="checkbox" value=1 name="unarchive" label="Archivé" checked="checked" help="décocher pour remettre le matériel en service"}}
</dl>
</fieldset>
<p class="submit">
{{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}}
</p>
</form>