Compare commits

...

145 commits
0.1 ... main

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

View file

@ -1,31 +1,28 @@
# Module de gestion de matériels pour Paheko # 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 module permet de gérer les matériels de l'association: stock,
entrées, sorties, classés par catégorie.
## Configuration Un matériel peut entrer temporairement (location, emprunt, ...) ou
- Il y a plusieurs types d'entrée et de sorties prédéfinies (Achat, définitivement dans l'association (achat, ...).
Location, Vente, ...) mais il est possible d'en ajouter d'autres.
## Démarrage Un matériel appartenant à l'association peut sortir :
- Il faut commencer par créer des catégories de matériel (ex: - temporairement (prêt, ...) : il est possible de lui associer un lieu
Audiovisuel, Informatique, Mobilier, ...). de stockage ainsi qu'un membre dépositaire du matériel ; il peut
- On peut ensuite ajouter des entrées puis des sorties. ensuite revenir dans l'association.
- définitivement (vente, ...) : il est possible de lui associer un
membre bénéficiaire du matériel.
### Entrées Un matériel présent temporairement dans l'association peut être
Il y a trois boutons pour ajouter une entrée : retourné à son propriétaire.
- 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)
### Sorties Un matériel dont il n'existe plus d'exemplaire en stock peut être archivé.
Il y a deux boutons pour ajouter une sortie :
- Matériel en stock disponible : ajouter une sortie pour du matériel On peut lister l'ensemble des mouvements des matériels ou seulement
propriété de l'association ceux d'un matériel donné.
- 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 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 ## Droits d'accès
Le module est accessible uniquement pour les membres ayant au moins le 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écupérer soit la config enregistrée, soit la config par défaut
résultat : config.input_nature et config.output_nature résultat : config.input_nature et config.output_nature
*}} *}}
{{* config par défaut *}} {{* 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}} {{:assign config_defaut=$config_defaut|json_decode}}
{{if $module.config.input_nature != null}} {{:assign var="directions.input" value="entrée"}}
{{#foreach from=$module.config.input_nature item="elem"}} {{:assign var="directions.output" value="sortie"}}
{{: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}}
{{if $module.config.output_nature != null}} {{#foreach from=$directions key="direction"}}
{{#foreach from=$module.config.output_nature item="elem"}} {{:assign var="nature" from="module.config.%s_nature"|args:$direction}}
{{:assign var="config.output_nature.%s"|args:$elem.label value=$elem.type}} {{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}} {{/foreach}}
{{* :assign var=config.output_nature value=$module.config.output_nature *}}
{{else}} {{else}}
{{* pas de config enregistrée : utiliser la config par défaut *}} {{* pas de config enregistrée : utiliser la config par défaut *}}
{{#foreach from=$config_defaut.outputs item="elem"}} {{:assign var="nature" from="config_defaut.%ss"|args:$direction}}
{{#foreach from=$elem key=label item=value}} {{#foreach from=$nature item="elem"}}
{{:assign var="config.output_nature.%s"|args:$label value=$value}} {{:assign var="item" label=$label type=$type}}
{{/foreach}} {{:assign var="config.%s_nature.%s"|args:$direction:$key value=$item}}
{{/foreach}} {{/foreach}}
{{/if}} {{/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"> <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> <ul>
<li {{if $current == 'index'}} class="current"{{/if}}><a href="{{$module.url}}index.html">Inventaire</a></li> <li {{if $current == 'inventaire'}} class="current"{{/if}}><a href="{{$module.url}}index.html?prop=1">Inventaire</a></li>
<li {{if $current == 'categories'}} class="current"{{/if}}><a href="{{$module.url}}categories/index.html">Catégories</a></li> <li {{if $current == 'historique'}} class="current"{{/if}}><a href="{{$module.url}}global_history.html">Historique</a></li>
<li {{if $current == 'entrees'}} class="current"{{/if}}><a href="{{$module.url}}mouvements/entrees/index.html">Entrées</a></li> <li {{if $current == 'archives'}} class="current"{{/if}}><a href="{{$module.url}}archives.html">Archives</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}}categories/index.html">Configuration</a></li>
<li {{if $current == 'config'}} class="current"{{/if}}><a href="{{$module.url}}config.html">Configuration</a></li>
</ul> </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> </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"}} {{#load key=$_GET.key assign="category"}}
{{else}} {{else}}
@ -12,10 +12,13 @@
{{else}} {{else}}
{{* supprimer la catégorie sélectionnée*}} {{* supprimer la catégorie sélectionnée*}}
{{:delete where="key = :key" :key=$category.key}} {{: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}} {{/load}}
{{/form}} {{/form}}
{{:admin_header title="Supprimer une catégorie" current="module_equipment"}}
{{:form_errors}}
{{:delete_form {{:delete_form
legend="Supprimer une catégorie" legend="Supprimer une catégorie"
warning="Supprimer la catégorie « %s » ?"|args:$category.name 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 *}} {{* barre de navigation *}}
{{:include file="../_nav.html" current="categories"}} {{:include file="../_nav.html" current="config" subcurrent="categories"}}
{{if $_GET.ok}} {{if $_GET.ok}}
{{if $_GET.msg == "modification"}} {{if $_GET.msg == "modification"}}
<p class="block confirm">Modification enregistrée</p> <p class="block confirm">Modification enregistrée</p>
{{elseif $_GET.msg == "suppression"}} {{elseif $_GET.msg == "suppression"}}
<p class="block confirm">Catégorie supprimée</p> <p class="block confirm">Catégorie supprimée</p>
{{elseif $_GET.msg == "ajout"}}
<p class="block confirm">Catégorie ajoutée</p>
{{/if}} {{/if}}
{{elseif $_GET.err}} {{elseif $_GET.err}}
{{if $_GET.msg == "modification"}} {{if $_GET.msg == "suppression"}}
<p class="block error">{{$_GET.msg}}</p>
{{elseif $_GET.msg == "suppression"}}
<p class="block error"> <p class="block error">
Cette catégorie ne peut être supprimée car elle contient encore des matériels Cette catégorie ne peut être supprimée car elle contient encore des matériels
</p> </p>
@ -22,10 +24,16 @@
{{* afficher les catégories déjà enregistrées *}} {{* afficher les catégories déjà enregistrées *}}
<section class="categories"> <section class="categories">
{{#list select="$$.name AS 'Catégorie'" order="1" where="$$.type = 'category'"}} {{#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> <tr>
<th>{{$name}}</th> <th>{{$name}}</th>
<td class="actions"> <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="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"}} {{:linkbutton label="Supprimer" href="delete_category.html?key=%s"|args:$key shape="delete" target="_dialog"}}
</td> </td>
@ -35,37 +43,4 @@
{{/list}} {{/list}}
</section> </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}} {{: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"}} {{#load key=$_GET.key assign="category"}}
{{else}} {{else}}
@ -7,6 +7,11 @@
{{* Traiter l'envoi du formulaire *}} {{* Traiter l'envoi du formulaire *}}
{{#form on="save"}} {{#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 {{:save
key=$category.key key=$category.key
validate_schema="./category.schema.json" validate_schema="./category.schema.json"
@ -16,10 +21,11 @@
{{:redirect force="./index.html?ok=1&msg=modification"}} {{:redirect force="./index.html?ok=1&msg=modification"}}
{{/form}} {{/form}}
{{:admin_header title="Modifier une catégorie" current="module_equipment"}}
{{:form_errors}} {{:form_errors}}
{{* formulaire de modification de catégorie *}} {{* formulaire de modification de catégorie *}}
<form method="post" action=""> <form method="post" action="" data-focus="1">
<fieldset class="modif_categorie"> <fieldset class="modif_categorie">
<legend>Modifier la catégorie « {{$category.name}} »</legend> <legend>Modifier la catégorie « {{$category.name}} »</legend>
<dl> <dl>

View file

@ -1,162 +1,52 @@
{{* -*- brindille -*- *}}
{{:admin_header title="Configuration" current="module_equipment"}} {{:admin_header title="Configuration" current="module_equipment"}}
{{* barre de navigation *}} {{* barre de navigation *}}
{{:include file="_nav.html" current="config"}} {{:include file="_nav.html" current="config" subcurrent="typesES"}}
{{if $_GET.ok}} {{if $_GET.ok}}
<p class="block confirm">Configuration enregistrée.</p> <p class="block confirm">Configuration enregistrée.</p>
{{/if}} {{/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) *}} {{* 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=$directions key="direction" item="item"}}
{{#foreach from=$config.input_nature key="label" item="type"}}
{{:assign var='input_types.%s'|args:$type value=$type}}
{{/foreach}}
{{* Natures d'entrées qui ne peuvent être supprimées *}} {{* types de mouvements qui ne peuvent être supprimés *}}
{{#load type="movement" where="$$.direction='input'" group="$$.input_nature"}} {{#load type="movement" where="$$.direction='%s'"|args:$direction group="$$.operation"}}
{{:assign var="locked_inputs." value=$input_nature}} {{:assign var="op_label" from="config.%s_nature.%s.label"|args:$direction:$operation}}
{{:assign var="locked_%ss."|args:$direction value=$op_label}}
{{/load}} {{/load}}
{{* types de sorties *}} <h2 class="ruler">{{$item|ucfirst}}s</h2>
{{#foreach from=$config.output_nature key="label" item="type"}} <table class="list">
{{:assign var='output_types.%s'|args:$type value=$type}}
{{/foreach}}
{{* Natures de sorties qui ne peuvent être supprimées *}}
{{#load type="movement" where="$$.direction='output'" group="$$.output_nature"}}
{{:assign var="locked_outputs." value=$output_nature}}
{{/load}}
<form method="post" action="">
<fieldset>
<legend>Entrées</legend>
<table class="list input_fields">
<thead> <thead>
<tr> <tr>
<th>Nature de l'entrée</th> <th>Libellé</th>
<th>Type</th> <th>Type</th>
<th>Action</th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody id="input_body"> <tbody>
{{#foreach from=$config.input_nature key="label" item="type"}} {{:assign var="nature" from="config.%s_nature"|args:$direction}}
{{#foreach from=$nature key=key}}
<tr> <tr>
<td>{{:input type="text" name="input_fields[label][]" default=$label}}</td> <td>{{$label}}</td>
<td>{{:input type="select" <td>{{$type}}</td>
name="input_fields[type][]" <td class="actions">
options=$input_types {{:assign var="locked" from="locked_%ss"|args:$direction}}
default=$type {{if ! $locked|has:$label}}
required=true {{:linkbutton label="Supprimer" shape="delete" href="config/delete_movement_type.html?dir=%s&op_key=%s"|args:$direction:$key target="_dialog"}}
default_empty="— Choisir un type —"}} {{/if}}
</td> {{:linkbutton label="Modifier" shape="edit" href="config/modify_movement_type.html?dir=%s&op_key=%s"|args:$direction:$key target="_dialog"}}
<td class="action">
{{:button
label="Supprimer" shape="minus"
disabled=$locked_inputs|has:$label
onclick="this.parentNode.parentNode.remove();"}}
</td> </td>
</tr> </tr>
{{/foreach}} {{/foreach}}
</tbody> </tbody>
</table> </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}} {{/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}} {{:admin_footer}}

View file

@ -8,6 +8,9 @@
"items": { "items": {
"type": "object", "type": "object",
"properties": { "properties": {
"key" : {
"type" : "string"
},
"label" : { "label" : {
"type" : "string" "type" : "string"
}, },
@ -24,6 +27,9 @@
"items": { "items": {
"type": "object", "type": "object",
"properties": { "properties": {
"key" : {
"type" : "string"
},
"label" : { "label" : {
"type" : "string" "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", "description": "Clé de la catégorie",
"type": "string" "type": "string"
}, },
"designation": { "name": {
"description": "Désignation du matériel", "description": "Désignation du matériel",
"type": "string" "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 *}} {{* 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.ok}}
{{if $_GET.msg == "ajout" }}
<p class="block confirm">Ajout effectué</p>
{{elseif $_GET.msg == "modification" }}
<p class="block confirm">Modification effectuée</p> <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}} {{elseif $_GET.err}}
<p class="block error">Modification refusée</p> <p class="block error">Modification refusée</p>
{{/if}} {{/if}}
{{#load type="category"}} {{if $result.count == 0}}
{{:assign var="category_keys." value=$key}}
{{/load}}
{{if $category_keys|count == 0}}
<p class="block alert">Il n'y a aucune catégorie : vous devez en ajouter.</p> <p class="block alert">Il n'y a aucune catégorie : vous devez en ajouter.</p>
{{else}} {{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}} {{/if}}
{{:admin_footer}} {{: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,7 +1,7 @@
name="Gestion des matériels" 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="Jean-Christophe Engel"
author_url="https://git.roflcopter.fr/lesanges" author_url="https://gitea.zaclys.com/lesanges"
home_button=false home_button=false
menu=true menu=true
restrict_section="accounting" restrict_section="accounting"

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