From de086d9f7265be112b1b3d88139ff0d2238dd0b1 Mon Sep 17 00:00:00 2001 From: engel <> Date: Tue, 24 Jan 2023 13:08:47 +0000 Subject: [PATCH] =?UTF-8?q?Finalisation=20num=C3=A9ro=20de=20re=C3=A7u=20e?= =?UTF-8?q?t=20impression=20adresse=20courriel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FossilOrigin-Name: c8806d21d99de18397e95e2a4aae69f3a68dd3c7fbb763aa987d267f0761f863 --- README.md | 6 +- garradin_plugin.ini | 4 +- templates/config.tpl | 84 ++++++++-------- templates/index.tpl | 4 +- www/admin/index.php | 5 - www/admin/script.js | 222 +++++++++++++++++++++---------------------- www/admin/style.css | 81 +++++++++++----- 7 files changed, 214 insertions(+), 192 deletions(-) diff --git a/README.md b/README.md index 42bd53f..83801e5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Plugin reçus fiscaux pour Garradin/Paheko Plugin de reçus fiscaux pour le logiciel de gestion d'association Garradin/Paheko (https://paheko.cloud). -Source : https://git.roflcopter.fr/lesanges/recus-fiscaux-garradin ## Installation ### Attention Les archives disponibles sur ce gitlab n'ont pas un format compatible avec Garragin/Paheko et ne peuvent donc être utilisées telles quelles ; il faut soit les transformer pour les rendre compatibles, soit (plus simple) télécharger l'archive indiquée ci-dessous. +### Archive Vous pouvez télécharger [l'archive .tar.gz](https://ncloud6.zaclys.com/index.php/s/RZQK2So8HemkH3w), et la copier dans le dossier plugins de Garradin/Paheko. ## Fonctionnalités @@ -27,4 +27,6 @@ Vous pouvez télécharger [l'archive .tar.gz](https://ncloud6.zaclys.com/index.p - signature (image) - autres - ville (précède la date sur le formulaire) - - champs pour le nom et prénom (le libellé doit contenir le terme 'nom', casse indifférente) + - paramétrage numéro de reçu (préfixe quelconque, année fiscale, numéro de memmbre ou séquentiel) + - possibilité imprimer adresse de courriel + - choix et ordre des champs pour le nom et prénom (le libellé doit contenir le terme 'nom', casse indifférente) diff --git a/garradin_plugin.ini b/garradin_plugin.ini index 81add01..27e3292 100644 --- a/garradin_plugin.ini +++ b/garradin_plugin.ini @@ -1,8 +1,8 @@ nom="Reçus fiscaux" description="Génération de reçus fiscaux pour les dons des membres" auteur="jce" -url="https://git.roflcopter.fr/lesanges/recus-fiscaux-garradin" -version="0.7" +url="https://ncloud6.zaclys.com/index.php/s/RZQK2So8HemkH3w" +version="0.8" menu=1 config=1 min_version="1.1.23" diff --git a/templates/config.tpl b/templates/config.tpl index 7fdb7cb..0e60b4e 100644 --- a/templates/config.tpl +++ b/templates/config.tpl @@ -44,14 +44,14 @@ (obligatoire ; sélectionnez tous les taux qui s'appliquent à l'association) - {foreach from=$plugin_config->reduction key="key" item="taux"} -
+
+ {foreach from=$plugin_config->reduction key="key" item="taux"} {/if} -
- {/foreach} + {/foreach} +
@@ -91,47 +91,49 @@ {* Numérotation des reçus *}
Numérotation des reçus -
- - Sélectionner les éléments qui doivent faire partie du numéro de reçu - -
-
    -
  • Préfixe : texte qui sera imprimé tel quel au début du numéro (ex : sigle de l'association) ; facultatif
  • -
  • Année fiscale : numéro de l'année fiscale (ex : 2022) ; facultatif
  • -
      - Sélectionner au moins un des deux numéros suivants -
    • Numéro de membre
    • -
    • Numéro séquentiel (1, 2, ...) : numéro d'ordre du reçu
    • -
    -
  • Valeur initiale : si vous avez choisi un numéro séquentiel, indiquez le numéro du premier reçu
  • -
-
-
+
+ + Sélectionner les éléments qui doivent faire partie du numéro de reçu + +
+
    +
  • Préfixe : texte qui sera imprimé tel quel au début du numéro (ex : sigle de l'association) ; + facultatif
  • +
  • Année fiscale : numéro de l'année fiscale (ex : 2022) ; facultatif
  • +
      + Sélectionner au moins un des deux numéros suivants +
    • Numéro de membre
    • +
    • Numéro séquentiel (1, 2, ...) : numéro d'ordre du reçu
    • +
    +
  • Valeur initiale : si vous avez choisi un numéro séquentiel, indiquez le numéro du premier reçu +
  • +
+
+
- {* Préfixe *} -
- {input type="text" name="prefixe" source=$numerotation label="Préfixe" maxlength=20} -
+ {* Préfixe *} +
+ {input type="text" name="prefixe" source=$numerotation label="Préfixe" maxlength=20} +
- {* Autres éléments de la numérotation *} -
- {input type="checkbox" name="annee" source=$numerotation label="Année fiscale" value=1} -
+ {* Autres éléments de la numérotation *} +
+ {input type="checkbox" name="annee" source=$numerotation label="Année fiscale" value=1} +
-
- {input type="checkbox" name="membre" source=$numerotation label="N° de membre" value=1} -
+
+ {input type="checkbox" name="membre" source=$numerotation label="N° de membre" value=1} +
-
- {input type="checkbox" name="sequentiel" source=$numerotation label="N° séquentiel" value=1} -
+
+ {input type="checkbox" name="sequentiel" source=$numerotation label="N° séquentiel" value=1} +
-
- {input type="number" name="valeur_init" source=$numerotation label="Valeur initiale"} -
-
+
+ {input type="number" name="valeur_init" source=$numerotation label="Valeur initiale"} +
+
@@ -174,7 +176,7 @@

{csrf_field key="recusfiscaux_config"} - {button type="submit" name="save" label="Enregistrer" shape="right" class="main" onclick="return verifierConfig(this.form, articles_cgi, taux_reduction)"} + {button type="submit" name="save" label="Enregistrer" shape="right" class="main" onclick="return verifierConfig(articles_cgi, taux_reduction)"}

@@ -200,4 +202,4 @@ {/literal} {* scripts divers *} - + \ No newline at end of file diff --git a/templates/index.tpl b/templates/index.tpl index b8621d4..583e1ff 100644 --- a/templates/index.tpl +++ b/templates/index.tpl @@ -78,7 +78,7 @@

{csrf_field key="generer_tous_recus"} - {button type="submit" name="generer_tous" label="Poursuivre" shape="right" class="main" onclick="return verifierRadio('menu_versements');" } + {button type="submit" name="generer_tous" label="Poursuivre" shape="right" class="main" onclick="return verifierTaux(menu_versements);" }

@@ -183,7 +183,7 @@

{csrf_field key="generer_recus_activites"} - {button type="submit" name="generer_activites" label="Poursuivre" shape="right" class="main" onclick="return verifierCases('menu_activites_tarifs');" } + {button type="submit" name="generer_activites" label="Poursuivre" shape="right" class="main" onclick="return verifierActivitésTaux(menu_activites_tarifs);" }

diff --git a/www/admin/index.php b/www/admin/index.php index a2a240b..4c5e0f3 100644 --- a/www/admin/index.php +++ b/www/admin/index.php @@ -10,11 +10,6 @@ if (! isset($_SESSION['annee_recu']) || $_SESSION['annee_recu'] == "") $_SESSION['annee_recu'] = date("Y") - 1; } -// error_log("config=" . print_r($plugin->getConfig(), true)); -// error_log("articlesCGI=" . print_r($plugin->getConfig('articlesCGI'), true)); -// error_log("reduction=" . print_r($plugin->getConfig('reduction'), true)); -// error_log("numerotation=" . print_r($plugin->getConfig('numerotation'), true)); - // nombre de taux de réduction activés $nbTaux = 0; foreach ($plugin->getConfig('reduction') as $taux) diff --git a/www/admin/script.js b/www/admin/script.js index fcc700f..e1b03b0 100644 --- a/www/admin/script.js +++ b/www/admin/script.js @@ -1,5 +1,9 @@ "use strict"; +// ------------------------------------------------------------------------ +// actions sur la liste des versements +// ------------------------------------------------------------------------ + /** * Fonction appelée quand on (dé)coche la case globale * (dé)sélectionner toutes les cases de toutes les activités @@ -128,104 +132,6 @@ function changerMessage(message, idCase) } } -/** - * fonction appelée lors de la validation du formulaire - * @return vrai si au moins un choix a été fait - * @param {HTMLFormElement} formulaire - */ -function verifierChoix(formulaire) -{ - let listeCheck = formulaire.getElementsByTagName("input"); - let ok = false; - for (let i = 1; i < listeCheck.length; ++i) - { - if (listeCheck[i].checked) - { - ok = true; - break; - } - } - if (! ok) - { - alert("Erreur : il faut sélectionner au moins un versement"); - } - return ok; -} - -/** - * positionner l'action déclenchée par l'envoi du formulaire - * afficher et masquer des portions de formulaire selon l'action - * @param {HTMLFormElement} formulaire - * @param {string} action après envoi du formulaire - * @param {any} idElem id de l'élément à afficher - * @param {any} nomClasse classe des éléments à masquer (sauf idElem) - */ -function choixMethodeGeneration(formulaire, action, idElem, nomClasse) -{ - formulaire.setAttribute('action', 'action.php?action=' + action); - for (let elem of formulaire.querySelectorAll(nomClasse)) - { - if (elem.id == idElem) - { - elem.classList.remove('hidden'); - } - else - { - elem.classList.add('hidden'); - } - } -} - -/** - * vérifier - * - qu'au moins une activité/tarif est sélectionnée - * - qu'un radio de chaque activité/tarif sélectionné a été sélectionné :) - * @param {string} idElem id du conteneur des cases à vérifier - */ -function verifierCases(idElem) -{ - let div = document.getElementById(idElem); - let nbChoix = 0; - // parcourir les cases à cocher - for (let idCase of div.querySelectorAll("input[type=checkbox]")) - { - if (idCase.checked) { - ++nbChoix; - // vérifier qu'un radio de la même ligne est sélectionné - let ligneCorrecte = false; - // trouver la ligne englobante - let ligne = idCase.closest("li"); - for (let idRadio of ligne.querySelectorAll('input[type=radio]')) - { - if (idRadio.checked) { ligneCorrecte = true; break; } - } - if (! ligneCorrecte) { - alert("Erreur : il faut sélectionner un taux de réduction dans chaque ligne cochée"); - return false; - } - } - } - if (nbChoix == 0) { - alert("Erreur : il faut sélectionner au moins une ligne"); - } - return nbChoix != 0; -} - -/** - * vérifier qu'un radio a été sélectionné dans la div paramètre - * @param {string} idElem id du conteneur des radios à vérifier - */ -function verifierRadio(idElem) -{ - let div = document.getElementById(idElem); - for (let idRadio of div.querySelectorAll('input[type=radio]')) - { - if (idRadio.checked) { return true; } - } - alert("Erreur : il faut sélectionner un taux de réduction"); - return false; -} - /** * afficher/masquer les détails * @param {string} idElem bouton de masquage/affichage @@ -260,32 +166,100 @@ function montrerMasquerDetails(idElem, classe, texte) } /** - * + * fonction appelée lors de la demande de génération des reçus + * vérifier qu'au moins un versement a été sélectionné + * @return vrai si au moins un choix a été fait + * @param {HTMLFormElement} formulaire */ -function aumoinsun(conteneur, message) +function verifierChoix(formulaire) { - let listeCheck = conteneur.querySelectorAll('input[type=checkbox]'); - for (let elem of listeCheck) - { - if (elem.checked) { return true; } - } - alert("Erreur : il faut sélectionner au moins " + message); - return false; + return verifierCases(formulaire, 'checkbox', "au moins un versement"); } + +// ------------------------------------------------------------------------ +// actions sur la page d'accueil +// ------------------------------------------------------------------------ + +/** + * positionner l'action déclenchée par l'envoi du formulaire + * afficher et masquer des portions de formulaire selon l'action + * @param {HTMLFormElement} formulaire + * @param {string} action après envoi du formulaire + * @param {any} idElem id de l'élément à afficher + * @param {any} nomClasse classe des éléments à masquer (sauf idElem) + */ +function choixMethodeGeneration(formulaire, action, idElem, nomClasse) +{ + formulaire.setAttribute('action', 'action.php?action=' + action); + for (let elem of formulaire.querySelectorAll(nomClasse)) + { + if (elem.id == idElem) + { + elem.classList.remove('hidden'); + } + else + { + elem.classList.add('hidden'); + } + } +} + +/** + * vérifier + * - qu'au moins une activité/tarif est sélectionnée + * - qu'un radio de chaque activité/tarif sélectionné a été sélectionné :) + * @param conteneur des cases à vérifier + */ +function verifierActivitésTaux(conteneur) +{ + let nbChoix = 0; + // parcourir les cases à cocher + for (let idCase of conteneur.querySelectorAll("input[type=checkbox]")) + { + if (idCase.checked) { + ++nbChoix; + // vérifier qu'un radio de la même ligne est sélectionné + let ligneCorrecte = false; + // trouver la ligne englobante + let ligne = idCase.closest("li"); + for (let idRadio of ligne.querySelectorAll('input[type=radio]')) + { + if (idRadio.checked) { ligneCorrecte = true; break; } + } + if (! ligneCorrecte) { + alert("Erreur : il faut sélectionner un taux de réduction dans chaque ligne cochée"); + return false; + } + } + } + if (nbChoix == 0) { + alert("Erreur : il faut sélectionner au moins une ligne"); + } + return nbChoix != 0; +} + +/** + * vérifier qu'un taux a été sélectionné dans le conteneur paramètre + */ +function verifierTaux(conteneur) +{ + return verifierCases(conteneur, 'radio', "un taux de réduction"); +} + +// ------------------------------------------------------------------------ +// actions sur la config +// ------------------------------------------------------------------------ + /** * vérifier les données saisies dans le formulaire de configuration -*/ -function verifierConfig( - formulaire, - divArticles, - divTauxReduc -) + */ +function verifierConfig(divArticles, divTauxReduc) { // articles - if (! aumoinsun(divArticles, "un article")) { return false; } + if (! verifierCases(divArticles, "checkbox", "au moins un article")) { return false; } // taux de réduction - if (! aumoinsun(divTauxReduc, "un taux de réduction")) { return false; } + if (! verifierCases(divTauxReduc, "checkbox", "au moins un taux de réduction")) { return false; } // Nom, fonction, signature @@ -293,3 +267,21 @@ function verifierConfig( // alert("Erreur : il faut sélectionner au moins un versement"); return true; } + +/** + * Vérifier qu'au moins une case est cochée dans le conteneur + * @param conteneur + * @param type de case à vérifier (radio, checkbox) + * @param message à afficher si erreur + */ +function verifierCases(conteneur, type, message) +{ + let selecteur = "input[type=" + type + "]"; + let listeCheck = conteneur.querySelectorAll(selecteur); + for (let elem of listeCheck) + { + if (elem.checked) { return true; } + } + alert("Erreur : il faut sélectionner " + message); + return false; +} diff --git a/www/admin/style.css b/www/admin/style.css index 9aad3a5..eb52c78 100644 --- a/www/admin/style.css +++ b/www/admin/style.css @@ -1,7 +1,11 @@ -/* liste des versements */ +/* + * liste des versements + */ + div.pair { background-color: rgba(var(--gSecondColor), 0.15); } + fieldset.versements { margin-bottom : 0; @@ -9,102 +13,128 @@ fieldset.versements -webkit-border-radius:8px; border-radius:8px; } + div span { padding-left : 0.5em; padding-right : 0.5em; } + td.montant { text-align : right; } + span.montant { width : 5em; text-align : right; } + span.total { font-weight : bold; } + summary.activite { margin-bottom : 0.5em; } + summary.personne { margin-bottom : 0.5em; padding-top : 0; padding-bottom : 0; } + div.activite { background-color: rgba(var(--gSecondColor), 0.3); } + div.personne { font-weight : normal; background-color: rgba(var(--gSecondColor), 0.25); } + h3.activite { display : inline; } + p.activite { margin-left : 2.5em; } -#signature -{ - padding : 1em 0.5em 0 0.5em; - max-width: 300px; - max-height: 150px; -} -div.explications ul -{ - list-style : initial; -} - -div.actions -{ - display : inline; -} input.check_global { margin : 0.2em 0.5em; } -dl#menu -{ - min-width : 40em; - width : 50%; -} + div.versements { margin-left : 4em; display: flex; flex-wrap: wrap; } -/* config */ + +/* + * page d'accueil +*/ + +div.explications ul +{ + list-style : initial; +} + +dl#menu +{ + min-width : 40em; + width : 50%; +} + +/* + * configuration + */ + +#signature +{ + padding : 1em 0.5em 0 0.5em; + max-width: 300px; + max-height: 120px; +} + +div.actions +{ + display : inline; +} + dl.config { padding-bottom : 1ex; padding-right : 1em; } -div#articles_cgi + +div#articles_cgi, div#config_nom_fonction, div#numero_recus { display: flex; } + div.article { margin-right : 3em; } +/* div#config_nom_fonction { display: flex; } + div#numero_recus { display:flex; -/* align-items: last baseline;*/ } +*/ div.champnom { display : flex; @@ -130,7 +160,8 @@ ul.reduction span.radio-btn } input#f_prefixe { - max-width : 8em; + width : 8em; + min-width : 8em; } input#f_valeur_init {