diff --git a/lib/Client.php b/lib/Client.php index 1bd92b6..d914047 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -3,6 +3,7 @@ namespace Garradin\Plugin\Facturation; use Garradin\DB; +use Garradin\DynamicList; use Garradin\Plugin; use Garradin\UserException; use Garradin\Utils; @@ -103,6 +104,44 @@ class Client return DB::getInstance()->get('SELECT *, strftime(\'%s\', date_creation) AS date_creation FROM plugin_facturation_clients'); } + public function list(): DynamicList + { + $columns = [ + 'id' => [ + 'label' => 'Numéro', + ], + 'nom' => [ + 'label' => 'Nom', + ], + 'adresse' => [ + 'label' => 'Adresse', + ], + 'code_postal' => [ + 'label' => 'Code postal', + ], + 'ville' => [ + 'label' => 'Ville', + ], + 'telephone' => [ + 'label' => 'Téléphone', + ], + 'email' => [ + 'label' => 'E-Mail', + ], + 'nb_documents' => [ + 'label' => 'Nombre de documents', + 'select' => '(SELECT COUNT(*) FROM plugin_facturation_factures WHERE receveur_id = c.id)', + ], + ]; + + $tables = 'plugin_facturation_clients AS c'; + + $list = new DynamicList($columns, $tables); + $list->orderBy('id', false); + $list->setPageSize(1000); + return $list; + } + public function edit($id, $data = []) { $db = DB::getInstance(); @@ -117,15 +156,15 @@ class Client return $db->update('plugin_facturation_clients', $data, $db->where('id', (int)$id)); } - public function isDeletable($id) + public function isDeletable($id): bool { $f = new Facture; - return $f->hasDocs(0, $id); + return !$f->hasDocs(0, $id); } public function delete($id) { - if($this->isDeletable($id)) + if(!$this->isDeletable($id)) { return false; } diff --git a/lib/Facture.php b/lib/Facture.php index dedf83b..017db78 100644 --- a/lib/Facture.php +++ b/lib/Facture.php @@ -3,12 +3,22 @@ namespace Garradin\Plugin\Facturation; use DateTime; +use Garradin\Config; use Garradin\DB; +use Garradin\DynamicList; use Garradin\UserException; +use Garradin\Utils; use Garradin\Services\Services_User; class Facture { + const TYPES_NAMES = [ + DEVIS => 'Devis', + FACT => 'Facture', + CERFA => 'Reçu fiscal', + COTIS => 'Reçu de cotisation', + ]; + private $keys = [ 'type_facture', // 0 : devis, 1 : facture, 2 : reçu cerfa, 3 : reçu cotis 'numero', @@ -235,6 +245,103 @@ class Facture return $r; } + public function list(): DynamicList + { + $id_field = Config::getInstance()->champ_identite; + + $columns = [ + // Sélectionner cette colonne, mais ne pas la mettre dans la liste des colonnes + // (absence de label) + 'id' => [ + 'select' => 'f.id', + ], + 'type_facture' => [ + ], + 'receveur_membre' => [ + ], + 'receveur_id' => [ + ], + // Créer une colonne virtuelle + 'type' => [ + 'label' => 'Type', + 'select' => null, + ], + 'numero' => [ + 'label' => 'Numéro', + 'select' => 'f.numero', + ], + 'receveur' => [ + 'label' => 'Receveur', + 'select' => sprintf('CASE WHEN receveur_membre THEN u.%s ELSE c.nom END', $id_field), + ], + 'receveur_adresse' => [ + 'label' => 'Son adresse', + 'select' => 'CASE WHEN receveur_membre THEN u.adresse ELSE c.adresse END', + ], + 'receveur_ville' => [ + 'label' => 'Sa ville', + 'select' => 'CASE WHEN receveur_membre THEN u.ville ELSE c.ville END', + ], + 'date_emission' => [ + 'label' => 'Émission', + ], + 'date_echeance' => [ + 'label' => 'Échéance', + ], + 'reglee' => [ + 'label' => 'Réglée', + ], + 'archivee' => [ + 'label' => 'Archivée', + ], + 'moyen_paiement' => [ + 'label' => 'Moyen de paiement', + 'select' => 'mp.nom', + ], + 'contenu' => [ + 'label' => 'Contenu', + ], + 'total' => [ + 'label' => 'Total', + ], + ]; + + $tables = 'plugin_facturation_factures AS f + 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 plugin_facturation_clients AS c ON f.receveur_membre = 0 AND c.id = f.receveur_id'; + + $list = new DynamicList($columns, $tables); + $list->orderBy('numero', true); + + $currency = Config::getInstance()->monnaie; + + $list->setModifier(function ($row) use ($currency) { + // Remplir la colonne virtuelle + $row->type = self::TYPES_NAMES[$row->type_facture] ?? null; + $row->reglee = $row->reglee ? 'Réglée' : 'Non'; + $row->archivee = $row->archivee ? 'Archivée' : 'Non'; + + // Remplir le contenu + $content = json_decode((string)$row->contenu); + + if ($row->type_facture == COTIS && isset($content->intitule, $content->souscription)) { + $row->contenu = sprintf("Cotisation %s\nSouscrite le %s", + $content->intitule, + Utils::date_fr($content->souscription, 'd/m/Y') + ); + } + else { + $row->contenu = implode("\n", array_map(function ($row) use ($currency) { + return sprintf('%s : %s %s', $row->designation, Utils::money_format($row->prix), $currency); + }, (array)$content)); + } + }); + + $list->setPageSize(1000); + return $list; + } + public function edit($id, $data = []) { $db = DB::getInstance(); @@ -296,7 +403,7 @@ class Facture throw new UserException("Woopsie, g pô encore implémenté l'usage des membres de l'asso comme clients"); } - return DB::getInstance()->test('plugin_facturation_factures', 'receveur_membre = '. $base .' AND receveur_id = '. $id); + return DB::getInstance()->test('plugin_facturation_factures', 'receveur_membre = ? AND receveur_id = ?', $base, $id); } // ** Pour type reçu ** @@ -348,5 +455,4 @@ class Facture { return DB::getInstance()->delete('plugin_facturation_factures', 'id = '. (int)$id); } - } diff --git a/templates/_js.tpl b/templates/_js.tpl index 53b96d5..301ddae 100644 --- a/templates/_js.tpl +++ b/templates/_js.tpl @@ -4,10 +4,14 @@ function updateSum(){ var total = 0; e = document.querySelectorAll('input[name="prix[]"]'); - e.forEach( function sum(item, index){ - total = total + Number(item.value); + e.forEach((item) => { + if (!item.value) { + return; + } + + total += g.getMoneyAsInt(item.value); }); - document.getElementById('total').innerHTML = total.toFixed(2); + document.getElementById('total').innerHTML = g.formatMoney(total); } (function () { @@ -21,6 +25,7 @@ this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); updateSum(); }; + newdiv.getElementsByTagName('input')[0].onkeyup = updateSum; document.getElementById('Lines').appendChild(newdiv); } plus(); @@ -40,10 +45,14 @@ function changeTypeSaisie(type) { g.toggle(['.type_client', '.type_membre'], false); - g.toggle('.type_' + type, true); + + if (type) { + g.toggle('.type_' + type, true); + } } - changeTypeSaisie(document.forms[0].base_receveur.value); + const form = document.querySelector('#f_numero_facture').form; + changeTypeSaisie(form.base_receveur.value); var inputs = $('input[name="base_receveur"]'); @@ -83,7 +92,6 @@ g.toggle(e, true); g.toggle('p.submit', true); }); - console.log(e.value); selectType(e.value); }; }); diff --git a/templates/client.tpl b/templates/client.tpl index e30dc2b..fbf2dd1 100644 --- a/templates/client.tpl +++ b/templates/client.tpl @@ -1,22 +1,22 @@ {include file="admin/_head.tpl" title="Client — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=0} {include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client"} -
{$client.id}
{$client.nom|escape|rtrim|nl2br}
- +{$client.adresse|escape|rtrim|nl2br}
{$client.ville|escape|rtrim|nl2br}
{$client.code_postal|escape|rtrim|nl2br}
{$contenu.designation} : {$contenu.prix|escape|money} {$config.monnaie}
+ {$contenu.designation} : {$contenu.prix|escape|money_currency} {/foreach}Ce client n'a pas de document associé.
{/if} {include file="admin/_foot.tpl"} \ No newline at end of file diff --git a/templates/client_modifier.tpl b/templates/client_modifier.tpl index 60c84a7..42dac42 100644 --- a/templates/client_modifier.tpl +++ b/templates/client_modifier.tpl @@ -7,24 +7,18 @@{csrf_field key="edit_client"} - + {button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
diff --git a/templates/client_supprimer.tpl b/templates/client_supprimer.tpl index 75dbfea..991ccf7 100644 --- a/templates/client_supprimer.tpl +++ b/templates/client_supprimer.tpl @@ -1,30 +1,15 @@ {include file="admin/_head.tpl" title="Supprimer un client — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=0} {include file="%s/templates/_menu_client.tpl"|args:$plugin_root current="client_supprimer"} - -{form_errors} - {if !$deletable} - +Ce/cette client·e ne peut pas être supprimé·e car des documents lui y sont liés.
{else} -Ce/cette client·e ne peut pas être supprimé·e car des documents lui y sont liés.
+ + {include file="common/delete_form.tpl" + legend="Supprimer ce client ?" + warning="Êtes-vous sûr de vouloir supprimer le client « %s » ?"|args:$client.nom + alert="Attention, cette action est irréversible."} + {/if} {include file="admin/_foot.tpl"} \ No newline at end of file diff --git a/templates/clients.tpl b/templates/clients.tpl index 3cf12cb..af1e1ce 100644 --- a/templates/clients.tpl +++ b/templates/clients.tpl @@ -1,77 +1,65 @@ {include file="admin/_head.tpl" title="Clients — %s"|args:$plugin.nom current="plugin_%s"|args:$plugin.id js=1} {include file="%s/templates/_menu.tpl"|args:$plugin_root current="clients"} -{form_errors} +{if $list->count()} + {include file="common/dynamic_list_head.tpl"} - - +{form_errors} diff --git a/templates/config.tpl b/templates/config.tpl index 4ec6e20..286582c 100644 --- a/templates/config.tpl +++ b/templates/config.tpl @@ -51,9 +51,7 @@ diff --git a/templates/facture.tpl b/templates/facture.tpl index 4c29ed8..5c26840 100644 --- a/templates/facture.tpl +++ b/templates/facture.tpl @@ -9,9 +9,11 @@ {linkbutton shape="download" href="%spdf.php?d&id=%d"|args:$plugin_url,$facture.id label="Télécharger ce document"} +{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"} +{/if}