Compare commits
No commits in common. "master" and "v0.8.2" have entirely different histories.
32
CHANGELOG
32
CHANGELOG
|
@ -1,33 +1,3 @@
|
|||
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
|
||||
- Correction erreur si pas de prix saisi
|
||||
0.8.5
|
||||
- Ajout numéro SIREN/SIRET pour les clients
|
||||
- Ajout pagination liste factures
|
||||
|
||||
0.8.4
|
||||
- Correction bug si identité définie par plusieurs champs
|
||||
- Correction bug oubli choix receveur
|
||||
- Mise-à-jour Changelog
|
||||
|
||||
0.8.3 :
|
||||
- Mise-à-jour README
|
||||
|
||||
0.8.2 :
|
||||
- Tri des membres en ordre alphabétique
|
||||
- Élimination de plusieurs bugs
|
||||
|
||||
0.8.1 :
|
||||
- reprise du code par jce (lesanges@zaclys.net ; https://git.roflcopter.fr/lesanges/paheko-plugin-facturation)
|
||||
- Achèvement migration vers Paheko 1.3
|
||||
|
||||
0.7.4 :
|
||||
- Corrections de dépréciations PHP, le plugin être compatible PHP8.2
|
||||
- Quelques problèmes réglés de formulaires invalidables
|
||||
|
@ -54,7 +24,7 @@
|
|||
- ajout d'une table `plugin_facturation_txt_cerfa` pour stocker les textes explicatifs additionnels
|
||||
- formulaires adaptés aux CERFA pour permettre le choix de la forme, de la nature, du mode de versement et du texte explicatif éventuel
|
||||
|
||||
0.6.0 :
|
||||
0.6.0 :
|
||||
- Génération des PDF par Garradin, on se débarasse de mPDF et l'installation du plugin devient standard
|
||||
- Fix #32 (prix total affiché incorrect), en stockant les prix sous formes d'entiers à la manière de Garradin
|
||||
- Possibilité de supprimer un document
|
||||
|
|
79
README.md
79
README.md
|
@ -1,50 +1,54 @@
|
|||
# Plugin Facturation pour Paheko (ex Garradin)
|
||||
# Plugin Facturation pour 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 Garradin ( https://garradin.eu/ - https://fossil.kd2.org/garradin ).
|
||||
Source : https://gitlab.com/ramoloss/garradin-plugin-facturation
|
||||
|
||||
Source :
|
||||
- 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://gitlab.com/ramoloss/garradin-plugin-facturation/-/releases), et la placer directement dans le dossier plugins de Garradin.
|
||||
|
||||
## 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 Garradin 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 garradin-plugin-facturation-v0.5.0.tar.gz
|
||||
mv garradin-plugin-facturation-v0.5.0 facturation
|
||||
rm garradin-plugin-facturation-v0.5.0.tar.gz
|
||||
chown -R www-data:www-data facturation/
|
||||
chmod -R g+w facturation/
|
||||
|
||||
|
||||
Supprimer l'archive permet à Garradin 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
|
||||
|
||||
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 +57,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/
|
||||
|
|
|
@ -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 {
|
||||
|
@ -56,14 +34,14 @@ $tpl->assign('formes_don', array('1' => 'Acte authentique',
|
|||
'3' => 'Don manuel',
|
||||
'4' => 'Autres'));
|
||||
$tpl->assign('natures_don', array('1' => 'Numéraire',
|
||||
'2' => 'Chèque',
|
||||
'3' => 'Virement, CB; ...'));
|
||||
'2' => 'Chèque',
|
||||
'3' => 'Virement, CB; ...'));
|
||||
$tpl->assign('textes_don', $facture->listTextesCerfa());
|
||||
|
||||
if ( !$target ) {
|
||||
f(['id' => 'required|numeric']);
|
||||
$id = (int) qg('id');
|
||||
|
||||
|
||||
if (!$f = $facture->get($id))
|
||||
{
|
||||
throw new UserException("Ce document n'existe pas.");
|
||||
|
@ -73,145 +51,134 @@ if ( !$target ) {
|
|||
// Traitement
|
||||
$data=[];
|
||||
$form->runIf(f('save') && !$form->hasErrors(),
|
||||
function () use ($client, &$data, $form)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( count(f('designation')) !== count(f('prix')) )
|
||||
{
|
||||
throw new UserException('Nombre de désignations et de prix reçus différent.');
|
||||
}
|
||||
function () use ($client, &$data)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( count(f('designation')) !== count(f('prix')) )
|
||||
{
|
||||
throw new UserException('Nombre de désignations et de prix reçus différent.');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'numero' => f('numero_facture'),
|
||||
'date_emission' => f('date_emission'),
|
||||
'date_echeance' => f('date_echeance'),
|
||||
'reglee' => f('reglee') == 1?1:0,
|
||||
'archivee' => f('archivee') == 1?1:0,
|
||||
'moyen_paiement' => f('moyen_paiement'),
|
||||
'toto' => 0
|
||||
];
|
||||
$data['type_facture'] = f('type');
|
||||
if (in_array(f('type'), [DEVIS, FACT]))
|
||||
{
|
||||
foreach(f('designation') as $k=>$value)
|
||||
{
|
||||
if ($value != '' && f('prix')[$k] == null) {
|
||||
throw new UserException('Il manque le prix sur la ligne '. $k+1 . ' !!');
|
||||
}
|
||||
$data = [
|
||||
'numero' => f('numero_facture'),
|
||||
'date_emission' => f('date_emission'),
|
||||
'date_echeance' => f('date_echeance'),
|
||||
'reglee' => f('reglee') == 1?1:0,
|
||||
'archivee' => f('archivee') == 1?1:0,
|
||||
'moyen_paiement' => f('moyen_paiement'),
|
||||
'toto' => 0
|
||||
];
|
||||
$data['type_facture'] = f('type');
|
||||
if (in_array(f('type'), [DEVIS, FACT]))
|
||||
{
|
||||
foreach(f('designation') as $k=>$value)
|
||||
{
|
||||
$data['contenu'][$k]['designation'] = $value;
|
||||
$data['contenu'][$k]['prix'] = Utils::moneyToInteger(f('prix')[$k]);
|
||||
$data['toto'] += Utils::moneyToInteger(f('prix')[$k]);
|
||||
}
|
||||
$data['total'] = $data['toto'];
|
||||
unset($data['toto']);
|
||||
}
|
||||
elseif ( f('type') == CERFA )
|
||||
{
|
||||
$data['moyen_paiement'] = f('moyen_paiement_cerfa');
|
||||
$data['contenu'] = [
|
||||
'forme' => f('forme_don'),
|
||||
'nature' => f('nature_don'),
|
||||
'texte' => f('texte_don')];
|
||||
$data['total'] = Utils::moneyToInteger(f('total'));
|
||||
unset($data['toto']);
|
||||
}
|
||||
if (f('base_receveur') == 'client')
|
||||
{
|
||||
$data['receveur_membre'] = 0;
|
||||
$data['receveur_id'] = f('client');
|
||||
}
|
||||
elseif (f('base_receveur') == 'membre')
|
||||
{
|
||||
$data['receveur_membre'] = 1;
|
||||
$data['receveur_id'] = f('membre');
|
||||
}
|
||||
|
||||
$data['contenu'][$k]['designation'] = $value;
|
||||
$data['contenu'][$k]['prix'] = Utils::moneyToInteger(f('prix')[$k]);
|
||||
$data['toto'] += Utils::moneyToInteger(f('prix')[$k]);
|
||||
}
|
||||
$data['total'] = $data['toto'];
|
||||
unset($data['toto']);
|
||||
}
|
||||
elseif ( f('type') == CERFA )
|
||||
{
|
||||
$data['moyen_paiement'] = f('moyen_paiement_cerfa');
|
||||
$data['contenu'] = [
|
||||
'forme' => f('forme_don'),
|
||||
'nature' => f('nature_don'),
|
||||
'texte' => f('texte_don')];
|
||||
$data['total'] = Utils::moneyToInteger(f('total'));
|
||||
unset($data['toto']);
|
||||
}
|
||||
if (f('base_receveur') == 'client')
|
||||
{
|
||||
$data['receveur_membre'] = 0;
|
||||
$data['receveur_id'] = f('client');
|
||||
}
|
||||
elseif (f('base_receveur') == 'membre')
|
||||
{
|
||||
$data['receveur_membre'] = 1;
|
||||
$data['receveur_id'] = f('membre');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UserException('Vous devez indiquer si le receveur est un client ou un membre');
|
||||
}
|
||||
|
||||
}
|
||||
catch(UserException $e)
|
||||
{
|
||||
$form->addError($e->getMessage());
|
||||
}
|
||||
|
||||
}, $csrf_key);
|
||||
}
|
||||
catch(UserException $e)
|
||||
{
|
||||
$form->addError($e->getMessage());
|
||||
}
|
||||
|
||||
}, $csrf_key);
|
||||
|
||||
$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);
|
||||
}
|
||||
function () use ($radio, $fields, $facture)
|
||||
{
|
||||
$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())
|
||||
if ($step)
|
||||
{
|
||||
if ($step)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
$liste = $facture->getCotis((int)f('membre_cotis'));
|
||||
}
|
||||
catch (UserException $e)
|
||||
{
|
||||
$form->addError($e->getMessage());
|
||||
}
|
||||
$liste = $facture->getCotis((int)f('membre_cotis'));
|
||||
}
|
||||
elseif (count($data) > 0)
|
||||
catch (UserException $e)
|
||||
{
|
||||
if ($target)
|
||||
{
|
||||
$id = $facture->add($data, $plugin->getConfig('pattern'));
|
||||
Utils::redirect(PLUGIN_ADMIN_URL . 'facture.php?id='.(int)$id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($facture->edit($id, $data))
|
||||
{
|
||||
Utils::redirect(PLUGIN_ADMIN_URL . 'facture.php?id='.(int)$id);
|
||||
}
|
||||
throw new UserException('Erreur d\'édition du reçu');
|
||||
}
|
||||
$form->addError($e->getMessage());
|
||||
}
|
||||
}
|
||||
elseif (count($data) > 0)
|
||||
{
|
||||
if ($target)
|
||||
{
|
||||
$id = $facture->add($data, $plugin->getConfig('pattern'));
|
||||
Utils::redirect(PLUGIN_ADMIN_URL . 'facture.php?id='.(int)$id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($facture->edit($id, $data))
|
||||
{
|
||||
Utils::redirect(PLUGIN_ADMIN_URL . 'facture.php?id='.(int)$id);
|
||||
}
|
||||
throw new UserException('Erreur d\'édition du reçu');
|
||||
}
|
||||
}
|
||||
|
||||
// Affichage
|
||||
|
||||
|
@ -250,12 +217,12 @@ if ($target)
|
|||
elseif (isset($doc['type'])) {
|
||||
$radio['type'] = $doc['type'];
|
||||
} // ... ou par défaut
|
||||
else
|
||||
else
|
||||
{
|
||||
$radio['type'] = FACT;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
$doc['moyen_paiement'] = $f->moyen_paiement;
|
||||
$doc['type'] = $f->type_facture;
|
||||
|
@ -265,7 +232,7 @@ else
|
|||
$doc['client'] = $f->receveur_id;
|
||||
$doc['membre'] = $f->receveur_id;
|
||||
$doc['contenu'] = $f->contenu;
|
||||
|
||||
|
||||
$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:---
|
||||
/* modif DD -- CERFA -------------------------------------- */
|
||||
|
@ -275,7 +242,7 @@ else
|
|||
$doc['nature_don'] = $f->contenu['nature'];
|
||||
$doc['texte_don'] = $f->contenu['texte'];
|
||||
}
|
||||
|
||||
|
||||
$radio['type'] = f('type')??$doc['type'];
|
||||
}
|
||||
$tpl->assign('types_details', $facture->types);
|
||||
|
@ -323,8 +290,9 @@ $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('require_number', $require_number);
|
||||
$tpl->assign('number_pattern', PATTERNS_LIST[$plugin->getConfig('pattern')]);
|
||||
|
|
|
@ -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('<td><nobr><input type="text" pattern="[0-9]*([.,][0-9]{1,2})?" inputmode="decimal" size="8" class="money" style="width: 60%%" onchange="updateSum();" name="%s" value="%s" /><b>%s</b></nobr></td>', $name, $current_value, $currency);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ if (!$c)
|
|||
}
|
||||
|
||||
$form->runIf(f('save') && !$form->hasErrors(),
|
||||
function () use ($client, $id, $form)
|
||||
function () use ($client, $id)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -26,7 +26,6 @@ $form->runIf(f('save') && !$form->hasErrors(),
|
|||
'adresse' => f('adresse'),
|
||||
'code_postal' => f('code_postal'),
|
||||
'ville' => f('ville'),
|
||||
'siret' => f('siret'),
|
||||
'telephone' => f('telephone'),
|
||||
'email' => f('email')
|
||||
]);
|
||||
|
|
|
@ -7,7 +7,7 @@ require_once __DIR__ . '/_inc.php';
|
|||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
||||
|
||||
$form->runIf(f('add') && !$form->hasErrors(),
|
||||
function () use ($client, $form)
|
||||
function () use ($client)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -16,7 +16,6 @@ $form->runIf(f('add') && !$form->hasErrors(),
|
|||
'adresse' => f('adresse'),
|
||||
'code_postal' => f('code_postal'),
|
||||
'ville' => f('ville'),
|
||||
'siret' => f('siret'),
|
||||
'telephone' => f('telephone'),
|
||||
'email' => f('email')
|
||||
]);
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace Paheko;
|
||||
use Paheko\Users\DynamicFields;
|
||||
|
||||
require_once __DIR__ . '/_inc.php';
|
||||
|
||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN);
|
||||
|
||||
$champsPaheko = DynamicFields::getInstance()->listAssocNames();
|
||||
$champsPaheko = array('' => '- Choisir un champ -') + $champsPaheko;
|
||||
|
||||
$form->runIf('save', function () use ($plugin) {
|
||||
$plugin->setConfigProperty('rna_asso', trim(f('rna_asso')));
|
||||
$plugin->setConfigProperty('siret_asso', trim(f('siret_asso')));
|
||||
|
@ -20,11 +16,18 @@ $form->runIf('save', function () use ($plugin) {
|
|||
$plugin->setConfigProperty('cp_asso', trim(f('cp_asso')));
|
||||
$plugin->setConfigProperty('ville_asso', trim(f('ville_asso')));
|
||||
|
||||
$plugin->setConfigProperty('logo', (bool)f('logo'));
|
||||
$plugin->setConfigProperty('footer', f('footer'));
|
||||
$plugin->setConfigProperty('droit_art200', (bool)f('droit_art200'));
|
||||
$plugin->setConfigProperty('droit_art238bis', (bool)f('droit_art238bis'));
|
||||
$plugin->setConfigProperty('droit_art885_0VbisA', (bool)f('droit_art885_0VbisA'));
|
||||
$plugin->setConfigProperty('objet_0', trim(f('objet_0')));
|
||||
$plugin->setConfigProperty('objet_1', trim(f('objet_1')));
|
||||
$plugin->setConfigProperty('objet_2', trim(f('objet_2')));;
|
||||
|
||||
$plugin->setConfigProperty('footer', f('footer'));
|
||||
|
||||
$plugin->setConfigProperty('validate_cp', (bool)f('validate_cp'));
|
||||
$plugin->setConfigProperty('unique_client_name', (bool)f('unique_client_name'));
|
||||
|
||||
$plugin->setConfigProperty('pattern', f('pattern'));
|
||||
|
||||
$plugin->save();
|
||||
|
@ -34,6 +37,5 @@ $form->runIf('save', function () use ($plugin) {
|
|||
$tpl->assign('ok', qg('ok') !== null);
|
||||
$tpl->assign('conf', $plugin->getConfig());
|
||||
$tpl->assign('patterns', \Paheko\Plugin\Facturation\PATTERNS_LIST);
|
||||
$tpl->assign('champsPaheko', $champsPaheko);
|
||||
|
||||
$tpl->display(PLUGIN_ROOT . '/templates/config.tpl');
|
||||
$tpl->display(PLUGIN_ROOT . '/templates/config.tpl');
|
|
@ -21,7 +21,7 @@ if (!$f)
|
|||
}
|
||||
|
||||
$tpl->assign('type', $f->type_facture);
|
||||
$tpl->assign('facture', $f);
|
||||
$tpl->assign('facture', $f);
|
||||
$tpl->assign('id', $id);
|
||||
$tpl->assign('footer', $plugin->getConfig('footer')?:'');
|
||||
$tpl->assign('siret_asso', $plugin->getConfig('siret_asso')?:'');
|
||||
|
|
|
@ -18,7 +18,7 @@ if (!$client)
|
|||
}
|
||||
|
||||
$form->runIf(f('delete') && !$form->hasErrors(),
|
||||
function () use ($facture, $f, $form)
|
||||
function () use ($facture, $f)
|
||||
{
|
||||
try {
|
||||
$facture->delete($f->id);
|
||||
|
|
|
@ -12,7 +12,6 @@ $session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
|||
|
||||
$list = $facture->list();
|
||||
$list->loadFromQueryString();
|
||||
$list->setPageSize(50);
|
||||
|
||||
$tpl->assign(compact('list'));
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ $users = new Users\Users;
|
|||
|
||||
f(['id' => 'required|numeric']);
|
||||
$id = (int) qg('id');
|
||||
$id_field = Users\DynamicFields::getNameFieldsSQL();
|
||||
$sign_tag = UserTemplate\Functions::signature();
|
||||
|
||||
// Vérification que le document existe
|
||||
|
@ -24,36 +25,19 @@ try
|
|||
if ($f->receveur_membre)
|
||||
{
|
||||
$c = $users->get($f->receveur_id);
|
||||
// l'identité du membre peut être redéfinie dans la configuration des membres
|
||||
$name_fields = \Paheko\Users\DynamicFields::getNameFields();
|
||||
array_walk($name_fields, function(&$elem) use ($c) {
|
||||
$elem = $c->$elem;
|
||||
});
|
||||
$nom_client = implode(" ", $name_fields);
|
||||
if (preg_match('/^ +$/', $nom_client)) {
|
||||
$nom_client = "** ABSENT **";
|
||||
}
|
||||
|
||||
// adresse, code postal et ville peuvent être redéfini(e)s dans la configuration du plugin
|
||||
$adresse_client = $plugin->getConfig('adresse_client');
|
||||
if ($adresse_client != null && $c->$adresse_client != null) { $c->adresse = $c->$adresse_client; }
|
||||
$code_postal_client = $plugin->getConfig('code_postal_client');
|
||||
if ($code_postal_client != null && $c->$code_postal_client != null) { $c->code_postal = $c->$code_postal_client; }
|
||||
$ville_client = $plugin->getConfig('ville_client');
|
||||
if ($ville_client != null && $c->$ville_client != null) { $c->ville = $c->$ville_client; }
|
||||
|
||||
$c->$id_field = $c->$identite;
|
||||
foreach(['ville','code_postal','adresse'] as $v)
|
||||
{
|
||||
if($c->$v == '')
|
||||
{
|
||||
$c->$v = '[À RENSEIGNER DANS LA FICHE MEMBRE]';
|
||||
$c->$v = '[A RENSEIGNER DANS LA FICHE MEMBRE]';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$c = $client->get($f->receveur_id);
|
||||
$nom_client = $c->nom;
|
||||
$c->$id_field = $c->nom;
|
||||
}
|
||||
}
|
||||
catch(UserException $e)
|
||||
|
@ -77,20 +61,14 @@ if ($f->type_facture != CERFA)
|
|||
switch ($f->type_facture)
|
||||
{
|
||||
case FACT:
|
||||
$doc = 'Facture n° '. $f->numero;
|
||||
$txtemis = $doc . " - Émise le " . $emission;
|
||||
$txtdest = "Adressée à :";
|
||||
break;
|
||||
$doc = 'Facture n°'. $f->numero;
|
||||
break;
|
||||
case DEVIS:
|
||||
$doc = 'Devis n° '. $f->numero;
|
||||
$txtemis = $doc . " - Émis le " . $emission;
|
||||
$txtdest = "Adressé à :";
|
||||
break;
|
||||
$doc = 'Devis n°'. $f->numero;
|
||||
break;
|
||||
case COTIS:
|
||||
$doc = 'Reçu de cotisation n° '. $f->numero;
|
||||
$txtemis = $doc . " - Émis le " . $emission;
|
||||
$txtdest = "Adressé à :";
|
||||
break;
|
||||
$doc = 'Reçu de cotisation n°'. $f->numero;
|
||||
break;
|
||||
}
|
||||
|
||||
// utiliser l'adresse configurée dans le plugin sinon celle de l'asso sinon rien !
|
||||
|
@ -112,25 +90,20 @@ if ($f->type_facture != CERFA)
|
|||
$adresse = "";
|
||||
}
|
||||
|
||||
$logo='';
|
||||
if ($plugin->getConfig('logo')) {
|
||||
$logo = '<img id="logo" src="' . $config->fileURL('logo') . '" />';
|
||||
}
|
||||
$asso =
|
||||
// 'Émis par :<br><br>'.
|
||||
'<b>'.$config->get('org_name')."</b><br>".
|
||||
$adresse ."<br>".
|
||||
(($t = $plugin->getConfig('rna_asso'))?"RNA : $t<br>":'').
|
||||
(($t = $plugin->getConfig('siret_asso'))?"SIRET : " . implode(' ', str_split($t, 3)) . "<br>":'').
|
||||
(($t = $plugin->getConfig('siret_asso'))?"SIRET : $t<br>":'').
|
||||
(($t = $config->get('email_asso'))?"Email : $t<br>":'').
|
||||
(($t = $config->get('site_asso'))?"Site web : $t<br>":'');
|
||||
|
||||
$receveur =
|
||||
$txtdest.'<br>'.
|
||||
'<b>'.$nom_client.'</b><br>'.
|
||||
'Adressé à :<br><br>'.
|
||||
'<b>'.$c->nom.'</b><br>'.
|
||||
$c->adresse."<br>".
|
||||
$c->code_postal.' '.$c->ville."<br>".
|
||||
(($t = $c->siret)?"SIREN/SIRET : " . implode(' ', str_split($t, 3)) . "<br>":'').
|
||||
(($t = $c->email)?"Email : $t<br>":'').
|
||||
(($t = $c->telephone)?"Tel : $t<br>":'');
|
||||
|
||||
|
@ -140,11 +113,7 @@ if ($f->type_facture != CERFA)
|
|||
if ($f->type_facture != COTIS)
|
||||
{
|
||||
$echeance = ($f->type_facture?'Échéance de paiement':'Échéance du devis')." : ".$echeance;
|
||||
if ($f->type_facture == FACT) {
|
||||
$reglee = !$f->reglee?'Cette facture est en attente de règlement.':'Cette facture a été réglée.';
|
||||
} else {
|
||||
$reglee = "";
|
||||
}
|
||||
$reglee = !$f->reglee?'Cette facture est en attente de règlement.':'Cette facture a été reglée.';
|
||||
$footer = str_replace("\n", '<br>', $plugin->getConfig('footer') ?? '[Pied de page à configurer]');
|
||||
$ttc = $plugin->getConfig('ttc') ? 'TTC':'HT';
|
||||
|
||||
|
@ -172,7 +141,7 @@ EOF;
|
|||
|
||||
$i = 1;
|
||||
foreach($f->contenu as $k=>$v)
|
||||
{
|
||||
{
|
||||
echo '<tr><td>';
|
||||
echo str_replace("\n", '<br>', $v['designation']);
|
||||
echo '</td><td>';
|
||||
|
@ -197,17 +166,12 @@ EOF;
|
|||
$echeance <br>
|
||||
$reglee
|
||||
Moyen de paiement : $moyen_paiement
|
||||
|
||||
<p>
|
||||
$footer
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
EOF;
|
||||
if ($f->type_facture == DEVIS) {
|
||||
echo <<<EOF
|
||||
<p><b>Bon pour accord, date et signature<b></p>
|
||||
EOF;
|
||||
}
|
||||
|
||||
$content = ob_get_clean();
|
||||
|
||||
|
@ -216,7 +180,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')
|
||||
|
@ -252,7 +216,7 @@ EOF;
|
|||
}
|
||||
|
||||
//-- Layout du document
|
||||
|
||||
|
||||
ob_start();
|
||||
echo <<<EOF
|
||||
<!DOCTYPE html>
|
||||
|
@ -265,7 +229,7 @@ EOF;
|
|||
size: A4 portrait;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
padding: 4mm;
|
||||
font-family: Helvetica, Arial, sans;
|
||||
|
@ -299,13 +263,6 @@ EOF;
|
|||
width: 40%;
|
||||
vertical-align: top;
|
||||
}
|
||||
.adressage td#logo {
|
||||
width: 20%;
|
||||
vertical-align: top;
|
||||
}
|
||||
.adressage img#logo {
|
||||
height : 3cm;
|
||||
}
|
||||
|
||||
.contenuTexte {
|
||||
padding: 0 6mm;
|
||||
|
@ -352,12 +309,11 @@ EOF;
|
|||
</head>
|
||||
<body>
|
||||
<p class="titre">
|
||||
$txtemis
|
||||
$doc - Émis le $emission
|
||||
</p>
|
||||
|
||||
<table class="adressage">
|
||||
<tr>
|
||||
<td id="logo">$logo</td>
|
||||
<td>$asso</td>
|
||||
<td>$receveur</td>
|
||||
</tr>
|
||||
|
@ -388,7 +344,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;
|
||||
|
@ -403,7 +359,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';
|
||||
|
@ -469,7 +425,7 @@ elseif ($f->type_facture == CERFA)
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans;
|
||||
font-size: 10pt;
|
||||
|
@ -491,11 +447,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;
|
||||
|
@ -559,7 +515,7 @@ if(qg('d') !== null)
|
|||
{
|
||||
$filename = 'Print';
|
||||
if (preg_match('!<title>(.*)</title>!U', $html, $match)) {
|
||||
$filename = str_replace(" ", "_", trim($match[1]));
|
||||
$filename = trim($match[1]);
|
||||
}
|
||||
|
||||
header('Content-type: application/pdf');
|
||||
|
|
|
@ -21,7 +21,7 @@ CREATE TABLE IF NOT EXISTS plugin_facturation_clients (
|
|||
adresse TEXT NOT NULL,
|
||||
code_postal TEXT NOT NULL,
|
||||
ville TEXT NOT NULL,
|
||||
siret TEXT,
|
||||
-- date_creation INTEGER NOT NULL,
|
||||
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
|
||||
|
|
|
@ -15,7 +15,6 @@ class Client
|
|||
'adresse',
|
||||
'code_postal',
|
||||
'ville',
|
||||
'siret',
|
||||
'telephone',
|
||||
'email'
|
||||
];
|
||||
|
@ -40,7 +39,7 @@ class Client
|
|||
{
|
||||
$data[$key] = trim($data[$key]);
|
||||
|
||||
if($data[$key] == '' && ($key != 'siret' && $key != 'telephone' && $key != 'email'))
|
||||
if($data[$key] == '' && ($key != 'telephone' && $key != 'email'))
|
||||
{
|
||||
throw new UserException('Le champs '.$key.' doit être renseigné.');
|
||||
}
|
||||
|
@ -56,10 +55,6 @@ class Client
|
|||
throw new UserException('Le code postal est erroné.');
|
||||
}
|
||||
}
|
||||
elseif ($key == "siret")
|
||||
{
|
||||
$data[$key] = str_replace(' ', '', $data[$key]);
|
||||
}
|
||||
elseif ($key == "telephone")
|
||||
{
|
||||
$data[$key] = Utils::normalizePhoneNumber($data[$key]);
|
||||
|
@ -89,7 +84,7 @@ class Client
|
|||
|
||||
if($this->config['unique_client_name'] && isset($data['nom']) && $db->test('plugin_facturation_clients', 'nom = ? COLLATE NOCASE', $data['nom']))
|
||||
{
|
||||
throw new UserException('La valeur du champ nom est déjà utilisée, or ce champ doit être unique à chaque client.');
|
||||
throw new UserException('La valeur du champ nom est déjà utilisée, hors ce champ doit être unique à chaque client.');
|
||||
}
|
||||
|
||||
$db->insert('plugin_facturation_clients', $data);
|
||||
|
@ -127,9 +122,6 @@ class Client
|
|||
'ville' => [
|
||||
'label' => 'Ville',
|
||||
],
|
||||
'siret' => [
|
||||
'label' => 'SIRET',
|
||||
],
|
||||
'telephone' => [
|
||||
'label' => 'Téléphone',
|
||||
],
|
||||
|
@ -158,7 +150,7 @@ class Client
|
|||
|
||||
if($this->config['unique_client_name'] && isset($data['nom']) && $db->test('plugin_facturation_clients', 'nom = ? COLLATE NOCASE AND id != ?', $data['nom'], (int)$id))
|
||||
{
|
||||
throw new UserException('La valeur du champ nom est déjà utilisée, or ce champ doit être unique à chaque client.');
|
||||
throw new UserException('La valeur du champ nom est déjà utilisée, hors ce champ doit être unique à chaque client.');
|
||||
}
|
||||
|
||||
return $db->update('plugin_facturation_clients', $data, $db->where('id', (int)$id));
|
||||
|
|
251
lib/Facture.php
251
lib/Facture.php
|
@ -34,27 +34,27 @@ class Facture
|
|||
];
|
||||
|
||||
public $types = [
|
||||
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'],
|
||||
];
|
||||
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()
|
||||
{
|
||||
|
@ -79,112 +79,112 @@ class Facture
|
|||
{
|
||||
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 (empty($r['prix']))
|
||||
$total = 0;
|
||||
foreach($datas[$k] as $g => $r)
|
||||
{
|
||||
$datas[$k]['prix'] = 0;
|
||||
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 && !$total)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -287,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.");
|
||||
}
|
||||
|
||||
|
@ -325,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
|
||||
|
@ -357,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),
|
||||
'label' => 'Son 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),
|
||||
'label' => 'Sa ville',
|
||||
'select' => 'CASE WHEN receveur_membre THEN u.ville ELSE c.ville END',
|
||||
],
|
||||
'date_emission' => [
|
||||
'label' => 'Émission',
|
||||
|
@ -402,7 +391,6 @@ class Facture
|
|||
|
||||
$list = new DynamicList($columns, $tables);
|
||||
$list->orderBy('date_emission', true);
|
||||
$list->setCount('COUNT(f.id)');
|
||||
|
||||
$currency = Config::getInstance()->monnaie;
|
||||
|
||||
|
@ -417,8 +405,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) {
|
||||
|
@ -432,6 +420,7 @@ class Facture
|
|||
}
|
||||
});
|
||||
|
||||
$list->setPageSize(1000);
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
@ -443,7 +432,7 @@ class Facture
|
|||
|
||||
if(isset($data['numero']) && $db->test('plugin_facturation_factures', 'numero = ? COLLATE NOCASE AND id != ?', $data['numero'], (int)$id))
|
||||
{
|
||||
throw new UserException('Un document avec ce numéro existe déjà, or le numéro doit être unique.');
|
||||
throw new UserException('Un document avec ce numéro existe déjà, hors le numéro doit être unique.');
|
||||
}
|
||||
return $db->update('plugin_facturation_factures', $data, $db->where('id', (int)$id));
|
||||
}
|
||||
|
@ -517,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;';
|
||||
|
||||
|
@ -537,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);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
name="Facturation"
|
||||
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"
|
||||
author="zou"
|
||||
url="https://git.roflcopter.fr/lesanges/paheko-plugin-facturation"
|
||||
version="0.11"
|
||||
version="0.8.2"
|
||||
menu=true
|
||||
restrict_section="accounting"
|
||||
restrict_level="read"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<legend data-types="t3">Créer un reçu de cotisation</legend>
|
||||
<dl>
|
||||
|
||||
{input type="text" name="numero_facture" maxlength=18 label="Numéro du document" required=$require_number source=$doc}
|
||||
{input type="text" name="numero_facture" maxlength=12 label="Numéro du document" required=$require_number source=$doc}
|
||||
|
||||
<dd class="help">
|
||||
{if $require_number}
|
||||
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
|
||||
<dt><label>Statut</label></dt>
|
||||
|
||||
|
||||
{input type="checkbox" name="reglee" value="1" label="Réglée" source=$doc data-types="t1"}
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="checkbox" name="archivee" value="1" label="Archivée" source=$doc disabled="disabled"}
|
||||
|
@ -113,14 +113,14 @@
|
|||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
|
||||
{foreach from=$designations item=designation key=key}
|
||||
{foreach from=$designations item=designation key=key}
|
||||
<tr>
|
||||
<td><textarea name="designation[]" style="width:98%;">{$designation}</textarea></td>
|
||||
{money_fac value=$prix[$key] user=$from_user}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
{else}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
|
@ -139,7 +139,7 @@
|
|||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<fieldset data-types="t2">
|
||||
<legend>Contenu</legend>
|
||||
<dl>
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
function plus(){
|
||||
var newdiv = document.createElement('tr');
|
||||
newdiv.innerHTML = document.getElementById('Line1').innerHTML;
|
||||
newdiv.getElementsByTagName('textarea')[0].setAttribute('name', 'designation[]');
|
||||
newdiv.getElementsByTagName('input')[0].setAttribute('name', 'prix[]');
|
||||
newdiv.getElementsByTagName('textarea')[0].setAttribute('name', 'designation[]');
|
||||
newdiv.getElementsByTagName('input')[0].setAttribute('name', 'prix[]');
|
||||
newdiv.querySelector('.fact_rm_line button').onclick = function(){
|
||||
this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
|
||||
updateSum();
|
||||
|
@ -33,12 +33,12 @@
|
|||
|
||||
$('#ajouter_ligne').onclick = plus;
|
||||
|
||||
a = document.querySelectorAll('[name="remove_line"]');
|
||||
a = document.querySelectorAll('[name="remove_line"]');
|
||||
l = a.length;
|
||||
for(i = 0; i < l; i++) {
|
||||
a[i].onclick = function(){
|
||||
this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
|
||||
updateSum();
|
||||
updateSum();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -99,4 +99,4 @@
|
|||
hideAllTypes();
|
||||
{/literal}
|
||||
selectType({$radio.type});
|
||||
</script>
|
||||
</script>
|
|
@ -7,15 +7,4 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
div.aide {
|
||||
margin: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
div.aide ul {
|
||||
list-style: square;
|
||||
margin: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
{/literal}
|
||||
{/literal}
|
|
@ -1,30 +1,21 @@
|
|||
{include file="_head.tpl" title="Aide — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id}
|
||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="aide"}
|
||||
|
||||
<h2>Quelques remarques et conseils sur l'utilisation du plugin Facturation</h2>
|
||||
<fieldset>
|
||||
<legend><h2>Quelques remarques et conseils sur l'utilisation du plugin Facturation</h2></legend>
|
||||
|
||||
<div class="aide">
|
||||
<p>Une des premières choses à faire est d'aller dans l'onglet {link href="config.php" label="Configuration du plugin"} pour renseigner les valeurs nécessaires à la génération des documents.</p>
|
||||
<fieldset>
|
||||
<legend>Informations à configurer</legend>
|
||||
<dl>
|
||||
<dt><label>Adresse</label></dt>
|
||||
<dd>Si elle n'est pas remplie, c'est l'adresse qui figure dans la {link href="!config" label="configuration de l'association"} qui sera utilisée</dd>
|
||||
<dt><label>Nom et prénom des membres</label></dt>
|
||||
<dd>Les champs qui définissent l'identité d'un membre peuvent être choisis dans la {link href="!config/users" label="configuration de la fiche membre"} </dd>
|
||||
<dt><label>Champs à faire figurer sur la facture</label></dt>
|
||||
<dd>Permet de choisir les champs pour l'adresse, le code postal et la ville parmi les {link href="!config/fields" label="champs de la fiche membre"}</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
<p>Une des premières choses à faire est d'aller dans l'onglet Configuration pour renseigner les valeurs nécessaires à la génération des documents.</p>
|
||||
<p>Pour l'instant, il y a des choses encore brouillonnes. Notamment, dans les factures et devis, c'est l'adresse postale renseignée dans la configuration de Paheko qui fait foi plutôt que celle dans le plugin (qui sert en revanche pour les reçus).</p>
|
||||
<p>Pensez à mettre une image en signature (cela sert pour les reçus fiscaux), cela se passe dans la configuration de Paheko, onglet personnalisation. Il est préférable d'avoir un fond transparent.
|
||||
</p>
|
||||
<br>
|
||||
<p>- Pour créer un reçu sur une cotisation, il faut pour le moment que cette cotisation soit attachée à la compta.</p>
|
||||
<p>- Pour créer un reçu fiscal, l'interface est pour l'instant la même que pour créer une facture/devis. Les champs correspondent mais les noms/labels autour ne sont pas adaptés. Vous pouvez de toutes façons tester, et si le résultat est pas celui attendu, remodifiez derrière :)</p>
|
||||
<p>- La partie « Droit à la réduction d'impôt » peut faire peur, elle correspond simplement à des cases du cerfa pour les reçus fiscaux. Je n'y connais pas grand chose pour le moment, je ne peux vous éclairer davantage, il va falloir se retourner vers légifrance :(</p>
|
||||
<br>
|
||||
<p>Hésitez pas à faire des retours, proposer meilleures explications, ou quoi, vous pouvez venir en causer soit <a href="https://gitlab.com/ramoloss/Paheko-plugin-facturation">sur mon gitlab</a>, soit sur l'adresse d'entraide de Paheko. Si vous êtes un peu dev, le code est un peu cracra mais j'espère que ça vous repoussera pas trop à le bidouiller :)</p>
|
||||
|
||||
<p>Pensez à mettre une image en signature (cela sert pour les reçus fiscaux), cela se passe dans la {link href="!config/custom.php" label="configuration de Paheko, onglet personnalisation"}. Il est préférable d'avoir un fond transparent.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Pour créer un reçu sur une cotisation, il vaut mieux utiliser le module {link href="!config/ext" label="Reçu de paiement"} intégré à Paheko.</li>
|
||||
<li>Pour créer un reçu fiscal, il vaut mieux utiliser le module {link href="!config/ext" label="Reçus fiscaux"} intégré à Paheko.</li>
|
||||
</ul>
|
||||
<p>N'hésitez pas à faire des retours, proposer de meilleures explications dans le forum d'entraide de Paheko. Si vous êtes un peu dev, le code est un peu cracra mais j'espère que ça ne vous repoussera pas trop à le bidouiller :)</p>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
|
||||
{include file="_foot.tpl"}
|
|
@ -18,18 +18,6 @@
|
|||
<dt>Code postal</dt>
|
||||
<dd>{$client.code_postal|escape|rtrim|nl2br}</dd>
|
||||
|
||||
<dt>SIREN/SIRET</dt>
|
||||
<dd>
|
||||
{if empty($client->siret)}
|
||||
<em>(Non renseigné)</em>
|
||||
{else}
|
||||
<?php
|
||||
$siret = implode(' ', str_split($client->siret, 3));
|
||||
?>
|
||||
{$siret|escape|trim}
|
||||
{/if}
|
||||
</dd>
|
||||
|
||||
<dt>Adresse électronique</dt>
|
||||
<dd>
|
||||
{if empty($client.email)}
|
||||
|
@ -44,7 +32,7 @@
|
|||
{if empty($client.telephone)}
|
||||
<em>(Non renseigné)</em>
|
||||
{else}
|
||||
<a href="tel:{$client.telephone}">{$client.telephone|format_phone_number}</a>
|
||||
<a href="tel:{$client.telephone}">{$client.telephone}</a>
|
||||
{/if}
|
||||
</dd>
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
{input type="text" name="adresse" label="Adresse" required=true source=$client}
|
||||
{input type="text" name="code_postal" label="Code postal" required=true source=$client}
|
||||
{input type="text" name="ville" label="Ville" required=true source=$client}
|
||||
{input type="text" name="siret" label="SIREN/SIRET" source=$client}
|
||||
{input type="tel" name="telephone" label="Téléphone" source=$client}
|
||||
{input type="email" name="email" label="Adresse e-mail" source=$client}
|
||||
</dl>
|
||||
|
|
|
@ -13,12 +13,6 @@
|
|||
{if $key == 'id' || $key == 'nom'}
|
||||
<?php continue; ?>
|
||||
{/if}
|
||||
{if $key == 'siret'}
|
||||
<?php
|
||||
if (null === $value) { $value = ""; }
|
||||
$value = implode(' ', str_split($value, 3));
|
||||
?>
|
||||
{/if}
|
||||
<td>{$value}</td>
|
||||
{/foreach}
|
||||
<td class="actions">
|
||||
|
@ -58,7 +52,6 @@
|
|||
{input type="text" name="adresse" label="Adresse" required=true}
|
||||
{input type="text" name="code_postal" label="Code postal" required=true}
|
||||
{input type="text" name="ville" label="Ville" required=true}
|
||||
{input type="text" name="siret" label="SIREN/SIRET"}
|
||||
{input type="tel" name="telephone" label="Téléphone"}
|
||||
{input type="email" name="email" label="Adresse e-mail"}
|
||||
</dl>
|
||||
|
|
|
@ -27,44 +27,33 @@
|
|||
{input type="text" name="ville_asso" source=$conf label="Ville"}
|
||||
</dl>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Objet</legend>
|
||||
<dl>
|
||||
<dt><label>L'objet (but) de l'association doit tenir sur 3 lignes, chaque ligne pouvant accueillir un maximum de 100 caractères.</label><b title="(Champ obligatoire)">obligatoire pour reçus fiscaux</b></dt>
|
||||
{input type="text" name="objet_0" source=$conf label="Ligne 1" maxlength=95}
|
||||
{input type="text" name="objet_1" source=$conf label="Ligne 2" maxlength=95}
|
||||
{input type="text" name="objet_2" source=$conf label="Ligne 3" maxlength=95}
|
||||
</dl>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Objet</legend>
|
||||
<dl>
|
||||
<dt><label>L'objet (but) de l'association doit tenir sur 3 lignes, chaque ligne pouvant accueillir un maximum de 100 caractères.</label><b title="(Champ obligatoire)">obligatoire pour reçus fiscaux</b></dt>
|
||||
{input type="text" name="objet_0" source=$conf label="Ligne 1" maxlength=95}
|
||||
{input type="text" name="objet_1" source=$conf label="Ligne 2" maxlength=95}
|
||||
{input type="text" name="objet_2" source=$conf label="Ligne 3" maxlength=95}
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Droit à la réduction d'impôt</legend>
|
||||
<dl>
|
||||
<dt><label>Articles concernés par l'association :</label> <b title="(Champ obligatoire)">obligatoire pour reçus fiscaux</b></dt>
|
||||
{input type="checkbox" name="droit_art200" value="1" source=$conf label="Article 200"}
|
||||
{input type="checkbox" name="droit_art238bis" value="1" source=$conf label="Article 238 bis"}
|
||||
{input type="checkbox" name="droit_art885_0VbisA" value="1" source=$conf label="Article 885-0V bis A"}
|
||||
</dl>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Droit à la réduction d'impôt</legend>
|
||||
<dl>
|
||||
<dt><label>Articles concernés par l'association :</label> <b title="(Champ obligatoire)">obligatoire pour reçus fiscaux</b></dt>
|
||||
{input type="checkbox" name="droit_art200" value="1" source=$conf label="Article 200"}
|
||||
{input type="checkbox" name="droit_art238bis" value="1" source=$conf label="Article 238 bis"}
|
||||
{input type="checkbox" name="droit_art885_0VbisA" value="1" source=$conf label="Article 885-0V bis A"}
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Factures</legend>
|
||||
<dl>
|
||||
{input type="checkbox" name="logo" value="1" source=$conf label="Imprimer le logo de l'association"}
|
||||
{input type="textarea" class="full-width" rows="5" name="footer" source=$conf label="Pied de document — informations légales" required=true}
|
||||
{input type="textarea" class="full-width" rows="10" name="footer" source=$conf label="Pied de document — informations légales" required=true}
|
||||
</dl>
|
||||
<fieldset>
|
||||
<legend>
|
||||
Choisir les champs à faire figurer sur la facture
|
||||
</legend>
|
||||
<dl>
|
||||
{input type="select" name="adresse_client" label="Adresse" required=true options=$champsPaheko source=$conf}
|
||||
{input type="select" name="code_postal_client" label="Code postal" required=true options=$champsPaheko source=$conf}
|
||||
{input type="select" name="ville_client" label="Ville" required=true options=$champsPaheko source=$conf}
|
||||
</dl>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
</tbody>
|
||||
</table>
|
||||
{$list->getHTMLPagination()|raw}
|
||||
|
||||
<p class="help">
|
||||
Export de la liste :
|
||||
|
|
34
upgrade.php
34
upgrade.php
|
@ -209,37 +209,3 @@ if (version_compare($old_version, '0.8.1', '<'))
|
|||
{
|
||||
$plugin->unregisterSignal('menu.item');
|
||||
}
|
||||
|
||||
// 0.8.5 Ajout champs SIREN/SIRET à la table clients
|
||||
|
||||
if (version_compare($old_version, '0.8.5', '<'))
|
||||
{
|
||||
$db->exec(<<<EOT
|
||||
CREATE TABLE IF NOT EXISTS plugin_facturation_clients_tmp
|
||||
(
|
||||
id INTEGER PRIMARY KEY,
|
||||
nom TEXT NOT NULL,
|
||||
adresse TEXT NOT NULL,
|
||||
code_postal TEXT NOT NULL,
|
||||
ville TEXT NOT NULL,
|
||||
siret TEXT,
|
||||
date_creation TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date_creation) IS NOT NULL AND date(date_creation) = date_creation),
|
||||
telephone TEXT,
|
||||
email TEXT
|
||||
);
|
||||
EOT
|
||||
);
|
||||
// copier les clients dans la table temporaire en ajoutant un siret fictif
|
||||
$sql = 'SELECT * FROM plugin_facturation_clients';
|
||||
foreach ($db->iterate($sql) as $client)
|
||||
{
|
||||
$db->insert('plugin_facturation_clients_tmp', $client);
|
||||
}
|
||||
// remplacer l'ancienne table par la nouvelle
|
||||
$db->exec(<<<EOT
|
||||
DROP TABLE plugin_facturation_clients;
|
||||
ALTER TABLE plugin_facturation_clients_tmp RENAME TO plugin_facturation_clients;
|
||||
EOT
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue