Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
4aafa3f44f | |||
aff20099aa | |||
950a6b8b2c | |||
4ee3f65d0a | |||
060802a43d | |||
f63f3b6ecd | |||
6e2ee31670 | |||
38494a1a85 | |||
6248904bd8 | |||
f6eef8897e | |||
201682f4d7 | |||
77180a38ff | |||
16daac2e24 | |||
46d0c838ae | |||
da713cc06d | |||
72999b9fc6 | |||
f321e83e20 | |||
57e6ad09f9 | |||
2ecbac159a | |||
3d5af4ebb0 | |||
f93bb57906 | |||
128e538431 | |||
bd1f541bc0 | |||
dc7f944ead | |||
1d4f17ead6 | |||
b0a44b85c6 | |||
26f4514fd0 | |||
e2065bdb37 | |||
fa519a9567 | |||
39bde25d24 | |||
b2e63c0383 | |||
b5dc9d0efa | |||
c9300fe943 | |||
b6bb4fd80d | |||
438e9c6116 | |||
e22ea9ca8b | |||
80a5245bc8 | |||
a187babbac | |||
93c1daeffd | |||
64ca9a6aba | |||
42e893f8d3 | |||
6c3af00f16 | |||
bf45ffd223 | |||
d258b21267 | |||
cff7b57a41 | |||
9de9e10987 | |||
b9e8115af4 | |||
2454883ffc | |||
0ed03eb362 | |||
|
ac8c79bf9e | ||
|
c4d9b8d38b | ||
|
d32c589a4a | ||
|
899bf02775 | ||
|
235f8ceeed | ||
|
161659acfb | ||
|
3537314762 | ||
|
4aaed6f3c2 | ||
|
b08572e6d2 | ||
|
97404460ee | ||
|
b74226871e | ||
|
868174e6ab | ||
|
00ae3cd89e | ||
|
56f90fad60 | ||
|
b2c1f2adea | ||
|
afedc83193 | ||
|
8a10dcfab3 | ||
|
4619ac0ffd | ||
|
5f87e96df4 | ||
|
3635f5a5da | ||
|
fd7adc2a58 | ||
|
c3da50df04 | ||
|
3f92e849fa | ||
|
0694d1fb51 | ||
|
3ae4b3f177 | ||
|
727d8b11f2 | ||
|
af7b3a9eaf | ||
|
5de9d9fa97 |
49
CHANGELOG
49
CHANGELOG
@ -1,4 +1,51 @@
|
|||||||
0.6.2 :
|
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
|
||||||
|
- 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
|
||||||
|
- Nettoyage du code et factorization des facture_{ajouter,modifier}.php
|
||||||
|
|
||||||
|
0.7.3 :
|
||||||
|
- Règle le problème de formulaire bloqué que je croyais avoir résolu la dernière fois :)
|
||||||
|
|
||||||
|
0.7.2 :
|
||||||
|
- Petite correction du moyen de paiement qui n'était pas retenu à cause d'un doublon dans le formulaire.
|
||||||
|
|
||||||
|
0.7.1 :
|
||||||
|
- Ajout d'une case dans la config pour choisir si les factures sont TTC ou HT
|
||||||
|
- Le formulaire de document était cassé à cause d'un champs obligatoire invisible
|
||||||
|
|
||||||
|
0.7.0 :
|
||||||
- Modernisation des formulaires, de la fiche client
|
- Modernisation des formulaires, de la fiche client
|
||||||
- Liste dynamiques des documents et des clients + export CSV/ODS
|
- Liste dynamiques des documents et des clients + export CSV/ODS
|
||||||
- Numérotation automatique des documents
|
- Numérotation automatique des documents
|
||||||
|
2
LICENCE
2
LICENCE
@ -1,4 +1,4 @@
|
|||||||
Plugin Facturation pour Garradin
|
Plugin Facturation pour Paheko
|
||||||
Copyright (C) 2019 zou
|
Copyright (C) 2019 zou
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
75
README.md
75
README.md
@ -1,53 +1,49 @@
|
|||||||
# Plugin Facturation pour Garradin
|
# Plugin Facturation pour Paheko (ex Garradin)
|
||||||
|
|
||||||
Plugin de facturation pour le logiciel de gestion d'association Garradin ( https://garradin.eu/ - https://fossil.kd2.org/garradin ).
|
Plugin de facturation pour le logiciel de gestion d'association Paheko
|
||||||
Source : https://gitlab.com/ramoloss/garradin-plugin-facturation
|
( https://paheko.eu/ - https://fossil.kd2.org/paheko ).
|
||||||
|
|
||||||
|
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 :
|
## 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.
|
Vous pouvez télécharger l'archive .tar.gz depuis la page des
|
||||||
|
[releases](https://git.roflcopter.fr/lesanges/paheko-plugin-facturation/releases),
|
||||||
### Anciennes versions (<0.6)
|
supprimer le numéro de version du nom de l'archive puis la placer dans
|
||||||
|
le dossier plugins de Paheko.
|
||||||
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 :
|
## Fonctionnalités :
|
||||||
- Créer et gérer une base de client·es
|
- 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
|
- Créer et modifier des factures et devis adressés aux membres de l'association ou des client·es ajouté·es
|
||||||
- Créer des reçus fiscaux pour des dons et génération du cerfa correspondant
|
- (obsolète) Créer des reçus fiscaux pour des dons et génération du CERFA correspondant
|
||||||
- Créer des reçus sur des cotisations
|
- (obsolète) Créer des reçus sur des cotisations
|
||||||
- Génération des documents (facture et devis) en PDF grâce à la librairie mPDF
|
- Génération des documents (facture et devis) en PDF
|
||||||
- Liste les documents associés sur la fiche d'un·e client·e
|
- Liste les documents associés sur la fiche d'un·e client·e
|
||||||
- Permet de définir le statut du document sur reglée
|
- Permet de définir le statut du document à « réglé »
|
||||||
- **Configuration** :
|
- **Configuration** :
|
||||||
- Possibilité d'ajouter un numéro RNA et SIRET de l'association si elle en possède (apparait alors sur les documents)
|
- 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)
|
- 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)
|
||||||
- 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)
|
- 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 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
|
- 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
|
||||||
- Informations relatives au cerfa pour les reçus fiscaux
|
- (obsolète) Informations relatives au CERFA pour les reçus fiscaux
|
||||||
- Image qui set de signature sur le cerfa
|
- (obsolète) Image qui sert 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 :
|
## 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
|
- Ajout des champs Référence, Prix unitaire, Quantité sur les documents
|
||||||
- Actions sur liste de client·es (exporter, supprimer)
|
- Actions sur liste de client·es (exporter, supprimer)
|
||||||
- Afficher/filtrer les documents par statuts réglé/archivé
|
- Afficher/filtrer les documents par statuts réglé/archivé
|
||||||
@ -57,15 +53,12 @@ Note : pour le moment, les actions sur la liste des clients à cocher ne fonctio
|
|||||||
- Gestion TVA ?
|
- Gestion TVA ?
|
||||||
- Un devis ne devrait pas pouvoir être réglé
|
- 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 ?
|
- 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
|
- Opérations de paiements dans la compta liés à une facture
|
||||||
- Gestion de produits
|
- Gestion de produits
|
||||||
|
|
||||||
|
|
||||||
Le plugin nécessite l'extension PHP mbstring.
|
Le plugin nécessite l'extension PHP mbstring.
|
||||||
|
|
||||||
## Inclus les bibliothèques suivantes :
|
## (???) Inclus les bibliothèques suivantes :
|
||||||
|
|
||||||
- Composer :
|
- Composer :
|
||||||
https://getcomposer.org/
|
https://getcomposer.org/
|
||||||
|
355
admin/_facture_common.php
Normal file
355
admin/_facture_common.php
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
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 {
|
||||||
|
$target = ($target === 'new' ? true:false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
||||||
|
|
||||||
|
use Paheko\DB;
|
||||||
|
use stdClass;
|
||||||
|
use const \Paheko\Plugin\Facturation\PATTERNS_LIST;
|
||||||
|
|
||||||
|
$db = DB::getInstance();
|
||||||
|
|
||||||
|
$step = false;
|
||||||
|
$radio = $liste = $designations = $prix = [];
|
||||||
|
|
||||||
|
$fields = $facture->recu_fields;
|
||||||
|
|
||||||
|
$moyens_paiement = $facture->listMoyensPaiement(true);
|
||||||
|
|
||||||
|
$tpl->assign('moyens_paiement', $moyens_paiement);
|
||||||
|
$tpl->assign('moyen_paiement', f('moyen_paiement') ?: 'ES');
|
||||||
|
$tpl->assign('moyen_paiement_cerfa', f('moyen_paiement_cerfa') ?: 'ES');
|
||||||
|
|
||||||
|
$tpl->assign('formes_don', array('1' => 'Acte authentique',
|
||||||
|
'2' => 'Acte sous seing privé',
|
||||||
|
'3' => 'Don manuel',
|
||||||
|
'4' => 'Autres'));
|
||||||
|
$tpl->assign('natures_don', array('1' => 'Numéraire',
|
||||||
|
'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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$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'),
|
||||||
|
'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)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
$data['contenu'][$k]['prix'] = Utils::moneyToInteger(f('prix')[$k]);
|
||||||
|
$data['toto'] += Utils::moneyToInteger(f('prix')[$k]);
|
||||||
|
}
|
||||||
|
$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');
|
||||||
|
$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);
|
||||||
|
|
||||||
|
$form->runIf(f('select_cotis') && !$form->hasErrors(),
|
||||||
|
function () use ($step)
|
||||||
|
{
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
|
||||||
|
$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'] ]
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (UserException $e)
|
||||||
|
{
|
||||||
|
$form->addError($e->getMessage());
|
||||||
|
}
|
||||||
|
}, 'add_cotis_2');
|
||||||
|
|
||||||
|
if (! $form->hasErrors())
|
||||||
|
{
|
||||||
|
if ($step)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$liste = $facture->getCotis((int)f('membre_cotis'));
|
||||||
|
}
|
||||||
|
catch (UserException $e)
|
||||||
|
{
|
||||||
|
$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
|
||||||
|
|
||||||
|
if ($target)
|
||||||
|
{
|
||||||
|
$doc = null;
|
||||||
|
|
||||||
|
if (qg('copy') !== null && $f = $facture->get((int)qg('copy'))) {
|
||||||
|
$doc = (array) $f;
|
||||||
|
// Copié depuis facture_modifier.php
|
||||||
|
$doc['type'] = $f->type_facture;
|
||||||
|
$doc['numero_facture'] = '';
|
||||||
|
$doc['base_receveur'] = $f->receveur_membre ? 'membre' : 'client';
|
||||||
|
$doc['client'] = $f->receveur_id;
|
||||||
|
$doc['membre'] = $f->receveur_id;
|
||||||
|
|
||||||
|
if ( $f->type_facture == CERFA ) {
|
||||||
|
$doc['forme_don'] = $f->contenu['forme'];
|
||||||
|
$doc['nature_don'] = $f->contenu['nature'];
|
||||||
|
$doc['texte_don'] = $f->contenu['texte'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type du document:
|
||||||
|
$type = qg('t') ? (int) qg('t') : null;
|
||||||
|
|
||||||
|
// Si le type est défini dans l'URL
|
||||||
|
if (in_array($type, [DEVIS, FACT, CERFA, COTIS], true))
|
||||||
|
{
|
||||||
|
$radio['type'] = $type;
|
||||||
|
} // ... s'il a été rempli dans le formulaire envoyé
|
||||||
|
elseif (null !== f('type'))
|
||||||
|
{
|
||||||
|
$radio['type'] = f('type');
|
||||||
|
} // ... s'il est défini dans le document copié
|
||||||
|
elseif (isset($doc['type'])) {
|
||||||
|
$radio['type'] = $doc['type'];
|
||||||
|
} // ... ou par défaut
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$radio['type'] = FACT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$doc['moyen_paiement'] = $f->moyen_paiement;
|
||||||
|
$doc['type'] = $f->type_facture;
|
||||||
|
$doc['numero_facture'] = $f->numero;
|
||||||
|
$doc['reglee'] = $f->reglee;
|
||||||
|
$doc['base_receveur'] = $f->receveur_membre?'membre':'client';
|
||||||
|
$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:---
|
||||||
|
$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;
|
||||||
|
$doc['forme_don'] = $f->contenu['forme'];
|
||||||
|
$doc['nature_don'] = $f->contenu['nature'];
|
||||||
|
$doc['texte_don'] = $f->contenu['texte'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$radio['type'] = f('type')??$doc['type'];
|
||||||
|
}
|
||||||
|
$tpl->assign('types_details', $facture->types);
|
||||||
|
|
||||||
|
$tpl->assign('client_id', f('client') ?: -1);
|
||||||
|
$tpl->assign('membre_id', f('membre') ?: -1);
|
||||||
|
|
||||||
|
|
||||||
|
// C'est un peu l'équivalent de form_field, mais j'avais écrit ça avant
|
||||||
|
// et oulala, c'est un peu complexe, faudrait réfléchir keskivomieux
|
||||||
|
$from_user = false;
|
||||||
|
if (in_array($radio['type'], [DEVIS, FACT]))
|
||||||
|
{
|
||||||
|
if (($d = f('designation')) && ($p = f('prix')) && implode($d))
|
||||||
|
{
|
||||||
|
foreach($d as $k=>$v)
|
||||||
|
{
|
||||||
|
if (empty($v) && empty($p[$k]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$designations[] = $v;
|
||||||
|
$prix[] = $p[$k];
|
||||||
|
}
|
||||||
|
$from_user = true;
|
||||||
|
}
|
||||||
|
else if (!empty($doc['contenu'])) {
|
||||||
|
foreach($doc['contenu'] as $k=>$v)
|
||||||
|
{
|
||||||
|
if (empty($v['designation']) && empty($v['prix']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$designations[] = $v['designation'];
|
||||||
|
$prix[] = $v['prix'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
$designations = ['Exemple'];
|
||||||
|
$prix = [250];
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$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('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')]);
|
||||||
|
|
||||||
|
if ($target) {
|
||||||
|
$tpl->display(PLUGIN_ROOT . '/templates/facture_ajouter.tpl');
|
||||||
|
} else {
|
||||||
|
$tpl->display(PLUGIN_ROOT . '/templates/facture_modifier.tpl');
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin\Plugin\Facturation;
|
namespace Paheko\Plugin\Facturation;
|
||||||
|
|
||||||
use Garradin\Config;
|
use Paheko\Config;
|
||||||
use Garradin\Utils;
|
use Paheko\Utils;
|
||||||
|
|
||||||
define('DEVIS', 0);
|
define('DEVIS', 0);
|
||||||
define('FACT', 1);
|
define('FACT', 1);
|
||||||
@ -25,11 +25,11 @@ const PATTERNS_LIST = [
|
|||||||
$client = new Client;
|
$client = new Client;
|
||||||
$facture = new Facture;
|
$facture = new Facture;
|
||||||
|
|
||||||
$tpl->assign('www_url', \Garradin\WWW_URL);
|
$tpl->assign('www_url', \Paheko\WWW_URL);
|
||||||
$tpl->assign('f_obj', $facture);
|
$tpl->assign('f_obj', $facture);
|
||||||
$tpl->assign('plugin_url', Utils::plugin_url());
|
|
||||||
|
|
||||||
$identite = (string) Config::getInstance()->get('champ_identite');
|
|
||||||
|
$identite = implode(',', \Paheko\Users\DynamicFields::getNameFields());
|
||||||
|
|
||||||
$tpl->register_function('money_fac', function (array $params)
|
$tpl->register_function('money_fac', function (array $params)
|
||||||
{
|
{
|
||||||
@ -59,7 +59,9 @@ $tpl->register_function('money_fac', function (array $params)
|
|||||||
$current_value = Utils::money_format($current_value, ',', '');
|
$current_value = Utils::money_format($current_value, ',', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null !== $current_value) {
|
||||||
$current_value = htmlspecialchars($current_value, ENT_QUOTES, 'UTF-8');
|
$current_value = htmlspecialchars($current_value, ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
$currency = Config::getInstance()->get('monnaie');
|
$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);
|
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);
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
f(['id' => 'required|numeric']);
|
||||||
|
|
||||||
$id = (int) qg('id');
|
$id = (int) qg('id');
|
||||||
|
|
46
admin/client_modifier.php
Normal file
46
admin/client_modifier.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Paheko;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
||||||
|
|
||||||
|
f(['id' => 'required|numeric']);
|
||||||
|
$id = (int) qg('id');
|
||||||
|
|
||||||
|
$c = $client->get($id);
|
||||||
|
|
||||||
|
if (!$c)
|
||||||
|
{
|
||||||
|
throw new UserException("Ce client n'existe pas.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$form->runIf(f('save') && !$form->hasErrors(),
|
||||||
|
function () use ($client, $id, $form)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$r = $client->edit($id,[
|
||||||
|
'nom' => f('nom'),
|
||||||
|
'adresse' => f('adresse'),
|
||||||
|
'code_postal' => f('code_postal'),
|
||||||
|
'ville' => f('ville'),
|
||||||
|
'siret' => f('siret'),
|
||||||
|
'telephone' => f('telephone'),
|
||||||
|
'email' => f('email'),
|
||||||
|
'nom_contact' => f('nom_contact'),
|
||||||
|
'note' => f('note')
|
||||||
|
]);
|
||||||
|
|
||||||
|
$r ? Utils::redirect(PLUGIN_ADMIN_URL . 'client.php?id='.(int)$id):'';
|
||||||
|
}
|
||||||
|
catch (UserException $e)
|
||||||
|
{
|
||||||
|
$form->addError($e->getMessage());
|
||||||
|
}
|
||||||
|
}, 'edit_client');
|
||||||
|
|
||||||
|
|
||||||
|
$tpl->assign('client', $c);
|
||||||
|
$tpl->display(PLUGIN_ROOT . '/templates/client_modifier.tpl');
|
@ -1,12 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
f(['id' => 'required|numeric']);
|
||||||
|
|
||||||
$id = (int) qg('id');
|
$id = (int) qg('id');
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ $csrf_key = 'delete_client_'.$c->id;
|
|||||||
|
|
||||||
$form->runIf('delete', function () use ($client, $c) {
|
$form->runIf('delete', function () use ($client, $c) {
|
||||||
$client->delete($c->id);
|
$client->delete($c->id);
|
||||||
}, $csrf_key, PLUGIN_URL . 'clients.php');
|
}, $csrf_key, PLUGIN_ADMIN_URL . 'clients.php');
|
||||||
|
|
||||||
$tpl->assign('deletable', $client->isDeletable($id));
|
$tpl->assign('deletable', $client->isDeletable($id));
|
||||||
$tpl->assign('client', $c);
|
$tpl->assign('client', $c);
|
39
admin/clients.php
Normal file
39
admin/clients.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Paheko;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
||||||
|
|
||||||
|
$form->runIf(f('add') && !$form->hasErrors(),
|
||||||
|
function () use ($client, $form)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$id = $client->add([
|
||||||
|
'nom' => f('nom'),
|
||||||
|
'adresse' => f('adresse'),
|
||||||
|
'code_postal' => f('code_postal'),
|
||||||
|
'ville' => f('ville'),
|
||||||
|
'siret' => f('siret'),
|
||||||
|
'telephone' => f('telephone'),
|
||||||
|
'email' => f('email'),
|
||||||
|
'nom_contact' => f('nom_contact'),
|
||||||
|
'note' => f('note')
|
||||||
|
]);
|
||||||
|
|
||||||
|
$id ? Utils::redirect(PLUGIN_ADMIN_URL . 'client.php?id='.(int)$id):'';
|
||||||
|
}
|
||||||
|
catch (UserException $e)
|
||||||
|
{
|
||||||
|
$form->addError($e->getMessage());
|
||||||
|
}
|
||||||
|
}, 'add_client');
|
||||||
|
|
||||||
|
$list = $client->list();
|
||||||
|
$list->loadFromQueryString();
|
||||||
|
|
||||||
|
$tpl->assign(compact('list'));
|
||||||
|
|
||||||
|
$tpl->display(PLUGIN_ROOT . '/templates/clients.tpl');
|
43
admin/config.php
Normal file
43
admin/config.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?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')));
|
||||||
|
$plugin->setConfigProperty('ttc', (bool) f('ttc'));
|
||||||
|
|
||||||
|
$plugin->setConfigProperty('numero_rue_asso', trim(f('numero_rue_asso')));
|
||||||
|
$plugin->setConfigProperty('rue_asso', trim(f('rue_asso')));
|
||||||
|
$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('adresse_client', f('adresse_client'));
|
||||||
|
$plugin->setConfigProperty('code_postal_client', f('code_postal_client'));
|
||||||
|
$plugin->setConfigProperty('ville_client', f('ville_client'));
|
||||||
|
|
||||||
|
$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();
|
||||||
|
}, 'facturation_config', PLUGIN_ADMIN_URL . 'config.php?ok');
|
||||||
|
|
||||||
|
|
||||||
|
$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');
|
@ -1,16 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
||||||
|
|
||||||
use Garradin\Membres;
|
use Paheko\Users\Users;
|
||||||
|
|
||||||
$membres = new Membres;
|
$users = new Users;
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
f(['id' => 'required|numeric']);
|
||||||
$id = (int) qg('id');
|
$id = (int) qg('id');
|
||||||
|
|
||||||
$f = $facture->get($id);
|
$f = $facture->get($id);
|
9
admin/facture_ajouter.php
Normal file
9
admin/facture_ajouter.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Paheko;
|
||||||
|
|
||||||
|
$target = 'new';
|
||||||
|
$csrf_key = 'ajout_facture';
|
||||||
|
$require_number = $plugin->getConfig('pattern') ? false : true;
|
||||||
|
|
||||||
|
require __DIR__ .'/_facture_common.php';
|
9
admin/facture_modifier.php
Normal file
9
admin/facture_modifier.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Paheko;
|
||||||
|
|
||||||
|
$target = 'edit';
|
||||||
|
$csrf_key = 'modifier_facture';
|
||||||
|
$require_number = true;
|
||||||
|
|
||||||
|
require __DIR__ .'/_facture_common.php';
|
34
admin/facture_supprimer.php
Normal file
34
admin/facture_supprimer.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Paheko;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
||||||
|
|
||||||
|
f(['id' => 'required|numeric']);
|
||||||
|
|
||||||
|
$id = (int) qg('id');
|
||||||
|
|
||||||
|
$f = $facture->get($id);
|
||||||
|
|
||||||
|
if (!$client)
|
||||||
|
{
|
||||||
|
throw new UserException("Ce document n'existe pas.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$form->runIf(f('delete') && !$form->hasErrors(),
|
||||||
|
function () use ($facture, $f, $form)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$facture->delete($f->id);
|
||||||
|
Utils::redirect(PLUGIN_ADMIN_URL . 'index.php');
|
||||||
|
}
|
||||||
|
catch (UserException $e)
|
||||||
|
{
|
||||||
|
$form->addError($e->getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$tpl->assign('doc', $f);
|
||||||
|
$tpl->display(PLUGIN_ROOT . '/templates/facture_supprimer.tpl');
|
@ -1,7 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
|
if ($plugin->needUpgrade()) {
|
||||||
|
$plugin->upgrade();
|
||||||
|
}
|
||||||
require_once __DIR__ . '/_inc.php';
|
require_once __DIR__ . '/_inc.php';
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
||||||
@ -9,6 +12,7 @@ $session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
|||||||
|
|
||||||
$list = $facture->list();
|
$list = $facture->list();
|
||||||
$list->loadFromQueryString();
|
$list->loadFromQueryString();
|
||||||
|
$list->setPageSize(50);
|
||||||
|
|
||||||
$tpl->assign(compact('list'));
|
$tpl->assign(compact('list'));
|
||||||
|
|
@ -1,13 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
require_once __DIR__ . '/_inc.php';
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
||||||
$membres = new Membres;
|
$users = new Users\Users;
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
f(['id' => 'required|numeric']);
|
||||||
$id = (int) qg('id');
|
$id = (int) qg('id');
|
||||||
|
$sign_tag = UserTemplate\Functions::signature();
|
||||||
|
|
||||||
// Vérification que le document existe
|
// Vérification que le document existe
|
||||||
if (!$f = $facture->get($id))
|
if (!$f = $facture->get($id))
|
||||||
@ -22,20 +23,37 @@ try
|
|||||||
{
|
{
|
||||||
if ($f->receveur_membre)
|
if ($f->receveur_membre)
|
||||||
{
|
{
|
||||||
$c = $membres->get($f->receveur_id);
|
$c = $users->get($f->receveur_id);
|
||||||
$c->identite = $c->$identite;
|
// 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; }
|
||||||
|
|
||||||
foreach(['ville','code_postal','adresse'] as $v)
|
foreach(['ville','code_postal','adresse'] as $v)
|
||||||
{
|
{
|
||||||
if($c->$v == '')
|
if($c->$v == '')
|
||||||
{
|
{
|
||||||
$c->$v = '[A RENSEIGNER DANS LA FICHE MEMBRE]';
|
$c->$v = '[À RENSEIGNER DANS LA FICHE MEMBRE]';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$c = $client->get($f->receveur_id);
|
$c = $client->get($f->receveur_id);
|
||||||
$c->identite = $c->nom;
|
$nom_client = $c->nom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(UserException $e)
|
catch(UserException $e)
|
||||||
@ -60,40 +78,80 @@ if ($f->type_facture != CERFA)
|
|||||||
{
|
{
|
||||||
case FACT:
|
case FACT:
|
||||||
$doc = 'Facture n° '. $f->numero;
|
$doc = 'Facture n° '. $f->numero;
|
||||||
|
$txtemis = $doc . " - Émise le " . $emission;
|
||||||
|
$txtdest = "Adressée à :";
|
||||||
break;
|
break;
|
||||||
case DEVIS:
|
case DEVIS:
|
||||||
$doc = 'Devis n° '. $f->numero;
|
$doc = 'Devis n° '. $f->numero;
|
||||||
|
$txtemis = $doc . " - Émis le " . $emission;
|
||||||
|
$txtdest = "Adressé à :";
|
||||||
break;
|
break;
|
||||||
case COTIS:
|
case COTIS:
|
||||||
$doc = 'Reçu de cotisation n° '. $f->numero;
|
$doc = 'Reçu de cotisation n° '. $f->numero;
|
||||||
|
$txtemis = $doc . " - Émis le " . $emission;
|
||||||
|
$txtdest = "Adressé à :";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// utiliser l'adresse configurée dans le plugin sinon celle de l'asso sinon rien !
|
||||||
|
if ($plugin->getConfig('rue_asso') != null &&
|
||||||
|
$plugin->getConfig('cp_asso') != null &&
|
||||||
|
$plugin->getConfig('ville_asso') != null)
|
||||||
|
{
|
||||||
|
$adresse =
|
||||||
|
(($plugin->getConfig('numero_rue_asso') != null) ? $plugin->getConfig('numero_rue_asso') . " " : "") .
|
||||||
|
$plugin->getConfig('rue_asso') . "<br>" .
|
||||||
|
$plugin->getConfig('cp_asso') . " " .
|
||||||
|
$plugin->getConfig('ville_asso');
|
||||||
|
}
|
||||||
|
else if ($config->get('org_address') != null)
|
||||||
|
{
|
||||||
|
$adresse = str_replace("\n", '<br>', $config->get('org_address'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$adresse = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$logo='';
|
||||||
|
if ($plugin->getConfig('logo')) {
|
||||||
|
$logo = '<img id="logo" src="' . $config->fileURL('logo') . '" />';
|
||||||
|
}
|
||||||
$asso =
|
$asso =
|
||||||
// 'Émis par :<br><br>'.
|
// 'Émis par :<br><br>'.
|
||||||
'<b>'.$config->get('nom_asso')."</b><br>".
|
'<b>'.$config->get('org_name')."</b><br>".
|
||||||
str_replace("\n", '<br>', $config->get('adresse_asso'))."<br>".
|
$adresse ."<br>".
|
||||||
(($t = $plugin->getConfig('rna_asso'))?"RNA : $t<br>":'').
|
(($t = $plugin->getConfig('rna_asso'))?"RNA : $t<br>":'').
|
||||||
(($t = $plugin->getConfig('siret_asso'))?"SIRET : $t<br>":'').
|
(($t = $plugin->getConfig('siret_asso'))?"SIRET : " . implode(' ', str_split($t, 3)) . "<br>":'').
|
||||||
(($t = $config->get('email_asso'))?"Email : $t<br>":'').
|
(($t = $config->get('email_asso'))?"Email : $t<br>":'').
|
||||||
(($t = $config->get('site_asso'))?"Site web : $t<br>":'');
|
(($t = $config->get('site_asso'))?"Site web : $t<br>":'');
|
||||||
|
|
||||||
$receveur =
|
$receveur =
|
||||||
'Adressé à :<br><br>'.
|
$txtdest.'<br>'.
|
||||||
'<b>'.$c->identite.'</b><br>'.
|
'<b>'.$nom_client.'</b><br>'.
|
||||||
|
(($t = $f->nom_contact)?"Contact : $t<br>":'').
|
||||||
$c->adresse."<br>".
|
$c->adresse."<br>".
|
||||||
$c->code_postal.' '.$c->ville."<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->email)?"Email : $t<br>":'').
|
||||||
(($t = $c->telephone)?"Tel : $t<br>":'');
|
(($t = $c->telephone)?"Tel : $t<br>":'');
|
||||||
|
if ($f->type_facture == FACT) {
|
||||||
|
$receveur .=
|
||||||
|
(($t = $f->numero_commande)?"Commande N° : $t<br>":'').
|
||||||
|
(($t = $f->reference_acheteur)?"Référence : $t<br>":'');
|
||||||
|
}
|
||||||
$total = Utils::money_format($f->total, ',', ' ');
|
$total = Utils::money_format($f->total, ',', ' ');
|
||||||
|
|
||||||
// Devis et facture
|
// Devis et facture
|
||||||
if ($f->type_facture != COTIS)
|
if ($f->type_facture != COTIS)
|
||||||
{
|
{
|
||||||
$echeance = ($f->type_facture?'Échéance de paiement':'Échéance du devis')." : ".$echeance;
|
$echeance = ($f->type_facture?'Échéance de paiement':'Échéance du devis')." : ".$echeance;
|
||||||
$reglee = !$f->reglee?'Cette facture est en attente de règlement.':'Cette facture a été reglée.';
|
if ($f->type_facture == FACT) {
|
||||||
$footer = str_replace("\n", '<br>', $plugin->getConfig('footer'));
|
$reglee = !$f->reglee?'Cette facture est en attente de règlement.':'Cette facture a été réglée.';
|
||||||
|
} else {
|
||||||
|
$reglee = "";
|
||||||
|
}
|
||||||
|
$footer = str_replace("\n", '<br>', $plugin->getConfig('footer') ?? '[Pied de page à configurer]');
|
||||||
|
$ttc = $plugin->getConfig('ttc') ? 'TTC':'HT';
|
||||||
|
|
||||||
// Génération du contenu de la facture
|
// Génération du contenu de la facture
|
||||||
ob_start();
|
ob_start();
|
||||||
@ -132,8 +190,8 @@ EOF;
|
|||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td><h3>Total</h3>Net à payer</td>
|
<td><b>Total</b><br>Net à payer</td>
|
||||||
<td><b>$total €</b><br>(HT)</td>
|
<td><b>$total €</b><br>({$ttc})</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
@ -144,12 +202,17 @@ EOF;
|
|||||||
$echeance <br>
|
$echeance <br>
|
||||||
$reglee
|
$reglee
|
||||||
Moyen de paiement : $moyen_paiement
|
Moyen de paiement : $moyen_paiement
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
$footer
|
$footer
|
||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
EOF;
|
EOF;
|
||||||
|
if ($f->type_facture == DEVIS) {
|
||||||
|
echo <<<EOF
|
||||||
|
<p><b>Bon pour accord, date et signature<b></p>
|
||||||
|
EOF;
|
||||||
|
}
|
||||||
|
|
||||||
$content = ob_get_clean();
|
$content = ob_get_clean();
|
||||||
|
|
||||||
@ -200,7 +263,8 @@ EOF;
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>${doc}_${emission}</title>
|
<meta charset="UTF-8">
|
||||||
|
<title>{$doc}_{$emission}</title>
|
||||||
<style>
|
<style>
|
||||||
@page {
|
@page {
|
||||||
size: A4 portrait;
|
size: A4 portrait;
|
||||||
@ -240,6 +304,13 @@ EOF;
|
|||||||
width: 40%;
|
width: 40%;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
.adressage td#logo {
|
||||||
|
width: 20%;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.adressage img#logo {
|
||||||
|
height : 3cm;
|
||||||
|
}
|
||||||
|
|
||||||
.contenuTexte {
|
.contenuTexte {
|
||||||
padding: 0 6mm;
|
padding: 0 6mm;
|
||||||
@ -286,11 +357,12 @@ EOF;
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p class="titre">
|
<p class="titre">
|
||||||
$doc - Émis le $emission
|
$txtemis
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table class="adressage">
|
<table class="adressage">
|
||||||
<tr>
|
<tr>
|
||||||
|
<td id="logo">$logo</td>
|
||||||
<td>$asso</td>
|
<td>$asso</td>
|
||||||
<td>$receveur</td>
|
<td>$receveur</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -312,7 +384,7 @@ elseif ($f->type_facture == CERFA)
|
|||||||
$libelles = $facture->listTextesCerfa(false);
|
$libelles = $facture->listTextesCerfa(false);
|
||||||
|
|
||||||
$t['numero'] = $f->numero;
|
$t['numero'] = $f->numero;
|
||||||
$t['nom_asso'] = $config->get('nom_asso');
|
$t['org_name'] = $config->get('org_name');
|
||||||
$t['n_rue_asso'] = $plugin->getConfig('numero_rue_asso');
|
$t['n_rue_asso'] = $plugin->getConfig('numero_rue_asso');
|
||||||
$t['rue_asso'] = $plugin->getConfig('rue_asso');
|
$t['rue_asso'] = $plugin->getConfig('rue_asso');
|
||||||
$t['cp_asso'] = $plugin->getConfig('cp_asso');
|
$t['cp_asso'] = $plugin->getConfig('cp_asso');
|
||||||
@ -321,7 +393,7 @@ elseif ($f->type_facture == CERFA)
|
|||||||
$t['objet1'] = $plugin->getConfig('objet_1');
|
$t['objet1'] = $plugin->getConfig('objet_1');
|
||||||
$t['objet2'] = $plugin->getConfig('objet_2');
|
$t['objet2'] = $plugin->getConfig('objet_2');
|
||||||
|
|
||||||
$t['nom'] = $c->identite;
|
$t['nom'] = $nom_client;
|
||||||
$t['adresse'] = $c->adresse;
|
$t['adresse'] = $c->adresse;
|
||||||
$t['cp'] = $c->code_postal;
|
$t['cp'] = $c->code_postal;
|
||||||
$t['ville'] = $c->ville;
|
$t['ville'] = $c->ville;
|
||||||
@ -329,9 +401,9 @@ elseif ($f->type_facture == CERFA)
|
|||||||
$t['total_lettre'] = numfmt_create('fr_FR', \NumberFormatter::SPELLOUT)->format($f->total/100). ' euros';
|
$t['total_lettre'] = numfmt_create('fr_FR', \NumberFormatter::SPELLOUT)->format($f->total/100). ' euros';
|
||||||
|
|
||||||
|
|
||||||
$t['d'] = utf8_decode($f->date_emission->format('d'));
|
$t['d'] = ($f->date_emission->format('d'));
|
||||||
$t['m'] = utf8_decode($f->date_emission->format('m'));
|
$t['m'] = ($f->date_emission->format('m'));
|
||||||
$t['Y'] = utf8_decode($f->date_emission->format('Y'));
|
$t['Y'] = ($f->date_emission->format('Y'));
|
||||||
|
|
||||||
$t['forme'] = $f->contenu['forme'];
|
$t['forme'] = $f->contenu['forme'];
|
||||||
$t['nature'] = $f->contenu['nature'];
|
$t['nature'] = $f->contenu['nature'];
|
||||||
@ -385,16 +457,17 @@ elseif ($f->type_facture == CERFA)
|
|||||||
$t['pos'] = 'left: 115.2mm;';
|
$t['pos'] = 'left: 115.2mm;';
|
||||||
}
|
}
|
||||||
|
|
||||||
$t['d2'] = utf8_decode($f->date_echeance->format('d'));
|
$t['d2'] = ($f->date_echeance->format('d'));
|
||||||
$t['m2'] = utf8_decode($f->date_echeance->format('m'));
|
$t['m2'] = ($f->date_echeance->format('m'));
|
||||||
$t['Y2'] = utf8_decode($f->date_echeance->format('Y'));
|
$t['Y2'] = ($f->date_echeance->format('Y'));
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
echo <<<EOF
|
echo <<<EOF
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>${doc}_${emission}</title>
|
<meta charset="UTF-8">
|
||||||
|
<title>{$doc}_{$emission}</title>
|
||||||
<style>
|
<style>
|
||||||
@page {
|
@page {
|
||||||
size: A4 portrait;
|
size: A4 portrait;
|
||||||
@ -425,11 +498,11 @@ elseif ($f->type_facture == CERFA)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#p1 {
|
#p1 {
|
||||||
background-image: url('${url}p/facturation/cerfa-1.png');
|
background-image: url('{$url}p/facturation/cerfa-1.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
#p2 {
|
#p2 {
|
||||||
background-image: url('${url}p/facturation/cerfa-2.png');
|
background-image: url('{$url}p/facturation/cerfa-2.png');
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,46 +510,46 @@ elseif ($f->type_facture == CERFA)
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="page" id="p1">
|
<div class="page" id="p1">
|
||||||
<div style="top: 10mm; left: 170mm;">${t['numero']}</div>
|
<div style="top: 10mm; left: 170mm;">{$t['numero']}</div>
|
||||||
|
|
||||||
<div style="top: 35mm; left: 20mm;">${t['nom_asso']}</div>
|
<div style="top: 35mm; left: 20mm;">{$t['org_name']}</div>
|
||||||
<div style="top: 46mm; left: 20mm;">${t['n_rue_asso']}</div>
|
<div style="top: 46mm; left: 20mm;">{$t['n_rue_asso']}</div>
|
||||||
<div style="top: 46mm; left: 40mm;">${t['rue_asso']}</div>
|
<div style="top: 46mm; left: 40mm;">{$t['rue_asso']}</div>
|
||||||
<div style="top: 51.5mm; left: 37mm;">${t['cp_asso']}</div>
|
<div style="top: 51.5mm; left: 37mm;">{$t['cp_asso']}</div>
|
||||||
<div style="top: 51.5mm; left: 75mm;">${t['ville_asso']}</div>
|
<div style="top: 51.5mm; left: 75mm;">{$t['ville_asso']}</div>
|
||||||
|
|
||||||
<div style="top: 62mm; left: 18mm;">${t['objet0']}</div>
|
<div style="top: 62mm; left: 18mm;">{$t['objet0']}</div>
|
||||||
<div style="top: 66.5mm; left: 18mm;">${t['objet1']}</div>
|
<div style="top: 66.5mm; left: 18mm;">{$t['objet1']}</div>
|
||||||
<div style="top: 70.8mm; left: 18mm;">${t['objet2']}</div>
|
<div style="top: 70.8mm; left: 18mm;">{$t['objet2']}</div>
|
||||||
|
|
||||||
<div style="top: 128.5mm; left: 15mm;">X</div>
|
<div style="top: 128.5mm; left: 15mm;">X</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page" id="p2">
|
<div class="page" id="p2">
|
||||||
<div style="top: 18mm; left: 18mm;">${t['nom']}</div>
|
<div style="top: 18mm; left: 18mm;">{$t['nom']}</div>
|
||||||
<div style="top: 32mm; left: 18mm;">${t['adresse']}</div>
|
<div style="top: 32mm; left: 18mm;">{$t['adresse']}</div>
|
||||||
<div style="top: 37mm; left: 40mm;">${t['cp']}</div>
|
<div style="top: 37mm; left: 40mm;">{$t['cp']}</div>
|
||||||
<div style="top: 37mm; left: 80mm;">${t['ville']}</div>
|
<div style="top: 37mm; left: 80mm;">{$t['ville']}</div>
|
||||||
|
|
||||||
<div style="top: 63mm; left: 87mm;">${t['total']}</div>
|
<div style="top: 63mm; left: 87mm;">{$t['total']}</div>
|
||||||
<div style="top: 73mm; left: 58mm;">${t['total_lettre']}</div>
|
<div style="top: 73mm; left: 58mm;">{$t['total_lettre']}</div>
|
||||||
|
|
||||||
<div style="top: 82mm; left: 69mm;">${t['d']}</div>
|
<div style="top: 82mm; left: 69mm;">{$t['d']}</div>
|
||||||
<div style="top: 82mm; left: 82mm;">${t['m']}</div>
|
<div style="top: 82mm; left: 82mm;">{$t['m']}</div>
|
||||||
<div style="top: 82mm; left: 99mm;">${t['Y']}</div>
|
<div style="top: 82mm; left: 99mm;">{$t['Y']}</div>
|
||||||
|
|
||||||
<div style="top: 96mm; left: 53mm;">${t['art200']}</div>
|
<div style="top: 96mm; left: 53mm;">{$t['art200']}</div>
|
||||||
<div style="top: 96mm; left: 103mm;">${t['art238']}</div>
|
<div style="top: 96mm; left: 103mm;">{$t['art238']}</div>
|
||||||
<div style="top: 96mm; left: 153.0mm;">${t['art885']}</div>
|
<div style="top: 96mm; left: 153.0mm;">{$t['art885']}</div>
|
||||||
<div style="top: 113mm; ${t['frm']}">X</div>
|
<div style="top: 113mm; {$t['frm']}">X</div>
|
||||||
<div style="top: 136mm; ${t['nat']}">X</div>
|
<div style="top: 136mm; {$t['nat']}">X</div>
|
||||||
<div style="top: 142mm; left: 25mm;">${t['texte']}</div>
|
<div style="top: 142mm; left: 25mm;">{$t['texte']}</div>
|
||||||
<div style="top: 158.2mm; ${t['pos']}">X</div>
|
<div style="top: 158.2mm; {$t['pos']}">X</div>
|
||||||
|
|
||||||
<div style="top: 239mm; left: 139mm;">${t['d2']}</div>
|
<div style="top: 239mm; left: 139mm;">{$t['d2']}</div>
|
||||||
<div style="top: 239mm; left: 148mm;">${t['m2']}</div>
|
<div style="top: 239mm; left: 148mm;">{$t['m2']}</div>
|
||||||
<div style="top: 239mm; left: 156mm;">${t['Y2']}</div>
|
<div style="top: 239mm; left: 156mm;">{$t['Y2']}</div>
|
||||||
|
|
||||||
<div style="top: 243mm; left: 137mm;"><img src="${url}plugin/facturation/sign.png" style="width: 50mm;"/></div>
|
<div style="top: 243mm; left: 137mm;">{$sign_tag}</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -491,7 +564,7 @@ if(qg('d') !== null)
|
|||||||
{
|
{
|
||||||
$filename = 'Print';
|
$filename = 'Print';
|
||||||
if (preg_match('!<title>(.*)</title>!U', $html, $match)) {
|
if (preg_match('!<title>(.*)</title>!U', $html, $match)) {
|
||||||
$filename = trim($match[1]);
|
$filename = str_replace(" ", "_", trim($match[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-type: application/pdf');
|
header('Content-type: application/pdf');
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"footer": "[EXEMPLE]\nAssociation exonérée des impôts commerciaux\nEn cas de retard de paiement, indemnité forfaitaire légale pour frais de recouvrement : 40,00 €\n[Coordonnées bancaires]\nAssociation enregistrée en préfecture de XXX au numéro YYY",
|
"footer": "[EXEMPLE]\nAssociation exonérée des impôts commerciaux\nEn cas de retard de paiement, indemnité forfaitaire légale pour frais de recouvrement : 40,00 €\n[Coordonnées bancaires]\nAssociation enregistrée en préfecture de XXX au numéro YYY",
|
||||||
"pattern": "%{type}-%{year}-%{ynumber}",
|
"pattern": "%{type}-%{year}-%{ynumber}",
|
||||||
|
"ttc": false,
|
||||||
"validate_cp": true
|
"validate_cp": true
|
||||||
}
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB |
@ -10,7 +10,10 @@ CREATE TABLE IF NOT EXISTS plugin_facturation_factures (
|
|||||||
archivee INTEGER DEFAULT 0, -- bool
|
archivee INTEGER DEFAULT 0, -- bool
|
||||||
moyen_paiement TEXT NOT NULL,
|
moyen_paiement TEXT NOT NULL,
|
||||||
contenu TEXT NOT NULL,
|
contenu TEXT NOT NULL,
|
||||||
total INTEGER DEFAULT 0
|
total INTEGER DEFAULT 0,
|
||||||
|
nom_contact TEXT,
|
||||||
|
numero_commande TEXT,
|
||||||
|
reference_acheteur TEXT
|
||||||
|
|
||||||
-- FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code)
|
-- FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code)
|
||||||
);
|
);
|
||||||
@ -21,10 +24,12 @@ CREATE TABLE IF NOT EXISTS plugin_facturation_clients (
|
|||||||
adresse TEXT NOT NULL,
|
adresse TEXT NOT NULL,
|
||||||
code_postal TEXT NOT NULL,
|
code_postal TEXT NOT NULL,
|
||||||
ville TEXT NOT NULL,
|
ville TEXT NOT NULL,
|
||||||
-- date_creation INTEGER 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), -- Date d\'inscription
|
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,
|
telephone TEXT,
|
||||||
email TEXT
|
email TEXT,
|
||||||
|
nom_contact TEXT,
|
||||||
|
note TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -43,6 +48,7 @@ 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 ('TI', 'TIP');
|
||||||
INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('VI', 'Virement');
|
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 ('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');
|
INSERT OR IGNORE INTO plugin_facturation_paiement (code, nom) VALUES ('AU', 'Autre');
|
||||||
|
|
||||||
-- Modif DD -- ajout de la table des textes associés aux CERFA
|
-- Modif DD -- ajout de la table des textes associés aux CERFA
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
nom="Facturation"
|
|
||||||
description="Permet d'éditer des factures, devis et reçus à ses membres ainsi qu'à une base de clients supplémentaire."
|
|
||||||
auteur="zou"
|
|
||||||
url="https://gitlab.com/ramoloss/garradin-plugin-facturation/"
|
|
||||||
version="0.6.2"
|
|
||||||
menu=1
|
|
||||||
config=1
|
|
||||||
min_version="1.1.0"
|
|
@ -1,10 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
use Garradin\Entities\Files\File;
|
use Paheko\Entities\Files\File;
|
||||||
|
use Paheko\Plugin\Facturation\Facture;
|
||||||
|
|
||||||
$db = DB::getInstance();
|
$db = DB::getInstance();
|
||||||
|
|
||||||
$db->import(dirname(__FILE__) . "/data/schema.sql");
|
$db->import(dirname(__FILE__) . "/data/schema.sql");
|
||||||
|
|
||||||
$path = __DIR__.'/data/default_sign.png';
|
|
||||||
$png = (new File)->createAndStore('skel/plugin/facturation','sign.png', $path, null);
|
|
@ -1,12 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin\Plugin\Facturation;
|
namespace Paheko\Plugin\Facturation;
|
||||||
|
|
||||||
use Garradin\DB;
|
use Paheko\DB;
|
||||||
use Garradin\DynamicList;
|
use Paheko\DynamicList;
|
||||||
use Garradin\Plugin;
|
use Paheko\Entities\Plugin;
|
||||||
use Garradin\UserException;
|
use Paheko\UserException;
|
||||||
use Garradin\Utils;
|
use Paheko\Utils;
|
||||||
|
|
||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
@ -15,8 +15,11 @@ class Client
|
|||||||
'adresse',
|
'adresse',
|
||||||
'code_postal',
|
'code_postal',
|
||||||
'ville',
|
'ville',
|
||||||
|
'siret',
|
||||||
'telephone',
|
'telephone',
|
||||||
'email'
|
'email',
|
||||||
|
'nom_contact',
|
||||||
|
'note'
|
||||||
];
|
];
|
||||||
|
|
||||||
private $config = [
|
private $config = [
|
||||||
@ -39,7 +42,7 @@ class Client
|
|||||||
{
|
{
|
||||||
$data[$key] = trim($data[$key]);
|
$data[$key] = trim($data[$key]);
|
||||||
|
|
||||||
if($data[$key] == '' && ($key != 'telephone' && $key != 'email'))
|
if($data[$key] == '' && ! in_array($key, ['siret', 'telephone', 'email', 'nom_contact', 'note']))
|
||||||
{
|
{
|
||||||
throw new UserException('Le champs '.$key.' doit être renseigné.');
|
throw new UserException('Le champs '.$key.' doit être renseigné.');
|
||||||
}
|
}
|
||||||
@ -55,6 +58,10 @@ class Client
|
|||||||
throw new UserException('Le code postal est erroné.');
|
throw new UserException('Le code postal est erroné.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elseif ($key == "siret")
|
||||||
|
{
|
||||||
|
$data[$key] = str_replace(' ', '', $data[$key]);
|
||||||
|
}
|
||||||
elseif ($key == "telephone")
|
elseif ($key == "telephone")
|
||||||
{
|
{
|
||||||
$data[$key] = Utils::normalizePhoneNumber($data[$key]);
|
$data[$key] = Utils::normalizePhoneNumber($data[$key]);
|
||||||
@ -84,7 +91,7 @@ class Client
|
|||||||
|
|
||||||
if($this->config['unique_client_name'] && isset($data['nom']) && $db->test('plugin_facturation_clients', 'nom = ? COLLATE NOCASE', $data['nom']))
|
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, hors ce champ doit être unique à chaque client.');
|
throw new UserException('La valeur du champ nom est déjà utilisée, or ce champ doit être unique à chaque client.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->insert('plugin_facturation_clients', $data);
|
$db->insert('plugin_facturation_clients', $data);
|
||||||
@ -122,12 +129,21 @@ class Client
|
|||||||
'ville' => [
|
'ville' => [
|
||||||
'label' => 'Ville',
|
'label' => 'Ville',
|
||||||
],
|
],
|
||||||
|
'siret' => [
|
||||||
|
'label' => 'SIRET',
|
||||||
|
],
|
||||||
'telephone' => [
|
'telephone' => [
|
||||||
'label' => 'Téléphone',
|
'label' => 'Téléphone',
|
||||||
],
|
],
|
||||||
'email' => [
|
'email' => [
|
||||||
'label' => 'E-Mail',
|
'label' => 'E-Mail',
|
||||||
],
|
],
|
||||||
|
'nom_contact' => [
|
||||||
|
'label' => 'Contact',
|
||||||
|
],
|
||||||
|
'note' => [
|
||||||
|
'label' => 'Note',
|
||||||
|
],
|
||||||
'nb_documents' => [
|
'nb_documents' => [
|
||||||
'label' => 'Nombre de documents',
|
'label' => 'Nombre de documents',
|
||||||
'select' => '(SELECT COUNT(*) FROM plugin_facturation_factures WHERE receveur_id = c.id)',
|
'select' => '(SELECT COUNT(*) FROM plugin_facturation_factures WHERE receveur_id = c.id)',
|
||||||
@ -150,7 +166,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))
|
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, hors ce champ doit être unique à chaque client.');
|
throw new UserException('La valeur du champ nom est déjà utilisée, or ce champ doit être unique à chaque client.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $db->update('plugin_facturation_clients', $data, $db->where('id', (int)$id));
|
return $db->update('plugin_facturation_clients', $data, $db->where('id', (int)$id));
|
||||||
|
112
lib/Facture.php
112
lib/Facture.php
@ -1,14 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin\Plugin\Facturation;
|
namespace Paheko\Plugin\Facturation;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Garradin\Config;
|
use Paheko\Config;
|
||||||
use Garradin\DB;
|
use Paheko\DB;
|
||||||
use Garradin\DynamicList;
|
use Paheko\DynamicList;
|
||||||
use Garradin\UserException;
|
use Paheko\UserException;
|
||||||
use Garradin\Utils;
|
use Paheko\Utils;
|
||||||
use Garradin\Services\Services_User;
|
use Paheko\Services\Services_User;
|
||||||
|
|
||||||
class Facture
|
class Facture
|
||||||
{
|
{
|
||||||
@ -30,7 +30,10 @@ class Facture
|
|||||||
'archivee',
|
'archivee',
|
||||||
'moyen_paiement',
|
'moyen_paiement',
|
||||||
'contenu',
|
'contenu',
|
||||||
'total'
|
'total',
|
||||||
|
'nom_contact',
|
||||||
|
'numero_commande',
|
||||||
|
'reference_acheteur'
|
||||||
];
|
];
|
||||||
|
|
||||||
public $types = [
|
public $types = [
|
||||||
@ -44,16 +47,6 @@ class Facture
|
|||||||
'accounts' => [],
|
'accounts' => [],
|
||||||
'label' => 'Facture',
|
'label' => 'Facture',
|
||||||
'help' => ''],
|
'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()
|
public function __construct()
|
||||||
@ -72,10 +65,10 @@ class Facture
|
|||||||
throw new UserException("Clé inattendue : $k.");
|
throw new UserException("Clé inattendue : $k.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!is_array($data)){
|
if(!is_array($data) && null !== $data){
|
||||||
$datas[$k] = trim($data);
|
$datas[$k] = trim($data);
|
||||||
}
|
}
|
||||||
if ($datas[$k] === '' && $k != 'numero')
|
if ($datas[$k] === '' && ! in_array($k, ['numero', 'nom_contact', 'numero_commande', 'reference_acheteur']))
|
||||||
{
|
{
|
||||||
throw new UserException("La valeur de $k est vide");
|
throw new UserException("La valeur de $k est vide");
|
||||||
}
|
}
|
||||||
@ -144,10 +137,13 @@ class Facture
|
|||||||
unset($datas[$k]['prix']);
|
unset($datas[$k]['prix']);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
elseif (empty($r['prix']))
|
elseif (! is_numeric($r['prix']) && empty($r['prix']))
|
||||||
{
|
{
|
||||||
$datas[$k]['prix'] = 0;
|
$datas[$k]['prix'] = 0;
|
||||||
}
|
}
|
||||||
|
elseif (empty($r['designation'])) {
|
||||||
|
throw new UserException("Une au moins des désignations est absente.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_int($r['prix']))
|
if (!is_int($r['prix']))
|
||||||
{
|
{
|
||||||
@ -157,7 +153,7 @@ class Facture
|
|||||||
$total += $r['prix'];
|
$total += $r['prix'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if($fac && !$total)
|
if ($fac && count($datas['contenu']) == 0)
|
||||||
{
|
{
|
||||||
throw new UserException("Toutes les désignations/prix sont vides.");
|
throw new UserException("Toutes les désignations/prix sont vides.");
|
||||||
}
|
}
|
||||||
@ -203,7 +199,7 @@ class Facture
|
|||||||
|
|
||||||
if ($db->test('plugin_facturation_factures', 'numero = ? COLLATE NOCASE', $data['numero']))
|
if ($db->test('plugin_facturation_factures', 'numero = ? COLLATE NOCASE', $data['numero']))
|
||||||
{
|
{
|
||||||
throw new UserException('Un document avec ce numéro existe déjà, hors le numéro doit être unique.');
|
throw new UserException('Le numéro de document doit être unique, or il existe déjà un document avec le numéro ' . $data['numero']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->insert('plugin_facturation_factures', $data);
|
$db->insert('plugin_facturation_factures', $data);
|
||||||
@ -242,15 +238,40 @@ class Facture
|
|||||||
$year = $date->format('Y');
|
$year = $date->format('Y');
|
||||||
$y = $date->format('y');
|
$y = $date->format('y');
|
||||||
|
|
||||||
// On récupère le nombre de documents pour cette année
|
// Garantir l'unicité du numéro
|
||||||
// vu qu'on vient d'ajouter un document, celui-ci est bien le dernier numéro
|
$db = DB::getInstance();
|
||||||
$ynumber = DB::getInstance()->count('plugin_facturation_factures', 'strftime(\'%Y\', date_emission) = ?', (string) $year);
|
$sql = sprintf('SELECT numero FROM plugin_facturation_factures');
|
||||||
|
$numeros = array_column($db->get($sql), 'numero');
|
||||||
|
|
||||||
|
//sélectionner les numéros qui correspondent au pattern
|
||||||
|
$selpattern = preg_replace('/%(\d+)?\{(ynumber|id)\}/', '', $pattern);
|
||||||
|
$data = compact('type', 't', 'year', 'y');
|
||||||
|
$prefixe = preg_replace_callback('/%(\d+)?\{([a-z]+)\}/', function ($match) use ($data) {
|
||||||
|
$v = (string) $data[$match[2]];
|
||||||
|
$type = ctype_digit($v) ? 'd' : 's';
|
||||||
|
return sprintf('%' . $match[1] . $type, $v);
|
||||||
|
}, $selpattern);
|
||||||
|
$modele = '/^' . $prefixe . '\d+$/';
|
||||||
|
$numeros_filtres = array_filter($numeros, function($elem) use ($modele) {
|
||||||
|
return preg_match($modele, $elem);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
// extraire le numéro d'ordre
|
||||||
|
$rangs = array_map(function($elem) use($prefixe) {
|
||||||
|
return (int) substr($elem, strlen($prefixe));
|
||||||
|
}, array_values($numeros_filtres));
|
||||||
|
sort($rangs);
|
||||||
|
if (empty($rangs)) {
|
||||||
|
$ynumber = 1;
|
||||||
|
} else {
|
||||||
|
$ynumber = end($rangs) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fabriquer le numéro selon le pattern
|
||||||
$data = compact('type', 't', 'year', 'y', 'ynumber', 'id');
|
$data = compact('type', 't', 'year', 'y', 'ynumber', 'id');
|
||||||
|
|
||||||
return preg_replace_callback('/%(\d+)?\{([a-z]+)\}/', function ($match) use ($data) {
|
return preg_replace_callback('/%(\d+)?\{([a-z]+)\}/', function ($match) use ($data) {
|
||||||
$v = $data[$match[2]];
|
$v = (string) $data[$match[2]];
|
||||||
$type = ctype_digit($data[$match[2]]) ? 'd' : 's';
|
$type = ctype_digit($v) ? 'd' : 's';
|
||||||
return sprintf('%' . $match[1] . $type, $v);
|
return sprintf('%' . $match[1] . $type, $v);
|
||||||
}, $pattern);
|
}, $pattern);
|
||||||
}
|
}
|
||||||
@ -299,7 +320,15 @@ class Facture
|
|||||||
|
|
||||||
public function list(): DynamicList
|
public function list(): DynamicList
|
||||||
{
|
{
|
||||||
$id_field = Config::getInstance()->champ_identite;
|
$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 = [
|
$columns = [
|
||||||
// Sélectionner cette colonne, mais ne pas la mettre dans la liste des colonnes
|
// Sélectionner cette colonne, mais ne pas la mettre dans la liste des colonnes
|
||||||
@ -324,15 +353,18 @@ class Facture
|
|||||||
],
|
],
|
||||||
'receveur' => [
|
'receveur' => [
|
||||||
'label' => 'Receveur',
|
'label' => 'Receveur',
|
||||||
'select' => sprintf('CASE WHEN receveur_membre THEN u.%s ELSE c.nom END', $id_field),
|
// 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),
|
||||||
],
|
],
|
||||||
'receveur_adresse' => [
|
'receveur_adresse' => [
|
||||||
'label' => 'Son adresse',
|
// l'adresse peut être redéfinie dans la configuration du plugin
|
||||||
'select' => 'CASE WHEN receveur_membre THEN u.adresse ELSE c.adresse END',
|
'label' => 'Adresse',
|
||||||
|
'select' => sprintf('CASE WHEN receveur_membre THEN %s ELSE c.adresse END', $adresse),
|
||||||
],
|
],
|
||||||
'receveur_ville' => [
|
'receveur_ville' => [
|
||||||
'label' => 'Sa ville',
|
// la ville peut être redéfinie dans la configuration du plugin
|
||||||
'select' => 'CASE WHEN receveur_membre THEN u.ville ELSE c.ville END',
|
'label' => 'Ville',
|
||||||
|
'select' => sprintf('CASE WHEN receveur_membre THEN %s ELSE c.ville END', $ville),
|
||||||
],
|
],
|
||||||
'date_emission' => [
|
'date_emission' => [
|
||||||
'label' => 'Émission',
|
'label' => 'Émission',
|
||||||
@ -361,11 +393,12 @@ class Facture
|
|||||||
|
|
||||||
$tables = 'plugin_facturation_factures AS f
|
$tables = 'plugin_facturation_factures AS f
|
||||||
INNER JOIN plugin_facturation_paiement AS mp ON mp.code = f.moyen_paiement
|
INNER JOIN plugin_facturation_paiement AS mp ON mp.code = f.moyen_paiement
|
||||||
LEFT JOIN membres AS u ON f.receveur_membre = 1 AND u.id = f.receveur_id
|
LEFT JOIN users AS u ON f.receveur_membre = 1 AND u.id = f.receveur_id
|
||||||
LEFT JOIN plugin_facturation_clients AS c ON f.receveur_membre = 0 AND c.id = f.receveur_id';
|
LEFT JOIN plugin_facturation_clients AS c ON f.receveur_membre = 0 AND c.id = f.receveur_id';
|
||||||
|
|
||||||
$list = new DynamicList($columns, $tables);
|
$list = new DynamicList($columns, $tables);
|
||||||
$list->orderBy('date_emission', true);
|
$list->orderBy('date_emission', true);
|
||||||
|
$list->setCount('COUNT(f.id)');
|
||||||
|
|
||||||
$currency = Config::getInstance()->monnaie;
|
$currency = Config::getInstance()->monnaie;
|
||||||
|
|
||||||
@ -395,7 +428,6 @@ class Facture
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$list->setPageSize(1000);
|
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +439,7 @@ class Facture
|
|||||||
|
|
||||||
if(isset($data['numero']) && $db->test('plugin_facturation_factures', 'numero = ? COLLATE NOCASE AND id != ?', $data['numero'], (int)$id))
|
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à, hors le numéro doit être unique.');
|
throw new UserException('Un document avec ce numéro existe déjà, or le numéro doit être unique.');
|
||||||
}
|
}
|
||||||
return $db->update('plugin_facturation_factures', $data, $db->where('id', (int)$id));
|
return $db->update('plugin_facturation_factures', $data, $db->where('id', (int)$id));
|
||||||
}
|
}
|
||||||
@ -425,7 +457,7 @@ class Facture
|
|||||||
}
|
}
|
||||||
else // Si c'est un membre de l'asso
|
else // Si c'est un membre de l'asso
|
||||||
{
|
{
|
||||||
throw new UserException("Woopsie, g pô encore implémenté l'usage des membres de l'asso comme clients");
|
throw new UserException("Woopsie, g pô encore implémenté l'usage des users de l'asso comme clients");
|
||||||
}
|
}
|
||||||
|
|
||||||
$r = (array)DB::getInstance()->get('SELECT *, strftime(\'%s\', date_emission) AS date_emission,
|
$r = (array)DB::getInstance()->get('SELECT *, strftime(\'%s\', date_emission) AS date_emission,
|
||||||
@ -457,7 +489,7 @@ class Facture
|
|||||||
}
|
}
|
||||||
else // Si c'est un membre de l'asso
|
else // Si c'est un membre de l'asso
|
||||||
{
|
{
|
||||||
throw new UserException("Woopsie, g pô encore implémenté l'usage des membres de l'asso comme clients");
|
throw new UserException("Woopsie, g pô encore implémenté l'usage des users de l'asso comme clients");
|
||||||
}
|
}
|
||||||
|
|
||||||
return DB::getInstance()->test('plugin_facturation_factures', 'receveur_membre = ? AND receveur_id = ?', $base, $id);
|
return DB::getInstance()->test('plugin_facturation_factures', 'receveur_membre = ? AND receveur_id = ?', $base, $id);
|
||||||
|
9
plugin.ini
Normal file
9
plugin.ini
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name="Facturation"
|
||||||
|
description="Permet d'éditer des factures et devis à 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.15"
|
||||||
|
menu=true
|
||||||
|
restrict_section="accounting"
|
||||||
|
restrict_level="read"
|
||||||
|
min_version="1.3.0"
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
@ -3,7 +3,7 @@
|
|||||||
<form method="post" action="{$self_url}">
|
<form method="post" action="{$self_url}">
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Type d'écriture</legend>
|
<legend>Type de document</legend>
|
||||||
<dl>
|
<dl>
|
||||||
{foreach from=$types_details item="type"}
|
{foreach from=$types_details item="type"}
|
||||||
<dd class="radio-btn">
|
<dd class="radio-btn">
|
||||||
@ -24,15 +24,13 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend data-types="t0">Créer un devis</legend>
|
<legend data-types="t0">Créer un devis</legend>
|
||||||
<legend data-types="t1">Créer une facture</legend>
|
<legend data-types="t1">Créer une facture</legend>
|
||||||
<legend data-types="t2">Créer un reçu fiscal</legend>
|
|
||||||
<legend data-types="t3">Créer un reçu de cotisation</legend>
|
|
||||||
<dl>
|
<dl>
|
||||||
|
|
||||||
{input type="text" name="numero_facture" maxlength=12 label="Numéro du document" required=$require_number source=$doc}
|
{input type="text" name="numero_facture" maxlength=18 label="Numéro du document" required=$require_number source=$doc}
|
||||||
|
|
||||||
<dd class="help">
|
<dd class="help">
|
||||||
{if $require_number}
|
{if $require_number}
|
||||||
Chaque document doit comporter un numéro unique délivré chronologiquement et de façon continue. Il faut que le système adopté par l'association garantisse que deux factures émises la même année ne peuvent pas porter le même numéro.
|
Chaque document doit comporter un numéro unique délivré chronologiquement et de façon continue. Il faut que le système adopté par l'association garantisse que deux factures émises la même année ne puissent pas porter le même numéro.
|
||||||
{else}
|
{else}
|
||||||
Laisser vide pour qu'un numéro soit automatiquement affecté au format <code>{$number_pattern}</code>.
|
Laisser vide pour qu'un numéro soit automatiquement affecté au format <code>{$number_pattern}</code>.
|
||||||
{/if}
|
{/if}
|
||||||
@ -59,7 +57,7 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset data-types="t0 t1 t2">
|
<fieldset data-types="t0 t1 t2">
|
||||||
<legend>Client</legend>
|
<legend>Destinataire</legend>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><label>Document adressé à :</label></dt>
|
<dt><label>Document adressé à :</label></dt>
|
||||||
@ -72,23 +70,35 @@
|
|||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="type_membre">
|
<dl class="type_membre">
|
||||||
{input type="select" name="membre" label="Membre" options=$membres required=1 source=$doc}
|
{input type="select" name="membre" label="Membre" options=$users required=1 source=$doc default_empty="— Choisir un membre —"}
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
{if !empty($clients)}
|
{if !empty($clients)}
|
||||||
<dl class="type_client">
|
<dl class="type_client">
|
||||||
{input type="select" name="client" label="Client" options=$clients required=1 class="type_client" source=$doc}
|
{input type="select" name="client" label="Client" options=$clients required=1 class="type_client" source=$doc default_empty="— Choisir un client —"}
|
||||||
</dl>
|
</dl>
|
||||||
{else}
|
{else}
|
||||||
<input type="hidden" name="base_receveur" value="membre" />
|
<input type="hidden" name="base_receveur" value="membre" />
|
||||||
{/if}
|
{/if}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset data-types="t0 t1">
|
||||||
|
<legend>Autres informations</legend>
|
||||||
|
{input type="text" name="nom_contact" label="Nom du contact" source=$doc}
|
||||||
|
<div class="hidden">
|
||||||
|
{input type="select" name="contact_list" options=$contacts}
|
||||||
|
</div>
|
||||||
|
<div data-types="t1">
|
||||||
|
{input type="text" name="numero_commande" label="Numéro de commande" source=$doc}
|
||||||
|
{input type="text" name="reference_acheteur" label="Référence acheteur" source=$doc}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<fieldset data-types="t0 t1">
|
<fieldset data-types="t0 t1">
|
||||||
<legend>Contenu</legend>
|
<legend>Contenu</legend>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
{input type="select" name="moyen_paiement" required=1 label="Moyen de paiement" source=$doc options=$moyens_paiement default="ES"}
|
{input type="select" name="moyen_paiement" required=1 label="Moyen de paiement" source=$doc options=$moyens_paiement default=$doc.moyen_paiement}
|
||||||
|
|
||||||
<dt><label for="f_contenu">Contenu du document</label><dt>
|
<dt><label for="f_contenu">Contenu du document</label><dt>
|
||||||
<dd>
|
<dd>
|
||||||
@ -143,11 +153,11 @@
|
|||||||
<fieldset data-types="t2">
|
<fieldset data-types="t2">
|
||||||
<legend>Contenu</legend>
|
<legend>Contenu</legend>
|
||||||
<dl>
|
<dl>
|
||||||
{input type="money" name="total" label="Montant du don" required=1 source=$doc}
|
{input type="money" name="total" label="Montant du don" required=1 source=$doc default="0,0"}
|
||||||
{input type="select" name="forme_don" required=1 label="Forme du don" source=$doc options=$formes_don default=$doc.forme_don}
|
{input type="select" name="forme_don" required=1 label="Forme du don" source=$doc options=$formes_don default=$doc.forme_don}
|
||||||
{input type="select" name="nature_don" required=1 label="Nature du don" source=$doc options=$natures_don default=$doc.nature_don}
|
{input type="select" name="nature_don" required=1 label="Nature du don" source=$doc options=$natures_don default=$doc.nature_don}
|
||||||
{input type="select" name="texte_don" required=1 label="Texte explicatif" source=$doc options=$textes_don default=$doc.texte_don}
|
{input type="select" name="texte_don" required=1 label="Texte explicatif" source=$doc options=$textes_don default=$doc.texte_don}
|
||||||
{input type="select" name="moyen_paiement" required=1 label="Moyen de paiement" source=$doc options=$moyens_paiement default=$doc.moyen_paiement}
|
{input type="select" name="moyen_paiement_cerfa" required=1 label="Moyen de paiement" source=$doc options=$moyens_paiement default=$doc.moyen_paiement_cerfa}
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@ -162,7 +172,7 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><label>Reçu adressée à :</label></dt>
|
<dt><label>Reçu adressée à :</label></dt>
|
||||||
<dd>
|
<dd>
|
||||||
{input type="select" name="membre_cotis" label="Membre" options=$membres required=1 default=$doc.membre}
|
{input type="select" name="membre_cotis" label="Membre" options=$users required=1 default=$doc.membre}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
@ -51,6 +51,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function modifierContact(client, idlist, idcontact)
|
||||||
|
{
|
||||||
|
let contactlist = document.querySelector(idlist);
|
||||||
|
let options = contactlist.querySelectorAll('option');
|
||||||
|
for (i=0; i < options.length; ++i) {
|
||||||
|
if (options[i].value == client.value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.querySelector(idcontact).value = options[i].textContent;
|
||||||
|
}
|
||||||
|
|
||||||
const form = document.querySelector('#f_numero_facture').form;
|
const form = document.querySelector('#f_numero_facture').form;
|
||||||
changeTypeSaisie(form.base_receveur.value);
|
changeTypeSaisie(form.base_receveur.value);
|
||||||
|
|
||||||
@ -63,6 +75,11 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selclient = document.querySelector('#f_client');
|
||||||
|
selclient.addEventListener("change", () => {
|
||||||
|
modifierContact(selclient, '#f_contact_list', '#f_nom_contact');
|
||||||
|
});
|
||||||
|
|
||||||
} ());
|
} ());
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<td></td>
|
<td></td>
|
||||||
<td class="tabs" colspan={$colspan}>
|
<td class="tabs" colspan={$colspan}>
|
||||||
<em>PAS FONCTIONNEL - Pour les client·es coché·es :</em>
|
<em>PAS FONCTIONNEL - Pour les client·es coché·es :</em>
|
||||||
{csrf_field key="membres_action"}
|
{csrf_field key="users_action"}
|
||||||
<select name="action">
|
<select name="action">
|
||||||
<option value="">— Choisir une action à effectuer —</option>
|
<option value="">— Choisir une action à effectuer —</option>
|
||||||
<option value="csv">Exporter en tableau CSV</option>
|
<option value="csv">Exporter en tableau CSV</option>
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
</style>
|
</style>
|
||||||
<nav class="tabs">
|
<nav class="tabs">
|
||||||
<ul>
|
<ul>
|
||||||
<li{if $current == 'index'} class="current"{/if}><a href="{plugin_url file=""}">Liste documents</a></li>
|
<li{if $current == 'index'} class="current"{/if}><a href="{$plugin_admin_url}">Liste documents</a></li>
|
||||||
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)}
|
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)}
|
||||||
<li{if $current == 'facture'} class="current"{/if}><a href="{plugin_url file="facture_ajouter.php"}">Nouveau document</a></li>
|
<li{if $current == 'facture'} class="current"{/if}><a href="{$plugin_admin_url}facture_ajouter.php">Nouveau document</a></li>
|
||||||
{/if}
|
{/if}
|
||||||
<li{if $current == 'clients'} class="current"{/if}><a href="{plugin_url file="clients.php"}">Liste clients</a></li>
|
<li{if $current == 'clients'} class="current"{/if}><a href="{$plugin_admin_url}clients.php">Liste clients</a></li>
|
||||||
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)}
|
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)}
|
||||||
<li{if $current == 'config'} class="current"{/if}><a href="{plugin_url file="config.php"}">Configuration</a></li>
|
<li{if $current == 'config'} class="current"{/if}><a href="{$plugin_admin_url}config.php">Configuration</a></li>
|
||||||
{/if}
|
{/if}
|
||||||
<li{if $current == 'aide'} class="current"{/if}><a href="{plugin_url file="aide.php"}">Aide</a></li>
|
<li{if $current == 'aide'} class="current"{/if}><a href="{$plugin_admin_url}aide.php">Aide</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
@ -1,12 +1,12 @@
|
|||||||
<nav class="tabs">
|
<nav class="tabs">
|
||||||
<ul>
|
<ul>
|
||||||
<li{if $current == 'clients'} class="current"{/if}><a href="{plugin_url file="clients.php"}">Liste clients</a></li>
|
<li{if $current == 'clients'} class="current"{/if}><a href="{$plugin_admin_url}clients.php">Liste clients</a></li>
|
||||||
<li{if $current == 'client'} class="current"{/if}><a href="{plugin_url file="client.php"}?id={$client.id}">{$client.nom}</a></li>
|
<li{if $current == 'client'} class="current"{/if}><a href="{$plugin_admin_url}client.php?id={$client.id}">{$client.nom}</a></li>
|
||||||
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)}
|
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)}
|
||||||
<li{if $current == 'client_modifier'} class="current"{/if}>
|
<li{if $current == 'client_modifier'} class="current"{/if}>
|
||||||
<a href="{plugin_url file="client_modifier.php"}?id={$client.id}">Modifier</a></li>{/if}
|
<a href="{$plugin_admin_url}client_modifier.php?id={$client.id}">Modifier</a></li>{/if}
|
||||||
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)}
|
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)}
|
||||||
<li{if $current == 'client_supprimer'} class="current"{/if}>
|
<li{if $current == 'client_supprimer'} class="current"{/if}>
|
||||||
<a href="{plugin_url file="client_supprimer.php"}?id={$client.id}">Supprimer</a></li>{/if}
|
<a href="{$plugin_admin_url}client_supprimer.php?id={$client.id}">Supprimer</a></li>{/if}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
@ -7,4 +7,15 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.aide {
|
||||||
|
margin: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.aide ul {
|
||||||
|
list-style: square;
|
||||||
|
margin: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
{/literal}
|
{/literal}
|
@ -1,21 +1,30 @@
|
|||||||
{include file="admin/_head.tpl" title="Aide — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id}
|
{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"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="aide"}
|
||||||
|
|
||||||
|
<h2>Quelques remarques et conseils sur l'utilisation du plugin Facturation</h2>
|
||||||
|
|
||||||
|
<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>
|
<fieldset>
|
||||||
<legend><h2>Quelques remarques et conseils sur l'utilisation du plugin Facturation</h2></legend>
|
<legend>Informations à configurer</legend>
|
||||||
|
<dl>
|
||||||
<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>
|
<dt><label>Adresse</label></dt>
|
||||||
<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 Garradin qui fait foi plutôt que celle dans le plugin (qui sert en revanche pour les reçus).</p>
|
<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>
|
||||||
<p>Pensez à mettre une image en signature (cela sert pour les reçus fiscaux), pour cela uploadez là dans les documents de Garradin, onglet Squelettes du site web, sous plugin/facturation/sign.png. Il est préférable d'avoir un fond transparent.
|
<dt><label>Nom et prénom des membres</label></dt>
|
||||||
</p>
|
<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>
|
||||||
<br>
|
<dt><label>Champs à faire figurer sur la facture</label></dt>
|
||||||
<p>- Pour créer un reçu sur une cotisation, il faut pour le moment que cette cotisation soit attachée à la compta.</p>
|
<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>
|
||||||
<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>
|
</dl>
|
||||||
<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/garradin-plugin-facturation">sur mon gitlab</a>, soit sur l'adresse d'entraide de garradin. 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>
|
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
</div>
|
||||||
|
|
||||||
|
{include file="_foot.tpl"}
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Client — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=0}
|
{include file="_head.tpl" title="Client — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=0}
|
||||||
{include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client"}
|
{include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client"}
|
||||||
|
|
||||||
<dl class="describe">
|
<dl class="describe">
|
||||||
@ -18,6 +18,18 @@
|
|||||||
<dt>Code postal</dt>
|
<dt>Code postal</dt>
|
||||||
<dd>{$client.code_postal|escape|rtrim|nl2br}</dd>
|
<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>
|
<dt>Adresse électronique</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{if empty($client.email)}
|
{if empty($client.email)}
|
||||||
@ -32,7 +44,25 @@
|
|||||||
{if empty($client.telephone)}
|
{if empty($client.telephone)}
|
||||||
<em>(Non renseigné)</em>
|
<em>(Non renseigné)</em>
|
||||||
{else}
|
{else}
|
||||||
<a href="tel:{$client.telephone}">{$client.telephone|format_tel}</a>
|
<a href="tel:{$client.telephone}">{$client.telephone|format_phone_number}</a>
|
||||||
|
{/if}
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Nom du contact</dt>
|
||||||
|
<dd>
|
||||||
|
{if empty($client.nom_contact)}
|
||||||
|
<em>(Non renseigné)</em>
|
||||||
|
{else}
|
||||||
|
{$client.nom_contact}
|
||||||
|
{/if}
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>Note</dt>
|
||||||
|
<dd>
|
||||||
|
{if empty($client.note)}
|
||||||
|
<em>(Non renseigné)</em>
|
||||||
|
{else}
|
||||||
|
{$client.note}
|
||||||
{/if}
|
{/if}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
@ -60,7 +90,7 @@
|
|||||||
{foreach from=$docs item=facture}
|
{foreach from=$docs item=facture}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{$f_obj->types[$facture.type_facture]['label'] }</td>
|
<td>{$f_obj->types[$facture.type_facture]['label'] }</td>
|
||||||
<td><a href="{plugin_url file="facture.php"}?id={$facture.id}">{$facture.numero}</a></td>
|
<td><a href="{$plugin_admin_url}facture.php?id={$facture.id}">{$facture.numero}</a></td>
|
||||||
<td>{$facture.date_emission|date:'d/m/Y'}</td>
|
<td>{$facture.date_emission|date:'d/m/Y'}</td>
|
||||||
<td>{$facture.date_echeance|date:'d/m/Y'}</td>
|
<td>{$facture.date_echeance|date:'d/m/Y'}</td>
|
||||||
<td>{$facture.reglee}</td>
|
<td>{$facture.reglee}</td>
|
||||||
@ -82,4 +112,4 @@
|
|||||||
<p class="alert block">Ce client n'a pas de document associé.</p>
|
<p class="alert block">Ce client n'a pas de document associé.</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Modifier un client — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=0}
|
{include file="_head.tpl" title="Modifier un client — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=0}
|
||||||
{include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client_modifier"}
|
{include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client_modifier"}
|
||||||
|
|
||||||
{form_errors}
|
{form_errors}
|
||||||
@ -11,8 +11,11 @@
|
|||||||
{input type="text" name="adresse" label="Adresse" required=true source=$client}
|
{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="code_postal" label="Code postal" required=true source=$client}
|
||||||
{input type="text" name="ville" label="Ville" 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="tel" name="telephone" label="Téléphone" source=$client}
|
||||||
{input type="email" name="email" label="Adresse e-mail" source=$client}
|
{input type="email" name="email" label="Adresse e-mail" source=$client}
|
||||||
|
{input type="text" name="nom_contact" label="Nom du contact" source=$client}
|
||||||
|
{input type="textarea" cols="60" rows="3" name="note" label="Note" source=$client}
|
||||||
</dl>
|
</dl>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@ -23,4 +26,4 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Supprimer un client — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=0}
|
{include file="_head.tpl" title="Supprimer un client — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=0}
|
||||||
{include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client_supprimer"}
|
{include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client_supprimer"}
|
||||||
|
|
||||||
{if !$deletable}
|
{if !$deletable}
|
||||||
@ -12,4 +12,4 @@
|
|||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Clients — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=1}
|
{include file="_head.tpl" title="Clients — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=1}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="clients"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="clients"}
|
||||||
|
|
||||||
{if $list->count()}
|
{if $list->count()}
|
||||||
@ -13,6 +13,12 @@
|
|||||||
{if $key == 'id' || $key == 'nom'}
|
{if $key == 'id' || $key == 'nom'}
|
||||||
<?php continue; ?>
|
<?php continue; ?>
|
||||||
{/if}
|
{/if}
|
||||||
|
{if $key == 'siret'}
|
||||||
|
<?php
|
||||||
|
if (null === $value) { $value = ""; }
|
||||||
|
$value = implode(' ', str_split($value, 3));
|
||||||
|
?>
|
||||||
|
{/if}
|
||||||
<td>{$value}</td>
|
<td>{$value}</td>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
@ -52,8 +58,11 @@
|
|||||||
{input type="text" name="adresse" label="Adresse" required=true}
|
{input type="text" name="adresse" label="Adresse" required=true}
|
||||||
{input type="text" name="code_postal" label="Code postal" 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="ville" label="Ville" required=true}
|
||||||
|
{input type="text" name="siret" label="SIREN/SIRET"}
|
||||||
{input type="tel" name="telephone" label="Téléphone"}
|
{input type="tel" name="telephone" label="Téléphone"}
|
||||||
{input type="email" name="email" label="Adresse e-mail"}
|
{input type="email" name="email" label="Adresse e-mail"}
|
||||||
|
{input type="text" name="nom_contact" label="Nom contact"}
|
||||||
|
{input type="textarea" cols="60" rows="3" name="note" label="Note"}
|
||||||
</dl>
|
</dl>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@ -64,4 +73,4 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Configuration — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id}
|
{include file="_head.tpl" title="Configuration — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="config"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="config"}
|
||||||
|
|
||||||
{if $ok && !$form->hasErrors()}
|
{if $ok && !$form->hasErrors()}
|
||||||
@ -13,56 +13,51 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Informations de l'association</legend>
|
<legend>Informations de l'association</legend>
|
||||||
<dl>
|
<dl>
|
||||||
{input type="text" name="rna_asso" label="RNA de l'association" source=$plugin.config}
|
{input type="text" name="rna_asso" label="RNA de l'association" source=$conf}
|
||||||
{input type="text" name="siret_asso" label="SIRET de l'association" source=$plugin.config}
|
{input type="text" name="siret_asso" label="SIRET de l'association" source=$conf}
|
||||||
|
{input type="checkbox" name="ttc" value="1" label="L'association émet des factures TTC (TVA)" source=$conf}
|
||||||
</dl>
|
</dl>
|
||||||
<br>
|
<br>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Adresse</legend>
|
<legend>Adresse de l'association</legend>
|
||||||
|
<dd class="help">
|
||||||
|
à saisir uniquement si elle n'est pas dans la configuration de la compta ou si elle doit remplacer celle qui est définie dans la configuration de la compta
|
||||||
|
</dd>
|
||||||
<dl>
|
<dl>
|
||||||
{input type="text" name="numero_rue_asso" source=$plugin.config label="Numéro de rue" maxlength=5}
|
{input type="text" name="numero_rue_asso" source=$conf label="Numéro de rue" maxlength=5}
|
||||||
{input type="text" name="rue_asso" source=$plugin.config label="Nom de rue"}
|
{input type="text" name="rue_asso" source=$conf label="Nom de rue"}
|
||||||
{input type="text" name="cp_asso" source=$plugin.config label="Code postal"}
|
{input type="text" name="cp_asso" source=$conf label="Code postal"}
|
||||||
{input type="text" name="ville_asso" source=$plugin.config label="Ville"}
|
{input type="text" name="ville_asso" source=$conf label="Ville"}
|
||||||
</dl>
|
</dl>
|
||||||
</fieldset>
|
</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=$plugin.config label="Ligne 1" maxlength=95}
|
|
||||||
{input type="text" name="objet_1" source=$plugin.config label="Ligne 2" maxlength=95}
|
|
||||||
{input type="text" name="objet_2" source=$plugin.config label="Ligne 3" maxlength=95}
|
|
||||||
</dl>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Droit à la réduction d'impôt</legend>
|
<legend>Factures et devis</legend>
|
||||||
<dl>
|
<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="logo" value="1" source=$conf label="Imprimer le logo de l'association"}
|
||||||
{input type="checkbox" name="droit_art200" value="1" source=$plugin.config label="Article 200"}
|
{input type="textarea" class="full-width" rows="5" name="footer" source=$conf label="Pied de document — informations légales" required=true}
|
||||||
{input type="checkbox" name="droit_art238bis" value="1" source=$plugin.config label="Article 238 bis"}
|
|
||||||
{input type="checkbox" name="droit_art885-0VbisA" value="1" source=$plugin.config label="Article 885-0V bis A"}
|
|
||||||
</dl>
|
</dl>
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Factures</legend>
|
<legend>
|
||||||
|
Choisir les champs à faire figurer sur la facture ou le devis pour l'adresse d'un membre
|
||||||
|
</legend>
|
||||||
<dl>
|
<dl>
|
||||||
{input type="textarea" class="full-width" rows="10" name="footer" source=$plugin.config label="Pied de document — informations légales" required=true}
|
{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>
|
</dl>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Configuration du plugin</legend>
|
<legend>Configuration du plugin</legend>
|
||||||
<dl>
|
<dl>
|
||||||
{input type="checkbox" name="validate_cp" value="1" source=$plugin.config label="Vérifier le code postal lors de saisie/modification de client (seulement FR)"}
|
{input type="checkbox" name="validate_cp" value="1" source=$conf label="Vérifier le code postal lors de saisie/modification de client (seulement FR)"}
|
||||||
{input type="checkbox" name="unique_client_name" value="1" source=$plugin.config label="Noms des clients uniques"}
|
{input type="checkbox" name="unique_client_name" value="1" source=$conf label="Noms des clients uniques"}
|
||||||
{input type="select" name="pattern" label="Format de numéro de document" required=false options=$patterns source=$plugin.config}
|
{input type="select" name="pattern" label="Format de numéro de document" required=false options=$patterns source=$conf}
|
||||||
<dd class="help">
|
<dd class="help">
|
||||||
F = Facture, D = Devis, RF = Reçu fiscal, RC = Reçu cotisation
|
F = Facture, D = Devis
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<i>Pour personnaliser l'apparence de la facture, il faut pour l'instant se retrousser les manches et éditer soi-même le fichier www/admin/pdf.php du plugin ! </i>
|
<i>Pour personnaliser l'apparence de la facture, il faut pour l'instant se retrousser les manches et éditer soi-même le fichier www/admin/pdf.php du plugin ! </i>
|
||||||
@ -74,25 +69,4 @@
|
|||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
{include file="_foot.tpl"}
|
||||||
<form method="post" enctype="multipart/form-data" action="{$self_url|escape}" id="f_upload">
|
|
||||||
<fieldset>
|
|
||||||
<legend>Signature du responsable</legend>
|
|
||||||
<p>
|
|
||||||
Uploadez votre signature dans les documents, onglet Squelettes du site web, sous plugin/facturation/sign.png
|
|
||||||
<br>
|
|
||||||
Il est préférable d'avoir un fond transparent.
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
La signature actuelle :
|
|
||||||
<br>
|
|
||||||
<img src="{$www_url}plugin/facturation/sign.png">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>A cause de l'implémentation de la signature, votre signature est acessible publiquement à l'adresse suivante : {$www_url}plugin/facturation/sign.png !</p>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
{include file="admin/_head.tpl" title="Document — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id}
|
{include file="_head.tpl" title="Document — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
||||||
|
|
||||||
{form_errors}
|
{form_errors}
|
||||||
|
|
||||||
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)}
|
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)}
|
||||||
{linkbutton shape="edit" href="%sfacture_modifier.php?id=%d"|args:$plugin_url,$facture.id label="Modifier ce document"}
|
{linkbutton shape="edit" href="%sfacture_modifier.php?id=%d"|args:$plugin_admin_url,$facture.id label="Modifier ce document"}
|
||||||
{linkbutton shape="plus" href="%sfacture_ajouter.php?copy=%d"|args:$plugin_url,$facture.id label="Dupliquer ce document"}
|
{linkbutton shape="plus" href="%sfacture_ajouter.php?copy=%d"|args:$plugin_admin_url,$facture.id label="Dupliquer ce document"}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{linkbutton shape="download" href="%spdf.php?d&id=%d"|args:$plugin_url,$facture.id label="Télécharger ce document"}
|
{linkbutton shape="download" href="%spdf.php?d&id=%d"|args:$plugin_admin_url,$facture.id label="Télécharger ce document"}
|
||||||
|
|
||||||
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)}
|
{if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)}
|
||||||
{linkbutton shape="delete" href="%sfacture_supprimer.php?id=%d"|args:$plugin_url,$facture.id label="Supprimer ce document"}
|
{linkbutton shape="delete" href="%sfacture_supprimer.php?id=%d"|args:$plugin_admin_url,$facture.id label="Supprimer ce document"}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div style="margin-top: 1em; width: min-content;">
|
<div style="margin-top: 1em; width: min-content;">
|
||||||
<embed src="pdf.php?id={$id}" width="840px" height="1188px" style="max-width: 900px; border: 1px solid black;">
|
<embed src="pdf.php?id={$id}" width="840px" height="1188px" style="max-width: 900px; border: 1px solid black;">
|
||||||
</div>
|
</div>
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
{include file="admin/_head.tpl" title="Créer un document — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=1}
|
{include file="_head.tpl" title="Créer un document — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=1}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="facture"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="facture"}
|
||||||
|
|
||||||
{include file="%s/templates/_form.tpl"|args:$plugin_root}
|
{include file="%s/templates/_form.tpl"|args:$plugin_root}
|
||||||
|
|
||||||
{include file="%s/templates/_js.tpl"|args:$plugin_root}
|
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{include file="admin/_head.tpl" title="Modifier un document — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=1}
|
{include file="_head.tpl" title="Modifier un document — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=1}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
||||||
|
|
||||||
{include file="%s/templates/_form.tpl"|args:$plugin_root}
|
{include file="%s/templates/_form.tpl"|args:$plugin_root}
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Supprimer un document — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=0}
|
{include file="_head.tpl" title="Supprimer un document — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id js=0}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
||||||
|
|
||||||
{form_errors}
|
{form_errors}
|
||||||
@ -22,4 +22,4 @@
|
|||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
@ -1,4 +1,4 @@
|
|||||||
{include file="admin/_head.tpl" title="Documents — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id}
|
{include file="_head.tpl" title="Documents — %s"|args:$plugin.name current="plugin_%s"|args:$plugin.id}
|
||||||
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
{include file="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
||||||
|
|
||||||
{form_errors}
|
{form_errors}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<td>{$facture.type}</td>
|
<td>{$facture.type}</td>
|
||||||
<th><a href="facture.php?id={$facture.id}">{$facture.numero}</a></th>
|
<th><a href="facture.php?id={$facture.id}">{$facture.numero}</a></th>
|
||||||
{if $facture.receveur_membre}
|
{if $facture.receveur_membre}
|
||||||
<td>{link href="!membres/fiche.php?id=%d"|args:$facture.receveur_id label=$facture.receveur}</td>
|
<td>{link href="!users/details.php?id=%d"|args:$facture.receveur_id label=$facture.receveur}</td>
|
||||||
{else}
|
{else}
|
||||||
<td>{link href="client.php?id=%d"|args:$facture.receveur_id label=$facture.receveur}</td>
|
<td>{link href="client.php?id=%d"|args:$facture.receveur_id label=$facture.receveur}</td>
|
||||||
{/if}
|
{/if}
|
||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{$list->getHTMLPagination()|raw}
|
||||||
|
|
||||||
<p class="help">
|
<p class="help">
|
||||||
Export de la liste :
|
Export de la liste :
|
||||||
@ -43,4 +44,4 @@
|
|||||||
<p class="help">Aucun document, vous pouvez commencer par {link href="facture_ajouter.php" label="créer un nouveau document"}.</p>
|
<p class="help">Aucun document, vous pouvez commencer par {link href="facture_ajouter.php" label="créer un nouveau document"}.</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{include file="admin/_foot.tpl"}
|
{include file="_foot.tpl"}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
|
|
||||||
$db = DB::getInstance();
|
$db = DB::getInstance();
|
||||||
|
|
||||||
|
161
upgrade.php
161
upgrade.php
@ -1,21 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Garradin;
|
namespace Paheko;
|
||||||
use Garradin\Plugin\Facturation\Facture;
|
use Paheko\Plugin\Facturation\Facture;
|
||||||
use Garradin\Entities\Files\File;
|
use Paheko\Entities\Files\File;
|
||||||
|
|
||||||
define('DEVIS', 0);
|
|
||||||
define('FACT', 1);
|
|
||||||
define('CERFA', 2);
|
|
||||||
define('COTIS', 3);
|
|
||||||
|
|
||||||
$db = DB::getInstance();
|
$db = DB::getInstance();
|
||||||
$facture = new Facture;
|
$old_version = $plugin->oldVersion();
|
||||||
$infos = $plugin->getInfos();
|
error_log("upgrade:: à partir de la version = " . $old_version);
|
||||||
|
|
||||||
|
|
||||||
// 0.2.0 - Stock le contenu en json plutôt qu'en serialized
|
// 0.2.0 - Stock le contenu en json plutôt qu'en serialized
|
||||||
if (version_compare($infos->version, '0.2.0', '<'))
|
if (version_compare($old_version, '0.2.0', '<'))
|
||||||
{
|
{
|
||||||
$r = (array) DB::getInstance()->get('SELECT * FROM plugin_facturation_factures');
|
$r = (array) DB::getInstance()->get('SELECT * FROM plugin_facturation_factures');
|
||||||
|
|
||||||
@ -26,7 +20,7 @@ if (version_compare($infos->version, '0.2.0', '<'))
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0.3.0 - Migration Facturation\Config vers la table plugins
|
// 0.3.0 - Migration Facturation\Config vers la table plugins
|
||||||
if (version_compare($infos->version, '0.3.0', '<'))
|
if (version_compare($old_version, '0.3.0', '<'))
|
||||||
{
|
{
|
||||||
$conf = $db->getAssoc('SELECT cle, valeur FROM plugin_facturation_config ORDER BY cle;');
|
$conf = $db->getAssoc('SELECT cle, valeur FROM plugin_facturation_config ORDER BY cle;');
|
||||||
foreach($conf as $k=>$v)
|
foreach($conf as $k=>$v)
|
||||||
@ -40,7 +34,7 @@ if (version_compare($infos->version, '0.3.0', '<'))
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0.4.0 -
|
// 0.4.0 -
|
||||||
if (version_compare($infos->version, '0.4.0', '<'))
|
if (version_compare($old_version, '0.4.0', '<'))
|
||||||
{
|
{
|
||||||
$db->exec(<<<EOT
|
$db->exec(<<<EOT
|
||||||
CREATE TABLE IF NOT EXISTS plugin_facturation_paiement
|
CREATE TABLE IF NOT EXISTS plugin_facturation_paiement
|
||||||
@ -85,8 +79,13 @@ EOT
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0.6.0 -
|
// 0.6.0 -
|
||||||
if (version_compare($infos->version, '0.6.0', '<'))
|
if (version_compare($old_version, '0.6.0', '<'))
|
||||||
{
|
{
|
||||||
|
define('DEVIS', 0);
|
||||||
|
define('FACT', 1);
|
||||||
|
define('CERFA', 2);
|
||||||
|
define('COTIS', 3);
|
||||||
|
$facture = new Facture;
|
||||||
$r = $db->first('SELECT id, total FROM plugin_facturation_factures;');
|
$r = $db->first('SELECT id, total FROM plugin_facturation_factures;');
|
||||||
if (strpos($r->total,'.'))
|
if (strpos($r->total,'.'))
|
||||||
{
|
{
|
||||||
@ -145,8 +144,13 @@ EOT
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0.6.2 -
|
// 0.6.2 -
|
||||||
if (version_compare($infos->version, '0.6.2', '<'))
|
if (version_compare($old_version, '0.6.2', '<'))
|
||||||
{
|
{
|
||||||
|
define('DEVIS', 0);
|
||||||
|
define('FACT', 1);
|
||||||
|
define('CERFA', 2);
|
||||||
|
define('COTIS', 3);
|
||||||
|
$facture = new Facture;
|
||||||
$db->exec(<<<EOT
|
$db->exec(<<<EOT
|
||||||
INSERT OR IGNORE INTO plugin_facturation_paiement
|
INSERT OR IGNORE INTO plugin_facturation_paiement
|
||||||
(code, nom) VALUES ('HA', 'HelloAsso');
|
(code, nom) VALUES ('HA', 'HelloAsso');
|
||||||
@ -193,3 +197,128 @@ EOT
|
|||||||
$facture->edit($f->id, $data);
|
$facture->edit($f->id, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0.7.1 - Ajout clé config TTC/HT
|
||||||
|
if (version_compare($old_version, '0.7.1', '<'))
|
||||||
|
{
|
||||||
|
$plugin->setConfig('ttc', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0.8.1 - Signal menu item
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0.12 Ajout Mollie à la table moyens de paiement
|
||||||
|
if (version_compare($old_version, '0.12', '<'))
|
||||||
|
{
|
||||||
|
$db->exec(<<<EOT
|
||||||
|
INSERT OR IGNORE INTO plugin_facturation_paiement
|
||||||
|
(code, nom) VALUES ('MO', 'Mollie');
|
||||||
|
EOT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// version 0.15
|
||||||
|
// Ajout champs note et contact à la table clients
|
||||||
|
// Ajout divers champs à la table factures
|
||||||
|
if (version_compare($old_version, '0.15', '<'))
|
||||||
|
{
|
||||||
|
$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,
|
||||||
|
nom_contact TEXT,
|
||||||
|
note TEXT
|
||||||
|
);
|
||||||
|
EOT
|
||||||
|
);
|
||||||
|
// copier les clients dans la table temporaire
|
||||||
|
$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
|
||||||
|
);
|
||||||
|
|
||||||
|
$db->exec(<<<EOT
|
||||||
|
CREATE TABLE IF NOT EXISTS plugin_facturation_factures_tmp(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
type_facture INTEGER NOT NULL DEFAULT 0,
|
||||||
|
numero TEXT NOT NULL UNIQUE,
|
||||||
|
receveur_membre INTEGER NOT NULL, -- bool
|
||||||
|
receveur_id INTEGER NOT NULL,
|
||||||
|
date_emission TEXT NOT NULL, -- CHECK (date(date_emission) IS NOT NULL AND date(date_emission) = date_emission),
|
||||||
|
date_echeance TEXT NOT NULL, -- CHECK (date(date_echeance) IS NOT NULL AND date(date_echeance) = date_echeance),
|
||||||
|
reglee INTEGER DEFAULT 0, -- bool
|
||||||
|
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
|
||||||
|
);
|
||||||
|
EOT
|
||||||
|
);
|
||||||
|
|
||||||
|
// copier les factures dans la table temporaire
|
||||||
|
$sql = 'SELECT * FROM plugin_facturation_factures';
|
||||||
|
foreach ($db->iterate($sql) as $facture)
|
||||||
|
{
|
||||||
|
$db->insert('plugin_facturation_factures_tmp', $facture);
|
||||||
|
}
|
||||||
|
// remplacer l'ancienne table par la nouvelle
|
||||||
|
$db->exec(<<<EOT
|
||||||
|
DROP TABLE plugin_facturation_factures;
|
||||||
|
ALTER TABLE plugin_facturation_factures_tmp RENAME TO plugin_facturation_factures;
|
||||||
|
EOT
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Garradin;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
|
||||||
$id = (int) qg('id');
|
|
||||||
|
|
||||||
$c = $client->get($id);
|
|
||||||
|
|
||||||
if (!$c)
|
|
||||||
{
|
|
||||||
throw new UserException("Ce client n'existe pas.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(f('save'))
|
|
||||||
{
|
|
||||||
$form->check('edit_client', [
|
|
||||||
'nom' => 'required|string',
|
|
||||||
'adresse' => 'required|string',
|
|
||||||
'code_postal' => 'required|string',
|
|
||||||
'ville' => 'required|string',
|
|
||||||
'telephone' => 'string',
|
|
||||||
'email' => 'email'
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$r = $client->edit($id,[
|
|
||||||
'nom' => f('nom'),
|
|
||||||
'adresse' => f('adresse'),
|
|
||||||
'code_postal' => f('code_postal'),
|
|
||||||
'ville' => f('ville'),
|
|
||||||
'telephone' => f('telephone'),
|
|
||||||
'email' => f('email')
|
|
||||||
]);
|
|
||||||
|
|
||||||
$r ? Utils::redirect(PLUGIN_URL . 'client.php?id='.(int)$id):'';
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$tpl->assign('client', $c);
|
|
||||||
$tpl->display(PLUGIN_ROOT . '/templates/client_modifier.tpl');
|
|
@ -1,48 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Garradin;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ);
|
|
||||||
|
|
||||||
if(f('add'))
|
|
||||||
{
|
|
||||||
$form->check('add_client', [
|
|
||||||
'nom' => 'required|string',
|
|
||||||
'adresse' => 'required|string',
|
|
||||||
'code_postal' => 'required|string',
|
|
||||||
'ville' => 'required|string',
|
|
||||||
'telephone' => 'string',
|
|
||||||
'email' => 'email'
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$id = $client->add([
|
|
||||||
'nom' => f('nom'),
|
|
||||||
'adresse' => f('adresse'),
|
|
||||||
'code_postal' => f('code_postal'),
|
|
||||||
'ville' => f('ville'),
|
|
||||||
'telephone' => f('telephone'),
|
|
||||||
'email' => f('email')
|
|
||||||
]);
|
|
||||||
|
|
||||||
$id ? Utils::redirect(PLUGIN_URL . 'client.php?id='.(int)$id):'';
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$list = $client->list();
|
|
||||||
$list->loadFromQueryString();
|
|
||||||
|
|
||||||
$tpl->assign(compact('list'));
|
|
||||||
|
|
||||||
$tpl->display(PLUGIN_ROOT . '/templates/clients.tpl');
|
|
@ -1,131 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Garradin;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN);
|
|
||||||
|
|
||||||
if (f('save') && $form->check('facturation_config'))
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$plugin->setConfig('rna_asso', trim(f('rna_asso')));
|
|
||||||
$plugin->setConfig('siret_asso', trim(f('siret_asso')));
|
|
||||||
|
|
||||||
$plugin->setConfig('numero_rue_asso', trim(f('numero_rue_asso')));
|
|
||||||
$plugin->setConfig('rue_asso', trim(f('rue_asso')));
|
|
||||||
$plugin->setConfig('cp_asso', trim(f('cp_asso')));
|
|
||||||
$plugin->setConfig('ville_asso', trim(f('ville_asso')));
|
|
||||||
|
|
||||||
$plugin->setConfig('droit_art200', (bool)f('droit_art200'));
|
|
||||||
$plugin->setConfig('droit_art238bis', (bool)f('droit_art238bis'));
|
|
||||||
$plugin->setConfig('droit_art885-0VbisA', (bool)f('droit_art885-0VbisA'));
|
|
||||||
$plugin->setConfig('objet_0', trim(f('objet_0')));
|
|
||||||
$plugin->setConfig('objet_1', trim(f('objet_1')));
|
|
||||||
$plugin->setConfig('objet_2', trim(f('objet_2')));;
|
|
||||||
|
|
||||||
$plugin->setConfig('footer', f('footer'));
|
|
||||||
|
|
||||||
$plugin->setConfig('validate_cp', (bool)f('validate_cp'));
|
|
||||||
$plugin->setConfig('unique_client_name', (bool)f('unique_client_name'));
|
|
||||||
|
|
||||||
$plugin->setConfig('pattern', f('pattern'));
|
|
||||||
|
|
||||||
Utils::redirect(PLUGIN_URL . 'config.php?ok');
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Traitement de l'image de signature
|
|
||||||
// Copié du plugin de nfrery
|
|
||||||
/*
|
|
||||||
if (f('upload') || isset($_POST['uploadHelper_status']))
|
|
||||||
{
|
|
||||||
$form->check('signature_config');
|
|
||||||
|
|
||||||
if (f('uploadHelper_status') > 0)
|
|
||||||
{
|
|
||||||
throw new UserException('Un seul fichier peut être envoyé en même temps.');
|
|
||||||
}
|
|
||||||
elseif (!empty($_POST['fichier']) || isset($_FILES['fichier']))
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (isset($_POST['uploadHelper_status']) && !empty($_POST['fichier']))
|
|
||||||
{
|
|
||||||
$fichier = Fichiers::uploadExistingHash(f('fichier'), f('uploadHelper_fileHash'));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$fichier = Fichiers::upload($_FILES['fichier']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ?? je comprends pas tout dans ce bloc
|
|
||||||
if (isset($_POST['uploadHelper_status']))
|
|
||||||
{
|
|
||||||
echo json_encode([
|
|
||||||
'redirect' => WWW_URL,
|
|
||||||
'callback' => 'insertHelper',
|
|
||||||
'file' => [
|
|
||||||
'image' => (int)$fichier->image,
|
|
||||||
'id' => (int)$fichier->id,
|
|
||||||
'nom' => $fichier->nom,
|
|
||||||
'thumb' => $fichier->image ? $fichier->getURL(200) : false
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$plugin->getConfig('signaturetxt') == "")
|
|
||||||
{
|
|
||||||
$fichier_old = new Fichiers($plugin->getConfig('signaturetxt'));
|
|
||||||
$fichier_old->remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
Static_Cache::storeFromUpload('fichiers.'.$fichier->id, $fichier->nom);
|
|
||||||
$plugin->setConfig('signaturetxt', $fichier->id);
|
|
||||||
Utils::redirect(PLUGIN_URL . 'config.php?ok');
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
throw new UserException($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$error = 'Aucun fichier envoyé.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$plugin->getConfig('signaturetxt') == "")
|
|
||||||
{
|
|
||||||
$img1 = new Fichiers($plugin->getConfig('signaturetxt'));
|
|
||||||
$cache_id = 'fichiers.' . $img1->id_contenu;
|
|
||||||
|
|
||||||
if (!Static_Cache::exists($cache_id))
|
|
||||||
{
|
|
||||||
$blob = DB::getInstance()->openBlob('fichiers_contenu', 'contenu', (int)$img1->id_contenu);
|
|
||||||
Static_Cache::storeFromPointer($cache_id, $blob);
|
|
||||||
fclose($blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = $img1->getURL();
|
|
||||||
$tpl->assign('image', $uri);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$tpl->assign('image', false);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$tpl->assign('ok', qg('ok') !== null);
|
|
||||||
|
|
||||||
$tpl->assign('patterns', \Garradin\Plugin\Facturation\PATTERNS_LIST);
|
|
||||||
|
|
||||||
// $tpl->assign('max_size', Utils::getMaxUploadSize());
|
|
||||||
|
|
||||||
$tpl->display(PLUGIN_ROOT . '/templates/config.tpl');
|
|
@ -1,280 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Garradin;
|
|
||||||
|
|
||||||
use const \Garradin\Plugin\Facturation\PATTERNS_LIST;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
|
||||||
|
|
||||||
use Garradin\DB;
|
|
||||||
use stdClass;
|
|
||||||
|
|
||||||
$db = DB::getInstance();
|
|
||||||
|
|
||||||
$step = $radio = false;
|
|
||||||
$liste = [];
|
|
||||||
$designations = [];
|
|
||||||
$prix = [];
|
|
||||||
|
|
||||||
$csrf_key = 'ajout_facture';
|
|
||||||
$fields = $facture->recu_fields;
|
|
||||||
|
|
||||||
$moyens_paiement = $facture->listMoyensPaiement(true);
|
|
||||||
|
|
||||||
$doc = null;
|
|
||||||
$require_number = $plugin->getConfig('pattern') ? false : true;
|
|
||||||
|
|
||||||
if (qg('copy') !== null && $f = $facture->get((int)qg('copy'))) {
|
|
||||||
$doc = (array) $f;
|
|
||||||
|
|
||||||
// Copié depuis facture_modifier.php
|
|
||||||
$doc['type'] = $f->type_facture;
|
|
||||||
$doc['numero_facture'] = '';
|
|
||||||
$doc['base_receveur'] = $f->receveur_membre ? 'membre' : 'client';
|
|
||||||
$doc['client'] = $f->receveur_id;
|
|
||||||
$doc['membre'] = $f->receveur_id;
|
|
||||||
|
|
||||||
if ( $f->type_facture == CERFA ) {
|
|
||||||
$doc['forme_don'] = $f->contenu['forme'];
|
|
||||||
$doc['nature_don'] = $f->contenu['nature'];
|
|
||||||
$doc['texte_don'] = $f->contenu['texte'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$tpl->assign('require_number', $require_number);
|
|
||||||
$tpl->assign('number_pattern', PATTERNS_LIST[$plugin->getConfig('pattern')]);
|
|
||||||
|
|
||||||
$tpl->assign('moyens_paiement', $moyens_paiement);
|
|
||||||
$tpl->assign('moyen_paiement', f('moyen_paiement') ?: 'ES');
|
|
||||||
|
|
||||||
$tpl->assign('formes_don', array('1' => 'Acte authentique',
|
|
||||||
'2' => 'Acte sous seing privé',
|
|
||||||
'3' => 'Don manuel',
|
|
||||||
'4' => 'Autres'));
|
|
||||||
$tpl->assign('natures_don', array('1' => 'Numéraire',
|
|
||||||
'2' => 'Chèque',
|
|
||||||
'3' => 'Virement, CB; ...'));
|
|
||||||
$tpl->assign('textes_don', $facture->listTextesCerfa());
|
|
||||||
|
|
||||||
if (f('save'))
|
|
||||||
{
|
|
||||||
$form->check($csrf_key, [
|
|
||||||
'type' => 'required|in:'.implode(',', [DEVIS, FACT, CERFA]),
|
|
||||||
'numero_facture' => $require_number ? 'required|string' : 'string',
|
|
||||||
'date_emission' => 'required|date_format:d/m/Y',
|
|
||||||
'date_echeance' => 'required|date_format:d/m/Y',
|
|
||||||
// 'reglee' => '',
|
|
||||||
// 'archivee' => '',
|
|
||||||
'base_receveur' => 'required|in:membre,client',
|
|
||||||
// 'client' => '',
|
|
||||||
// 'membre' => '',
|
|
||||||
'moyen_paiement' => 'required|in:' . implode(',', array_keys($moyens_paiement)),
|
|
||||||
'designation' => 'array|required',
|
|
||||||
'prix' => 'array|required'
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if ( count(f('designation')) !== count(f('prix')) )
|
|
||||||
{
|
|
||||||
throw new UserException('Nombre de désignations et de prix reçus différent.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$truc = [
|
|
||||||
'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
|
|
||||||
];
|
|
||||||
$truc['type_facture'] = f('type');
|
|
||||||
if (in_array(f('type'), [DEVIS, FACT]))
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
foreach(f('designation') as $k=>$value)
|
|
||||||
{
|
|
||||||
$truc['contenu'][$k]['designation'] = $value;
|
|
||||||
$truc['contenu'][$k]['prix'] = Utils::moneyToInteger(f('prix')[$k]);
|
|
||||||
$truc['toto'] += Utils::moneyToInteger(f('prix')[$k]);
|
|
||||||
}
|
|
||||||
$truc['total'] = $truc['toto'];
|
|
||||||
unset($truc['toto']);
|
|
||||||
}
|
|
||||||
elseif (f('type') == CERFA)
|
|
||||||
{
|
|
||||||
$truc['contenu'] = [
|
|
||||||
'forme' => f('forme_don'),
|
|
||||||
'nature' => f('nature_don'),
|
|
||||||
'texte' => f('texte_don')];
|
|
||||||
unset($truc['toto']);
|
|
||||||
$truc['total'] = Utils::moneyToInteger(f('total'));
|
|
||||||
}
|
|
||||||
if (f('base_receveur') == 'client')
|
|
||||||
{
|
|
||||||
$truc['receveur_membre'] = 0;
|
|
||||||
$truc['receveur_id'] = f('client');
|
|
||||||
}
|
|
||||||
elseif (f('base_receveur') == 'membre')
|
|
||||||
{
|
|
||||||
$truc['receveur_membre'] = 1;
|
|
||||||
$truc['receveur_id'] = f('membre');
|
|
||||||
}
|
|
||||||
|
|
||||||
$id = $facture->add($truc, $plugin->getConfig('pattern'));
|
|
||||||
|
|
||||||
Utils::redirect(PLUGIN_URL . 'facture.php?id='.(int)$id);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
elseif (f('select_cotis'))
|
|
||||||
{
|
|
||||||
$form->check('add_cotis_1',[
|
|
||||||
'numero_facture' => 'required|string',
|
|
||||||
'date_emission' => 'required|date_format:d/m/Y',
|
|
||||||
'membre_cotis' => 'required|numeric',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$step = true;
|
|
||||||
}
|
|
||||||
elseif (f('add_cotis'))
|
|
||||||
{
|
|
||||||
$form->check('add_cotis_2',[
|
|
||||||
'numero_facture' => 'required|string',
|
|
||||||
'date_emission' => 'required|date_format:d/m/Y',
|
|
||||||
'membre_cotis' => 'required|numeric',
|
|
||||||
'cotisation' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$radio['type'] = f('cotisation');
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
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];
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'type_facture' => COTIS,
|
|
||||||
'numero' => f('numero_facture'),
|
|
||||||
'receveur_membre' => 1,
|
|
||||||
'receveur_id' => f('membre_cotis'),
|
|
||||||
'date_emission' => f('date_emission'),
|
|
||||||
'moyen_paiement' => f('moyen_paiement'),
|
|
||||||
'total' => $r->paid_amount ?? $r->amount,
|
|
||||||
'contenu' => ['id' => $cotis['id'],
|
|
||||||
'intitule' => $cotis['label'],
|
|
||||||
'souscription' => $cotis['date'],
|
|
||||||
'expiration' => $cotis['expiry'] ]
|
|
||||||
];
|
|
||||||
|
|
||||||
$id = $facture->add($data, $plugin->getConfig('pattern'));
|
|
||||||
|
|
||||||
Utils::redirect(PLUGIN_URL . 'facture.php?id='.(int)$id);
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$step = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($step)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$liste = $facture->getCotis((int)f('membre_cotis'));
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$type = qg('t') ? (int) qg('t') : null;
|
|
||||||
|
|
||||||
if (in_array($type, [DEVIS, FACT, CERFA, COTIS], true))
|
|
||||||
{
|
|
||||||
$radio['type'] = $type;
|
|
||||||
}
|
|
||||||
elseif (null !== f('type'))
|
|
||||||
{
|
|
||||||
$radio['type'] = f('type');
|
|
||||||
}
|
|
||||||
elseif (isset($doc['type'])) {
|
|
||||||
$radio['type'] = $doc['type'];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$radio['type'] = FACT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$tpl->assign('types_details', $facture->types);
|
|
||||||
|
|
||||||
$tpl->assign('client_id', f('client') ?: -1);
|
|
||||||
$tpl->assign('membre_id', f('membre') ?: -1);
|
|
||||||
|
|
||||||
$from_user = false;
|
|
||||||
if (($d = f('designation')) && ($p = f('prix')) && implode($d))
|
|
||||||
{
|
|
||||||
foreach($d as $k=>$v)
|
|
||||||
{
|
|
||||||
if (empty($v) && empty($p[$k]))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$designations[] = $v;
|
|
||||||
$prix[] = $p[$k];
|
|
||||||
}
|
|
||||||
$from_user = true;
|
|
||||||
}
|
|
||||||
else if (!empty($doc['contenu'])) {
|
|
||||||
foreach($doc['contenu'] as $k=>$v)
|
|
||||||
{
|
|
||||||
if (empty($v['designation']) && empty($v['prix']))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$designations[] = $v['designation'];
|
|
||||||
$prix[] = $v['prix'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$designations = ['Exemple'];
|
|
||||||
$prix = [250];
|
|
||||||
}
|
|
||||||
|
|
||||||
$tpl->assign(compact('liste', 'radio', 'step'));
|
|
||||||
|
|
||||||
$date = new \DateTime;
|
|
||||||
$date->setTimestamp(time());
|
|
||||||
$tpl->assign('date', $date->format('d/m/Y'));
|
|
||||||
|
|
||||||
$tpl->assign(compact('designations', 'prix', 'from_user', 'identite', 'csrf_key', 'doc'));
|
|
||||||
$tpl->assign('membres', $db->getAssoc('SELECT id, '.$identite.' FROM membres WHERE id_category != -2 NOT IN (SELECT id FROM users_categories WHERE hidden = 1);'));
|
|
||||||
$tpl->assign('clients', $db->getAssoc('SELECT id, nom FROM plugin_facturation_clients;'));
|
|
||||||
|
|
||||||
$tpl->display(PLUGIN_ROOT . '/templates/facture_ajouter.tpl');
|
|
@ -1,291 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Garradin;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
|
||||||
|
|
||||||
use Garradin\DB;
|
|
||||||
|
|
||||||
$db = DB::getInstance();
|
|
||||||
|
|
||||||
$step = false;
|
|
||||||
$liste = [];
|
|
||||||
|
|
||||||
$moyens_paiement = $facture->listMoyensPaiement(true);
|
|
||||||
|
|
||||||
$tpl->assign('moyens_paiement', $moyens_paiement);
|
|
||||||
$tpl->assign('moyen_paiement', f('moyen_paiement') ?: 'ES');
|
|
||||||
|
|
||||||
$tpl->assign('formes_don', array('1' => 'Acte authentique',
|
|
||||||
'2' => 'Acte sous seing privé',
|
|
||||||
'3' => 'Don manuel',
|
|
||||||
'4' => 'Autres'));
|
|
||||||
$tpl->assign('natures_don', array('1' => 'Numéraire',
|
|
||||||
'2' => 'Chèque',
|
|
||||||
'3' => 'Virement, CB; ...'));
|
|
||||||
$tpl->assign('textes_don', $facture->listTextesCerfa());
|
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
|
||||||
$id = (int) qg('id');
|
|
||||||
|
|
||||||
if (!$f = $facture->get($id))
|
|
||||||
{
|
|
||||||
throw new UserException("Ce document n'existe pas.");
|
|
||||||
}
|
|
||||||
|
|
||||||
$csrf_key = 'modifier_facture';
|
|
||||||
|
|
||||||
// Traitement
|
|
||||||
|
|
||||||
if(f('save'))
|
|
||||||
{
|
|
||||||
$form->check($csrf_key, [
|
|
||||||
'type' => 'required|in:'.implode(',', [DEVIS, FACT, CERFA]),
|
|
||||||
'numero_facture' => 'required|string',
|
|
||||||
'date_emission' => 'required|date_format:d/m/Y',
|
|
||||||
'date_echeance' => 'required|date_format:d/m/Y',
|
|
||||||
// 'reglee' => '',
|
|
||||||
// 'archivee' => '',
|
|
||||||
'base_receveur' => 'required|in:membre,client',
|
|
||||||
// 'client' => '',
|
|
||||||
// 'membre' => '',
|
|
||||||
'moyen_paiement' => 'required|in:' . implode(',', array_keys($moyens_paiement)),
|
|
||||||
'designation' => 'array|required',
|
|
||||||
'prix' => 'array|required'
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if ( count(f('designation')) !== count(f('prix')) )
|
|
||||||
{
|
|
||||||
throw new UserException('Nombre de désignations et de prix reçus différent.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$truc = [
|
|
||||||
'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
|
|
||||||
];
|
|
||||||
$truc['type_facture'] = f('type');
|
|
||||||
|
|
||||||
if (in_array(f('type'), [DEVIS, FACT]))
|
|
||||||
{
|
|
||||||
foreach(f('designation') as $k=>$value)
|
|
||||||
{
|
|
||||||
$truc['contenu'][$k]['designation'] = $value;
|
|
||||||
$truc['contenu'][$k]['prix'] = Utils::moneyToInteger(f('prix')[$k]);
|
|
||||||
$truc['toto'] += Utils::moneyToInteger(f('prix')[$k]);
|
|
||||||
|
|
||||||
}
|
|
||||||
$truc['total'] = $truc['toto'];
|
|
||||||
unset($truc['toto']);
|
|
||||||
}
|
|
||||||
elseif ( f('type') == CERFA )
|
|
||||||
{
|
|
||||||
$truc['contenu'] = [
|
|
||||||
'forme' => f('forme_don'),
|
|
||||||
'nature' => f('nature_don'),
|
|
||||||
'texte' => f('texte_don')];
|
|
||||||
$truc['total'] = Utils::moneyToInteger(f('total'));
|
|
||||||
unset($truc['toto']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (f('base_receveur') == 'client')
|
|
||||||
{
|
|
||||||
$truc['receveur_membre'] = 0;
|
|
||||||
$truc['receveur_id'] = f('client');
|
|
||||||
}
|
|
||||||
elseif (f('base_receveur') == 'membre')
|
|
||||||
{
|
|
||||||
$truc['receveur_membre'] = 1;
|
|
||||||
$truc['receveur_id'] = f('membre');
|
|
||||||
}
|
|
||||||
|
|
||||||
$r = $facture->edit($id, $truc);
|
|
||||||
|
|
||||||
Utils::redirect(PLUGIN_URL . 'facture.php?id='.(int)$id);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Cotis
|
|
||||||
|
|
||||||
$fields = $facture->recu_fields;
|
|
||||||
|
|
||||||
$membre_id = f('membre') ?: $f->receveur_id;
|
|
||||||
|
|
||||||
$values['numero_facture'] = $f->numero;
|
|
||||||
$values['date_emission'] = $f->date_emission;
|
|
||||||
|
|
||||||
$radio = $liste = [];
|
|
||||||
|
|
||||||
if (f('select_cotis'))
|
|
||||||
{
|
|
||||||
$form->check('add_cotis_1',[
|
|
||||||
'numero_facture' => 'required|string',
|
|
||||||
'date_emission' => 'required|date_format:d/m/Y',
|
|
||||||
'membre_cotis' => 'required|numeric',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$step = true;
|
|
||||||
}
|
|
||||||
elseif (f('add_cotis'))
|
|
||||||
{
|
|
||||||
$form->check('add_cotis_2',[
|
|
||||||
'numero_facture' => 'required|string',
|
|
||||||
'date_emission' => 'required|date_format:d/m/Y',
|
|
||||||
'membre_cotis' => 'required|numeric',
|
|
||||||
'cotisation' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$radio['type'] = f('cotisation');
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
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];
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'type_facture' => 3,
|
|
||||||
'numero' => f('numero_facture'),
|
|
||||||
'receveur_membre' => 1,
|
|
||||||
'receveur_id' => f('membre_cotis'),
|
|
||||||
'date_emission' => f('date_emission'),
|
|
||||||
'moyen_paiement' => f('moyen_paiement'),
|
|
||||||
'total' => $r->paid_amount ?? $r->amount,
|
|
||||||
'contenu' => ['id' => $cotis['id'],
|
|
||||||
'intitule' => $cotis['label'],
|
|
||||||
'souscription' => $cotis['date'],
|
|
||||||
'expiration' => $cotis['expiry'] ]
|
|
||||||
];
|
|
||||||
|
|
||||||
if($facture->edit($id, $data))
|
|
||||||
{
|
|
||||||
Utils::redirect(PLUGIN_URL . 'facture.php?id='.(int)$id);
|
|
||||||
}
|
|
||||||
throw new UserException('Erreur d\'édition du reçu');
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$step = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($step)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$liste = $facture->getCotis((int)f('membre_cotis'));
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Affichage
|
|
||||||
|
|
||||||
// $doc['moyen_paiement'] = $doc['moyens_paiement'][$f->moyen_paiement];
|
|
||||||
$doc['moyen_paiement'] = $f->moyen_paiement;
|
|
||||||
$doc['type'] = $f->type_facture;
|
|
||||||
$doc['numero_facture'] = $f->numero;
|
|
||||||
$doc['reglee'] = $f->reglee;
|
|
||||||
$doc['base_receveur'] = $f->receveur_membre?'membre':'client';
|
|
||||||
$doc['client'] = $f->receveur_id;
|
|
||||||
$doc['membre'] = $f->receveur_id;
|
|
||||||
|
|
||||||
$doc['date_emission'] = strtotime(f('date_emission')) ?: $f->date_emission;
|
|
||||||
$doc['date_echeance'] = strtotime(f('date_echeance')) ?: $f->date_echeance; // Smarty m'a saoulé pour utiliser form_field|date_fr:---
|
|
||||||
/* modif DD -- CERFA -------------------------------------- */
|
|
||||||
if ( $f->type_facture == CERFA ) {
|
|
||||||
$doc['total'] = $f->total;
|
|
||||||
$doc['forme_don'] = $f->contenu['forme'];
|
|
||||||
$doc['nature_don'] = $f->contenu['nature'];
|
|
||||||
$doc['texte_don'] = $f->contenu['texte'];
|
|
||||||
}
|
|
||||||
$tpl->assign('doc', $doc);
|
|
||||||
|
|
||||||
$radio['type'] = f('type')??$doc['type'];
|
|
||||||
$tpl->assign('types_details', $facture->types);
|
|
||||||
|
|
||||||
$tpl->assign('client_id', f('client') ?: -1);
|
|
||||||
$tpl->assign('membre_id', f('membre') ?: -1);
|
|
||||||
|
|
||||||
$tpl->assign(compact('liste', 'radio', 'step'));
|
|
||||||
|
|
||||||
$designations = [];
|
|
||||||
$prix = [];
|
|
||||||
|
|
||||||
// C'est un peu l'équivalent de form_field, mais j'avais écrit ça avant
|
|
||||||
// et oulala, c'est un peu complexe, faudrait réfléchir keskivomieux
|
|
||||||
$from_user = false;
|
|
||||||
if (in_array($f->type_facture, [DEVIS, FACT]))
|
|
||||||
{
|
|
||||||
if (($d = f('designation')) && ($p = f('prix')))
|
|
||||||
{
|
|
||||||
foreach($d as $k=>$v)
|
|
||||||
{
|
|
||||||
if (empty($v) && empty($p[$k]))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$designations[] = $v;
|
|
||||||
$prix[] = $p[$k];
|
|
||||||
}
|
|
||||||
$from_user = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach($f->contenu as $k=>$v)
|
|
||||||
{
|
|
||||||
if (empty($v['designation']) && empty($v['prix']))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$designations[] = $v['designation'];
|
|
||||||
$prix[] = $v['prix'];
|
|
||||||
}
|
|
||||||
$from_user = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$tpl->assign(compact('designations', 'prix', 'from_user', 'identite', 'csrf_key'));
|
|
||||||
$tpl->assign('membres', $db->getAssoc('SELECT id, '.$identite.' FROM membres WHERE id_category != -2 NOT IN (SELECT id FROM users_categories WHERE hidden = 1);'));
|
|
||||||
$tpl->assign('clients', $db->getAssoc('SELECT id, nom FROM plugin_facturation_clients;'));
|
|
||||||
|
|
||||||
$date = new \DateTime;
|
|
||||||
$date->setTimestamp(time());
|
|
||||||
$tpl->assign('date', $date->format('d/m/Y'));
|
|
||||||
|
|
||||||
$tpl->assign('require_number', true);
|
|
||||||
|
|
||||||
$tpl->display(PLUGIN_ROOT . '/templates/facture_modifier.tpl');
|
|
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Garradin;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_inc.php';
|
|
||||||
|
|
||||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
|
||||||
|
|
||||||
qv(['id' => 'required|numeric']);
|
|
||||||
|
|
||||||
$id = (int) qg('id');
|
|
||||||
|
|
||||||
$f = $facture->get($id);
|
|
||||||
|
|
||||||
if (!$client)
|
|
||||||
{
|
|
||||||
throw new UserException("Ce document n'existe pas.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f('delete'))
|
|
||||||
{
|
|
||||||
$form->check('delete_doc_'.$f->id);
|
|
||||||
|
|
||||||
if (!$form->hasErrors())
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$facture->delete($f->id);
|
|
||||||
Utils::redirect(PLUGIN_URL . 'index.php');
|
|
||||||
}
|
|
||||||
catch (UserException $e)
|
|
||||||
{
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$tpl->assign('doc', $f);
|
|
||||||
$tpl->display(PLUGIN_ROOT . '/templates/facture_supprimer.tpl');
|
|
Loading…
Reference in New Issue
Block a user