Compare commits

..

145 Commits
0.1 ... main

Author SHA1 Message Date
2c20102254 Update README.md 2025-06-03 09:13:20 +02:00
ec249b78ee Modification condition archivage matériel 2025-05-19 14:16:06 +02:00
8d5ea202fe Contournement dysfonctionnement chemin fichier style 2025-05-19 14:15:31 +02:00
e32693ed31 Réorganisation fichiers et répertoires 2025-05-19 11:31:00 +02:00
da6b550cb6 Modifications mineures 2025-05-12 14:21:19 +02:00
e3d494422f Correction dysfonctionnement incompréhensible 2025-05-12 14:20:55 +02:00
afab91e414 Opérateur = conforme norme SQL 2025-05-12 14:18:23 +02:00
4736cce759 Amélioration condition filtrage compatible pagination 2025-04-24 10:15:30 +02:00
96251821da amélioration affichage erreur 2025-04-22 14:32:40 +02:00
99ed711eb7 Correction erreur retour d'entrée temporaire 2025-04-22 14:28:27 +02:00
638855e6fc correction erreur modification mouvement 2025-04-22 14:23:09 +02:00
467a094b14 Amélioration création et modification lieu stockage 2025-04-18 21:42:02 +02:00
92ec78b6c1 historiques : ajout id mouvement à la date pour tri 2025-04-18 17:56:12 +02:00
00388f86ba Déplacement gestion lieu stockage dans configuration 2025-04-18 17:55:17 +02:00
6c5ea7e064 Retour de sortie temporaire : correction erreur membre 2025-04-09 20:14:32 +02:00
11d4946b92 correction erreur suppression lieu de stockage 2025-04-08 20:32:55 +02:00
ef69c76e7c Fiche membre : ajout total et amélioration présentation 2025-04-08 20:32:15 +02:00
d3b48c677e Simplification sortie matériel en stock 2025-04-04 12:31:17 +02:00
c681b47e7f Distinguer matériel de stock nul et matériel non présent 2025-04-04 11:07:41 +02:00
f8e5d43888 Amélioration navigation fiche membre 2025-04-04 11:02:39 +02:00
0110cf277a Suppression bouton inutile 2025-04-02 11:06:49 +02:00
bcb8cd581d correction erreur matériel membre 2025-04-02 10:12:43 +02:00
300f9b8248 Améliorations cosmétiques 2025-04-02 10:12:15 +02:00
6a603d1713 mise à jour et simplification README 2025-03-31 22:01:36 +02:00
7340f44aa8 fiche membre : ajout bouton retour et séparation mouvements temporaires et définitifs 2025-03-31 12:26:06 +02:00
8f759dcf77 Amélioration cosmétique 2025-03-31 12:25:44 +02:00
c0ed6d4401 correction erreur suppression mouvement 2025-03-31 12:25:14 +02:00
72d1ed010f Traitement cas aucun lieu stockage 2025-03-31 12:23:25 +02:00
68284ee309 fusion branche retourhisto 2025-03-31 12:21:22 +02:00
7b3dcbce01 Ajout lieu de stockage et membre destinataire sortie 2025-03-28 10:43:54 +01:00
c251573049 onglet historique : ajout boutons entrée/sortie/retour 2025-03-27 15:53:55 +01:00
c6177b4438 correction erreur retour de sortie temporaire 2025-03-27 14:06:54 +01:00
610af4e6a8 simplification casse et améliorations présentation 2025-03-27 11:20:55 +01:00
5c7e6e9b0f petites améliorations présentation 2025-03-27 10:59:00 +01:00
c10ff02403 Enregistrement quantités avec matériel 2025-03-24 20:47:49 +01:00
3ba67d0c65 modification schéma entrées/sorties temporaires liées 2025-03-22 11:33:35 +01:00
16d6ac752a suppression fichiers inutiles 2025-03-21 15:41:07 +01:00
ce87720d41 ajout liaison entre entrée temporaire et retour 2025-03-21 14:58:52 +01:00
144a909494 ajout liaison entre sortie temporaire et retour 2025-03-20 17:18:34 +01:00
bea3a2f0e8 Correction erreur validation retour 2025-03-06 17:26:34 +01:00
95db394d7a Bouton retour dans historique 2025-03-06 13:29:56 +01:00
f0a30a7c5d fusion branche main 2025-03-06 10:16:15 +01:00
ea57338cb8 Correction erreur validation retour 2025-03-06 10:05:30 +01:00
d241546371 modification affichage suppression 2025-03-05 20:26:33 +01:00
6d05a8f95c Modification légendes 2025-03-03 12:15:16 +01:00
1f38e394fc Poursuite gestion lieu stockage 2025-03-03 12:14:31 +01:00
966323acdf début ajout lieu stockage 2025-03-01 10:17:44 +01:00
42210d2c9a suppression fichiers inutiles 2025-03-01 09:02:17 +01:00
ceb88fafda début traitement membre dépositaire 2025-03-01 09:02:03 +01:00
1478f7dbdc suppression fichiers inutiles 2025-02-28 22:33:37 +01:00
3ebcd07b23 Ajout choix vide aux sélecteurs 2025-02-28 10:20:29 +01:00
a2488aaf52 Mise-à-jour README 2025-02-27 13:35:29 +01:00
5d65786913 petites simplifications 2025-02-27 11:50:47 +01:00
8c31491c19 Modification paramétrage calcul_dispo 2025-02-27 11:03:33 +01:00
262d1935ca Mutualisation E/S et petites simplifications 2025-02-27 10:35:27 +01:00
55e649ce0d Correction erreur modification mouvement 2025-02-26 18:55:41 +01:00
63abb4f573 Correction erreur navigation fin saisie 2025-02-26 12:39:55 +01:00
28abe5ce9e Filtrage historique global par catégorie 2025-02-26 12:25:39 +01:00
e856347d40 Simplification messages 2025-02-25 15:31:53 +01:00
5757c4161d historique global : désactiver tri par opération 2025-02-25 15:31:32 +01:00
688c335dd3 config : mutualisation E/S et correction erreur 2025-02-25 12:21:24 +01:00
0d48d9999c Simplification mineure 2025-02-24 15:18:57 +01:00
cd4220546e Amélioration présentation colonnes non triables 2025-02-24 15:18:54 +01:00
849dcf00c9 Ajout tri inventaire sur quantité disponible 2025-02-24 14:57:10 +01:00
39bd89234a Suppression scripts inutiles 2025-02-22 13:11:16 +01:00
c893639b9e désactiver tri colonnes de class nosort dans une liste triable 2025-02-22 13:09:46 +01:00
0be13c1c11 inventaire : ajout tri par quantité 2025-02-21 13:34:49 +01:00
17052676df inventaire : ajout tri par catégorie 2025-02-20 11:58:57 +01:00
7fd67d7d9d Modification titres 2025-02-20 11:40:57 +01:00
81040dc040 Simplification filtrage inventaire 2025-02-20 11:40:27 +01:00
cb91f0a624 Ajout filtrage archives par catégorie 2025-02-20 11:39:51 +01:00
4a46099275 Ajout archivage matériels de stock nul 2025-02-20 10:29:57 +01:00
3e0f3159ae ajout historique global des mouvements 2025-02-19 15:12:17 +01:00
dbbff606f6 renommage champ designation => name 2025-02-18 14:13:11 +01:00
9ac71344fb Interdire date dans le futur 2025-02-18 13:38:28 +01:00
92b79b75dc Modifications cosmétiques 2025-02-18 12:13:56 +01:00
0af9cee03c fin refonte config types ES 2025-02-17 21:02:46 +01:00
08ff1f82fd refonte config types ES 2025-02-17 14:23:09 +01:00
b19904b05b début nouvelle config types ES 2025-02-17 09:10:02 +01:00
b6de0c59c0 correction typo 2025-02-11 11:10:22 +01:00
5967686228 Améliorations cosmétiques 2025-02-10 10:25:10 +01:00
1f7d1cc682 dropdown : suppression balise inutile 2025-01-31 17:09:41 +01:00
76bd293930 Utilisation fonction :dropdown 2025-01-31 15:34:31 +01:00
64b2a37541 fusion branche evolUX dans main 2025-01-31 14:40:36 +01:00
fd4f9ee94e Mise-à-jour README 2025-01-31 14:35:24 +01:00
72cd82d254 amélioration vérification nom catégorie et matériel 2025-01-31 14:17:12 +01:00
42d85fb528 Bouton Ajouter catégorie sur page inventaire si aucune catégorie 2025-01-22 14:51:03 +01:00
f2a9cb6af6 déplacement admin_header et form_errors 2025-01-22 11:56:07 +01:00
be14aa6809 simplification formulaires 2025-01-22 11:18:32 +01:00
551097fbd1 modifications cosmétiques 2025-01-21 20:49:24 +01:00
f41caf7ad7 Correction présentation erreur 2025-01-17 21:47:18 +01:00
a77ce407cc Amélioration présentation nombres dans tables 2024-12-26 10:08:12 +01:00
e8da809830 Afficher les quantités en stock, sorties et dispo dans l'historique 2024-12-20 14:01:02 +01:00
e4ad0b6982 amélioration validation modification et copie mouvement 2024-12-20 11:22:24 +01:00
77b8f892cc correction typo 2024-12-12 09:44:46 +01:00
d40b17ef2c ajout catégorie formulaire retour emprunt 2024-12-12 09:43:04 +01:00
1c395c48e0 simplification et correction erreur stock_disponible 2024-12-11 16:39:46 +01:00
11806b11da simplification retour emprunt 2024-12-11 16:20:09 +01:00
7364deda87 Simplification calcul dispo 2024-12-11 10:08:13 +01:00
74ee34104f Suppression fichier inutile 2024-12-10 14:29:54 +01:00
75447396c4 Suppression paramètre prop inutile 2024-12-09 16:50:09 +01:00
edcecfd9e2 suppresssion module.url dans redirect 2024-12-02 10:47:38 +01:00
b5afcb8ea3 correction libellé retour 2024-12-02 09:33:42 +01:00
3132f3b7ce ajout contrôle quantité entrée matériel 2024-12-02 09:33:02 +01:00
3e3ae7b033 simplification affichage inventaire 2024-12-02 09:32:20 +01:00
56b11a0edf amélioration gestion casse modif catégorie 2024-11-27 13:53:21 +01:00
64d57b8560 fin réorganisation configuration 2024-11-21 12:26:30 +01:00
5c26cf3ad7 réorganisation ajout type mouvement 2024-11-20 10:28:58 +01:00
f4b98a6eac réorganisation ajout catégorie 2024-11-19 16:04:50 +01:00
e17613e532 amélioration navigation 2024-11-19 15:18:51 +01:00
09e4ce2a42 simplification modifier_mouvements 2024-11-19 15:18:09 +01:00
79a3719892 améliorations mineures 2024-11-18 20:47:48 +01:00
6757757f63 Amélioration navigation inventaire prop/non 2024-11-18 14:43:23 +01:00
c20be00ea4 Simplification ajouter_entree et amélioration retour 2024-11-18 11:10:47 +01:00
4d0bcc1bdd inventaire : amélioration cas 0 matériel 2024-11-16 10:26:48 +01:00
58c9de9870 Amélioration navigation/onglets 2024-11-16 10:25:16 +01:00
498e24e7ed Filtrage inventaire matériel temporaire par catégorie 2024-11-15 20:40:35 +01:00
dc314dcb3d Réorganisation onglet navigation 2024-11-15 20:27:42 +01:00
8305433f5b Filtrage inventaire par catégorie 2024-11-15 20:26:29 +01:00
ea0fd3b1a2 Début réorganisation après consultation bohwaz 2024-11-14 16:21:10 +01:00
a99f263196 affichage matériel propriété ou non dans historique après saisie 2024-11-12 16:55:51 +01:00
924c0f2e8e harmonisation présentation saisie mouvement 2024-11-12 16:54:56 +01:00
39733d8fcd simplification dupliquer mouvement 2024-11-12 16:53:53 +01:00
164c63dc14 suppression boutons Retour et Sortie de l'historique 2024-11-11 15:35:00 +01:00
ebda00d590 ajout retour sur page inventaire 2024-11-11 15:09:41 +01:00
e7538a11c8 ajout sortie sur page inventaire 2024-11-11 13:42:01 +01:00
528120d3a0 ajout entrée sur page inventaire 2024-11-08 19:49:23 +01:00
34f3328f12 suppression ajout matériel existant dans ajouter_entree 2024-11-08 16:58:20 +01:00
0b8e9e8f69 garantir quantité saisie positive 2024-10-29 15:19:04 +01:00
cdb7b83325 inventaire : ajout présence matériel propriété ou non 2024-10-29 14:56:05 +01:00
c2844a17bf ajout contrôle quantité positive 2024-10-29 14:52:34 +01:00
86443b9bb0 test présence matériel dans catégorie 2024-10-29 14:20:06 +01:00
795e55e172 vérification ajout matériel en double 2024-10-29 11:57:14 +01:00
4a24ea40db amélioration comparaison nom catégorie 2024-10-29 11:55:10 +01:00
5307a847b9 modification url et déplacement bouton créer nouveau matériel 2024-10-29 10:24:50 +01:00
9a11e55ad7 Suppression fichiers inutilisés 2024-10-28 13:41:19 +01:00
553cbdf978 Réorganisation module 2024-10-28 10:11:06 +01:00
4bba00f8e5 correction erreur modif mvt 2024-10-24 12:23:09 +02:00
84fb29c15d Ajout opérations lignes historique 2024-10-24 12:19:13 +02:00
8454c15225 Correction bug incompatibilité sortie matériel 2024-10-21 12:21:44 +02:00
c1b9aa25c2 calcul dispo : ajout condition date manquante 2024-10-21 11:02:47 +02:00
7575cc8a71 Dissocier dans l'inventaire les matériels propriété de l'asso ou non 2024-10-18 17:15:56 +02:00
5e5c470a24 correction typos 2024-10-17 12:22:03 +02:00
6b78d480f6 Corrections mineures 2024-03-26 17:58:24 +01:00
5eb8fa63fd Correction typos 2024-03-25 20:57:19 +01:00
61 changed files with 3418 additions and 1802 deletions

