diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..e69de29
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..ad1b3a4
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,14 @@
+Plugin Facturation pour Garradin
+Copyright (C) 2019 zou
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation version 3 of the License
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
\ No newline at end of file
diff --git a/README.md b/README.md
index 0136279..8bcd025 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,30 @@
-# Plugin reçus fiscaux pour Paheko
+# Plugin reçus fiscaux pour Garradin
-Plugin de reçus fiscaux pour le logiciel de gestion d'association [Paheko](https://paheko.cloud).
+Plugin de reçus fiscaux pour le logiciel de gestion d'association Garradin ( https://garradin.eu/ - https://fossil.kd2.org/garradin ).
+Source : https://
-## Installation
+## Installation:
+Vous pouvez télécharger l'archive .tar.gz depuis la page des [releases](https://), et la placer directement dans le dossier plugins de Garradin.
-Télécharger la [version la plus récente](https://git.roflcopter.fr/lesanges/recusfiscaux/releases) au format tar.gz, supprimer le numéro de version du nom de l'archive et la copier dans le répertoire data/plugins de Paheko
-
-## Fonctionnalités
-- Créer des reçus fiscaux pour les dons des membres
- - reçu par activité et tarif : un, plusieurs ou tous
- - reçu par personne : une, plusieurs ou tous
+## Fonctionnalités :
+- Créer des reçus fiscaux pour des dons et génération du cerfa correspondant
+ - reçu par type d'activité : 1, n ou tous
+ - reçu par tarif d'activité : 1, n ou tous
+ - reçu par personne : 1, n ou tous
+ - reçu par versement : 1, n ou tous
- distinguer les différents taux de réduction
- - génération des reçus au format PDF avec un générateur PDF externe
- ou impression depuis le navigateur
+- Créer des reçus sur des cotisations
+- **Configuration** :
+ - Possibilité d'ajouter un numéro RNA et SIRET de l'association si elle en possède (apparait alors sur les documents)
+ - Modification du pied de page des documents (notament pour y inscrire des mentions légales)
+ - Informations relatives au cerfa pour les reçus fiscaux
+ - Image qui set de signature sur le cerfa
-## Configuration
-- association
- - Objet (but) de l'association
- - articles du CGI concernés par la réduction fiscale
- - taux de réduction applicables
-- responsable
- - nom
- - fonction
- - signature (image)
-- autres
- - ville (précède la date sur le formulaire)
- - paramétrage du numéro de reçu (préfixe quelconque, année fiscale, numéro de membre ou séquentiel)
- - possibilité d'imprimer l'adresse de courriel
- - choix et ordre des champs pour le nom et prénom (le libellé doit contenir le terme 'nom', casse indifférente)
+Le plugin nécessite l'extension PHP mbstring.
+
+## Inclus les bibliothèques suivantes :
+
+- Composer :
+ https://getcomposer.org/
+ Copyright (c) Nils Adermann, Jordi Boggiano,
+ Licence: MIT
diff --git a/admin/action.php b/admin/action.php
deleted file mode 100644
index f3aa4dc..0000000
--- a/admin/action.php
+++ /dev/null
@@ -1,219 +0,0 @@
-position - $b->position;
-});
-$champsNom = array();
-foreach ($confNoms as $nom => $champ)
-{
- if ($champ->position != 0) { $champsNom[] = $nom; }
-}
-
-// membres donateurs
-$_SESSION['membresDonateurs'] = Utils::getDonateurs($_SESSION['annee_recu'],
- $champsNom);
-
-// comparaison de lignes de versements
-// comparer 2 lignes selon le nom
-function comparerNoms($ligne1, $ligne2)
-{
- return
- $_SESSION['membresDonateurs'][$ligne1->idUser]->rang
- -
- $_SESSION['membresDonateurs'][$ligne2->idUser]->rang;
-}
-
-// comparer 2 activités par leur libellé
-function comparerActivites($ligne1, $ligne2)
-{
- return strcoll(
- $_SESSION['lesActivites'][$_SESSION['lesTarifs'][$ligne1->idTarif]->idActivite]->label,
- $_SESSION['lesActivites'][$_SESSION['lesTarifs'][$ligne2->idTarif]->idActivite]->label);
-}
-
-// comparer 2 lignes selon la date
-function comparerDate($ligne1, $ligne2)
-{
- return
- strtotime($ligne1->date) - strtotime($ligne2->date);
-}
-
-// comparer 2 lignes selon un champ numérique entier
-function comparerChamp($ligne1, $ligne2, $champ)
-{
- return $ligne1->$champ - $ligne2->$champ;
-}
-
-// ------------------------------------------------------------------------
-// fonctions pour l'affichage
-// ------------------------------------------------------------------------
-
-// afficher les informations d'une activité et d'un tarif
-$tpl->register_function('afficher_debut_tarif', function ($params)
-{
- $versement = $params['versement'];
- $idTarif = $versement->idTarif;
-
- $out = sprintf('
-
-
-
-
',
- $idTarif, "total_general");
- if ($idTarif == 0) {
- // versement sur un compte non rattaché à une activité
- $out .= sprintf('
-
- Versements non rattachés à une activité ',
- $idTarif);
- }
- else {
- $tarif = $_SESSION['lesTarifs'][$idTarif];
- $idActivite = $tarif->idActivite;
- $activite = $_SESSION['lesActivites'][$idActivite];
-
- $out .= sprintf('
-
- Activité « %s » ',
- $idTarif,
- $activite->label);
-
- if (!empty($activite->description)) {
- $out .= sprintf('
- %s
', $activite->description);
- }
- $out .= sprintf('
- tarif « %s »', $tarif->label);
- if ($tarif->montant > 0) {
- $out .= sprintf(' montant : %.2f €
', $tarif->montant/100);
- } else {
- $out .= ' montant : libre';
- }
- }
- $out .= '
-
-
- ';
- return $out;
-});
-
-// Afficher les informations d'une personne
-$tpl->register_function('afficher_debut_personne', function ($params)
-{
- $idUser = $params['user'];
- $idVersement = $params['idVersement'];
-
- $personne = $_SESSION['membresDonateurs'][$idUser];
- $out = sprintf('
-
-
-
-
-
- %2$s : 0,00 €
-
-
-
- ',
- $idVersement,
- $personne->nomPrenom,
- "total_general"
- );
- return $out;
-});
-
-// afficher infos compte
-$tpl->register_function('afficher_debut_compte', function ($params)
-{
- $idCompte = $params['idCompte'];
- $out = sprintf('
-
- ',
- $_SESSION['comptes'][$idCompte]->codeCompte,
- $_SESSION['comptes'][$idCompte]->nomCompte);
- return $out;
-});
-
-// afficher un versement
-$tpl->register_function('afficher_versement', function ($params)
-{
- $versement = $params['versement'];
- $idVersement = $params['idVersement'];
- $rang = $params['rang'];
- $pair = $params['pair'];
-
- $out = '' : 'impair">';
- $out .= sprintf('
-
- %3$s
- %4$s
-
-
',
- $idVersement,
- $rang,
- number_format(
- $versement->versement/100,
- 2,
- ",",
- " "
- ),
- date_format(date_create($versement->date),"d/m/Y"),
- "total_general"
- );
- return $out;
-});
-
-$tpl->register_function('fin_compte', function ()
-{
- $out = '
- ';
- return $out;
-});
-
-$tpl->register_function('fin_personne', function ()
-{
- $out = '
-
- ';
- return $out;
-});
-
-$tpl->register_function('fin_tarif', function ($params)
-{
- $out = '
- ';
- return $out;
-});
-
-// ------------------------------------------------------------------------
-// aiguillage
-// ------------------------------------------------------------------------
-unset($_SESSION['comptesSelectionnes']);
-unset($_SESSION['tauxSelectionnes']);
-unset($_SESSION['lesVersements']);
-
-if ($_GET['action'] == 'personne') {
- require('versements_personnes.php');
-} else if ($_GET['action'] == 'activite') {
- require('versements_activites.php');
-}
diff --git a/admin/choix_annee.php b/admin/choix_annee.php
deleted file mode 100644
index 4a95bdb..0000000
--- a/admin/choix_annee.php
+++ /dev/null
@@ -1,24 +0,0 @@
-runIf('change', function () {
- $_SESSION['annee_recu'] = f('annee_recu');
-}, $csrf_key, PLUGIN_ROOT . '/admin/index.php');
-
-$tpl->assign(compact('anneesFiscales', 'csrf_key'));
-
-$tpl->assign('annee_recu', $_SESSION['annee_recu']);
-
-$tpl->display(PLUGIN_ROOT . '/templates/choix_annee.tpl');
diff --git a/admin/config.php b/admin/config.php
deleted file mode 100644
index a5d7c51..0000000
--- a/admin/config.php
+++ /dev/null
@@ -1,123 +0,0 @@
-requireAccess($session::SECTION_CONFIG, $session::ACCESS_ADMIN);
-
-// récupérer les champs des noms
-$champsNom = Utils::getChampsNom($config, $plugin);
-
-$csrf_key = 'recusfiscaux_config';
-
-$form->runIf('save', function () use ($plugin, $champsNom) {
- // Objet de l'asso
- $plugin->setConfigProperty('objet_asso', trim(f('objet_asso')));
-
- // Articles du CGI
- $confArticles = $plugin->getConfig('articlesCGI');
- // effacer l'ancienne configuration
- for ($i = 0; $i < count($confArticles); ++$i) {
- $confArticles[$i]->valeur = false;
- }
- // et copier la nouvelle
- $art_sel = f('articlesCGI') ?: [];
- foreach ($art_sel as $article) {
- $confArticles[$article]->valeur = true;
- }
- $plugin->setConfigProperty('articlesCGI', $confArticles);
-
- // Taux de réduction
- $confTaux = $plugin->getConfig('reduction');
- // effacer l'ancienne configuration
- for ($i = 0; $i < count($confTaux); ++$i) {
- $confTaux[$i]->valeur = false;
- }
- // et copier la nouvelle
- $taux_sel = f('tauxReduction') ?: [];
- foreach ($taux_sel as $taux) {
- $confTaux[$taux]->valeur = true;
- }
- $plugin->setConfigProperty("reduction", $confTaux);
-
- // Informations au sujet du responsable
- $plugin->setConfigProperty('nom_responsable', trim(f('nom_responsable') ?: '') ?: null);
- $plugin->setConfigProperty('fonction_responsable', trim(f('fonction_responsable') ?: '') ?: null);
- $plugin->setConfigProperty('ville_asso', trim(f('ville_asso') ?: '') ?: null);
-
- // signature
- if (isset($_SESSION['sig_file']) && count($_SESSION['sig_file']) > 0) {
- // supprimer la signature précédente, si besoin
- if (
- null !== $plugin->getConfig('signature')
- &&
- $plugin->getConfig('signature') != $_SESSION['sig_file'][0]->path
- ) {
- $sig_file = \Paheko\Files\Files::get($plugin->getConfig('signature'));
- if (null !== $sig_file) {
- $sig_file->delete();
- }
- }
- // puis installer la nouvelle
- $plugin->setConfigProperty('signature', $_SESSION['sig_file'][0]->path);
- }
-
- // Numérotation des reçus
- $configNum = $plugin->getConfig('numerotation');
- $formNum = clone $configNum;
- if ($configNum->prefixe != trim(f('prefixe'))) {
- $formNum->prefixe = trim(f('prefixe'));
- }
- $formNum->annee = f('annee');
- $formNum->membre = f('membre');
- $formNum->sequentiel = f('sequentiel');
- $formNum->valeur_init = f('valeur_init');
- $plugin->setConfigProperty('numerotation', $formNum);
-
- // Impression des adresses de courriel
- $plugin->setConfigProperty('imprimerCourriel', trim(f('imprimerCourriel') ?: '') ?: null);
-
- // champs pour le nom et prénom
- foreach ($champsNom as $nom => $champ) {
- $champ->position = 0;
- }
- $noms_sel = f('champsNom') ?: [];
- $i = -count($noms_sel);
- foreach ($noms_sel as $nom) {
- $champsNom[$nom]->position = $i++;
- }
- $plugin->setConfigProperty('champsNom', $champsNom);
-
- // enregistrer la nouvelle config
- $plugin->save();
-}, $csrf_key, PLUGIN_ADMIN_URL . 'config.php?ok');
-
-
-// test fonctions fichiers : voir files.sor
-// $fichiers = Files::list('config');
-// error_log("fichiers config = " . print_r($fichiers, true));
-// $fichiers = Files::list('ext/recusfiscaux');
-// error_log("fichiers ext/recusfiscaux = " . print_r($fichiers, true));
-$sig_file = Files::get('ext/recusfiscaux/default_signature.png');
-// error_log("sig_file = " . print_r($sig_file, true));
-
-//error_log("config.php::config=" . print_r($plugin->getConfig(), true));
-
-
-// trier les champs de nom pour l'affichage
-uasort($champsNom, function ($a, $b) {
- return $a->position - $b->position;
-});
-
-$path = qg('path') ?: File::CONTEXT_CONFIG;
-$tpl->assign('default_signature', '/' . 'ext/recusfiscaux/default_signature.png');
-// $tpl->assign('default_signature', \Paheko\WWW_URL . "plugin/recusfiscaux/default_signature.png");
-$tpl->assign('plugin_config', $plugin->getConfig());
-$tpl->assign('plugin_css', ['style.css']);
-$tpl->assign('numerotation', $plugin->getConfig('numerotation'));
-$tpl->assign(compact('csrf_key', 'path', 'champsNom'));
-$tpl->display(PLUGIN_ROOT . '/templates/config.tpl');
diff --git a/admin/generer_recus.php b/admin/generer_recus.php
deleted file mode 100644
index 6fa83bf..0000000
--- a/admin/generer_recus.php
+++ /dev/null
@@ -1,473 +0,0 @@
-fileURL('signature')) ?
- $config->fileURL('signature') :
- ((null !== $plugin->getConfig('signature')) ?
- \KD2\HTTP::getScheme() . '://' . \KD2\HTTP::getHost() . WWW_URI . $plugin->getConfig('signature') :
- "");
-
-// logo
-$config = Config::getInstance();
-$logo_asso =
- (null !== $config->fileURL('logo')) ?
- $config->fileURL('logo') :
- "";
-
-// articles du CGI
-$articlesCGI = array();
-foreach ($plugin->getConfig('articlesCGI') as $article) {
- if ($article->valeur == 1) {
- $articlesCGI[] = $article->titre;
- }
-}
-$nbArticles = count($articlesCGI);
-if ($nbArticles == 1) {
- $texteArticles = 'à l’article ' . $articlesCGI[0];
-} elseif ($nbArticles > 1) {
- $texteArticles = 'aux articles ';
- for ($i = 0; $i < $nbArticles; ++$i) {
- $texteArticles .= $articlesCGI[$i];
- if ($i < $nbArticles - 2) {
- $texteArticles .= ", ";
- } else if ($i == $nbArticles - 2) {
- $texteArticles .= " et ";
- }
- }
-}
-
-// libellés pour les taux de réduction
-$libelles_taux = Utils::getLignesReduction($plugin->getConfig('reduction'));
-
-// numérotation des reçus
-$configNum = $plugin->getConfig('numerotation');
-
-// filtrer les versements sélectionnés
-$lesLignes = f('selected');
-$versementsSelectionnes = array();
-foreach ($lesLignes as $ligne) {
- $versementsSelectionnes[] = $_SESSION['lesVersements'][$ligne];
-}
-
-// cumuler les versements
-if ($_GET['type'] == 'personne') {
- $totalPersonnes = cumulerVersementsPersonne($versementsSelectionnes);
-} elseif ($_GET['type'] == 'activite') {
- $totalPersonnes = cumulerVersementsTarif($versementsSelectionnes);
-}
-
-// générer les reçus
-if ($_GET['format'] == 'pdf') {
- genererRecusPDF($totalPersonnes,
- $signature,
- $logo_asso,
- $texteArticles,
- $plugin,
- $configNum,
- $libelles_taux
- );
-} else if ($_GET['format'] == 'print') {
- generererRecusHTML($tpl,
- $totalPersonnes,
- $signature,
- $logo_asso,
- $texteArticles,
- $plugin,
- $configNum,
- $libelles_taux
- );
-} else {
- // Erreur : format inconnu ; ne devrait pas se produire
-}
-
-function genererRecusPDF($totalPersonnes,
- $signature,
- $logo_asso,
- $texteArticles,
- $plugin,
- $configNum,
- $libelles_taux
-)
-{
- //
- $fichierHTML = sprintf('%s/print-%s.html', CACHE_ROOT, md5(random_bytes(16)));
- //
- $listeFichiersPDF = array();
- $fmt = new \NumberFormatter('fr_FR', \NumberFormatter::SPELLOUT);
- $prefixeNum = getNumPrefixe($configNum);
- $numero_sequentiel = getNumSequentiel($configNum);
- foreach ($totalPersonnes as $idPersonne => $personne) {
- $tpl = new UserTemplate(null);
- /* $tpl->setSource(PLUGIN_ROOT . '/templates/recu.skel'); */
- $tpl->setSourcePath(PLUGIN_ROOT . '/templates/recu.skel');
-
- $tpl->assignArray(compact('signature', 'logo_asso', 'texteArticles'));
- $tpl->assign('objet_asso', $plugin->getConfig('objet_asso'));
- $tpl->assign('nom_responsable', $plugin->getConfig('nom_responsable'));
- $tpl->assign('fonction_responsable', $plugin->getConfig('fonction_responsable'));
- $tpl->assign('ville_asso', $plugin->getConfig('ville_asso'));
- $tpl->assign('nom', $personne->nomPrenom);
- $tpl->assign('adresse', $personne->adresse);
- $tpl->assign('code_postal', $personne->codePostal);
- $tpl->assign('ville', $personne->ville);
- $tpl->assign('date', date("j/m/Y"));
-
- // numéro de reçu
- $tpl->assign('numero',
- faireNumeroRecu($prefixeNum,
- $configNum->membre,
- $personne->numero,
- $numero_sequentiel));
-
- // adresse de courriel
- if ($plugin->getConfig('imprimerCourriel')) {
- $courriel = $personne->courriel;
- } else {
- $courriel = "";
- }
- $tpl->assign('courriel', $courriel);
-
- // les versements
- $tpl->registerSection(
- 'versements',
- function () use ($personne, $libelles_taux, $fmt) {
- foreach ($personne->versements as $taux => $versement) {
- $ligne['montant'] = $versement->montant;
- $ligne['euros'] = $fmt->format((int)($versement->montant / 100));
- if ($versement->montant % 100 != 0) {
- $ligne['cents'] = $fmt->format($versement->montant % 100);
- } else {
- $ligne['cents'] = "";
- }
- $ligne['libelle'] = $libelles_taux[$taux];
- $ligne['dateMin'] = date("d/m/Y", $versement->dateMin);
- $ligne['dateMax'] = date("d/m/Y", $versement->dateMax);
- yield $ligne;
- }
- }
- );
-
- // mentions complémentaires
- $complements = mentionsComplémentaires();
-
- $tpl->registerSection(
- 'informations',
- function () use ($complements) {
- foreach ($complements as $elem) {
- yield (array) $elem;
- }
- }
- );
-
- //
- // récupérer les reçus au format html
- $recuHTML = $tpl->fetch();
- // enregistrer dans le fichier
- file_put_contents($fichierHTML, $recuHTML, FILE_APPEND);
- //
-
- // fabriquer le fichier PDF
- genererPDF($tpl->fetch(), $personne->nomPrenom, $listeFichiersPDF);
- }
-
- // afficher dans un dialog
- //marche pas
- // printf('
- //
- // Fermer
- //
- //
- //
- // ', $fichierHTML, "90%", "90%");
-
- // affiche une page vide
- // $link = "";
- // echo $link;
-
- // faire une archive zip
- $fichierZip = Utils::makeArchive(
- $listeFichiersPDF,
- $_SESSION['annee_recu'],
- PLUGIN_ROOT . "/zip"
- );
-
- //supprimer les fichiers pdf
- foreach ($listeFichiersPDF as $f) {
- \Paheko\Utils::safe_unlink($f);
- }
-} // genererRecusPDF
-
-function generererRecusHTML($tpl,
- $totalPersonnes,
- $signature,
- $logo_asso,
- $texteArticles,
- $plugin,
- $configNum,
- $libelles_taux
-)
-{
- $tpl->register_function('afficher_numero_recu', function($params)
- {
- $prefixeNum = $params['prefixe'];
- $membre = $params['membre'];
- $numero_personne = $params['numero_personne'];
- $numero_sequentiel = $params['numero_sequentiel'];
- $numero = faireNumeroRecu($prefixeNum,
- $membre,
- $numero_personne,
- $numero_sequentiel);
- $out = sprintf('
-
Reçu %s
',
- $numero
- );
- return $out;
- });
-
- $tpl->assign(compact(
- 'totalPersonnes',
- 'logo_asso',
- 'signature',
- 'libelles_taux',
- 'texteArticles'
- ));
- $tpl->assign('prefixeNum', getNumPrefixe($configNum));
- $tpl->assign('membre', $configNum->membre);
- $tpl->assign('numero_sequentiel', getNumSequentiel($configNum));
- $tpl->assign('org_name', Config::getInstance()->get('org_name'));
- $tpl->assign('org_address', Config::getInstance()->get('org_address'));
- $tpl->assign('objet_asso', $plugin->getConfig('objet_asso'));
- $tpl->assign('courriel', $plugin->getConfig('imprimerCourriel'));
- $tpl->assign('complements', mentionsComplémentaires());
- $tpl->assign('ville_asso', $plugin->getConfig('ville_asso'));
- $tpl->assign('date', date("j/m/Y"));
- $tpl->assign('nom_responsable', $plugin->getConfig('nom_responsable'));
- $tpl->assign('fonction_responsable', $plugin->getConfig('fonction_responsable'));
-
- $tpl->assign('plugin_css', ['previs_recu.css', 'imprimer_recu.css']);
- $tpl->display(PLUGIN_ROOT . '/templates/recu_html.tpl');
-} // generererRecusHTML
-
-/**
- * Cumuler les versements de chaque personne
- * @param tableau des versements triés par idUser, date
- * @return tableau des versements cumulés : id => Personne
- */
-function cumulerVersementsPersonne($versements)
-{
- $totalPersonnes = array();
- $idPersonneCourant = -1;
- $dateMin = PHP_INT_MAX;
- $dateMax = -1;
- $totalVersements = 0;
- foreach ($versements as $ligne) {
- if ($ligne->idUser != $idPersonneCourant) {
- // changement de personne
- if ($idPersonneCourant != -1) {
- $totalPersonnes[$idPersonneCourant]->ajouterVersement(
- $_SESSION['taux_reduction'],
- $totalVersements,
- $dateMin,
- $dateMax
- );
- }
- $dateMin = strtotime($ligne->date);
- $dateMax = strtotime($ligne->date);
- $idPersonneCourant = $ligne->idUser;
- $totalVersements = $ligne->versement;
- // créer les infos de la personne, sauf si elle est déjà présente
- if (!array_key_exists($idPersonneCourant, $totalPersonnes)) {
- $totalPersonnes[$idPersonneCourant] = $_SESSION['membresDonateurs'][$ligne->idUser]->clone();
- }
- } else {
- // même personne : cumuler versements et mettre à jour les dates
- $totalVersements += $ligne->versement;
- if (strtotime($ligne->date) < $dateMin) {
- $dateMin = strtotime($ligne->date);
- }
- if (strtotime($ligne->date) > $dateMax) {
- $dateMax = strtotime($ligne->date);
- }
- }
- }
- // et le dernier
- $totalPersonnes[$idPersonneCourant]->ajouterVersement(
- $_SESSION['taux_reduction'],
- $totalVersements,
- $dateMin,
- $dateMax
- );
- return $totalPersonnes;
-} // cumulerVersementsPersonne
-
-/**
- * Cumuler les versements de chaque personne par tarif
- * @param tableau des versements triés par idTarif, idUser, date
- * @return tableau des versements cumulés : id => Personne
- */
-function cumulerVersementsTarif($versements)
-{
- $totalPersonnes = array();
- $idTarifCourant = -1;
- $idPersonneCourant = -1;
- $idCompteCourant = -1;
- $dateMin = PHP_INT_MAX;
- $dateMax = -1;
- $totalVersements = 0;
- foreach ($versements as $ligne) {
- if (
- $ligne->idTarif != $idTarifCourant ||
- $ligne->idUser != $idPersonneCourant ||
- $ligne->idCompte != $idCompteCourant
- ) {
- if ($idTarifCourant != -1) {
- // changement de tarif, de personne ou de compte
- $tarifCompte = ($idTarifCourant == 0) ?
- $idCompteCourant :
- $idTarifCourant . "_" . $idCompteCourant;
- $totalPersonnes[$idPersonneCourant]->ajouterVersement(
- $_SESSION['tauxSelectionnes'][$tarifCompte],
- $totalVersements,
- $dateMin,
- $dateMax
- );
- }
- $dateMin = strtotime($ligne->date);
- $dateMax = strtotime($ligne->date);
- $idTarifCourant = $ligne->idTarif;
- $idPersonneCourant = $ligne->idUser;
- $idCompteCourant = $ligne->idCompte;
- $totalVersements = $ligne->versement;
- // créer les infos de la personne, sauf si elle est déjà présente
- if (!array_key_exists($idPersonneCourant, $totalPersonnes)) {
- $totalPersonnes[$idPersonneCourant] = $_SESSION['membresDonateurs'][$ligne->idUser]->clone();
- }
- } else {
- // même personne : cumuler versements et mettre à jour les dates
- $totalVersements += $ligne->versement;
- if (strtotime($ligne->date) < $dateMin) {
- $dateMin = strtotime($ligne->date);
- }
- if (strtotime($ligne->date) > $dateMax) {
- $dateMax = strtotime($ligne->date);
- }
- }
- }
- // et le dernier
- $tarifCompte = ($idTarifCourant == 0) ?
- $idCompteCourant :
- $idTarifCourant . "_" . $idCompteCourant;
- $totalPersonnes[$idPersonneCourant]->ajouterVersement(
- $_SESSION['tauxSelectionnes'][$tarifCompte],
- $totalVersements,
- $dateMin,
- $dateMax
- );
- return $totalPersonnes;
-} // cumulerVersementsTarif
-
-/**
- * génère un fichier PDF à partir d'un document html
- * ajoute son nom à la liste de fichiers
- */
-function genererPDF($docHTML, $nomPersonne, &$listeFichiersPDF)
-{
- // fabriquer le fichier PDF
- $nomPDF = \Paheko\Utils::filePDF($docHTML);
- // changer le nom du fichier
- $nom = str_replace(' ', '_', $nomPersonne);
- $nom = str_replace("'", "", $nom);
- $nomFichier = sprintf(
- '%s/recu_%s_%s.pdf',
- dirname($nomPDF),
- $_SESSION['annee_recu'],
- $nom
- );
- rename($nomPDF, $nomFichier);
- // ajouter le nom du fichier à la liste pour mettre dans une archive
- $listeFichiersPDF[] = $nomFichier;
-} // genererPDF
-
-function faireNumeroRecu($prefixeNum, $membre, $numero, &$numero_sequentiel)
-{
- if (isset($membre) && $membre) {
- if ($prefixeNum != "") {
- $prefixeNum .= "-";
- }
- $prefixeNum .= $numero;
- }
- if ($numero_sequentiel) {
- if ($prefixeNum != "") {
- $prefixeNum .= "-";
- }
- $prefixeNum .= $numero_sequentiel;
- ++$numero_sequentiel;
- }
- return $prefixeNum;
-}
-
-/**
- * renvoyer le préfixe du numéro de reçu
- */
-function getNumPrefixe($configNum)
-{
- $prefixeNum = "";
- if (isset($configNum->prefixe) && $configNum->prefixe != "") {
- $prefixeNum = $configNum->prefixe;
- }
- if (isset($configNum->annee) && $configNum->annee) {
- if ($prefixeNum != "") {
- $prefixeNum .= "-";
- }
- $prefixeNum .= $_SESSION['annee_recu'];
- }
- return $prefixeNum;
-}
-
-/**
- * renvoyer le premier numéro de la numérotation séquentielle
- * renvoie false si pas de numérotation séquentielle
- */
-function getNumSequentiel($configNum)
-{
- if (isset($configNum->sequentiel) && $configNum->sequentiel) {
- if (isset($configNum->valeur_init) && $configNum->valeur_init != "") {
- $numero_sequentiel = $configNum->valeur_init;
- } else {
- $numero_sequentiel = 1;
- }
- }
- return isset($numero_sequentiel) ? $numero_sequentiel : false;
-}
-
-function mentionsComplémentaires()
-{
- $donnees = array(
- 'Nature du don : ' => "Numéraire",
- 'Mode de versement : ' => "chèque et/ou virement"
- );
- $complements = array();
- foreach ($donnees as $titre => $libelle) {
- $elem = new \stdClass();
- $elem->titre = $titre;
- $elem->libelle = $libelle;
- $complements[] = $elem;
- }
- return $complements;
-}
diff --git a/admin/imprimer_recu.css b/admin/imprimer_recu.css
deleted file mode 100644
index 31778da..0000000
--- a/admin/imprimer_recu.css
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * impression
- */
-@page
-{
- size: A4 portrait;
-}
-
-header.header {
- display: none;
-}
-
-body {
- background: #fff;
- padding: 0;
- margin: 0;
-}
-
-.noprint {
- display: none;
-}
-
-nav.tabs
-{
- display: none;
-}
-
-main {
- margin: 0;
-}
-
-div.previs_recu
-{
- font-family: Serif;
- font-size: 11pt;
- background-color: white;
- break-after: always;
-}
-
-/* supprimer saut de page après dernier */
-div.previs_recu:last-of-type
-{
- font-family: Serif;
- font-size: 11pt;
- background-color: white;
- break-after: avoid;
-}
-
-#__profiler {
- display: none;
-}
diff --git a/admin/index.php b/admin/index.php
deleted file mode 100644
index 3b1e76f..0000000
--- a/admin/index.php
+++ /dev/null
@@ -1,75 +0,0 @@
-needUpgrade()) {
- $plugin->upgrade();
-}
-
-// Année fiscale par défaut
-if (! isset($_SESSION['annee_recu']) || $_SESSION['annee_recu'] == "")
-{
- $_SESSION['annee_recu'] = date("Y") - 1;
-}
-
-// nombre de taux de réduction activés
-$nbTaux = 0;
-foreach ($plugin->getConfig('reduction') as $taux)
-{
- if ($taux->valeur) { ++$nbTaux; }
-}
-
-// idem avec les champs nom/prénom
-$nbChamps = 0;
-$champsNom = Utils::getChampsNom($config, $plugin);
-if (null !== $champsNom)
-{
- foreach ($champsNom as $nom => $champ)
- {
- if ($champ->position != 0) { ++$nbChamps; }
- }
-}
-
-// comptes sur lesquels des versements de membres ont été faits
-// pendant l'année fiscale choisie
-$_SESSION['comptes'] = Utils::getComptes($_SESSION['annee_recu'], 'like', '7%');
-
-// liste des activités, tarifs et comptes associés
-$activitesTarifsComptes = Utils::getTarifsComptes($_SESSION['annee_recu'], 'like', '7%');
-$_SESSION['lesTarifs'] = Utils::getTarifs();
-$_SESSION['lesActivites'] = Utils::getActivites();
-
-// liste des comptes associés à aucune activité
-$comptesSansActivite = array();
-foreach ($_SESSION['comptes'] as $id => $elem)
-{
- $trouve = false;
- foreach ($activitesTarifsComptes as $elem)
- {
- if ($id == $elem->idCompte) { $trouve = true ; break; }
- }
- if (! $trouve) { $comptesSansActivite[] = $id; }
-}
-
-// préparation de l'affichage
-$tpl->assign('annee_recu', $_SESSION['annee_recu']);
-$tpl->assign('lesComptes', $_SESSION['comptes']);
-$tpl->assign('lesTarifs', $_SESSION['lesTarifs']);
-$tpl->assign('lesActivites', $_SESSION['lesActivites']);
-$tpl->assign('activitesTarifsComptes', $activitesTarifsComptes);
-$tpl->assign('comptesSansActivite', $comptesSansActivite);
-$tpl->assign('nbComptesSansActivite',count($comptesSansActivite));
-$tpl->assign('nbTarifs', count($activitesTarifsComptes));
-$tpl->assign('nbComptes', count($_SESSION['comptes']));
-$tpl->assign('plugin_config', $plugin->getConfig());
-$tpl->assign('nbTaux', $nbTaux);
-$tpl->assign('nbChamps', $nbChamps);
-$tpl->assign('plugin_css', ['style.css']);
-$tpl->assign('plugin_url', \Paheko\Utils::plugin_url());
-
-// envoyer au template
-$tpl->display(PLUGIN_ROOT . '/templates/index.tpl');
diff --git a/admin/previs_recu.css b/admin/previs_recu.css
deleted file mode 100644
index 3605d4b..0000000
--- a/admin/previs_recu.css
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * prévisualisation reçu au format HTML
- */
-
-div.previs_recu
-{
- width : 18.5cm;
-}
-
-#logo
-{
- max-height : 4cm;
-}
-
-#titre
-{
- margin : 0 2cm 0 2cm;
- text-align : center;
- font-size : 14pt;
- font-weight: bold;
-}
-
-#articles
-{
- margin-bottom: 0.5cm;
- text-align : center;
-}
-
-#numRecu
-{
- text-align : right;
- margin-right: 1em;
-}
-
-#versements
-{
- border-top: 1px solid rgb(0, 0, 128);
- border-bottom: 1px solid rgb(0, 0, 128);
- padding-top: 1em;
- margin-bottom: 1em;
-}
-
-.cartouche
-{
- padding-bottom: 1em;
-}
-
-.rubrique
-{
- background-color : rgb(200, 200, 250);
- padding : 0 0 0 1mm;
- margin-bottom: 1em;
-}
-
-.titre, .important
-{
- font-weight:bold;
-}
-.libelle
-{
- font-weight: normal;
-}
-
-#ville
-{
- margin-bottom: 0;
-}
-
-#signature
-{
- display: block;
- max-width : 7cm;
- max-height : 4cm;
- margin: 0 auto;
- padding-bottom : 2mm;
-}
-
-#versements > ul
-{
- list-style: inside;
- margin-left: 2em;
-}
-
-#date_versements
-{
- margin-left: 1.5em;
-}
-
-p.complements
-{
- margin-top : 1em;
-}
-
-span.titre, span.libelle
-{
- display : inline;
-}
-
-/* Ne pas imprimer le bandeau des boutons du profiler */
-#__profiler
-{
- display: none;
-}
diff --git a/admin/script.js b/admin/script.js
deleted file mode 100644
index 8f68766..0000000
--- a/admin/script.js
+++ /dev/null
@@ -1,292 +0,0 @@
-"use strict";
-
-/**
- * renvoyer la valeur numérique d'un montant formaté en €
- * @param texte qui représente nu nombre
- */
-function getNumber(texte) {
- return Number(texte.replace(/[^0-9,]/g, '').replace(/,/, '.'));
-}
-
-/**
- * afficher un montant au format monétaire
- * @param montant à afficher
- * @param idElem : élément où faire l'affichage
- */
-function displayNumber(montant, idElem) {
- idElem.innerHTML =
- montant.toLocaleString('fr-FR', {
- style: 'currency', currency: 'EUR',
- minimumFractionDigits: 2
- });
-}
-
-// ------------------------------------------------------------------------
-// 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
- * @param {HTMLInputElement} idCaseGlobale id de la case globale
- * @param {HTMLSpanElement} idTotalGeneral id du total général
- */
-function cocherDecocherTout(idCaseGlobale, idTotalGeneral) {
- // itérer sur la liste des éléments détails : 1 par couple
- let lesDetails = document.querySelectorAll("details.activite");
- for (let i = 0; i < lesDetails.length; ++i) {
- let idCase = lesDetails[i].querySelector("input[type=checkbox]");
- idCase.checked = idCaseGlobale.checked;
- cocherDecocherTarif(idCase, idTotalGeneral);
- }
- // changer le message
- changerMessage(idCaseGlobale.nextElementSibling, idCaseGlobale);
-}
-
-/**
- * Fonction appelée quand on (dé)coche la case d'activité
- * (dé)sélectionner toutes les cases de cette activité
- * @param {HTMLInputElement} idCaseGlobale id de la case d'activité
- * @param {HTMLSpanElement} idTotalGeneral id du total général
- */
-function cocherDecocherTarif(idCaseGlobale, idTotalGeneral) {
- let lesPersonnes = idCaseGlobale.closest("details").querySelectorAll("div.personne");
- cocherDecocherLesPersonnes(idCaseGlobale, lesPersonnes, idTotalGeneral);
-}
-
-/**
- * idem dans le cas des versements des personnes
- * @param {HTMLInputElement} idCaseGlobale id case à cocher d'une personne
- */
-function cocherDecocherToutesLesPersonnes(idCaseGlobale, idTotalGeneral) {
- let lesPersonnes = document.querySelectorAll("summary.personne");
- cocherDecocherLesPersonnes(idCaseGlobale, lesPersonnes, idTotalGeneral);
- changerMessage(idCaseGlobale.nextElementSibling, idCaseGlobale);
-}
-
-/**
- * @param {HTMLInputElement} idCaseGlobale
- * @param {NodeListOf} lesPersonnes
- * @param {HTMLSpanElement} idTotalGeneral id du total général
-*/
-function cocherDecocherLesPersonnes(idCaseGlobale, lesPersonnes, idTotalGeneral) {
- for (let j = 0; j < lesPersonnes.length; ++j) {
- // trouver l'élément total de la personne
- let idTotal = lesPersonnes[j].querySelector("span.total");
- // puis la case à cocher
- let idCase = lesPersonnes[j].querySelector("input[type=checkbox]");
- idCase.checked = idCaseGlobale.checked;
- // puis traiter toutes les cases de la personne
- cocherDecocherPersonne(idCase, idTotal, idTotalGeneral);
- }
-}
-
-/**
- * Fonction appelée quand on (dé)coche la case d'une personne
- * - (dé)sélectionner toutes les cases à cocher
- * - faire le total des cases cochées et l'afficher
- * @param {HTMLInputElement} idCase id de la case qui a été cochée
- * @param {HTMLSpanElement} idTotal id de l'élément où afficher le total de la personne
- * @param {HTMLSpanElement} idTotalGeneral id de l'élément où afficher le total général
- */
-function cocherDecocherPersonne(idCase, idTotal, idTotalGeneral) {
- let conteneur = idCase.closest("details").querySelector("div.versements");
- let listeCases = conteneur.querySelectorAll("input[type=checkbox]");
-
- for (let i = 0; i < listeCases.length; ++i) {
- if (listeCases[i].checked != idCase.checked) {
- listeCases[i].checked = idCase.checked;
- cocherDecocherVersement(listeCases[i], idTotal, idTotalGeneral);
- }
- }
-}
-
-/**
- * Fonction appelée quand on (dé)coche la case d'un versement
- * Mettre à jour le total des cases cochées et le total global et les afficher
- *
- * @param {HTMLInputElement} idCase id de la case qui a été (dé)cochée
- * @param {HTMLSpanElement} idTotal id du total de la personne
- * @param {HTMLSpanElement} idTotalGeneral id du total général
- */
-
-function cocherDecocherVersement(idCase, idTotal, idTotalGeneral) {
- let div = idCase.closest("div");
- let idmontant = div.querySelector("span.montant");
- let montant = getNumber(idmontant.textContent);
- let totalPersonne = getNumber(idTotal.textContent);
- let totalGeneral = getNumber(idTotalGeneral.textContent);
- if (idCase.checked) {
- totalPersonne += montant;
- totalGeneral += montant;
- } else {
- totalPersonne -= montant;
- totalGeneral -= montant;
- }
- displayNumber(totalPersonne, idTotal);
- displayNumber(totalGeneral, idTotalGeneral);
-}
-
-/**
- * changer le message en fonction de l'état coché de la case
- * @param {Element} message
- * @param {HTMLInputElement} idCase
- */
-function changerMessage(message, idCase) {
- if (idCase.checked) {
- message.innerHTML = "Cliquer pour dé-cocher toutes les lignes";
- } else {
- message.innerHTML = "Cliquer pour cocher toutes les lignes";
- }
-}
-
-/**
- * afficher/masquer les détails
- * @param {string} idElem bouton de masquage/affichage
- * @param {string} classe des détails à afficher/masquer
- * @param {string} texte du bouton
- */
-function montrerMasquerDetails(idElem, classe, texte) {
- let lesDetails = document.querySelectorAll(classe);
- if (lesDetails.length > 0) {
- let leBouton = document.getElementById(idElem);
- if (leBouton.textContent.includes('Replier')) {
- // masquer
- lesDetails.forEach((e) => {
- e.removeAttribute('open');
- });
- leBouton.textContent = "Déplier " + texte;
- leBouton.setAttribute('data-icon', '↓');
- }
- else {
- // montrer
- lesDetails.forEach((e) => {
- e.setAttribute('open', 'open');
- });
- leBouton.textContent = "Replier " + texte;
- leBouton.setAttribute('data-icon', '↑');
- }
- }
-}
-
-/**
- * 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 verifierChoix(formulaire) {
- 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(divArticles, divTauxReduc) {
- // articles
- if (!verifierCases(divArticles, "checkbox", "au moins un article")) { return false; }
-
- // taux de réduction
- if (!verifierCases(divTauxReduc, "checkbox", "au moins un taux de réduction")) { return false; }
-
- // Nom, fonction, signature
-
-
- // 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;
-}
-
-/**
- * petite bidouille pour utiliser ma feuille de style pour imprimer les reçus
- * à la place de la feuille de style de paheko
- * @param {*} document
- */
-function changerStyle(document) {
- let styles = document.querySelectorAll('link[rel="stylesheet"]');
- for (let sheet of styles) {
- if (sheet.href.includes('print.css')) { sheet.media = "tv"; }
- if (sheet.href.includes('imprimer_recu.css')) { sheet.media = 'print'; }
- }
-}
diff --git a/admin/style.css b/admin/style.css
deleted file mode 100644
index 23b3976..0000000
--- a/admin/style.css
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * liste des versements
- */
-
-label.strong {
- font-weight : bold;
-}
-
-div.pair {
- background-color: rgba(var(--gSecondColor), 0.15);
-}
-
-fieldset.versements
-{
- margin-bottom : 0;
- margin-right : 0.5em;
- -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;
-}
-
-input.check_global
-{
- margin : 0.2em 0.5em;
-}
-
-div.versements
-{
- margin-left : 4em;
- display: flex;
- flex-wrap: wrap;
-}
-
-/*
- * 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;
-}
-
-a.icn-btn {
- font-family: "paheko", sans-serif;
- font-size : 1.2em;
-}
-
-dl.config
-{
- padding-bottom : 1ex;
- padding-right : 1em;
-}
-
-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;
-}
-*/
-div.champnom
-{
- display : flex;
- margin-top : 0.25rem;
-}
-div.infos
-{
- border : 1px solid rgba(var(--gMainColor));
- border-radius : 0.25rem;
- padding : 0.4rem;
- margin-left : 1em;
- width : 20em;
-}
-ul#liste_activites dd
-{
- display: inline-block;
-}
-
-ul.reduction span.radio-btn
-{
- margin-left : 2em;
- border-spacing : 0.1em;
-}
-input#f_prefixe
-{
- width : 8em;
- min-width : 8em;
-}
-input#f_valeur_init
-{
- max-width: 4em;
-}
diff --git a/admin/upload.php b/admin/upload.php
deleted file mode 100644
index fca8872..0000000
--- a/admin/upload.php
+++ /dev/null
@@ -1,24 +0,0 @@
-runIf('upload', function () use ($parent, $session) {
- $_SESSION['sig_file'] = \Paheko\Files\Files::uploadMultiple($parent, 'file', $session);
-}, $csrf_key, PLUGIN_ROOT . '/admin/config.php');
-
-$tpl->assign(compact('parent', 'csrf_key'));
-
-$tpl->display(PLUGIN_ROOT . '/templates/upload.tpl');
diff --git a/admin/versements_activites.php b/admin/versements_activites.php
deleted file mode 100644
index 56114bf..0000000
--- a/admin/versements_activites.php
+++ /dev/null
@@ -1,98 +0,0 @@
-
- strpos($elem, '_') !== false ? substr($elem, 0, strpos($elem, '_')) : "",
- $tarifsSelectionnes);
-$lesComptes = array_map(fn($elem) : string =>
- strpos($elem, '_') !== false ? substr($elem, 1 + strpos($elem, '_')) : "",
- $tarifsSelectionnes);
-
-# versements des tarifs sélectionnées et de leur compte associé
-if (count($lesTarifs) != 0)
-{
- $_SESSION['lesVersements'] =
- Utils::getVersementsTarifsComptes(
- $_SESSION['annee_recu'],
- $lesTarifs,
- $lesComptes,
- $champsNom);
- // error_log("lesVersements=" . print_r($_SESSION['lesVersements'], true));
-}
-
-// ajouter les versements sans tarif (tri par nom, compte, date)
-if (isset($_SESSION['comptesSelectionnes']))
-{
- $versementsSansTarif = Utils::getVersementsComptes($_SESSION['annee_recu'],
- $_SESSION['comptesSelectionnes'],
- $champsNom);
- foreach ($versementsSansTarif as $versement)
- {
- $_SESSION['lesVersements'][] = $versement;
- }
-}
-//error_log("lesVersements=" . print_r($_SESSION['lesVersements'], true));
-
-// préparation de l'affichage
-$tpl->assign('lesVersements', $_SESSION['lesVersements']);
-$tpl->assign('annee_recu', $_SESSION['annee_recu']);
-$tpl->assign('plugin_css', ['style.css']);
-
-// envoyer au template
-$tpl->display(PLUGIN_ROOT . '/templates/versements_activites.tpl');
-
diff --git a/admin/versements_personnes.php b/admin/versements_personnes.php
deleted file mode 100644
index 8db95e8..0000000
--- a/admin/versements_personnes.php
+++ /dev/null
@@ -1,34 +0,0 @@
-assign('lesVersements', $_SESSION['lesVersements']);
-$tpl->assign('annee_recu', $_SESSION['annee_recu']);
-$tpl->assign('plugin_css', ['style.css']);
-
-// envoyer au template
-$tpl->assign('plugin_config', $plugin->getConfig());
-$tpl->display(PLUGIN_ROOT . '/templates/versements_personnes.tpl');
diff --git a/config.json b/config.json
index 622936c..59b6ce7 100644
--- a/config.json
+++ b/config.json
@@ -1,38 +1,28 @@
{
"articlesCGI" : [
{
- "titre" : "200",
- "valeur" : false
+ "titre" : "Article 200",
+ "valeur" : 0
},
{
- "titre" : "238 bis",
- "valeur" : false
+ "titre" : "Article 228 bis",
+ "valeur" : 0
},
{
- "titre" : "978",
- "valeur" : false
+ "titre" : "Article 978",
+ "valeur" : 0
}
],
"reduction" : [
{
"taux" : "normal",
"ligne" : "UF",
- "remarque" : "",
- "valeur" : false
+ "remarque" : ""
},
{
"taux" : "majoré",
"ligne" : "UD",
- "remarque" : "aide aux personnes en difficulté",
- "valeur" : false
+ "remarque" : "aide aux personnes en difficulté"
}
- ],
- "numerotation" : {
- "prefixe" : "",
- "annee" : false,
- "membre" : false,
- "sequentiel" : false,
- "valeur_init": 1
- },
- "imprimerCourriel" : false
+ ]
}
diff --git a/data/default_signature.png b/data/default_signature.png
index 4ea7ecf..38aa69f 100644
Binary files a/data/default_signature.png and b/data/default_signature.png differ
diff --git a/garradin_plugin.ini b/garradin_plugin.ini
new file mode 100644
index 0000000..1660303
--- /dev/null
+++ b/garradin_plugin.ini
@@ -0,0 +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.1"
+menu=1
+config=1
+min_version="1.1"
diff --git a/install.php b/install.php
index c9b26e3..3405396 100644
--- a/install.php
+++ b/install.php
@@ -1,23 +1,20 @@
get('name');
-const SIGNATURE_DEFAUT = 'default_signature.png';
-const CONFIG_INIT = 'config.json';
+//$db->import(dirname(__FILE__) . "/data/schema.sql");
-// configuration initiale
-$config_init = json_decode(file_get_contents(Plugins::getPath($nom_plugin) . '/' . CONFIG_INIT),
- true);
+/*
+$plugin->setConfig('footer', "[EXEMPLE]\n".
+ "Association exonérée des impôts commerciaux\n".
+ "En cas de retard de paiement, indemnité forfaitaire légale pour frais de recouvrement : 40,00 €\n".
+ "[Coordonnées bancaires]\n".
+ "Association enregistrée en préfecture de XXX au numéro YYY"
+ );
+$plugin->setConfig('validate_cp', true);
-// enregistrer dans la config du plugin
-foreach ($config_init as $cle => $valeur) {
- $plugin->setConfigProperty($cle, $valeur);
-}
-$plugin->save();
-
-// « signature » par défaut à remplacer (voir l'onglet de configuration)
-$path = __DIR__ . '/data/' . SIGNATURE_DEFAUT;
-$default_signature_file = Files::createFromPath('ext/' . $nom_plugin . '/' . SIGNATURE_DEFAUT,
- $path);
+$path = __DIR__.'/data/default_signature.png';
+$png = (new File)->createAndStore('skel/plugin/recusDons','signature.png', $path, null);
+*/
diff --git a/lib/Personne.php b/lib/Personne.php
index 1f639af..ab34dbf 100644
--- a/lib/Personne.php
+++ b/lib/Personne.php
@@ -1,6 +1,6 @@
id = $id;
- $this->numero = $numero;
- $this->courriel = $courriel;
- $this->rang = $rang;
$this->nomPrenom = $nomPrenom;
$this->adresse = $adresse;
$this->codePostal = $codePostal;
$this->ville = $ville;
- $this->versements = array(); // clé = tarif, valeur = Versement
+ $this->courriel = $courriel;
+ $this->versements = array();
}
/**
* return copie d'une personne
+ * @param $p
*/
- public function clone()
+ public static function copier($p)
{
return new Personne(
- $this->id,
- $this->numero,
- $this->courriel,
- $this->rang,
- $this->nomPrenom,
- $this->adresse,
- $this->codePostal,
- $this->ville);
+ $p->id,
+ $p->nomPrenom,
+ $p->adresse,
+ $p->codePostal,
+ $p->ville,
+ $p->courriel);
}
+
/**
* ajouter un versement
- * @param $tauxReduction
+ * @param $idActivite
+ * @param $idTarif
* @param $montant
- * @param $dateMin
- * @param $dateMax
+ * @param $tauxReduction
*/
public function ajouterVersement(
- $tauxReduction,
+ $idActivite,
+ $idTarif,
$montant,
- $dateMin,
- $dateMax
- )
- {
- if (array_key_exists($tauxReduction, $this->versements))
- {
- $this->versements[$tauxReduction]->ajouter($montant, $dateMin, $dateMax);
- }
- else
- {
- $this->versements[$tauxReduction] = new Versement($montant, $dateMin, $dateMax);
- }
+ $tauxReduction
+ ) {
+ $this->versements[] =
+ new Versement(
+ $idActivite,
+ $idTarif,
+ $montant,
+ $tauxReduction
+ );
}
-
}
diff --git a/lib/RecusPDF.php b/lib/RecusPDF.php
new file mode 100644
index 0000000..9891cc2
--- /dev/null
+++ b/lib/RecusPDF.php
@@ -0,0 +1,196 @@
+AddFont($family,
+ '',
+ $family.$style.".ttf",
+ true);
+ // bold
+ $this->AddFont($family,
+ 'B',
+ $family.$style."-Bold.ttf",
+ true);
+ $this->nomAsso = $nomAsso;
+ $this->adresseAsso = $adresseAsso;
+ $this->logoCerfa = $logo;
+ $this->signature = $signature;
+ }
+
+ // Header
+ function Header()
+ {
+ parent::Header();
+ // Logo
+ $this->Image($this->logoCerfa, 10, 6, 30);
+
+ // document title
+ $this->SetTextColor(0, 0, 0);
+ $this->SetFont('DejaVu','B',12);
+ $titre = "Reçu au titre des dons à certains organismes d'intérêt général";
+ $this->SetXY(50, 10);
+ // Titre
+ $this->MultiCell(100,
+ 6,
+ $titre,
+ 0,
+ 'C');
+
+ // numéro de Cerfa
+ $cerfa = "N° 11580*3";
+ $this->SetFont('DejaVu', 'B', 10);
+ $this->SetXY(10, 25);
+ $this->Cell(100, 0, $cerfa);
+
+ // Articles
+ $this->SetFont('DejaVu', '', 9);
+ $this->SetXY(50, 25);
+ $this->Cell(100, 0, 'Article 200, 238 bis et 885-0 V bis A du code général des impôts');
+ }
+
+ // imprimer les informations du bénéficiaire
+ function imprimer_beneficiaire($nom, $adresse)
+ {
+ $this->titre_rubrique("Bénéficiaire des versements");
+ $this->SetFont('DejaVu', 'B', 11);
+ $this->Cell(0, 6, 'Association « ' . $nom . ' »', 'LR', 1);
+ $this->Cell(0, 6, str_replace(array("\r\n", "\n", "\r"), " ", $adresse), 'LR', 1);
+ $this->imprimer_description("Objet : ",
+ "célébrer le culte protestant évangélique et pourvoir aux frais et besoins de ce culte.");
+ $this->Cell(0, 6, "", 'LRB', 1);
+ }
+
+ // imprimer un libellé précédé de son titre en gras
+ function imprimer_description($titre, $libelle)
+ {
+ $this->SetFont('DejaVu', 'B', 11);
+ $this->Cell($this->GetStringWidth($titre), 6, $titre, 'L', 0);
+ $this->SetFont('DejaVu', '', 11);
+ $this->Cell(0, 6, $libelle, 'R', 1);
+ }
+
+ // imprimer le montant de la réduction et un libellé
+ function imprimer_montant($texte, $montant, $libelle = "")
+ {
+ $this->SetFont('DejaVu');
+ $this->Cell($this->GetStringWidth($texte),
+ 6,
+ $texte,
+ 'L',
+ 0);
+ $this->SetFont('DejaVu','B');
+ $valeur = number_format($montant, 2, "," , "") . " euros";
+ $this->Cell($this->GetStringWidth($valeur),
+ 6,
+ $valeur,
+ '',
+ 0);
+ $this->SetFont('DejaVu');
+ if ($libelle != "")
+ {
+ $this->Cell(0,
+ 6,
+ " : " . $libelle,
+ 'R',
+ 1);
+ }
+ else
+ {
+ $this->Cell(0, 6, "", 'R', 1);
+ }
+ }
+
+ function titre_rubrique($texte)
+ {
+ $this->SetFont('DejaVu','B',12);
+ $largeur_texte = $this->GetStringWidth($texte);
+ $this->setX(10);
+ $this->SetFillColor(0, 255, 255);
+ $this->Cell(0, 6, $texte, 'LTR', 1, 'C', true);
+ $this->Cell(0, 6, "", 'LR', 1);
+ }
+
+ // imprimer le reçu
+ function imprimer_recu($annee_recu,
+ $numero,
+ $nom,
+ $lesMontants,
+ $adresse,
+ $code_postal,
+ $ville)
+ {
+
+ $this->AddPage();
+ // Numéro de reçu
+ $this->SetFont('DejaVu', 'B', 11);
+ $this->MultiCell(0, 20, 'Reçu numéro ' . $annee_recu . '/' . $numero);
+
+ // bénéficiaire
+ $this->imprimer_beneficiaire($this->nomAsso, $this->adresseAsso);
+
+ // donateur
+ $this->Ln(10);
+ $this->titre_rubrique("Donateur");
+ $this->SetFont('DejaVu', 'B', 11);
+ $this->Cell(0, 6, $nom, 'LR', 1);
+ $this->Cell(0, 6, $adresse, 'LR', 1);
+ $this->Cell(0, 6, $code_postal . " " . $ville, 'LR', 1);
+ $this->Cell(0, 6, "", 'LRB', 1);
+
+ // Montant et autres informations
+ $this->Ln(10);
+ $this->SetFont('DejaVu', '', 11);
+ $this->Cell(0,
+ 6,
+ "Le bénéficiaire reconnaît avoir reçu au titre des dons et versements ouvrant droit à réduction d'impôt :",
+ 'LTR',
+ 1);
+ foreach ($lesMontants as $taux => $montant)
+ {
+ $this->imprimer_montant(" - la somme de ", $montant, Utils::getLigneReduction($taux));
+ }
+ $this->Cell(0, 3, "", 'LR', 1);
+ $this->imprimer_description('Date des versements : ',
+ 'année ' . $annee_recu);
+ $this->Cell(0, 3, "", 'LR', 1);
+ $this->MultiCell(0, 6,
+ "Le bénéficiaire certifie sur l’honneur que les dons et versements qu’il reçoit ouvrent droit à la réduction
+d'impôt prévue à l’article 200 du CGI",
+ 'LR');
+ $this->Cell(0, 3, "", 'LR', 1);
+ $this->imprimer_description("Forme du don : ", "Autre");
+ $this->Cell(0, 3, "", 'LR', 1);
+ $this->imprimer_description("Nature du don : ", "Numéraire");
+ $this->Cell(0, 3, "", 'LR', 1);
+ $this->imprimer_description("Mode de versement : ", "chèque et/ou virement");
+ $this->Cell(0, 0, "", 'LRB', 1);
+
+ // cartouche final
+ $this->Ln(10);
+ $this->Cell(0, 6, "", 'LRT', 1);
+ $this->Cell(0, 6, "Rennes le " . date("j/m/Y"), 'LR', 1, 'R');
+ $this->Cell(0, 36, "", 'LR', 1);
+ $this->Cell(0, 0, "", 'LBR', 1);
+ $this->SetXY(100, 220);
+ $this->Image($this->signature, null, null, 50);
+ }
+} // class RecusPDF
diff --git a/lib/Utils.php b/lib/Utils.php
index 343616f..0d0bfb2 100644
--- a/lib/Utils.php
+++ b/lib/Utils.php
@@ -1,465 +1,418 @@
getGrouped($sql);
- }
+ // ------------------------------------------------------------
+ // test nouvelle organisation
+ /**
+ * @return tarifs demandés
+ * @param array $tarifs
+ */
+ public static function getTarifs($tarifs)
+ {
+ $db = DB::getInstance();
+ $sql = sprintf(
+ 'SELECT id, id_service as idActivite, label, description, amount as montant
+ FROM services_fees
+ WHERE services_fees.%s',
+ $db->where('id', $tarifs));
+ return $db->get($sql);
+ }
- /**
- * @return informations sur les activités
- */
- public static function getActivites()
- {
- $db = DB::getInstance();
- $sql = sprintf(
- 'SELECT
- services.id,
- services.label,
- services.description
- FROM services');
- return $db->getGrouped($sql);
- }
+ /**
+ * @return activités correspondant aux tarifs demandés
+ * @param array $tarifs
+ */
+ public static function getActivites($tarifs)
+ {
+ $db = DB::getInstance();
+ $sql = sprintf(
+ 'SELECT services.id, services.label, services.description
+ FROM services
+ LEFT JOIN services_fees ON services_fees.id_service = services.id
+ WHERE services_fees.%s
+ GROUP BY services.id',
+ $db->where('id', $tarifs));
+ return $db->get($sql);
+ }
- /**
- * @return comptes sur lesquels des versements de membres ont été faits
- * @param string $annee
- * @param $op : opérateur de combinaison des comptes
- * @param array $comptes
- */
- public static function getComptes($annee, $op, $comptes)
- {
- $db = DB::getInstance();
- $sql = sprintf(
- 'SELECT
- acc_accounts.id,
- acc_years.label,
- acc_accounts.code as codeCompte,
- acc_accounts.label as nomCompte
- FROM acc_transactions_users
- INNER JOIN users
- ON acc_transactions_users.id_user = users.id
- INNER JOIN acc_transactions
- ON acc_transactions_users.id_transaction = acc_transactions.id
- INNER JOIN acc_transactions_lines
- ON acc_transactions_lines.id_transaction = acc_transactions.id
- INNER JOIN acc_accounts
- ON acc_transactions_lines.id_account = acc_accounts.id
- INNER JOIN acc_years
- ON acc_transactions.id_year = acc_years.id
- WHERE
- (strftime("%%Y", acc_transactions.date) = "%d"
- AND
- acc_accounts.%s
- )
- GROUP by acc_accounts.id
- ORDER by acc_accounts.code',
- $annee,
- $db->where('code', $op, $comptes)
- );
- return $db->getGrouped($sql);
- }
+ /**
+ * @return versements correspondants à l'année et aux tarifs donnés
+ * @param $annee
+ * @param array $tarifs
+ */
+ public static function getVersementsTarifs($annee, $tarifs)
+ {
+ $db = DB::getInstance();
+ $sql = sprintf(
+ 'SELECT
+ services_fees.id as idTarif,
+ membres.id as idUser,
+ acc_transactions_lines.credit as versement,
+ acc_transactions.date
+ FROM acc_transactions_users
+ INNER JOIN membres on acc_transactions_users.id_user = membres.id
+ INNER JOIN acc_transactions on acc_transactions_users.id_transaction = acc_transactions.id
+ INNER JOIN services_users on acc_transactions_users.id_service_user = services_users.id
+ INNER JOIN services_fees on services_users.id_fee = services_fees.id
+ INNER JOIN acc_transactions_lines on acc_transactions_lines.id_transaction = acc_transactions.id
+ WHERE
+ (strftime(%s, acc_transactions.date) = "%d"
+ AND
+ services_fees.%s
+ AND
+ acc_transactions_lines.credit > 0)
+ ORDER by services_fees.id, membres.nom, acc_transactions.date',
+ '"%Y"',
+ $annee,
+ $db->where('id', $tarifs));
+ return $db->get($sql);
+ }
- /**
- * @return tarifs des activités et comptes ayant des versements de
- * membres dans l'année
- * @param string $annee
- * @param $op : opérateur de combinaison des comptes
- * @param array $comptes
- */
- public static function getTarifsComptes($annee, $op, $comptes)
- {
- $db = DB::getInstance();
- $sql = sprintf(
- '
- SELECT
- services_users.id_fee as idTarif,
- acc_accounts.id as idCompte,
- acc_accounts.code as codeCompte
- FROM acc_transactions_users
- INNER JOIN acc_transactions
- ON acc_transactions_users.id_transaction = acc_transactions.id
- INNER JOIN services_users
- ON acc_transactions_users.id_service_user = services_users.id
- INNER JOIN services_fees
- ON services_users.id_fee = services_fees.id
- INNER JOIN acc_transactions_lines
- ON acc_transactions_lines.id_transaction = acc_transactions.id
- INNER JOIN acc_accounts
- ON acc_transactions_lines.id_account = acc_accounts.id
- WHERE
- (strftime("%%Y", acc_transactions.date) = "%d"
- AND
- acc_accounts.%s
- )
- GROUP BY services_fees.id, acc_accounts.code
- ORDER BY acc_accounts.code
- ',
- $annee,
- $db->where('code', $op, $comptes)
- );
- return $db->get($sql);
- }
+ /**
+ * Versements totaux par personne pour une année donnée
+ * @param année
+ */
+ public static function getVersementsTotaux($annee)
+ {
+ $sql =
+ "SELECT
+ membres.id as idUser,
+ sum(acc_transactions_lines.credit) AS versement
+ FROM
+ acc_transactions_users,
+ membres,
+ acc_transactions
+ INNER JOIN acc_transactions_lines
+ ON acc_transactions_lines.id_transaction = acc_transactions.id
+ WHERE (
+ strftime('%Y', acc_transactions.date) = ?
+ AND
+ acc_transactions_lines.credit > 0
+ AND
+ acc_transactions_users.id_transaction = acc_transactions.id
+ AND
+ acc_transactions_users.id_user = membres.id
+ )
+ GROUP by acc_transactions_users.id_user
+ ORDER by membres.nom COLLATE U_NOCASE;
+ ";
+ return DB::getInstance()->get($sql, $annee);
+ }
- /**
- * @return versements correspondants à l'année donnée
- * @param $annee
- * @param array $champsNom : liste non vide des champs de nom/prénom
- */
- public static function getVersementsPersonnes($annee, $op, $comptes, $champsNom)
- {
- $db = DB::getInstance();
- $tri = Utils::combinerTri($champsNom);
- $sql = sprintf(
- 'SELECT
- users.id as idUser,
- acc_accounts.id as idCompte,
- acc_accounts.code as codeCompte,
- acc_transactions_lines.credit as versement,
- acc_transactions.date
- FROM acc_transactions_users
- INNER JOIN users
- ON acc_transactions_users.id_user = users.id
- INNER JOIN acc_transactions
- ON acc_transactions_users.id_transaction = acc_transactions.id
- INNER JOIN acc_transactions_lines
- ON acc_transactions_lines.id_transaction = acc_transactions.id
- INNER JOIN acc_accounts
- ON acc_transactions_lines.id_account = acc_accounts.id
- WHERE
- (strftime("%%Y", acc_transactions.date) = "%d"
- AND
- acc_accounts.%s
- )
- GROUP BY acc_transactions.id, acc_accounts.id
- ORDER by %s, acc_accounts.code, acc_transactions.date',
- $annee,
- $db->where('code', $op, $comptes),
- $tri
- );
- return $db->get($sql);
- }
+ /**
+ * @return personnes ayant versé des dons pour une année donnée
+ * @param $annee
+ */
+ public static function getDonateurs($annee)
+ {
+ $sql =
+ "SELECT
+ membres.id as idUser,
+ membres.nom as nom,
+ membres.adresse as adresse,
+ membres.code_postal as codePostal,
+ membres.ville as ville
+ FROM
+ acc_transactions_users,
+ membres,
+ acc_transactions
+ INNER JOIN acc_transactions_lines
+ ON acc_transactions_lines.id_transaction = acc_transactions.id
+ WHERE (
+ strftime('%Y', acc_transactions.date) = ?
+ AND
+ acc_transactions_lines.credit > 0
+ AND
+ acc_transactions_users.id_transaction = acc_transactions.id
+ AND
+ acc_transactions_users.id_user = membres.id
+ )
+ GROUP by membres.id
+ ORDER by membres.nom COLLATE U_NOCASE;
+ ";
+ return DB::getInstance()->get($sql, $annee);
+ }
- /**
- * @return versements correspondants à :
- * @param $annee : année fiscale
- * @param array $tarifs : tarifs sélectionnés
- * @param array $comptes : comptes associés aux tarifs
- * @param array $champsNom : liste non vide des champs de nom/prénom
- * @remarks tri par tarif, nom, compte, date
- */
- public static function getVersementsTarifsComptes($annee,
- $tarifs,
- $comptes,
- $champsNom)
- {
- $db = DB::getInstance();
- $tri = Utils::combinerTri($champsNom);
- $condition = Utils::combinerTarifsComptes($tarifs, $comptes);
- $sql = sprintf(
- 'SELECT
- services_fees.id as idTarif,
- acc_accounts.id as idCompte,
- acc_accounts.code as codeCompte,
- users.id as idUser,
- acc_transactions_lines.credit as versement,
- acc_transactions.date
- FROM acc_transactions_users
- INNER JOIN users
- ON acc_transactions_users.id_user = users.id
- INNER JOIN acc_transactions
- ON acc_transactions_users.id_transaction = acc_transactions.id
- INNER JOIN services_users
- ON acc_transactions_users.id_service_user = services_users.id
- INNER JOIN services_fees
- ON services_users.id_fee = services_fees.id
- INNER JOIN acc_transactions_lines
- ON acc_transactions_lines.id_transaction = acc_transactions.id
- INNER JOIN acc_accounts
- ON acc_transactions_lines.id_account = acc_accounts.id
- WHERE
- (strftime("%%Y", acc_transactions.date) = "%d"
- AND
- %s
- )
- GROUP BY acc_transactions.id, acc_accounts.id
- ORDER by %s, acc_accounts.code, acc_transactions.date',
- $annee,
- $condition,
- $tri
- );
- // error_log("\ngetVersementsTarifsComptes : sql=" . $sql);
- return $db->get($sql);
- }
+ public static function getLignesReduction($lesTaux)
+ {
+ foreach ($lesTaux as $elem)
+ {
+ $ligne = "taux " . $elem->taux . ", ligne " . $elem->ligne;
+ if ($elem->remarque != "") {
+ $ligne .= ", " . $elem->remarque;
+ }
+ $lignes[$elem->taux] = $ligne;
+ }
+ return $lignes;
+ }
+ public static function getLigneReduction($taux)
+ {
+ return $_SESSION['ligneReduction'][$taux];
+ }
- /**
- * @return versements correspondants à :
- * @param $annee année fiscale
- * @param $comptesIsoles comptes NON associés à un tarif
- * @param array $champsNom : liste non vide des champs de nom/prénom
- * @remarks tri par nom, compte, date
- */
- public static function getVersementsComptes($annee,
- $comptesIsoles,
- $champsNom)
- {
- $db = DB::getInstance();
- $tri = Utils::combinerTri($champsNom);
- $sql = sprintf(
- '
- SELECT
- 0 as idTarif,
- acc_accounts.id as idCompte,
- acc_accounts.code as codeCompte,
- users.id as idUser,
- acc_transactions_lines.credit as versement,
- acc_transactions.date
- FROM acc_transactions_users
- INNER JOIN users
- ON acc_transactions_users.id_user = users.id
- INNER JOIN acc_transactions
- ON acc_transactions_users.id_transaction = acc_transactions.id
- INNER JOIN acc_transactions_lines
- ON acc_transactions_lines.id_transaction = acc_transactions.id
- INNER JOIN acc_accounts
- ON acc_transactions_lines.id_account = acc_accounts.id
- WHERE
- (strftime("%%Y", acc_transactions.date) = "%d"
- AND
- acc_accounts.%s
- )
- GROUP BY acc_transactions.id, acc_accounts.id
- ORDER by %s, acc_accounts.code, acc_transactions.date
- ',
- $annee,
- $db->where('id', 'in', $comptesIsoles),
- $tri
- );
- return $db->get($sql);
- }
+ // ------------------------------------------------------------
- /**
- * @return personnes ayant versé des dons pour une année donnée
- * @param $annee
- * @param array $champsNom : champs qui définissent le nom et le prénom d'une personne
- */
- public static function getDonateurs($annee, $champsNom) : array
- {
- // concaténer les champs nom/prénoms pour la sélection
- $nom = Utils::combinerChamps($champsNom);
- // et pour le tri
- $tri = Utils::combinerTri($champsNom);
- $sql = sprintf(
- 'SELECT
- users.id as idUser,
- users.numero,
- users.email,
- row_number() over(order by %s) as rang,
- %s as nom,
- users.adresse as adresse,
- users.code_postal as codePostal,
- users.ville as ville
- FROM
- acc_transactions_users,
- users,
- acc_transactions
- INNER JOIN acc_transactions_lines
- ON acc_transactions_lines.id_transaction = acc_transactions.id
- WHERE (
- strftime("%%Y", acc_transactions.date) = "%d"
- AND
- acc_transactions_users.id_transaction = acc_transactions.id
- AND
- acc_transactions_users.id_user = users.id
- )
- GROUP by users.id
- ORDER by %1$s COLLATE U_NOCASE
- ',
- $tri,
- $nom,
- $annee
- );
- $donateurs = array();
- foreach (DB::getInstance()->iterate($sql) as $personne)
- {
- $donateurs[$personne->idUser] = new Personne($personne->idUser,
- $personne->numero,
- $personne->email,
- $personne->rang,
- $personne->nom,
- $personne->adresse,
- $personne->codePostal,
- $personne->ville);
- }
- return $donateurs;
- }
+ /**
+ * @return liste des activités
+ */
+ public static function getToutesActivites()
+ {
+ return DB::getInstance()->get(
+ "SELECT
+ id as idActivite,
+ label,
+ description
+ FROM services
+ ORDER BY label"
+ );
+ }
- /**
- * combiner les champs avec un opérateur
- * @param array $champs : liste (non vide) de champs
- * @return chaîne combinée
- */
- private static function combinerChamps($champs)
- {
- $op = ' || " " || ';
- $result = 'ifnull(users.' . $champs[0] . ', "")';
- for ($i = 1; $i < count($champs); ++$i)
- {
- $result .= $op . 'ifnull(users.' . $champs[$i] . ', "")';
- }
- return 'trim(' . $result . ')';
- }
+ /**
+ * @return liste des tarifs d'une activité
+ * @param $activite : identifiant de l'activité
+ */
+ public static function getTarifsActivite($activite)
+ {
+ return DB::getInstance()->get(
+ "SELECT
+ services_fees.id as idTarif,
+ services_fees.label as titreTarif,
+ services_fees.description as descTarif,
+ services_fees.amount as montantTarif
+ FROM services_fees
+ WHERE services_fees.id_service = ?",
+ $activite
+ );
+ }
- /**
- * combiner les clés de tri
- * @param clés de tri
- * @return chaîne combinée
- */
- private static function combinerTri(array $champs) : string
- {
- $tri = 'users.' . $champs[0];
- for ($i = 1; $i < count($champs); ++$i)
- {
- $tri .= ', users.' . $champs[$i];
- }
- return $tri;
- }
+ /**
+ * @return liste de toutes les activités et tarifs
+ */
+ public static function getActivitesEtTarifs()
+ {
+ return DB::getInstance()->get(
+ "SELECT
+ services.id as idActivite,
+ services.label as titreActivite,
+ services.description as descActivite,
+ services_fees.id as idTarif,
+ services_fees.label as titreTarif,
+ services_fees.description as descTarif
+ FROM services
+ LEFT JOIN services_fees ON services_fees.id_service = services.id
+ ORDER BY services.id, services_fees.id"
+ );
+ }
- /**
- * combiner chaque tarif avec le numéro de compte associé
- */
- private static function combinerTarifsComptes($tarifs, $comptes)
- {
- $condition = '(';
- $lesCond = array_map(fn($e1, $e2) : string =>
- "(services_fees.id = '$e1' AND acc_accounts.id = '$e2')",
- $tarifs, $comptes);
- $nb = 0;
- foreach ($lesCond as $cond)
- {
- if ($nb > 0) { $condition .= ' OR '; }
- $condition .= $cond;
- ++$nb;
- }
- $condition .= ')';
- return $condition;
- }
+ /**
+ * @return liste de toutes les activités, tarifs et comptes associés
+ */
+ public static function getActivitesTarifsEtComptes()
+ {
+ return DB::getInstance()->get(
+ "SELECT
+ services.id as idActivite,
+ services.label as titreActivite,
+ services.description as descActivite,
+ services_fees.id as idTarif,
+ services_fees.label as titreTarif,
+ services_fees.description as descTarif,
+ acc_accounts.code as numeroCpt,
+ acc_accounts.label as nomCpt
+ FROM services
+ LEFT JOIN services_fees ON services_fees.id_service = services.id
+ LEFT JOIN acc_accounts ON services_fees.id_account = acc_accounts.id
+ ORDER BY services.label"
+ );
+ }
- /**
- * @return liste des années fiscales
- */
- public static function getAnneesFiscales() : array
- {
- $rows = DB::getInstance()->get(
- "SELECT strftime('%Y', start_date) as annee
- FROM acc_years
- UNION
- SELECT strftime('%Y', end_date) as annee
- FROM acc_years
- ORDER by annee DESC"
- );
- $anneesFiscales = array();
- foreach ($rows as $row) {
- $anneesFiscales[] = $row->annee;
- }
- return $anneesFiscales;
- }
+ /**
+ * @return tous les versements de l'année
+ * @param $annee
+ */
+ public static function getTousLesVersements($annee)
+ {
+ $sql =
+ "SELECT
+ services.id as idActivite,
+ services_fees.id as idTarif,
+ services.label as activite,
+ services_fees.label as tarif,
+ services_fees.amount as montant,
+ acc_transactions_users.id_user as idUser,
+ acc_transactions_lines.credit as versement,
+ membres.nom as nom,
+ membres.adresse as adresse,
+ membres.ville as ville,
+ membres.code_postal as codePostal,
+ membres.email as courriel,
+ acc_transactions.date,
+ acc_transactions_users.id_transaction as idTrans
+ FROM acc_transactions_users
+ INNER JOIN membres on acc_transactions_users.id_user = membres.id
+ INNER JOIN acc_transactions on acc_transactions_users.id_transaction = acc_transactions.id
+ INNER JOIN services_users on acc_transactions_users.id_service_user = services_users.id
+ INNER JOIN services on services_users.id_service = services.id
+ INNER JOIN services_fees on services_users.id_fee = services_fees.id
+ INNER JOIN acc_transactions_lines on acc_transactions_lines.id_transaction = acc_transactions.id
+ WHERE
+ (strftime(\"%Y\", acc_transactions.date) = ?
+ AND
+ acc_transactions_lines.credit > 0)
+ ORDER by services.id, services_fees.id, membres.nom, acc_transactions.date";
+ return DB::getInstance()->get($sql, $annee);
+ }
- public static function getLignesReduction($lesTaux)
- {
- foreach ($lesTaux as $elem)
- {
- $lignes[$elem->taux] = $elem->remarque;
- }
- return $lignes;
- }
+ /**
+ * @return versements d'une année pour un ensemble de tarifs donnés
+ * @param $annee
+ * @param array $lesTarifs
+ */
+ public static function getVersementsActivite($annee, $lesTarifs)
+ {
+ $db = DB::getInstance();
+ $sql = sprintf(
+ 'SELECT
+ services.id as idActivite,
+ services_fees.id as idTarif,
+ services.label as activite,
+ services_fees.label as tarif,
+ services_fees.amount as montant,
+ acc_transactions_users.id_user as idUser,
+ acc_transactions_lines.credit as versement,
+ membres.nom as nom,
+ membres.adresse as adresse,
+ membres.ville as ville,
+ membres.code_postal as codePostal,
+ membres.email as courriel,
+ acc_transactions.date,
+ acc_transactions_users.id_transaction as idTrans
+ FROM acc_transactions_users
+ INNER JOIN membres on acc_transactions_users.id_user = membres.id
+ INNER JOIN acc_transactions on acc_transactions_users.id_transaction = acc_transactions.id
+ INNER JOIN services_users on acc_transactions_users.id_service_user = services_users.id
+ INNER JOIN services on services_users.id_service = services.id
+ INNER JOIN services_fees on services_users.id_fee = services_fees.id
+ INNER JOIN acc_transactions_lines on acc_transactions_lines.id_transaction = acc_transactions.id
+ WHERE
+ (strftime(%s, acc_transactions.date) = "%d"
+ AND
+ services_fees.%s
+ AND
+ acc_transactions_lines.credit > 0)
+ ORDER by membres.nom, acc_transactions.date',
+ '"%Y"',
+ $annee,
+ $db->where('id', $lesTarifs));
+ return $db->get($sql);
+ }
- /**
- * récupérer dans la config du plugin les champs des membres
- * utilisés pour le nom et le prénom ; ajouter/supprimer les
- * modifications par rapport à la config paheko
- * @return array tableau des champs : clé = nom, valeur = { titre, position }
- */
- public static function getChampsNom($config, $plugin) : array
- {
- // récupérer dans la config du plugin les champs mémorisés
- // pour le nom et le prénom (le tableau est vide si pas mémorisé)
- $champsNom = (array) $plugin->getConfig('champsNom');
+ /**
+ * Versements totaux par personne pour une année donnée
+ * @param année
+ */
+ public static function getVersementsTotaux_old($annee) {
+ $sql =
+ "SELECT
+ acc_transactions_users.id_user as idUser,
+ membres.nom as nom,
+ sum(acc_transactions_lines.credit) AS montant,
+ membres.adresse as adresse,
+ membres.code_postal as codePostal,
+ membres.ville as ville
+ FROM
+ acc_transactions_users,
+ membres,
+ acc_transactions
+ INNER JOIN acc_transactions_lines
+ ON acc_transactions_lines.id_transaction = acc_transactions.id
+ WHERE (
+ strftime('%Y', acc_transactions.date) = ?
+ AND
+ acc_transactions_lines.credit > 0
+ AND
+ acc_transactions_users.id_transaction = acc_transactions.id
+ AND
+ acc_transactions_users.id_user = membres.id
+ )
+ GROUP by acc_transactions_users.id_user
+ ORDER by membres.nom COLLATE U_NOCASE;
+ ";
+ return DB::getInstance()->get($sql, $annee);
+ }
- // récupérer dans la config Paheko les champs des membres
- // utilisés pour le nom et le prénom
- $champsPaheko = DynamicFields::getInstance()->listAssocNames();
+ /**
+ * @return nom de l'association
+ */
+ public static function getNomAsso() {
+ return DB::getInstance()->first(
+ "SELECT value
+ FROM config
+ WHERE key = 'nom_asso'"
+ )->value;
+ }
- foreach ($champsPaheko as $name => $title)
- {
- if (stristr($title, 'nom'))
- {
- // retenir les champs dont le titre contient le terme 'nom'
- // est-il présent dans la config du plugin ?
- if (! array_key_exists($name, $champsNom))
- {
- // absent => l'ajouter
- $champ = new \stdClass();
- $champ->titre = $title;
- $champ->position = 0;
- $champsNom[$name] = $champ;
- }
- }
- }
- // opération symétrique : un champ mémorisé dans la config du
- // plugin a-t-il disparu de la config paheko ?
- foreach ($champsNom as $nom => $champ)
- {
- if (! array_key_exists($nom, $champsPaheko))
- {
- // absent => le supprimer
- unset($champsNom[$nom]);
- }
- }
- // mettre à jour la config du plugin
- $plugin->setConfigProperty('champsNom', $champsNom);
- return $champsNom;
- }
+ /**
+ * @return adresse de l'association
+ */
+ public static function getAdresseAsso() {
+ return DB::getInstance()->first(
+ "SELECT value
+ FROM config
+ WHERE key = 'adresse_asso'"
+ )->value;
+ }
- /**
- * enregistrer les fichiers dans une archive zip
- * @param $fileList : liste des fichiers à archiver
- * @param $year : pour générer le nom de l'archive
- * @param $archiveDir : ne sert plus
- */
- static function makeArchive(
- $fileList,
- $year,
- $archiveDir = null)
- {
- $zipFilename = "recus_dons" . $year . ".zip";
- header('Content-type: application/zip');
- header(sprintf('Content-Disposition: attachment; filename="%s"', $zipFilename));
- $zip = new ZipWriter('php://output');
- $zip->setCompression(0);
- foreach ($fileList as $fileName)
- {
- $zip->add(basename($fileName), null, $fileName);
- }
- $zip->close();
- } // makeArchive
+ /**
+ * @return liste des années fiscales
+ */
+ public static function getAnneesFiscales() {
+ $rows = DB::getInstance()->get(
+ "SELECT strftime('%Y', start_date) as annee
+ FROM acc_years
+ ORDER by start_date DESC"
+ );
+ $anneesFiscales = array();
+ foreach ($rows as $row) {
+ $anneesFiscales[] = $row->annee;
+ }
+ return $anneesFiscales;
+ }
+
+ /** TODO
+ * générer les reçus
+ * @param tableau des versements par personne
+ */
+ static function genererRecus() {
+
+ }
+
+ /**
+ * enregistrer les fichiers dans une archive zip
+ * @param $fileList : liste des fichiers à archiver
+ * @param $year : pour générer le nom de l'archive
+ * @param $archiveDir : ne sert plus
+ */
+ static function makeArchive(
+ $fileList,
+ $year,
+ $archiveDir = null)
+ {
+ $zipFilename = "recus_dons" . $year . ".zip";
+ header('Content-type: application/zip');
+ header(sprintf('Content-Disposition: attachment; filename="%s"', $zipFilename));
+ $zip = new ZipWriter('php://output');
+ $zip->setCompression(0);
+ foreach ($fileList as $fileName)
+ {
+ $zip->add(basename($fileName), null, $fileName);
+ }
+ $zip->close();
+ } // makeArchive
}
diff --git a/lib/Versement.php b/lib/Versement.php
index 35fa9ec..3ac3f07 100644
--- a/lib/Versement.php
+++ b/lib/Versement.php
@@ -1,40 +1,24 @@
idActivite = $idActivite;
+ $this->idTarif = $idTarif;
$this->montant = $montant;
- $this->dateMin = $dateMin;
- $this->dateMax = $dateMax;
+ $this->tauxReduction = $tauxReduction;
}
-
- /**
- * ajouter un versement en fixant les dates min et max
- * @param $montant
- * @param $dateMin
- * @param $dateMax
- */
- public function ajouter($montant, $dateMin, $dateMax)
- {
- $this->montant += $montant;
- if ($dateMin < $this->dateMin)
- {
- $this->dateMin = $dateMin;
- }
- if ($dateMax > $this->dateMax)
- {
- $this->dateMax = $dateMax;
- }
- }
}
diff --git a/plugin.ini b/plugin.ini
deleted file mode 100644
index 61216fc..0000000
--- a/plugin.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-name="Reçus fiscaux"
-description="Génération de reçus fiscaux pour les dons des membres"
-author="Jean-Christophe Engel"
-url="https://acloud8.zaclys.com/index.php/s/n9daWAND24T2W3e"
-version="0.10"
-menu=1
-config=1
-min_version="1.3"
diff --git a/templates/_nav.tpl b/templates/_nav.tpl
index 4f41861..3c501aa 100644
--- a/templates/_nav.tpl
+++ b/templates/_nav.tpl
@@ -1,12 +1,12 @@
-{include file="_head.tpl" title="%s"|args:$plugin.label current="plugin_%s"|args:$plugin.name}
+{include file="admin/_head.tpl" title="%s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id}
-
-{include file="_foot.tpl"}
\ No newline at end of file
diff --git a/templates/config.tpl b/templates/config.tpl
index 250a67e..fef9049 100644
--- a/templates/config.tpl
+++ b/templates/config.tpl
@@ -1,210 +1,42 @@
{include file="%s/templates/_nav.tpl"|args:$plugin_root current_nav="config"}
-{form_errors}
-
Configuration
-{if isset($_GET['ok'])}
+{if $ok && !$form->hasErrors()}
La configuration a bien été enregistrée.
{/if}
-
-
-{literal}
-
-{/literal}
-{* scripts divers *}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/templates/index.tpl b/templates/index.tpl
index 3ca8ea7..92a8be0 100644
--- a/templates/index.tpl
+++ b/templates/index.tpl
@@ -1,217 +1,144 @@
{include file="%s/templates/_nav.tpl"|args:$plugin_root current_nav="index"}
-
- Année fiscale sélectionnée :
- {$annee_recu}
- {linkbutton label="Changer d'année fiscale" target="_dialog" href="%s/choix_annee.php"|args:$plugin_url shape="settings"}
-
-
+Choisir l'année fiscale
{literal}
+ // activer/désactiver les radios des activités/tarifs
+ for (var laCase of document.querySelectorAll("input[type=checkbox]")) {
+ laCase.addEventListener('change', (evt) => {
+ var idCase = evt.target;
+ // chercher la ligne englobante ()
+ var ligne = idCase.closest("tr");
+ // itérer sur les radio de cette ligne
+ var lesRadios = ligne.querySelectorAll('input[type=radio]');
+ for (var idRadio of lesRadios) {
+ if (idCase.checked) {
+ idRadio.disabled = '';
+ } else {
+ idRadio.disabled = 'disabled';
+ }
+ }
+ });
+ }
+
{/literal}
-{include file="_foot.tpl"}
+{include file="admin/_foot.tpl"}
\ No newline at end of file
diff --git a/templates/recu.skel b/templates/recu.skel
deleted file mode 100644
index 8691222..0000000
--- a/templates/recu.skel
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
Reçu au titre des dons à certains organismes d'intérêt général
-
Articles 200, 238 bis et 978 du code général des impôts
-
-
-
-
-
Bénéficiaire des versements
-
Association « {{$config.org_name}} »
- {{$config.org_address}}
- Objet : {{$objet_asso}}
-
-
-
-
-
Donateur
-
- {{$nom}}
- {{$adresse}}
- {{$code_postal}} {{$ville}}
- {{if $courriel != ""}}
- courriel : {{$courriel}}
- {{/if}}
-
-
-
-
-
Le bénéficiaire reconnaît avoir reçu au titre des dons et versements ouvrant droit à réduction d'impôt :
-
- {{#versements}}
-
- la somme de ***{{$montant|raw|money}}*** euros
- {{if $cents != ""}}
- ({{$euros}} euros et {{$cents}} cents )
- {{else}}
- ({{$euros}} euros )
- {{/if}}
- {{if $libelle != ""}}
- ({{$libelle}})
- {{/if}}
- date des versements :
- {{if $dateMin == $dateMax}}
- le {{$dateMin}}
- {{else}}
- du {{$dateMin}} au {{$dateMax}}
- {{/if}}
-
- {{/versements}}
-
-
- {{#informations}}
-
{{$titre}} {{$libelle}}
- {{/informations}}
-
-
Le bénéficiaire certifie sur l’honneur que les dons et versements qu’il reçoit ouvrent droit à la réduction d'impôt prévue {{$texteArticles}} du code général des impôts.
-
-
-
-
{{$ville_asso}} le {{$date}}
-
-
-
- {{$nom_responsable}}
- {{$fonction_responsable}}
-
-
-
-
diff --git a/templates/recu_html.tpl b/templates/recu_html.tpl
deleted file mode 100644
index 2bed92f..0000000
--- a/templates/recu_html.tpl
+++ /dev/null
@@ -1,136 +0,0 @@
-{include file="_head.tpl" title="%s"|args:$plugin.label current="plugin_%s"|args:$plugin.id}
-
-
-
-{* Itération sur les personnes *}
-{foreach from=$totalPersonnes key="idPersonne" item="personne"}
-
-
-
-
-
Reçu au titre des dons à certains organismes d'intérêt général
-
Articles 200, 238 bis et 978 du code général des impôts
-
- {if $numero_sequentiel}
- {afficher_numero_recu prefixe=$prefixeNum membre=$membre numero_personne=$personne->numero numero_sequentiel=$numero_courant}
-
- {else}
- {afficher_numero_recu prefixe=$prefixeNum membre=$membre numero_personne=$personne->numero numero_sequentiel=$numero_sequentiel}
- {/if}
-
-
-
-
-
Bénéficiaire des versements
-
Association « {$org_name} »
- {$org_address}
- Objet : {$objet_asso}
-
-
-
-
-
Donateur
-
- {$personne.nomPrenom}
- {$personne.adresse}
- {$personne.codePostal} {$personne.ville}
- {if $courriel && $personne.courriel != ""}
- courriel : {$personne.courriel}
- {/if}
-
-
-
-
-
Le bénéficiaire reconnaît avoir reçu au titre des dons et versements ouvrant droit à réduction d'impôt :
-
- {foreach from=$personne.versements key="taux" item="versement"}
-
- la somme de ***{$versement.montant|raw|money}*** euros
- format((int)($versement->montant / 100));
- if ($versement->montant % 100 != 0) {
- $cents = $fmt->format($versement->montant % 100);
- } else {
- $cents = "";
- }
- ?>
- {if $cents != ""}
- ({$euros} euros et {$cents} cents )
- {else}
- ({$euros} euros )
- {/if}
-
- {if $libelle != ""}
- ({$libelle})
- {/if}
- date des versements :
- dateMin);
- $dmax = date("d/m/Y", $versement->dateMax);
- ?>
- {if $versement.dateMin == $versement.dateMax}
- le {$dmin}
- {else}
- du {$dmin} au {$dmax}
- {/if}
-{*
- Erreur : dates décalées d'un jour (en arrière)
- {if $versement.dateMin == $versement.dateMax}
- le {$versement.dateMin|date_format:"%d/%m/%Y"}
- {else}
- du {$versement.dateMin|date_format:"%d/%m/%Y"} au {$versement.dateMax|date_format:"%d/%m/%Y"}
- {/if}
-*}
-
-
- {/foreach}
-
-
- {foreach from=$complements item="elem"}
-
{$elem.titre} {$elem.libelle}
- {/foreach}
-
-
Le bénéficiaire certifie sur l’honneur que les dons et versements qu’il reçoit ouvrent droit à la réduction d'impôt prévue {$texteArticles} du code général des impôts.
-
-
-
-
{$ville_asso} le {$date}
-
-
-
- {$nom_responsable}
- {$fonction_responsable}
-
-
-
-
-{/foreach} {* Itération sur les personnes *}
-
-{* scripts divers *}
-
-
-{*
- * remplacer la feuille de style d'impression de paheko par la mienne
- * puis déclencher l'impression
-*}
-{literal}
-
-{/literal}
-
-
-{include file="_foot.tpl"}
diff --git a/templates/upload.tpl b/templates/upload.tpl
deleted file mode 100644
index 70f4cff..0000000
--- a/templates/upload.tpl
+++ /dev/null
@@ -1,18 +0,0 @@
-{include file="_head.tpl" title="Envoi de fichier"}
-
-{form_errors}
-
-
-
-{include file="_foot.tpl"}
diff --git a/templates/versements_activites.tpl b/templates/versements_activites.tpl
index 3775378..83dc026 100644
--- a/templates/versements_activites.tpl
+++ b/templates/versements_activites.tpl
@@ -1,104 +1,88 @@
-{include file="%s/templates/_nav.tpl"|args:$plugin_root current_nav="activite"}
+{include file="%s/templates/_nav.tpl"|args:$plugin_root current_nav="versements"}
-Année {$annee_recu} : versements par activité et tarif
+Liste des versements par activité et tarif
-
-
-
- Total des cases cochées :
- 0,00 €
-
-
-
- Cliquer pour cocher toutes les lignes
-
-
-
- Replier toutes les activités
-
- Replier toutes les personnes
-
-
- {button type="submit" label="Télécharger les reçus au format PDF" shape="download"
- form="versements_activites"
- formaction="generer_recus.php?type=activite&format=pdf"
- onclick="return verifierChoix(this.form)"}
- {button type="submit" target="_dialog" label="Imprimer les reçus" shape="print"
- form="versements_activites"
- formaction="generer_recus.php?type=activite&format=print"
- onclick="return verifierChoix(this.form)"}
-
-
-
+
-
+*}
- {* Itération sur les versements *}
- {foreach from=$lesVersements key="rang" item="versement"}
- {if $rang == 0}
- {* premier versement *}
- idTarif;
- $personneCourante = $versement->idUser;
- $compteCourant = $versement->idCompte;
- $codeCompte = $versement->codeCompte;
- ?>
- {afficher_debut_tarif versement=$versement}
- {afficher_debut_personne user=$personneCourante idVersement="%s_%s"|args:$tarifCourant,$personneCourante}
- {afficher_debut_compte idCompte=$compteCourant}
- {elseif $versement.idTarif != $tarifCourant}
- {* changement de tarif *}
- {fin_compte}
- {fin_personne}
- {fin_tarif}
- idTarif;
- $personneCourante = $versement->idUser;
- $compteCourant = $versement->idCompte;
- $codeCompte = $versement->codeCompte;
- ?>
- {afficher_debut_tarif versement=$versement}
- {afficher_debut_personne user=$personneCourante idVersement="%s_%s"|args:$tarifCourant,$personneCourante}
- {afficher_debut_compte idCompte=$compteCourant}
- {elseif $versement.idUser != $personneCourante}
- {* changement de personne *}
- {fin_compte}
- {fin_personne}
- idUser;
- $compteCourant = $versement->idCompte;
- $codeCompte = $versement->codeCompte;
- ?>
- {afficher_debut_personne user=$personneCourante idVersement="%s_%s"|args:$tarifCourant,$personneCourante}
- {afficher_debut_compte idCompte=$compteCourant}
- {elseif $versement.codeCompte != $codeCompte}
- {fin_compte}
- {* changement de compte *}
- idCompte;
- $codeCompte = $versement->codeCompte;
- ?>
- {afficher_debut_compte idCompte=$compteCourant}
- {else}
- {* même personne, même compte *}
- {/if}
- {afficher_versement versement=$versement idVersement="%s_%s"|args:$tarifCourant,$personneCourante rang=$rang pair=$pair}
-
- {/foreach} {* Itération sur les versements *}
- {fin_compte}
- {fin_personne}
- {fin_tarif}
+
-{* scripts divers *}
+{* scripts pour cases à cocher *}
+{literal}
+
+{/literal}
+
-{include file="_foot.tpl"}
+{include file="admin/_foot.tpl"}
\ No newline at end of file
diff --git a/templates/versements_personnes.tpl b/templates/versements_personnes.tpl
index e5ce3c2..4005c8b 100644
--- a/templates/versements_personnes.tpl
+++ b/templates/versements_personnes.tpl
@@ -1,86 +1,51 @@
{include file="%s/templates/_nav.tpl"|args:$plugin_root current_nav="personne"}
-Année {$annee_recu} : versements par personne
+Liste des versements totaux par personne
-
-
+
+ {* Itération sur les personnes *}
+
-
-{* scripts divers *}
+{* scripts pour cases à cocher *}
-{include file="_foot.tpl"}
+{include file="admin/_foot.tpl"}
\ No newline at end of file
diff --git a/uninstall.php b/uninstall.php
deleted file mode 100644
index 4246dbe..0000000
--- a/uninstall.php
+++ /dev/null
@@ -1,20 +0,0 @@
-delete();
-}
-
-// signature réelle
-$signature = $plugin->getConfig('signature');
-if (null !== $signature) {
- $sig_file = \Paheko\Files\Files::get($signature);
- if (null !== $sig_file) {
- $sig_file->delete();
- }
-}
-unset($_SESSION['sig_file']);
diff --git a/upgrade.php b/upgrade.php
deleted file mode 100644
index 699d018..0000000
--- a/upgrade.php
+++ /dev/null
@@ -1,19 +0,0 @@
-getInfos('version');
-
-if (version_compare($old_version, '0.9', '<'))
-{
- $configNum = new \stdClass();
- $configNum->prefixe = "";
- $configNum->annee = false;
- $configNum->membre = false;
- $configNum->sequentiel = false;
- $configNum->valeur_init = 1;
- $plugin->setConfigProperty('numerotation', $configNum);
- $plugin->setConfigProperty('imprimerCourriel', false);
-}
diff --git a/www/admin/action.php b/www/admin/action.php
new file mode 100644
index 0000000..4fef81e
--- /dev/null
+++ b/www/admin/action.php
@@ -0,0 +1,9 @@
+requireAccess($session::SECTION_CONFIG, $session::ACCESS_ADMIN);
+$art_sel=f('articlesCGI') ? : [];
+
+if (f('save') && $form->check('recusfiscaux_config'))
+{
+ try {
+ $plugin->setConfig('objet_asso', trim(f('objet_asso')));
+ $confArticles = $plugin->getConfig('articlesCGI');
+ // effacer l'ancienne configuration
+ for ($i = 0; $i < count($confArticles); ++$i) {
+ $confArticles[$i]->valeur = 0;
+ }
+ // et copier la nouvelle
+ foreach ($art_sel as $article) {
+ $confArticles[$article]->valeur = 1;
+ }
+ $plugin->setConfig("articlesCGI", $confArticles);
+ \Garradin\Utils::redirect(PLUGIN_URL . 'config.php?ok');
+ }
+ catch (UserException $e)
+ {
+ $form->addError($e->getMessage());
+ }
+}
+
+$tpl->assign('ok', qg('ok') !== null);
+$tpl->assign('plugin_config', $plugin->getConfig());
+$tpl->assign('plugin_css', ['style.css']);
+
+$tpl->display(PLUGIN_ROOT . '/templates/config.tpl');
diff --git a/www/admin/generer_activites.php b/www/admin/generer_activites.php
new file mode 100644
index 0000000..26f7d95
--- /dev/null
+++ b/www/admin/generer_activites.php
@@ -0,0 +1,128 @@
+ $personne) {
+ // générer un fichier par reçu
+ $pdf = new RecusPDF(
+ 'DejaVu',
+ 'SerifCondensed',
+ $nomAsso,
+ $adresseAsso,
+ $logoCERFA,
+ $signature
+ );
+ // extraire les montants des versements
+ $lesMontants = array();
+ foreach ($personne->versements as $versement)
+ {
+ if (array_key_exists($versement->tauxReduction, $lesMontants)) {
+ $lesMontants[$versement->tauxReduction] += $versement->montant;
+ }
+ else {
+ $lesMontants[$versement->tauxReduction] = $versement->montant;
+ }
+ }
+ $pdf->imprimer_recu(
+ $_SESSION['annee_recu'],
+ $personne->id,
+ $personne->nomPrenom,
+ $lesMontants,
+ $personne->adresse,
+ $personne->codePostal,
+ $personne->ville
+ );
+ // fabriquer le nom du fichier PDF
+ $nom = str_replace(' ', '_', $personne->nomPrenom);
+ $nom = str_replace("'", "", $nom);
+ // $nomFichier = Utils::getPDFDirectory() . "/" . 'recu_' . $annee_recu . '_' . $nom . '.pdf';
+ $nomFichier = PLUGIN_ROOT . '/pdf/recu_' . $_SESSION['annee_recu'] . '_' . $nom . '.pdf';
+
+ $pdf->Output('F', $nomFichier);
+ // ajouter le nom du fichier à la liste pour mettre dans une archive
+ $listeFichiers[] = $nomFichier;
+}
+
+// faire une archive zip
+$fichierZip = Utils::makeArchive(
+ $listeFichiers,
+ $_SESSION['annee_recu'],
+ PLUGIN_ROOT . "/zip"
+);
+
+/**
+ * Cumuler les versements de chaque personne par tarif
+ * @param tableau des versements triés par idTarif, idUser, date
+ * @return tableau des versements cumulés : id => Personne
+ */
+function cumulerVersements($versements)
+{
+ $totalPersonnes = array();
+ $idTarif_courant = -1;
+ $idPersonne_courant = -1;
+ $totalVersements = 0;
+ foreach ($versements as $ligne)
+ {
+ if (
+ $ligne->idTarif != $idTarif_courant ||
+ $ligne->idUser != $idPersonne_courant
+ )
+ {
+ if ($idTarif_courant != -1) {
+ $totalPersonnes[$idPersonne_courant]->ajouterVersement(
+ $_SESSION['lesTarifs'][$idTarif_courant]->idActivite,
+ $idTarif_courant,
+ $totalVersements/100,
+ $_SESSION['tauxSelectionnes'][$idTarif_courant]
+ );
+ }
+ $idTarif_courant = $ligne->idTarif;
+ $idPersonne_courant = $ligne->idUser;
+ $totalVersements = $ligne->versement;
+ // créer les infos de la personne, sauf si elle est déjà présente
+ if (!array_key_exists($idPersonne_courant, $totalPersonnes))
+ {
+ $totalPersonnes["$idPersonne_courant"] = Personne::copier($_SESSION['membresDonateurs'][$ligne->idUser]);
+ }
+ } else {
+ // cumuler versements
+ $totalVersements += $ligne->versement;
+ }
+ }
+ // et le dernier
+ $totalPersonnes[$idPersonne_courant]->ajouterVersement(
+ $_SESSION['lesTarifs'][$idTarif_courant]->idActivite,
+ $idTarif_courant,
+ $totalVersements/100,
+ $_SESSION['tauxSelectionnes'][$idTarif_courant]
+ );
+
+ return $totalPersonnes;
+}
diff --git a/www/admin/generer_personnes.php b/www/admin/generer_personnes.php
new file mode 100644
index 0000000..696410d
--- /dev/null
+++ b/www/admin/generer_personnes.php
@@ -0,0 +1,62 @@
+versement/100;
+ $pdf->imprimer_recu(
+ $_SESSION['annee_recu'],
+ $ligne->idUser,
+ $_SESSION['membresDonateurs'][$ligne->idUser]->nomPrenom,
+ $lesMontants,
+ $_SESSION['membresDonateurs'][$ligne->idUser]->adresse,
+ $_SESSION['membresDonateurs'][$ligne->idUser]->codePostal,
+ $_SESSION['membresDonateurs'][$ligne->idUser]->ville
+ );
+ // fabriquer le nom du fichier PDF
+ $nom = str_replace(' ', '_', $_SESSION['membresDonateurs'][$ligne->idUser]->nomPrenom);
+ $nom = str_replace("'", "", $nom);
+ // $nomFichier = Utils::getPDFDirectory() . "/" . 'recu_' . $annee_recu . '_' . $nom . '.pdf';
+ $nomFichier = PLUGIN_ROOT . '/pdf/recu_' . $_SESSION['annee_recu'] . '_' . $nom . '.pdf';
+
+ $pdf->Output('F', $nomFichier);
+ // ajouter le nom du fichier à la liste pour mettre dans une archive
+ $listeFichiers[] = $nomFichier;
+}
+// faire une archive zip
+$fichierZip = Utils::makeArchive(
+ $listeFichiers,
+ $_SESSION['annee_recu'],
+ PLUGIN_ROOT . "/zip"
+);
diff --git a/www/admin/index.php b/www/admin/index.php
new file mode 100644
index 0000000..e4d20dd
--- /dev/null
+++ b/www/admin/index.php
@@ -0,0 +1,31 @@
+getConfig('reduction'));
+
+// liste des activités, cotisations et comptes associés
+$activitesTarifsComptes = Utils::getActivitesTarifsEtComptes();
+
+// actions
+//lesActions = [ 'versements_personnes.php', 'versements_activites.php' ];
+
+// préparation de l'affichage
+$tpl->assign('anneesFiscales', $anneesFiscales);
+$tpl->assign('anneeCourante', $anneeCourante);
+$tpl->assign('activitesTarifsComptes', $activitesTarifsComptes);
+$tpl->assign('plugin_config', $plugin->getConfig());
+$tpl->assign('plugin_css', ['style.css']);
+
+// envoyer au template
+$tpl->display(PLUGIN_ROOT . '/templates/index.tpl');
diff --git a/www/admin/script.js b/www/admin/script.js
new file mode 100644
index 0000000..4c18d31
--- /dev/null
+++ b/www/admin/script.js
@@ -0,0 +1,220 @@
+/**
+ * Fonction appelée quand on (dé)coche la case de sélection globale
+ * (dé)sélectionner toutes les cases à cocher de toutes les activités
+ * @param id de la case globale
+ */
+function cocherDecocherTout(idCaseGlobale)
+{
+ // chercher le formulaire englobant
+ var formulaire = idCaseGlobale.closest("form");
+ // itérer sur la liste des éléments détails : 1 par couple
+ var lesDetails = formulaire.querySelectorAll("details");
+ for (var i = 0; i < lesDetails.length; ++i) {
+ // itérer sur les personnes
+ var lesH3 = lesDetails[i].querySelectorAll("h3.personne");
+ for (var j = 0; j < lesH3.length; ++j) {
+ // trouver l'élément total de la personne
+ var idTotal = lesH3[j].querySelector("span");
+ // puis la case à cocher
+ var fieldset = lesH3[j].nextElementSibling;
+ var idCase = fieldset.querySelector("input");
+ idCase.checked = idCaseGlobale.checked;
+ // puis traiter toutes les cases de la personne
+ cocherDecocherPersonne(idCase, idTotal);
+ }
+ }
+ // changer le message
+ var message = idCaseGlobale.nextElementSibling;
+ if (idCase.checked) {
+ message.innerHTML = "Cliquer pour dé-cocher toutes les lignes";
+ } else {
+ message.innerHTML = "Cliquer pour cocher toutes les lignes";
+ }
+}
+
+/**
+ * Fonction appelée quand on (dé)coche la case d'une personne
+ * - (dé)sélectionner toutes les cases à cocher
+ * - faire le total des cases cochées et l'afficher
+ *
+ * @param id de la case qui a été cochée
+ * @param id de l'élément où afficher le total
+ */
+function cocherDecocherPersonne(idCase, idTotal)
+{
+ // chercher le fieldset englobant
+ var fieldset = idCase.closest("fieldset");
+ var listeCases = fieldset.querySelectorAll("input[type=checkbox]");
+ for (var i = 1; i < listeCases.length; ++i)
+ {
+ listeCases[i].checked = idCase.checked;
+ }
+ // changer le message
+ var message = idCase.nextElementSibling;
+ if (idCase.checked) {
+ message.innerHTML = "Cliquer pour dé-cocher toutes les lignes";
+ } else {
+ message.innerHTML = "Cliquer pour cocher toutes les lignes";
+ }
+ // calculer et afficher le total
+ var listeMontants = fieldset.querySelectorAll("span.montant");
+ calculerTotal(listeCases, listeMontants, idTotal);
+}
+
+/**
+ * Fonction appelée quand on (dé)coche la case d'un versement
+ * - (dé)sélectionner cette case (?)
+ * - faire le total des cases cochées et l'afficher
+ *
+ * @param id de la case qui a été cochée
+ * @param id de l'élément où afficher le total
+ */
+function cocherDecocherVersement(idCase, idTotal)
+{
+ var fieldset = idCase.closest("fieldset");
+ var listeCases = fieldset.querySelectorAll("input[type=checkbox]");
+ var listeMontants = fieldset.querySelectorAll("span.montant");
+ calculerTotal(listeCases, listeMontants, idTotal);
+}
+
+/**
+ * Faire le total des cases cochées et l'afficher
+ * @param listes des cases
+ * @param listes des montants associés
+ * @param id de l'élément où afficher le total
+*/
+function calculerTotal(listeCases, listeMontants, idTotal)
+{
+ var total = 0;
+ for (var i = 1; i < listeCases.length; ++i)
+ {
+ if (listeCases[i].checked) {
+ total += parseFloat(listeMontants[i-1].textContent.replace(/\s/g, ""));
+ }
+ }
+ // "afficher" le total
+ idTotal.innerHTML =
+ total.toLocaleString('fr-FR', {style: 'currency', currency: 'EUR',
+ minimumFractionDigits: 2});
+}
+
+/**
+ * fonction appelée lors de la validation du formulaire
+ * @return vrai si au moins un choix a été fait
+ * @param : formulaire
+*/
+function verifierChoix(formulaire)
+{
+ var listeCheck = formulaire.getElementsByTagName("input");
+ var ok = false;
+ for (var 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;
+}
+
+/**
+ * fonction appelée pour afficher et masquer des portions de formulaire
+*/
+function afficherMasquer(formulaire, nomClasse1, nomClasse2)
+{
+ for (var elem of formulaire.querySelectorAll(nomClasse1)) {
+ elem.classList.remove('hidden');
+ }
+ for (var elem of formulaire.querySelectorAll(nomClasse2)) {
+ 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é :)
+function verifierCases(idElem)
+{
+ var div = document.getElementById(idElem);
+ var nbChoix = 0;
+ // parcourir les cases à cocher
+ for (var idCase of div.querySelectorAll("input[type=checkbox]"))
+ {
+ if (idCase.checked) {
+ ++nbChoix;
+ // vérifier qu'un radio de la même ligne est sélectionné
+ var ligneCorrecte = false;
+ // trouver la ligne englobante
+ var ligne = idCase.closest("tr");
+ for (var 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 activité/tarif");
+ }
+ return nbChoix != 0;
+}
+
+// vérifier qu'un radio a été sélectionné dans la div paramètre
+function verifierRadio(idElem)
+{
+ var div = document.getElementById(idElem);
+ for (var 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;
+}
+
+// inutilisé
+function activerDesactiverRadio(evt)
+{
+ var idCase = evt.target;
+ // checher la ligne englobante ( )
+ var ligne = idCase.closest("tr");
+ // itérer sur les radio de cette ligne
+ var lesRadios = ligne.querySelectorAll('input[type=radio]');
+ for (var idRadio of lesRadios) {
+ if (idCase.checked) {
+ idRadio.disabled = '';
+ } else {
+ idRadio.disabled = 'disabled';
+ }
+ }
+}
+
+/**
+ * Associer un écouteur à la première case à cocher de chaque table
+ * @remarks : n'est plus utile
+ */
+function activerListener()
+{
+ // parcourir les tables
+ const lesTables = document.querySelectorAll("table.list");
+ for (let i = 0; i < lesTables.length; ++i) {
+ // vérifier si c'est l'une des tables qui nous intéresse
+ // l'id est du genre : versements_xx où xx est un entier
+ const id = lesTables[i].id;
+ const re = /^versements_[0-9]+/;
+ console.log("id = " + id + " => " + re.test(id));
+ if (re.test(id)) {
+ // chercher le premier élément input
+ const premierInput = lesTables[i].querySelector("input");
+ // associer un écouteur à la première case à cocher
+ premierInput.addEventListener('change', cocherDecocher);
+ }
+ }
+}
diff --git a/www/admin/style.css b/www/admin/style.css
new file mode 100644
index 0000000..39b958a
--- /dev/null
+++ b/www/admin/style.css
@@ -0,0 +1,32 @@
+/* liste des versements */
+div.pair {
+ padding : 0.1em;
+ background: rgba(var(--gSecondColor), 0.2);
+}
+div.impair {
+ padding : 0.1em;
+}
+fieldset {
+ border:2px solid brown;
+ -webkit-border-radius:8px;
+ border-radius:8px;
+}
+fieldset label {
+ font-weight:bold;
+}
+div span {
+ padding-left : 0.5em;
+ padding-right : 0.5em;
+}
+td.montant {
+ text-align : right;
+}
+summary.activite {
+ background: rgba(var(--gMainColor), 0.25);
+}
+h3.personne {
+ background: rgba(var(--gSecondColor), 0.35);
+}
+input[type="text"] {
+ width: 50em;
+}
diff --git a/www/admin/versements_activites.php b/www/admin/versements_activites.php
new file mode 100644
index 0000000..4f263c1
--- /dev/null
+++ b/www/admin/versements_activites.php
@@ -0,0 +1,148 @@
+id] = Tarif::copier($ot);
+}
+$_SESSION['lesTarifs'] = $lesTarifs;
+
+// activités correspondants aux tarifs sélectionnés
+$lesActivites = array();
+foreach (Utils::getActivites($tarifsSelectionnes) as $activite) {
+ $lesActivites[$activite->id] = Activite::copier($activite);
+}
+$_SESSION['lesActivites'] = $lesActivites;
+
+// versements correspondants aux tarifs sélectionnés
+$_SESSION['lesVersements'] = Utils::getVersementsTarifs($_SESSION['annee_recu'], $tarifsSelectionnes);
+
+// membres donateurs
+$membresDonateurs = array();
+$versementsMembres = Utils::getDonateurs($_SESSION['annee_recu']);
+foreach ($versementsMembres as $versement) {
+ $membresDonateurs[$versement->idUser] = new Personne($versement->idUser,
+ $versement->nom,
+ $versement->adresse,
+ $versement->codePostal,
+ $versement->ville);
+}
+$_SESSION['membresDonateurs'] = $membresDonateurs;
+
+// ------------------------------------------------------------------------
+// fonctions pour l'affichage
+
+// afficher les informations d'une activité et d'un tarif
+$tpl->register_function('afficher_debut_tarif', function ($params)
+{
+ $versement = $params['versement'];
+ $idTarif = $versement->idTarif;
+ $tarif = $_SESSION['lesTarifs'][$idTarif];
+ $idActivite = $tarif->idActivite;
+ $activite = $_SESSION['lesActivites'][$idActivite];
+
+ $out = '
+ ';
+ $out .= sprintf('
+ Activité « %s » ', $activite->label);
+ if (!empty($activite->description)) {
+ $out .= sprintf('
+ %s ', $activite->description);
+ }
+ $out .= sprintf('
+ tarif « %s »', $tarif->label);
+ if ($tarif->montant > 0) {
+ $out .= sprintf(' montant : %.2f €', $tarif->montant/100);
+ } else {
+ $out .= ' montant : libre';
+ }
+ $out .= '
+ ';
+ return $out;
+});
+
+// afficher les informations d'une personne
+$tpl->register_function('afficher_debut_personne', function ($params)
+{
+ $versement = $params['versement'];
+ $idUser = $versement->idUser;
+ $personne = $_SESSION['membresDonateurs'][$idUser];
+ $idVersement = $versement->idTarif . "_" . $versement->idUser;
+ $out = sprintf('Versements de %s : 0,00 € ',
+ $personne->nomPrenom,
+ $idVersement);
+ $out .= sprintf('
+ ',
+ $idVersement);
+ $out .= sprintf('
+ ',
+ $idVersement,
+ $idVersement);
+ $out .= sprintf('
+ Cliquer pour cocher toutes les lignes ',
+ $idVersement);
+ $out .= '
+ ';
+ return $out;
+});
+
+// afficher un versement
+$tpl->register_function('afficher_versement', function ($params)
+{
+ $versement = $params['versement'];
+ $rang = $params['rang'];
+ $idVersement = $versement->idTarif . "_" . $versement->idUser;
+ $out = '' : 'impair">';
+ $out .= sprintf('
+
+
+ %.2f
+ %s
+
',
+ $idVersement, $idVersement,
+ $rang, $rang,
+ $idVersement, $rang, $idVersement, $idVersement, $rang,
+ $versement->versement/100,
+ date_format(date_create($versement->date),"d/m/Y"));
+ return $out;
+});
+// ------------------------------------------------------------------------
+
+// préparation de l'affichage
+$tpl->assign('lesActivites', $lesActivites);
+$tpl->assign('lesTarifs', $lesTarifs);
+$tpl->assign('lesVersements', $_SESSION['lesVersements']);
+$tpl->assign('plugin_css', ['style.css']);
+
+// envoyer au template
+$tpl->display(PLUGIN_ROOT . '/templates/versements_activites.tpl');
diff --git a/www/admin/versements_personnes.php b/www/admin/versements_personnes.php
new file mode 100644
index 0000000..209c7fc
--- /dev/null
+++ b/www/admin/versements_personnes.php
@@ -0,0 +1,37 @@
+idUser] = new Personne($versement->idUser,
+ $versement->nom,
+ $versement->adresse,
+ $versement->codePostal,
+ $versement->ville);
+}
+$_SESSION['membresDonateurs'] = $membresDonateurs;
+
+// préparation de l'affichage
+$tpl->assign('lesVersementsTotaux', $_SESSION['lesVersementsTotaux']);
+$tpl->assign('lesDonateurs', $membresDonateurs);
+$tpl->assign('plugin_css', ['style.css']);
+
+// envoyer au template
+$tpl->display(PLUGIN_ROOT . '/templates/versements_personnes.tpl');