diff --git a/CHANGELOG b/CHANGELOG
index e4e5dae..e42abea 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,11 +1,3 @@
-0.12
-- Ajout Mollie à la table moyens de paiement
-0.11
-- Changement mention finale pour devis
-0.9
-- Ajout possibilité choisir champs identité et adresse membre
-0.8.8
-- correction typo
0.8.7
- correction typo
0.8.6
diff --git a/README.md b/README.md
index 8685449..1829668 100644
--- a/README.md
+++ b/README.md
@@ -1,50 +1,56 @@
# Plugin Facturation pour Paheko (ex Garradin)
-Plugin de facturation pour le logiciel de gestion d'association Paheko
-( https://paheko.eu/ - https://fossil.kd2.org/paheko ).
-
+Plugin de facturation pour le logiciel de gestion d'association Paheko ( https://paheko.eu/ - https://fossil.kd2.org/paheko ).
Source :
+- version historique : https://gitlab.com/noizette/garradin-plugin-facturation
- version compatible paheko 1.3.x : https://git.roflcopter.fr/lesanges/facturation
-- version historique non compatible paheko 1.3.x : https://gitlab.com/noizette/garradin-plugin-facturation
-## Installation :
-Vous pouvez télécharger l'archive .tar.gz depuis la page des
-[releases](https://git.roflcopter.fr/lesanges/paheko-plugin-facturation/releases),
-supprimer le numéro de version du nom de l'archive puis la placer dans
-le dossier plugins de Paheko.
+## Installation:
+Vous pouvez télécharger l'archive .tar.gz depuis la page des [releases](https://git.roflcopter.fr/lesanges/paheko-plugin-facturation/releases), supprimer le numéro de version du nom de l'archive puis la placer dans le dossier plugins de Paheko.
+
+### Anciennes versions (<0.6)
+
+Normalement, les plugins de Paheko doivent seulement être laissé sous forme d'archive .tar.gz dans le dossier plugins, or pour la génération des PDF, la librairie mPDF a besoin d'écrire des fichiers temporaires.
+
+Il faut pour cela faire :
+
+ tar xvf paheko-plugin-facturation-v0.5.0.tar.gz
+ mv paheko-plugin-facturation-v0.5.0 facturation
+ rm paheko-plugin-facturation-v0.5.0.tar.gz
+ chown -R www-data:www-data facturation/
+ chmod -R g+w facturation/
+
+
+Supprimer l'archive permet à Paheko de ne pas la lire à la place du dossier.
+
+*Note : www-data correspond dans la plupart des cas à l'utlisateur d'Apache, si vous utilisez un autre serveur web, il faudra probablement adapter.*
+
+## Migration vers Garradin 1.0 (obsolète)
+
+Lorsque vous tentez de mettre à jour une installation de Garradin avec le plugin facturation vers Garradin 1.0, l'upgrade est bloquée par le plugin.
+
+Pour remédier à cela et parvenir à faire la mise à jour, il faut dans un premier temps installer la version 0.4 du plugin sur votre installation Garradin 0.9.8, se rendre sur la page principale du plugin (menu > Facturation), vous pouvez ensuite mettre à jour Garradin vers la 1.0.
## Fonctionnalités :
- Créer et gérer une base de client·es
- Créer et modifier des factures et devis adressés aux membres de l'association ou des client·es ajouté·es
-- (obsolète) Créer des reçus fiscaux pour des dons et génération du CERFA correspondant
-- (obsolète) Créer des reçus sur des cotisations
-- Génération des documents (facture et devis) en PDF
+- Créer des reçus fiscaux pour des dons et génération du cerfa correspondant
+- Créer des reçus sur des cotisations
+- Génération des documents (facture et devis) en PDF grâce à la librairie mPDF
- Liste les documents associés sur la fiche d'un·e client·e
-- Permet de définir le statut du document à « réglé »
+- Permet de définir le statut du document sur reglée
- **Configuration** :
- Possibilité d'ajouter un numéro RNA et SIRET de l'association si elle en possède (apparait alors sur les documents)
- - Possibilité de choisir certains champs à faire figurer sur la facture (adresse, code postal, ville)
- - Modification du pied de page des documents (notamment pour y inscrire des mentions légales)
+ - Modification du pied de page des documents (notament pour y inscrire des mentions légales)
- Vérifier le code postal : si coché, lors d'ajout ou de modification de client, le plugin vérifiera que le code postal entré est bien formaté (par rapport aux codes postaux français seulement)
- - Noms de client·es uniques : si coché, lors d'ajout ou de modification de client·e, le nom du/de la client·e ne pourra pas être le même que celui d'un·e client·e déjà existant
- - (obsolète) Informations relatives au CERFA pour les reçus fiscaux
- - (obsolète) Image qui sert de signature sur le CERFA
+ - Noms de client·es uniques : si coché, lors d'ajout ou de modicifation de client·e, le nom du/de la client·e ne pourra pas être le même que celui d'un·e client·e déjà existant
+ - Informations relatives au cerfa pour les reçus fiscaux
+ - Image qui set de signature sur le cerfa
-Note : pour le moment, les actions sur la liste des clients à cocher
-ne fonctionnent pas. Pour supprimer un client, le faire depuis sa
-fiche.
+Note : pour le moment, les actions sur la liste des clients à cocher ne fonctionnent pas. Pour supprimer un client, le faire depuis sa fiche.
-## Futur de ce plugin :
-Un nouveau plugin est en cours de développement par BohwaZ, donc il
-n'est pas pertinent d'ajouter de nouvelles fonctionnalités à celui-ci.
-
-Par contre, si des bugs sont signalés sur la liste
-hebergement@paheko.cloud ou aide@paheko.cloud, je
-(lesanges@zaclys.net) peux tenter de les corriger, à condition que ça
-n'impacte pas trop la structure du plugin.
-
-## Futur improbable (obsolète) :
-- Ajout des champs Référence, Prix unitaire, Quantité sur les documents
+## Futur :
+- Ajout des champs Référence, Prix unitaire, Quantité sur les documents
- Actions sur liste de client·es (exporter, supprimer)
- Afficher/filtrer les documents par statuts réglé/archivé
- Changer statut depuis la liste des documents
@@ -53,12 +59,15 @@ n'impacte pas trop la structure du plugin.
- Gestion TVA ?
- Un devis ne devrait pas pouvoir être réglé
- Quid si un·e membre de l'asso est supprimé·e alors que des documents lui sont adressés ?
+
+## Futur improbable :
- Opérations de paiements dans la compta liés à une facture
- Gestion de produits
-Le plugin nécessite l'extension PHP mbstring.
-## (???) Inclus les bibliothèques suivantes :
+Le plugin nécessite l'extension PHP mbstring.
+
+## Inclus les bibliothèques suivantes :
- Composer :
https://getcomposer.org/
diff --git a/admin/_facture_common.php b/admin/_facture_common.php
index b729f34..ecc0c30 100644
--- a/admin/_facture_common.php
+++ b/admin/_facture_common.php
@@ -4,28 +4,6 @@ namespace Paheko;
require_once __DIR__ . '/_inc.php';
-function toArray($array, $cle, $sep=",")
-{
- $result = array();
- foreach ($array as $elem)
- {
- $ro = new \ReflectionObject($elem);
- $proprietes = $ro->getProperties();
- $ligne = "";
- foreach ($proprietes as $p)
- {
- if ($p->getName() == $cle) {
- $key = $p->getValue($elem);
- }
- else {
- $ligne .= $sep . $p->getValue($elem);
- }
- }
- $result[$key] = substr($ligne, strlen($sep));
- }
- return $result;
-}
-
if (!isset($target) || !in_array( $target, ['new', 'edit'])) {
throw new Exception('blabla illegal call'); // Fix: exception type?
} else {
@@ -89,21 +67,15 @@ $form->runIf(f('save') && !$form->hasErrors(),
'reglee' => f('reglee') == 1?1:0,
'archivee' => f('archivee') == 1?1:0,
'moyen_paiement' => f('moyen_paiement'),
- 'nom_contact' => f('nom_contact'),
'toto' => 0
];
$data['type_facture'] = f('type');
if (in_array(f('type'), [DEVIS, FACT]))
{
- foreach(f('designation') as $k=>$value)
+ foreach(f('designation') as $k=>$value)
{
- if (empty($value) && f('prix')[$k] != null) {
- throw new UserException("Il manque la désignation de la ligne " . $k+1 . " !!");
- }
- elseif ($value != '' && f('prix')[$k] == null) {
+ if ($value != '' && f('prix')[$k] == null) {
throw new UserException('Il manque le prix sur la ligne '. $k+1 . ' !!');
- } elseif (empty($value) && f('prix')[$k] == null) {
- continue;
}
$data['contenu'][$k]['designation'] = $value;
@@ -112,14 +84,7 @@ $form->runIf(f('save') && !$form->hasErrors(),
}
$data['total'] = $data['toto'];
unset($data['toto']);
- if (! isset($data['contenu'])) {
- throw new UserException("Aucune désignation ni aucun prix saisi !!");
- }
- if (f('type') == FACT) {
- $data['numero_commande'] = f('numero_commande');
- $data['reference_acheteur'] = f('reference_acheteur');
- }
- }
+ }
elseif ( f('type') == CERFA )
{
$data['moyen_paiement'] = f('moyen_paiement_cerfa');
@@ -155,45 +120,45 @@ $form->runIf(f('save') && !$form->hasErrors(),
$form->runIf(f('select_cotis') && !$form->hasErrors(),
function () use ($step)
- {
- $step = true;
- }, 'add_cotis_1');
+ {
+ $step = true;
+ }, 'add_cotis_1');
$form->runIf(f('add_cotis') && !$form->hasErrors(),
function () use ($radio, $fields, $facture, $form)
- {
- $radio['type'] = f('cotisation');
- try
- {
- $num = (int) str_replace('cotis_', '', $radio['type']);
- foreach($fields as $field)
- {
- $cotis[$field] = f($field.'_'.$num);
- }
+ {
+ $radio['type'] = f('cotisation');
+ try
+ {
+ $num = (int) str_replace('cotis_', '', $radio['type']);
+ foreach($fields as $field)
+ {
+ $cotis[$field] = f($field.'_'.$num);
+ }
- $r = $facture->getCotis(f('membre_cotis'), $cotis['id']);
- $r = $r[0];
+ $r = $facture->getCotis(f('membre_cotis'), $cotis['id']);
+ $r = $r[0];
- $data = [
- 'type_facture' => COTIS,
- 'numero' => f('numero_facture'),
- 'receveur_membre' => 1,
- 'receveur_id' => f('membre_cotis'),
- 'date_emission' => f('date_emission'),
- 'moyen_paiement' => 'AU',
- 'total' => $r->paid_amount ?? $r->amount,
- 'contenu' => ['id' => $cotis['id'],
- 'intitule' => $cotis['label'],
- 'souscription' => $cotis['date'],
- 'expiration' => $cotis['expiry'] ]
- ];
+ $data = [
+ 'type_facture' => COTIS,
+ 'numero' => f('numero_facture'),
+ 'receveur_membre' => 1,
+ 'receveur_id' => f('membre_cotis'),
+ 'date_emission' => f('date_emission'),
+ 'moyen_paiement' => 'AU',
+ 'total' => $r->paid_amount ?? $r->amount,
+ 'contenu' => ['id' => $cotis['id'],
+ 'intitule' => $cotis['label'],
+ 'souscription' => $cotis['date'],
+ 'expiration' => $cotis['expiry'] ]
+ ];
- }
- catch (UserException $e)
- {
- $form->addError($e->getMessage());
- }
- }, 'add_cotis_2');
+ }
+ catch (UserException $e)
+ {
+ $form->addError($e->getMessage());
+ }
+ }, 'add_cotis_2');
if (! $form->hasErrors())
{
@@ -281,9 +246,6 @@ else
$doc['date_emission'] = f('date_emission') ?: $f->date_emission;
$doc['date_echeance'] = f('date_echeance')?: $f->date_echeance; // Smarty m'a saoulé pour utiliser form_field|date_fr:---
- $doc['nom_contact'] = $f->nom_contact;
- $doc['numero_commande'] = $f->numero_commande;
- $doc['reference_acheteur'] = $f->reference_acheteur;
/* modif DD -- CERFA -------------------------------------- */
if ( $f->type_facture == CERFA ) {
$doc['total'] = $f->total;
@@ -330,10 +292,8 @@ if (in_array($radio['type'], [DEVIS, FACT]))
}
}
else {
- /*
- $designations = ['Exemple'];
- $prix = [250];
- */
+ $designations = ['Exemple'];
+ $prix = [250];
}
}
@@ -341,10 +301,10 @@ $date = new \DateTime;
$date->setTimestamp(time());
$tpl->assign('date', $date->format('d/m/Y'));
+
$tpl->assign(compact('liste', 'radio', 'step', 'designations', 'prix', 'from_user', 'identite', 'csrf_key', 'doc'));
-$tpl->assign('users', toArray($db->get('SELECT id, '.$identite.' FROM users WHERE id_category != -2 NOT IN (SELECT id FROM users_categories WHERE hidden = 1) ORDER BY ' .$identite. ';'), 'id', " "));
+$tpl->assign('users', $db->getAssoc('SELECT id, '.$identite.' FROM users WHERE id_category != -2 NOT IN (SELECT id FROM users_categories WHERE hidden = 1) ORDER BY ' .$identite. ';'));
$tpl->assign('clients', $db->getAssoc('SELECT id, nom FROM plugin_facturation_clients;'));
-$tpl->assign('contacts', $db->getAssoc('SELECT id, nom_contact FROM plugin_facturation_clients;'));
$tpl->assign('require_number', $require_number);
$tpl->assign('number_pattern', PATTERNS_LIST[$plugin->getConfig('pattern')]);
diff --git a/admin/_inc.php b/admin/_inc.php
index f11fc22..582e462 100644
--- a/admin/_inc.php
+++ b/admin/_inc.php
@@ -11,7 +11,7 @@ define('CERFA', 2);
define('COTIS', 3);
const PATTERNS_LIST = [
- '' => 'Aucun, le numéro sera à spécifier manuellement pour chaque document',
+ null => 'Aucun, le numéro sera à spécifier manuellement pour chaque document',
'%{type}-%{year}-%{ynumber}' => 'Type-Année-Numéro du document par année ("FACT-2021-42")',
'%{year}-%{type}-%04{ynumber}' => 'Année-Type-Numéro du document par année ("2021-DEVIS-0042")',
'%{t}-%{year}-%{ynumber}' => 'Type court-Année-Numéro du document par année ("F-2021-42")',
@@ -48,11 +48,11 @@ $tpl->register_function('money_fac', function (array $params)
if (!isset($user)) {
$user = false;
- }
+ }
if (!isset($name))
{
- $name = 'prix[]';
+ $name = 'prix[]';
}
if (null !== $current_value && !$user) {
@@ -62,7 +62,7 @@ $tpl->register_function('money_fac', function (array $params)
if (null !== $current_value) {
$current_value = htmlspecialchars($current_value, ENT_QUOTES, 'UTF-8');
}
-
+
$currency = Config::getInstance()->get('monnaie');
return sprintf('
';
echo str_replace("\n", ' ', $v['designation']);
echo ' | ';
@@ -202,17 +170,12 @@ EOF;
$echeance
$reglee
Moyen de paiement : $moyen_paiement
+
$footer
-
EOF;
- if ($f->type_facture == DEVIS) {
- echo <<Bon pour accord, date et signature
-EOF;
- }
$content = ob_get_clean();
@@ -221,7 +184,7 @@ EOF;
{
$lieu = $plugin->getConfig('ville_asso');
$intitule = $f->contenu['intitule'];
-
+
$souscription = date('d/m/Y', strtotime($f->contenu['souscription']));
if($f->contenu['expiration'] == '1970-01-01')
@@ -257,7 +220,7 @@ EOF;
}
//-- Layout du document
-
+
ob_start();
echo <<
@@ -270,7 +233,7 @@ EOF;
size: A4 portrait;
margin: 0;
}
-
+
body {
padding: 4mm;
font-family: Helvetica, Arial, sans;
@@ -304,13 +267,6 @@ EOF;
width: 40%;
vertical-align: top;
}
- .adressage td#logo {
- width: 20%;
- vertical-align: top;
- }
- .adressage img#logo {
- height : 3cm;
- }
.contenuTexte {
padding: 0 6mm;
@@ -362,7 +318,6 @@ EOF;
- | $logo |
$asso |
$receveur |
@@ -393,7 +348,7 @@ elseif ($f->type_facture == CERFA)
$t['objet1'] = $plugin->getConfig('objet_1');
$t['objet2'] = $plugin->getConfig('objet_2');
- $t['nom'] = $nom_client;
+ $t['nom'] = $c->nom;
$t['adresse'] = $c->adresse;
$t['cp'] = $c->code_postal;
$t['ville'] = $c->ville;
@@ -408,7 +363,7 @@ elseif ($f->type_facture == CERFA)
$t['forme'] = $f->contenu['forme'];
$t['nature'] = $f->contenu['nature'];
$t['texte'] = $libelles[$f->contenu['texte']];
-
+
$t['art200'] = $t['art238'] = $t['art885'] = '';
if($plugin->getConfig('droit_art200')){
$t['art200'] = 'X';
@@ -474,7 +429,7 @@ elseif ($f->type_facture == CERFA)
margin: 0;
padding: 0;
}
-
+
body {
font-family: Helvetica, Arial, sans;
font-size: 10pt;
@@ -496,11 +451,11 @@ elseif ($f->type_facture == CERFA)
background-size: cover;
background-position: -5mm -4.8mm;
}
-
+
#p1 {
background-image: url('{$url}p/facturation/cerfa-1.png');
}
-
+
#p2 {
background-image: url('{$url}p/facturation/cerfa-2.png');
position: relative;
@@ -564,7 +519,7 @@ if(qg('d') !== null)
{
$filename = 'Print';
if (preg_match('!(.*)!U', $html, $match)) {
- $filename = str_replace(" ", "_", trim($match[1]));
+ $filename = trim($match[1]);
}
header('Content-type: application/pdf');
diff --git a/data/schema.sql b/data/schema.sql
index 923b4eb..0cc7a67 100644
--- a/data/schema.sql
+++ b/data/schema.sql
@@ -10,10 +10,7 @@ CREATE TABLE IF NOT EXISTS plugin_facturation_factures (
archivee INTEGER DEFAULT 0, -- bool
moyen_paiement TEXT NOT NULL,
contenu TEXT NOT NULL,
- total INTEGER DEFAULT 0,
- nom_contact TEXT,
- numero_commande TEXT,
- reference_acheteur TEXT
+ total INTEGER DEFAULT 0
-- FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code)
);
@@ -27,9 +24,7 @@ CREATE TABLE IF NOT EXISTS plugin_facturation_clients (
siret TEXT,
date_creation TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date_creation) IS NOT NULL AND date(date_creation) = date_creation), -- Date d\'inscription
telephone TEXT,
- email TEXT,
- nom_contact TEXT,
- note TEXT
+ email TEXT
);
@@ -48,7 +43,6 @@ INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('PR', 'Pr
INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('TI', 'TIP');
INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('VI', 'Virement');
INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('HA', 'HelloAsso');
-INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('MO', 'Mollie');
INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('AU', 'Autre');
-- Modif DD -- ajout de la table des textes associés aux CERFA
diff --git a/lib/Client.php b/lib/Client.php
index 66e7d75..66aabf3 100644
--- a/lib/Client.php
+++ b/lib/Client.php
@@ -17,9 +17,7 @@ class Client
'ville',
'siret',
'telephone',
- 'email',
- 'nom_contact',
- 'note'
+ 'email'
];
private $config = [
@@ -42,7 +40,7 @@ class Client
{
$data[$key] = trim($data[$key]);
- if($data[$key] == '' && ! in_array($key, ['siret', 'telephone', 'email', 'nom_contact', 'note']))
+ if($data[$key] == '' && ($key != 'siret' && $key != 'telephone' && $key != 'email'))
{
throw new UserException('Le champs '.$key.' doit être renseigné.');
}
@@ -138,12 +136,6 @@ class Client
'email' => [
'label' => 'E-Mail',
],
- 'nom_contact' => [
- 'label' => 'Contact',
- ],
- 'note' => [
- 'label' => 'Note',
- ],
'nb_documents' => [
'label' => 'Nombre de documents',
'select' => '(SELECT COUNT(*) FROM plugin_facturation_factures WHERE receveur_id = c.id)',
diff --git a/lib/Facture.php b/lib/Facture.php
index 270fca7..0776728 100644
--- a/lib/Facture.php
+++ b/lib/Facture.php
@@ -30,24 +30,31 @@ class Facture
'archivee',
'moyen_paiement',
'contenu',
- 'total',
- 'nom_contact',
- 'numero_commande',
- 'reference_acheteur'
+ 'total'
];
public $types = [
- DEVIS => [
- 'id' => DEVIS,
- 'accounts' => [],
- 'label' => 'Devis',
- 'help' => ''],
- FACT => [
- 'id' => FACT,
- 'accounts' => [],
- 'label' => 'Facture',
- 'help' => ''],
- ];
+ DEVIS => [
+ 'id' => DEVIS,
+ 'accounts' => [],
+ 'label' => 'Devis',
+ 'help' => ''],
+ FACT => [
+ 'id' => FACT,
+ 'accounts' => [],
+ 'label' => 'Facture',
+ 'help' => ''],
+ CERFA => [
+ 'id' => CERFA,
+ 'accounts' => [],
+ 'label' => 'Reçu fiscal',
+ 'help' => 'Reçu fiscal pour un don (membre ou client)'],
+ COTIS => [
+ 'id' => COTIS,
+ 'accounts' => [],
+ 'label' => 'Reçu de cotisation',
+ 'help' => 'Reçu pour une cotisation payée par un·e membre'],
+ ];
public function __construct()
{
@@ -68,119 +75,116 @@ class Facture
if(!is_array($data) && null !== $data){
$datas[$k] = trim($data);
}
- if ($datas[$k] === '' && ! in_array($k, ['numero', 'nom_contact', 'numero_commande', 'reference_acheteur']))
+ if ($datas[$k] === '' && $k != 'numero')
{
throw new UserException("La valeur de $k est vide");
}
-
+
switch($k)
{
case 'type_facture':
- if (!array_key_exists($datas[$k], $this->types)) {
- throw new UserException("$k est de type non-attendue ($data).");
- }
- if ($datas[$k] < 2) {
- $fac = true;
- $cerfa = false;
- $recu = false;
- }
- elseif ($datas[$k] == 2) {
- $fac = false;
- $cerfa = true;
- $recu = false;
- }
- elseif ($datas[$k] == 3) {
- $fac = false;
- $cerfa = false;
- $recu = true;
- }
- break;
+ if (!array_key_exists($datas[$k], $this->types)) {
+ throw new UserException("$k est de type non-attendue ($data).");
+ }
+ if ($datas[$k] < 2) {
+ $fac = true;
+ $cerfa = false;
+ $recu = false;
+ }
+ elseif ($datas[$k] == 2) {
+ $fac = false;
+ $cerfa = true;
+ $recu = false;
+ }
+ elseif ($datas[$k] == 3) {
+ $fac = false;
+ $cerfa = false;
+ $recu = true;
+ }
+ break;
case 'receveur_membre':
case 'reglee':
case 'archivee':
- if ($datas[$k] != 1 && $datas[$k] != 0) {
- throw new UserException("$k est de valeur non-attendue ($data).");
- }
- break;
+ if ($datas[$k] != 1 && $datas[$k] != 0) {
+ throw new UserException("$k est de valeur non-attendue ($data).");
+ }
+ break;
case 'receveur_id':
- if (!is_numeric($datas[$k]) || $datas[$k] < 0) {
- throw new UserException("L'id du receveur est non-attendu ($data).");
- }
- break;
+ if (!is_numeric($datas[$k]) || $datas[$k] < 0) {
+ throw new UserException("L'id du receveur est non-attendu ($data).");
+ }
+ break;
case 'date_emission':
- $datas[$k] = \DateTime::createFromFormat('!d/m/Y', $data)->format('Y-m-d');
- break;
+ $datas[$k] = \DateTime::createFromFormat('!d/m/Y', $data)->format('Y-m-d');
+ break;
case 'date_echeance':
- $datas[$k] = \DateTime::createFromFormat('!d/m/Y', $data)->format('Y-m-d');
- if (DateTime::createFromFormat('!Y-m-d', $datas[$k])->format('U') < DateTime::createFromFormat('!Y-m-d', $datas['date_emission'])->format('U'))
- {
- throw new UserException("La date d'échéance est antérieure à la date d'émission ($data).");
- }
- break;
+ $datas[$k] = \DateTime::createFromFormat('!d/m/Y', $data)->format('Y-m-d');
+ if (DateTime::createFromFormat('!Y-m-d', $datas[$k])->format('U') < DateTime::createFromFormat('!Y-m-d', $datas['date_emission'])->format('U'))
+ {
+ throw new UserException("La date d'échéance est antérieure à la date d'émission ($data).");
+ }
+ break;
case 'moyen_paiement':
- if (!array_key_exists($datas[$k], $this->listMoyensPaiement())) {
- throw new UserException("Le moyen de paiement ne correspond pas à la liste interne ($data).");
- }
- break;
+ if (!array_key_exists($datas[$k], $this->listMoyensPaiement())) {
+ throw new UserException("Le moyen de paiement ne correspond pas à la liste interne ($data).");
+ }
+ break;
case 'contenu':
- if ($fac)
- {
- if (!is_array($datas[$k]) || empty($datas[$k])) {
- throw new UserException("Le contenu du document est vide ($data).");
- }
- $total = 0;
- foreach($datas[$k] as $g => $r)
+ if ($fac)
{
- if (empty($r['designation']) && empty($r['prix']))
- {
- unset($datas[$k][$g]);
- unset($datas[$k]['prix']);
- continue;
+ if (!is_array($datas[$k]) || empty($datas[$k])) {
+ throw new UserException("Le contenu du document est vide ($data).");
}
- elseif (! is_numeric($r['prix']) && empty($r['prix']))
+ $total = 0;
+ foreach($datas[$k] as $g => $r)
{
- $datas[$k]['prix'] = 0;
- }
- elseif (empty($r['designation'])) {
- throw new UserException("Une au moins des désignations est absente.");
+ if (empty($r['designation']) && empty($r['prix']))
+ {
+ unset($datas[$k][$g]);
+ unset($datas[$k]['prix']);
+ continue;
+ }
+ elseif (empty($r['prix']))
+ {
+ $datas[$k]['prix'] = 0;
+ }
+
+ if (!is_int($r['prix']))
+ {
+ throw new UserException('Un (ou plus) des prix n\'est pas un entier.');
+ }
+
+ $total += $r['prix'];
}
- if (!is_int($r['prix']))
+ if($fac && !$total)
{
- throw new UserException('Un (ou plus) des prix n\'est pas un entier.');
+ throw new UserException("Toutes les désignations/prix sont vides.");
}
-
- $total += $r['prix'];
}
-
- if ($fac && count($datas['contenu']) == 0)
+ elseif ($cerfa)
{
- throw new UserException("Toutes les désignations/prix sont vides.");
- }
- }
- elseif ($cerfa)
- {
- }
- elseif ($recu)
- {
- // $fields = ['id', 'intitule', 'date', 'expiration'];
- // foreach ($datas[$k]as $)
- }
- $datas[$k] = json_encode($datas[$k]);
- break;
+ }
+ elseif ($recu)
+ {
+ // $fields = ['id', 'intitule', 'date', 'expiration'];
+ // foreach ($datas[$k]as $)
+ }
+ $datas[$k] = json_encode($datas[$k]);
+ break;
case 'total':
- if ($cerfa && $datas[$k] < 1) {
- throw new UserException('Le total ne peut être inférieur à 1€ pour les reçus (bug encore non résolu).');
- }
- if ($fac && !isset($datas['contenu'])) {
- throw new UserException("Pas de contenu fourni pour vérifier le total.");
- }
- if ($fac && $total != $datas[$k])
- {
- throw new UserException("Les totaux sont différents ($total != $datas[$k].");
- }
- break;
+ if ($cerfa && $datas[$k] < 1) {
+ throw new UserException('Le total ne peut être inférieur à 1€ pour les reçus (bug encore non résolu).');
+ }
+ if ($fac && !isset($datas['contenu'])) {
+ throw new UserException("Pas de contenu fourni pour vérifier le total.");
+ }
+ if ($fac && $total != $datas[$k])
+ {
+ throw new UserException("Les totaux sont différents ($total != $datas[$k].");
+ }
+ break;
}
}
}
@@ -283,7 +287,7 @@ class Facture
$r = $db->first('SELECT * FROM plugin_facturation_factures WHERE id = ? LIMIT 1;', (int)$id);
if(!$r)
- {
+ {
throw new UserException("Pas de document retournée avec cet id.");
}
@@ -321,14 +325,6 @@ class Facture
public function list(): DynamicList
{
$id_field = \Paheko\Users\DynamicFields::getNameFieldsSQL('u');
- $plugin_name = preg_replace('/^.*\/(\w+)\/$/', '${1}', \Paheko\PLUGIN_ADMIN_URL);
- $plugin = \Paheko\Plugins::get($plugin_name);
-
- // adresse et ville peuvent être redéfinies dans la configuration du plugin
- $adresse_client = $plugin->getConfig('adresse_client');
- if ($adresse_client == null) { $adresse = 'u.adresse'; } else { $adresse = 'u.' . $adresse_client; }
- $ville_client = $plugin->getConfig('ville_client');
- if ($ville_client == null) { $ville = 'u.ville'; } else { $ville = 'u.' . $ville_client; }
$columns = [
// Sélectionner cette colonne, mais ne pas la mettre dans la liste des colonnes
@@ -353,18 +349,15 @@ class Facture
],
'receveur' => [
'label' => 'Receveur',
- // l'identité du membre peut être redéfinie dans la configuration des membres
- 'select' => sprintf('CASE WHEN receveur_membre THEN CASE %s WHEN "" THEN "** ABSENT **" ELSE %s END ELSE c.nom END', $id_field, $id_field),
+ 'select' => sprintf('CASE WHEN receveur_membre THEN %s ELSE c.nom END', $id_field),
],
'receveur_adresse' => [
- // l'adresse peut être redéfinie dans la configuration du plugin
'label' => 'Adresse',
- 'select' => sprintf('CASE WHEN receveur_membre THEN %s ELSE c.adresse END', $adresse),
+ 'select' => 'CASE WHEN receveur_membre THEN u.adresse ELSE c.adresse END',
],
'receveur_ville' => [
- // la ville peut être redéfinie dans la configuration du plugin
'label' => 'Ville',
- 'select' => sprintf('CASE WHEN receveur_membre THEN %s ELSE c.ville END', $ville),
+ 'select' => 'CASE WHEN receveur_membre THEN u.ville ELSE c.ville END',
],
'date_emission' => [
'label' => 'Émission',
@@ -398,6 +391,7 @@ class Facture
$list = new DynamicList($columns, $tables);
$list->orderBy('date_emission', true);
+ $list->setCount('COUNT(f.id)');
$currency = Config::getInstance()->monnaie;
@@ -412,8 +406,8 @@ class Facture
if ($row->type_facture == COTIS && isset($content->intitule, $content->souscription)) {
$row->contenu = sprintf("Cotisation %s\nSouscrite le %s",
- $content->intitule,
- Utils::date_fr($content->souscription, 'd/m/Y')
+ $content->intitule,
+ Utils::date_fr($content->souscription, 'd/m/Y')
);
}
elseif ($row->type_facture != CERFA) {
@@ -498,7 +492,7 @@ class Facture
public $recu_fields = ['id', 'label', 'amount', 'date', 'expiry', 'paid', 'paid_amount'];
- public function getCotis(int $user_id, ?int $su_id = null)
+ public function getCotis(int $user_id, int $su_id = null)
{
$where = 'WHERE su.id_user = ?';
if (null !== $su_id)
@@ -512,7 +506,7 @@ class Facture
LEFT JOIN services_fees sf ON sf.id = su.id_fee
LEFT JOIN acc_transactions_users tu ON tu.id_service_user = su.id
LEFT JOIN acc_transactions_lines tl ON tl.id_transaction = tu.id_transaction
- '.$where.'
+ '.$where.'
GROUP BY su.id
ORDER BY su.date;';
@@ -532,24 +526,24 @@ class Facture
return $db->getGrouped($query);
}
}
-
+
/* modif DD -- lecture et retour des textes de CERFA -- */
public function listTextesCerfa($menu = true)
{
$db = DB::getInstance();
-
+
$sel = ($menu) ? 'id, menu' : 'id, texte';
$query = 'SELECT '.$sel.' FROM "plugin_facturation_txt_cerfa" WHERE 1 ORDER BY id ;';
return $db->getAssoc($query);
}
-
+
public function getMoyenPaiement($code)
{
$db = DB::getInstance();
return $db->firstColumn('SELECT nom FROM plugin_facturation_paiement WHERE code = ?;', $code);
}
-
+
public function delete($id)
{
return DB::getInstance()->delete('plugin_facturation_factures', 'id = '. (int)$id);
diff --git a/plugin.ini b/plugin.ini
index c75a449..e4cd258 100644
--- a/plugin.ini
+++ b/plugin.ini
@@ -1,8 +1,8 @@
name="Facturation"
-description="Permet d'éditer des factures et devis à ses membres ainsi qu'à une base de clients supplémentaire."
+description="Permet d'éditer des factures, devis et reçus à ses membres ainsi qu'à une base de clients supplémentaire."
author="zou ; adapté par jce"
url="https://git.roflcopter.fr/lesanges/paheko-plugin-facturation"
-version="0.16"
+version="0.8.7"
menu=true
restrict_section="accounting"
restrict_level="read"
diff --git a/templates/_form.tpl b/templates/_form.tpl
index f533acf..3e6029d 100644
--- a/templates/_form.tpl
+++ b/templates/_form.tpl
@@ -3,7 +3,7 @@
|