View File

@ -1,31 +1,30 @@
# Module de gestion de matériels pour Paheko
Ce module permet de gérer les matériels de l'association: stock, entrées, sorties.
## Ce dépôt n'est plus mis à jour ; nouvel emplacement https://gitea.zaclys.com/lesanges/equipment
## 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.
Ce module permet de gérer les matériels de l'association: stock,
entrées, sorties, classés par catégorie.
## 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 peut entrer temporairement (location, emprunt, ...) ou
définitivement dans l'association (achat, ...).
### 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 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.
### 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
Un matériel présent temporairement dans l'association peut être
retourné à son propriétaire.
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.
## Droits d'accès
Le module est accessible uniquement pour les membres ayant au moins le

View File

@ -1,112 +0,0 @@
{{*
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,35 +1,30 @@
{{* -*- 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="./defaut.json" assign="config_defaut"}}
{{:read file="./default.json" assign="config_defaut"}}
{{:assign config_defaut=$config_defaut|json_decode}}
{{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 *}}
{{#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}}
{{:assign var="directions.input" value="entrée"}}
{{:assign var="directions.output" value="sortie"}}
{{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 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}}
{{/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}}
{{: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}}
{{/if}}
{{/foreach}}

94
_inventory.html Normal file
View File

@ -0,0 +1,94 @@
{{* -*- 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,9 +1,59 @@
{{* -*- 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 == '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>
<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>
</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>

76
_temp_inventory.html Normal file
View File

@ -0,0 +1,76 @@
{{* -*- 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}}

68
archives.html Normal file
View File

@ -0,0 +1,68 @@
{{* -*- 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

@ -0,0 +1,43 @@
{{* -*- 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 @@
{{:admin_header title="Supprimer une catégorie" current="module_equipment"}}
{{* -*- brindille -*- *}}
{{#load key=$_GET.key assign="category"}}
{{else}}
@ -12,10 +12,13 @@
{{else}}
{{* supprimer la catégorie sélectionnée*}}
{{:delete where="key = :key" :key=$category.key}}
{{:redirect force="./index.html?ok=1&msg=suppression"}}
{{:redirect force="./index.html?ok=1&msg=suppression"|args:$msg}}
{{/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,18 +1,20 @@
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{* -*- brindille -*- *}}
{{:admin_header title="Configuration" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="../_nav.html" current="categories"}}
{{:include file="../_nav.html" current="config" subcurrent="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 == "modification"}}
<p class="block error">{{$_GET.msg}}</p>
{{elseif $_GET.msg == "suppression"}}
{{if $_GET.msg == "suppression"}}
<p class="block error">
Cette catégorie ne peut être supprimée car elle contient encore des matériels
</p>
@ -22,10 +24,16 @@
{{* 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>
@ -35,37 +43,4 @@
{{/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

@ -1,15 +0,0 @@
{{#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 @@
{{:admin_header title="Modifier une catégorie" current="module_equipment"}}
{{* -*- brindille -*- *}}
{{#load key=$_GET.key assign="category"}}
{{else}}
@ -7,6 +7,11 @@
{{* 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"
@ -16,10 +21,11 @@
{{: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="">
<form method="post" action="" data-focus="1">
<fieldset class="modif_categorie">
<legend>Modifier la catégorie « {{$category.name}} »</legend>
<dl>

View File

@ -1,162 +1,52 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Configuration" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="_nav.html" current="config"}}
{{:include file="_nav.html" current="config" subcurrent="typesES"}}
{{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"}}
{{:include file="./_get_config.html" keep="config, directions"}}
{{* types d'entrées *}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{:assign var='input_types.%s'|args:$type value=$type}}
{{/foreach}}
{{#foreach from=$directions key="direction" item="item"}}
{{* 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}}
{{* 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}}
{{/load}}
{{* 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">
<h2 class="ruler">{{$item|ucfirst}}s</h2>
<table class="list">
<thead>
<tr>
<th>Nature de l'entrée</th>
<th>Libellé</th>
<th>Type</th>
<th>Action</th>
<th></th>
</tr>
</thead>
<tbody id="input_body">
{{#foreach from=$config.input_nature key="label" item="type"}}
<tbody>
{{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key=key}}
<tr>
<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>{{$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>
</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,6 +8,9 @@
"items": {
"type": "object",
"properties": {
"key" : {
"type" : "string"
},
"label" : {
"type" : "string"
},
@ -24,6 +27,9 @@
"items": {
"type": "object",
"properties": {
"key" : {
"type" : "string"
},
"label" : {
"type" : "string"
},

View File

@ -0,0 +1,136 @@
{{* -*- 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

@ -0,0 +1,49 @@
{{* -*- 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

@ -0,0 +1,58 @@
{{* -*- 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>

37
default.json Normal file
View File

@ -0,0 +1,37 @@
{
"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"
}
]
}

View File

@ -1,12 +0,0 @@
{
"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,10 +10,30 @@
"description": "Clé de la catégorie",
"type": "string"
},
"designation": {
"name": {
"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", "designation"]
"required": ["type", "category", "name", "status", "stock", "out", "notowned"]
}

341
equipment_history.html Normal file
View File

@ -0,0 +1,341 @@
{{* -*- 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>

94
global_history.html Normal file
View File

@ -0,0 +1,94 @@
{{* -*- 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>

View File

@ -1,34 +0,0 @@
{{: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,22 +1,39 @@
{{:admin_header title="Gestion des matériels" custom_css=$custom_css current="module_equipment"}}
{{* -*- brindille -*- *}}
{{:admin_header title="Gestion des matériels" current="module_equipment"}}
{{* barre de navigation *}}
{{:include file="_nav.html" current="index"}}
{{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}}
{{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}}
{{#load type="category"}}
{{:assign var="category_keys." value=$key}}
{{/load}}
{{if $category_keys|count == 0}}
{{if $result.count == 0}}
<p class="block alert">Il n'y a aucune catégorie : vous devez en ajouter.</p>
{{else}}
{{:include file="./inventaire.html" print_cat_name=true}}
{{if $_GET.prop == null || $_GET.prop == "1"}}
{{:include file="./_inventory.html"}}
{{else}}
{{:include file="./_temp_inventory.html"}}
{{/if}}
{{/if}}
{{:admin_footer}}

View File

@ -1,150 +0,0 @@
{{* 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}}

View File

@ -1,73 +0,0 @@
{{: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>

95
modify_equipment.html Normal file
View File

@ -0,0 +1,95 @@
{{* -*- 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,5 +1,5 @@
name="Gestion des matériels"
description="Gestion des matériels: stock, entrées, sorties."
description="Permet de gérer un inventaire de matériels, ainsi que de suivre les prêts (en test)."
author="Jean-Christophe Engel"
author_url="https://git.roflcopter.fr/lesanges"
home_button=false

View File

@ -1,12 +0,0 @@
{{* 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

@ -1,85 +0,0 @@
{{: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

@ -1,103 +0,0 @@
{{: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

@ -1,99 +0,0 @@
{{: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

@ -1,83 +0,0 @@
{{: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

@ -1,99 +0,0 @@
{{: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

@ -1,185 +0,0 @@
{{: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

@ -1,12 +0,0 @@
{{* 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

@ -1,87 +0,0 @@
{{: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

@ -1,110 +0,0 @@
{{: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

@ -1,101 +0,0 @@
{{: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

@ -1,121 +0,0 @@
{{: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

@ -1,44 +0,0 @@
{{*
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

@ -0,0 +1,44 @@
{{* -*- 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

@ -0,0 +1,155 @@
{{* -*- 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

@ -0,0 +1,257 @@
{{* -*- 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

@ -0,0 +1,171 @@
{{* -*- 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

@ -0,0 +1,120 @@
{{* -*- 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}}

205
movements/input_return.html Normal file
View File

@ -0,0 +1,205 @@
{{* -*- 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

@ -0,0 +1,23 @@
{
"$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

@ -0,0 +1,275 @@
{{* -*- 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

@ -11,13 +11,9 @@
"type": "string",
"enum": ["input", "output"]
},
"input_nature": {
"description": "Nature de l'entrée",
"type": ["null", "string"]
},
"output_nature": {
"description": "Nature de la sortie",
"type": ["null", "string"]
"operation": {
"description": "clé de l'opération",
"type": "string"
},
"amount": {
"description": "Quantité ajoutée ou retirée",
@ -36,7 +32,15 @@
"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", "amount", "equipment", "date", "comment"]
"required": ["type", "direction", "operation", "amount", "equipment", "date", "comment"]
}

View File

@ -0,0 +1,199 @@
{{* -*- 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

@ -0,0 +1,209 @@
{{* -*- 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}}

27
scripts.js Normal file
View File

@ -0,0 +1,27 @@
/**
* 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);
}
}
}

149
snippets/user_details.html Normal file
View File

@ -0,0 +1,149 @@
{{* -*- 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}}

43
storage/add_storage.html Normal file
View File

@ -0,0 +1,43 @@
{{* -*- 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

@ -0,0 +1,27 @@
{{* -*- 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
}}

44
storage/index.html Normal file
View File

@ -0,0 +1,44 @@
{{* -*- 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

@ -0,0 +1,53 @@
{{* -*- 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

@ -0,0 +1,19 @@
{
"$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"]
}

26
style.css Normal file
View File

@ -0,0 +1,26 @@
.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.);
}

51
unarchive_equipment.html Normal file
View File

@ -0,0 +1,51 @@
{{* -*- 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>