Merge branch 'duplicate' from bohwaz
Duplication de document et numérotation automatique See merge request ramoloss/garradin-plugin-facturation!5
This commit is contained in:
commit
ec1b1f3c65
@ -1,3 +1,3 @@
|
||||
{
|
||||
|
||||
'pattern': '%{type}-%{year}-%{ynumber}'
|
||||
}
|
@ -75,7 +75,7 @@ class Facture
|
||||
if(!is_array($data)){
|
||||
$datas[$k] = trim($data);
|
||||
}
|
||||
if ($datas[$k] === '')
|
||||
if ($datas[$k] === '' && $k != 'numero')
|
||||
{
|
||||
throw new UserException("La valeur de $k est vide");
|
||||
}
|
||||
@ -189,18 +189,70 @@ class Facture
|
||||
}
|
||||
}
|
||||
|
||||
public function add($data)
|
||||
public function add($data, ?string $number_pattern = null)
|
||||
{
|
||||
$db = DB::getInstance();
|
||||
|
||||
$this->_checkFields($data);
|
||||
$generate_number = false;
|
||||
|
||||
if(isset($data['numero']) && $db->test('plugin_facturation_factures', 'numero = ? COLLATE NOCASE', $data['numero']))
|
||||
if (empty($data['numero']) && $number_pattern) {
|
||||
$generate_number = true;
|
||||
$data['numero'] = sha1(random_bytes(10));
|
||||
}
|
||||
|
||||
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.');
|
||||
}
|
||||
|
||||
$db->insert('plugin_facturation_factures', $data);
|
||||
return $db->lastInsertRowId();
|
||||
$id = $db->lastInsertRowId();
|
||||
|
||||
if ($generate_number) {
|
||||
$numero = $this->getNewNumber($number_pattern, $data['type_facture'], \DateTime::createFromFormat('!Y-m-d', $data['date_emission']), $id);
|
||||
$db->update('plugin_facturation_factures', compact('numero'), 'id = ' . (int) $id);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie un nouveau numéro de facture selon un motif défini et le type de document
|
||||
*/
|
||||
public function getNewNumber(string $pattern, int $type, \DateTimeInterface $date, int $id)
|
||||
{
|
||||
if ($type == DEVIS) {
|
||||
$type = 'DEVIS';
|
||||
$t = 'D';
|
||||
}
|
||||
elseif ($type == FACT) {
|
||||
$type = 'FACT';
|
||||
$t = 'F';
|
||||
}
|
||||
elseif ($type == CERFA) {
|
||||
$type = 'CERFA';
|
||||
$t = 'RF';
|
||||
}
|
||||
else {
|
||||
$type = 'COTIS';
|
||||
$t = 'RC';
|
||||
}
|
||||
|
||||
$year = $date->format('Y');
|
||||
$y = $date->format('y');
|
||||
|
||||
// On récupère le nombre de documents pour cette année
|
||||
// vu qu'on vient d'ajouter un document, celui-ci est bien le dernier numéro
|
||||
$ynumber = DB::getInstance()->count('plugin_facturation_factures', 'strftime(\'%Y\', date_emission) = ?', (string) $year);
|
||||
|
||||
$data = compact('type', 't', 'year', 'y', 'ynumber', 'id');
|
||||
|
||||
return preg_replace_callback('/%(\d+)?\{([a-z]+)\}/', function ($match) use ($data) {
|
||||
$v = $data[$match[2]];
|
||||
$type = ctype_digit($data[$match[2]]) ? 'd' : 's';
|
||||
return sprintf('%' . $match[1] . $type, $v);
|
||||
}, $pattern);
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
@ -284,6 +336,7 @@ class Facture
|
||||
],
|
||||
'date_emission' => [
|
||||
'label' => 'Émission',
|
||||
'order' => 'date_emission %s, id %1$s',
|
||||
],
|
||||
'date_echeance' => [
|
||||
'label' => 'Échéance',
|
||||
@ -312,7 +365,7 @@ class Facture
|
||||
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);
|
||||
$list->orderBy('date_emission', true);
|
||||
|
||||
$currency = Config::getInstance()->monnaie;
|
||||
|
||||
|
228
templates/_form.tpl
Normal file
228
templates/_form.tpl
Normal file
@ -0,0 +1,228 @@
|
||||
{form_errors}
|
||||
|
||||
<form method="post" action="{$self_url}">
|
||||
|
||||
<fieldset>
|
||||
<legend>Type d'écriture</legend>
|
||||
<dl>
|
||||
{foreach from=$types_details item="type"}
|
||||
<dd class="radio-btn">
|
||||
{input type="radio" name="type" value=$type.id source=$radio label=null}
|
||||
<label for="f_type_{$type.id}">
|
||||
<div>
|
||||
<h3>{$type.label}</h3>
|
||||
{if !empty($type.help)}
|
||||
<p>{$type.help}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</label>
|
||||
</dd>
|
||||
{/foreach}
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend data-types="t0">Créer un devis</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>
|
||||
|
||||
{input type="text" name="numero_facture" maxlength=12 label="Numéro du document" required=$require_number source=$doc}
|
||||
|
||||
<dd class="help">
|
||||
{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.
|
||||
{else}
|
||||
Laisser vide pour qu'un numéro soit automatiquement affecté au format <code>{$number_pattern}</code>.
|
||||
{/if}
|
||||
|
||||
{input type="date" name="date_emission" default=$date label="Date d'émission" required=1 source=$doc}
|
||||
<dd class="help" data-types="t2">
|
||||
<p>Date du versemen du don</p>
|
||||
</dd>
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="date" name="date_echeance" default=$date label="Date d'échéance" required=1 source=$doc}
|
||||
<dd class="help" data-types="t2">
|
||||
<p>Date d'établissement du document</p>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<dt><label>Statut</label></dt>
|
||||
|
||||
{input type="checkbox" name="reglee" value="1" label="Réglée" source=$doc data-types="t1"}
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="checkbox" name="archivee" value="1" label="Archivée" source=$doc disabled="disabled"}
|
||||
</div>
|
||||
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset data-types="t0 t1 t2">
|
||||
<legend>Client</legend>
|
||||
|
||||
<dl>
|
||||
<dt><label>Document adressé à :</label></dt>
|
||||
{if !empty($clients)}
|
||||
<dd>
|
||||
{input type="radio" name="base_receveur" value="membre" label="Un·e membre" default=1 source=$doc}
|
||||
{input type="radio" name="base_receveur" value="client" label="Un·e client·e" source=$doc}
|
||||
</dd>
|
||||
{/if}
|
||||
</dl>
|
||||
|
||||
<dl class="type_membre">
|
||||
{input type="select" name="membre" label="Membre" options=$membres required=1 source=$doc}
|
||||
</dl>
|
||||
|
||||
{if !empty($clients)}
|
||||
<dl class="type_client">
|
||||
{input type="select" name="client" label="Client" options=$clients required=1 class="type_client" source=$doc}
|
||||
</dl>
|
||||
{else}
|
||||
<input type="hidden" name="base_receveur" value="membre" />
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
||||
<fieldset data-types="t0 t1 t2">
|
||||
<legend>Contenu</legend>
|
||||
|
||||
<dl>
|
||||
{input type="select" name="moyen_paiement" required=1 label="Moyen de paiement" source=$doc options=$moyens_paiement default="ES"}
|
||||
|
||||
<dt><label for="f_contenu">Contenu du document</label><dt>
|
||||
<dd>
|
||||
<table class="list" style="max-width: 800px;">
|
||||
<colgroup>
|
||||
<col width="65%">
|
||||
<col width="33%">
|
||||
<col width="2%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Désignation</td>
|
||||
<td>Prix</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="Lines">
|
||||
{if count($designations) > 0}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
|
||||
{foreach from=$designations item=designation key=key}
|
||||
<tr>
|
||||
<td><textarea name="designation[]" style="width:98%;">{$designation}</textarea></td>
|
||||
{money_fac value=$prix[$key] user=$from_user}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td style="text-align: right;">Total :</td>
|
||||
<td><span id="total">0.00</span> €</td>
|
||||
<td>{button label="Ajouter" title="Ajouter une ligne" id="ajouter_ligne" shape="plus"}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t0 t1 t2">
|
||||
{csrf_field key=$csrf_key}
|
||||
{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
|
||||
</p>
|
||||
|
||||
<fieldset data-types="t3">
|
||||
<legend>Membre</legend>
|
||||
<dl>
|
||||
<dt><label>Reçu adressée à :</label></dt>
|
||||
<dd>
|
||||
{input type="select" name="membre_cotis" label="Membre" options=$membres required=1 default=$doc.membre}
|
||||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t3">
|
||||
{csrf_field key="add_cotis_1"}
|
||||
{button type="submit" name="select_cotis" label="Sélectionner" shape="right" class="main"}
|
||||
</p>
|
||||
|
||||
|
||||
{if $step}
|
||||
<fieldset data-types="t3">
|
||||
<legend>Cotisation</legend>
|
||||
{if count($liste)}
|
||||
<dl>
|
||||
<dt>Sélectionnez la cotisation concernée :</dt>
|
||||
|
||||
<table class='list'>
|
||||
<thead>
|
||||
<td></td>
|
||||
<td>Id</td>
|
||||
<td>Intitulé</td>
|
||||
<td>Date d'inscription</td>
|
||||
<td>Expiration d'expiration</td>
|
||||
<td>Tarif</td>
|
||||
<td>Montant</td>
|
||||
<td>Somme payée</td>
|
||||
</thead>
|
||||
|
||||
{foreach from=$liste item=cotis key=i}
|
||||
{if !$cotis.paid}
|
||||
{continue}
|
||||
{/if}
|
||||
<tr>
|
||||
<td>
|
||||
{input type="radio" name="cotisation" value="%s"|args:$i}
|
||||
</td>
|
||||
{foreach from=$cotis item=element key=key}
|
||||
{if $key == 'paid'}
|
||||
{continue}
|
||||
{/if}
|
||||
<td>
|
||||
<label for="f_cotisation_{$i}">
|
||||
{if ($key == 'date' || $key == 'expiry') && $element > 0}
|
||||
{$element|date_short}
|
||||
{elseif $key == 'amount' OR $key == 'paid_amount'}
|
||||
{$element|raw|money_currency}
|
||||
{else}
|
||||
{$element}
|
||||
{/if}
|
||||
|
||||
<input type="hidden" name="{$key}_{$i}" value="{$element}">
|
||||
</label>
|
||||
</td>
|
||||
{/foreach}
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t3">
|
||||
{csrf_field key="add_cotis_2"}
|
||||
{button type="submit" name="add_cotis" label="Enregistrer" shape="right" class="main"}
|
||||
</p>
|
||||
{else}
|
||||
<p>Ce membre n'a aucune cotisation payée.</p>
|
||||
</fieldset>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</form>
|
||||
|
||||
{include file="%s/templates/_js.tpl"|args:$plugin_root}
|
@ -20,10 +20,10 @@
|
||||
<fieldset>
|
||||
<legend>Adresse</legend>
|
||||
<dl>
|
||||
{input type="text" name="numero_rue_asso" source=$plugin.config label="Numéro de rue" required=1 maxlength=5}
|
||||
{input type="text" name="rue_asso" source=$plugin.config label="Nom de rue" required=1}
|
||||
{input type="text" name="cp_asso" source=$plugin.config label="Code postal" required=1}
|
||||
{input type="text" name="ville_asso" source=$plugin.config label="Ville" required=1}
|
||||
{input type="text" name="numero_rue_asso" source=$plugin.config label="Numéro de rue" maxlength=5}
|
||||
{input type="text" name="rue_asso" source=$plugin.config label="Nom de rue"}
|
||||
{input type="text" name="cp_asso" source=$plugin.config label="Code postal"}
|
||||
{input type="text" name="ville_asso" source=$plugin.config label="Ville"}
|
||||
</dl>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
@ -60,6 +60,10 @@
|
||||
<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="unique_client_name" value="1" source=$plugin.config label="Noms des clients uniques"}
|
||||
{input type="select" name="pattern" label="Format de numéro de document" required=false options=$patterns source=$plugin.config}
|
||||
<dd class="help">
|
||||
F = Facture, D = Devis, RF = Reçu fiscal, RC = Reçu cotisation
|
||||
</dd>
|
||||
</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>
|
||||
</fieldset>
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
{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="plus" href="%sfacture_ajouter.php?copy=%d"|args:$plugin_url,$facture.id label="Dupliquer ce document"}
|
||||
{/if}
|
||||
|
||||
{linkbutton shape="download" href="%spdf.php?d&id=%d"|args:$plugin_url,$facture.id label="Télécharger ce document"}
|
||||
|
@ -1,232 +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="%s/templates/_menu.tpl"|args:$plugin_root current="facture"}
|
||||
|
||||
{form_errors}
|
||||
|
||||
<form method="post" action="{$self_url}">
|
||||
|
||||
<fieldset>
|
||||
<legend>Type d'écriture</legend>
|
||||
<dl>
|
||||
{foreach from=$types_details item="type"}
|
||||
<dd class="radio-btn">
|
||||
{input type="radio" name="type" value=$type.id source=$radio label=null}
|
||||
<label for="f_type_{$type.id}">
|
||||
<div>
|
||||
<h3>{$type.label}</h3>
|
||||
{if !empty($type.help)}
|
||||
<p>{$type.help}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</label>
|
||||
</dd>
|
||||
{/foreach}
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend data-types="t0">Créer un devis</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>
|
||||
|
||||
{input type="text" name="numero_facture" maxlength=12 label="Numéro du document" required=1 help="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."}
|
||||
|
||||
{input type="date" name="date_emission" default=$date label="Date d'émission" required=1 }
|
||||
<dd class="help" data-types="t2">
|
||||
<p>Date du versemen du don</p>
|
||||
</dd>
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="date" name="date_echeance" default=$date label="Date d'échéance" required=1 }
|
||||
<dd class="help" data-types="t2">
|
||||
<p>Date d'établissement du document</p>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<dt><label>Statut</label></dt>
|
||||
|
||||
{input type="checkbox" name="reglee" value="" label="Réglée" data-types="t1"}
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="checkbox" name="archivee" value="" label="Archivée" disabled="disabled"}
|
||||
</div>
|
||||
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset data-types="t0 t1 t2">
|
||||
<legend>Client</legend>
|
||||
|
||||
<dl>
|
||||
<dt><label>Document adressé à :</label></dt>
|
||||
{if !empty($clients)}
|
||||
<dd>
|
||||
{input type="radio" name="base_receveur" value="membre" label="Un·e membre" default=1}
|
||||
{input type="radio" name="base_receveur" value="client" label="Un·e client·e"}
|
||||
</dd>
|
||||
{/if}
|
||||
</dl>
|
||||
|
||||
<dl class="type_membre">
|
||||
{input type="select" name="membre" label="Membre" options=$membres required=1}
|
||||
</dl>
|
||||
|
||||
{if !empty($clients)}
|
||||
<dl class="type_client">
|
||||
{input type="select" name="client" label="Client" options=$clients required=1 class="type_client"}
|
||||
</dl>
|
||||
{else}
|
||||
<input type="hidden" name="base_receveur" value="membre" />
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
||||
<fieldset data-types="t0 t1 t2">
|
||||
<legend>Contenu</legend>
|
||||
|
||||
<dl>
|
||||
<dt><label for="f_moyen_paiement">Moyen de paiement</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
|
||||
<dd>
|
||||
<select name="moyen_paiement" id="f_moyen_paiement" required="required">
|
||||
{foreach from=$moyens_paiement item="moyen"}
|
||||
<option value="{$moyen.code}"{if $moyen.code == $moyen_paiement} selected="selected"{/if}>{$moyen.nom}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</dd>
|
||||
|
||||
<dt><label for="f_contenu">Contenu du document</label><dt>
|
||||
<dd>
|
||||
<table class="list" style="max-width: 800px;">
|
||||
<colgroup>
|
||||
<col width="65%">
|
||||
<col width="33%">
|
||||
<col width="2%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Désignation</td>
|
||||
<td>Prix</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="Lines">
|
||||
{if count($designations) > 0}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
|
||||
{foreach from=$designations item=designation key=key}
|
||||
<tr>
|
||||
<td><textarea name="designation[]" style="width:98%;">{$designation}</textarea></td>
|
||||
{money_fac value=$prix[$key] user=$from_user}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td style="text-align: right;">Total :</td>
|
||||
<td><span id="total">0.00</span> €</td>
|
||||
<td>{button label="Ajouter" title="Ajouter une ligne" id="ajouter_ligne" shape="plus"}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t0 t1 t2">
|
||||
{csrf_field key="ajout_facture"}
|
||||
{button type="submit" name="add" label="Enregistrer" shape="right" class="main"}
|
||||
</p>
|
||||
|
||||
<fieldset data-types="t3">
|
||||
<legend>Membre</legend>
|
||||
<dl>
|
||||
<dt><label>Reçu adressée à :</label></dt>
|
||||
<dd>
|
||||
{input type="select" name="membre_cotis" label="Membre" options=$membres required=1}
|
||||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t3">
|
||||
{csrf_field key="add_cotis_1"}
|
||||
{button type="submit" name="select_cotis" label="Sélectionner" shape="right" class="main"}
|
||||
</p>
|
||||
|
||||
|
||||
{if $step}
|
||||
<fieldset data-types="t3">
|
||||
<legend>Cotisation</legend>
|
||||
{if count($liste)}
|
||||
<dl>
|
||||
<dt>Sélectionnez la cotisation concernée :</dt>
|
||||
|
||||
<table class='list'>
|
||||
<thead>
|
||||
<td></td>
|
||||
<td>Id</td>
|
||||
<td>Intitulé</td>
|
||||
<td>Date d'inscription</td>
|
||||
<td>Expiration d'expiration</td>
|
||||
<td>Tarif</td>
|
||||
<td>Montant</td>
|
||||
<td>Somme payée</td>
|
||||
</thead>
|
||||
|
||||
{foreach from=$liste item=cotis key=i}
|
||||
{if !$cotis.paid}
|
||||
{continue}
|
||||
{/if}
|
||||
<tr>
|
||||
<td>
|
||||
{input type="radio" name="cotisation" value="%s"|args:$i}
|
||||
</td>
|
||||
{foreach from=$cotis item=element key=key}
|
||||
{if $key == 'paid'}
|
||||
{continue}
|
||||
{/if}
|
||||
<td>
|
||||
<label for="f_cotisation_{$i}">
|
||||
{if ($key == 'date' || $key == 'expiry') && $element > 0}
|
||||
{$element|date_short}
|
||||
{elseif $key == 'amount' OR $key == 'paid_amount'}
|
||||
{$element|raw|money_currency}
|
||||
{else}
|
||||
{$element}
|
||||
{/if}
|
||||
|
||||
<input type="hidden" name="{$key}_{$i}" value="{$element}">
|
||||
</label>
|
||||
</td>
|
||||
{/foreach}
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t3">
|
||||
{csrf_field key="add_cotis_2"}
|
||||
{button type="submit" name="add_cotis" label="Enregistrer" shape="right" class="main"}
|
||||
</p>
|
||||
{else}
|
||||
<p>Ce membre n'a aucune cotisation payée.</p>
|
||||
</fieldset>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</form>
|
||||
{include file="%s/templates/_form.tpl"|args:$plugin_root}
|
||||
|
||||
{include file="%s/templates/_js.tpl"|args:$plugin_root}
|
||||
|
||||
|
@ -1,226 +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="%s/templates/_menu.tpl"|args:$plugin_root current="index"}
|
||||
|
||||
{form_errors}
|
||||
|
||||
<form method="post" action="{$self_url}">
|
||||
|
||||
<fieldset>
|
||||
<legend>Type d'écriture</legend>
|
||||
<dl>
|
||||
{foreach from=$types_details item="type"}
|
||||
<dd class="radio-btn">
|
||||
{input type="radio" name="type" value=$type.id source=$radio label=null}
|
||||
<label for="f_type_{$type.id}">
|
||||
<div>
|
||||
<h3>{$type.label}</h3>
|
||||
{if !empty($type.help)}
|
||||
<p>{$type.help}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</label>
|
||||
</dd>
|
||||
{/foreach}
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend data-types="t0">Créer un devis</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>
|
||||
|
||||
{input type="text" name="numero_facture" maxlength=12 label="Numéro du document" required=1 source=$doc help="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."}
|
||||
|
||||
{input type="date" name="date_emission" default=$date label="Date d'émission" required=1 source=$doc}
|
||||
<dd class="help" data-types="t2">
|
||||
<p>Date du versemen du don</p>
|
||||
</dd>
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="date" name="date_echeance" default=$date label="Date d'échéance" required=1 source=$doc}
|
||||
<dd class="help" data-types="t2">
|
||||
<p>Date d'établissement du document</p>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<dt><label>Statut</label></dt>
|
||||
|
||||
{input type="checkbox" name="reglee" value="1" label="Réglée" source=$doc data-types="t1"}
|
||||
<div data-types="t0 t1 t2">
|
||||
{input type="checkbox" name="archivee" value="1" label="Archivée" source=$doc disabled="disabled"}
|
||||
</div>
|
||||
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<fieldset data-types="t0 t1 t2">
|
||||
<legend>Client</legend>
|
||||
|
||||
<dl>
|
||||
<dt><label>Document adressé à :</label></dt>
|
||||
{if !empty($clients)}
|
||||
<dd>
|
||||
{input type="radio" name="base_receveur" value="membre" label="Un·e membre" default=1 source=$doc}
|
||||
{input type="radio" name="base_receveur" value="client" label="Un·e client·e" source=$doc}
|
||||
</dd>
|
||||
{/if}
|
||||
</dl>
|
||||
|
||||
<dl class="type_membre">
|
||||
{input type="select" name="membre" label="Membre" options=$membres required=1 source=$doc}
|
||||
</dl>
|
||||
|
||||
{if !empty($clients)}
|
||||
<dl class="type_client">
|
||||
{input type="select" name="client" label="Client" options=$clients required=1 class="type_client" source=$doc}
|
||||
</dl>
|
||||
{else}
|
||||
<input type="hidden" name="base_receveur" value="membre" />
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
||||
<fieldset data-types="t0 t1 t2">
|
||||
<legend>Contenu</legend>
|
||||
|
||||
<dl>
|
||||
{input type="select" name="moyen_paiement" required=1 label="Moyen de paiement" source=$doc options=$doc.moyens_paiement}
|
||||
|
||||
<dt><label for="f_contenu">Contenu du document</label><dt>
|
||||
<dd>
|
||||
<table class="list" style="max-width: 800px;">
|
||||
<colgroup>
|
||||
<col width="65%">
|
||||
<col width="33%">
|
||||
<col width="2%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Désignation</td>
|
||||
<td>Prix</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="Lines">
|
||||
{if count($designations) > 0}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
|
||||
{foreach from=$designations item=designation key=key}
|
||||
<tr>
|
||||
<td><textarea name="designation[]" style="width:98%;">{$designation}</textarea></td>
|
||||
{money_fac value=$prix[$key] user=$from_user}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
<tr id="Line1" class="hidden">
|
||||
<td><textarea name="designation_tpl[]" style="width:98%;"></textarea></td>
|
||||
{money_fac name="prix_tpl[]"}
|
||||
<td class="fact_rm_line">{button label="Enlever" title="Enlever la ligne" shape="minus" min="2" name="remove_line"}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td style="text-align: right;">Total :</td>
|
||||
<td><span id="total">0.00</span> €</td>
|
||||
<td>{button label="Ajouter" title="Ajouter une ligne" id="ajouter_ligne" shape="plus"}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t0 t1 t2">
|
||||
{csrf_field key="modifier_facture"}
|
||||
{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
|
||||
</p>
|
||||
|
||||
<fieldset data-types="t3">
|
||||
<legend>Membre</legend>
|
||||
<dl>
|
||||
<dt><label>Reçu adressée à :</label></dt>
|
||||
<dd>
|
||||
{input type="select" name="membre_cotis" label="Membre" options=$membres required=1 source=$doc}
|
||||
</dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t3">
|
||||
{csrf_field key="add_cotis_1"}
|
||||
{button type="submit" name="select_cotis" label="Sélectionner" shape="right" class="main"}
|
||||
</p>
|
||||
|
||||
|
||||
{if $step}
|
||||
<fieldset data-types="t3">
|
||||
<legend>Cotisation</legend>
|
||||
{if count($liste)}
|
||||
<dl>
|
||||
<dt>Sélectionnez la cotisation concernée :</dt>
|
||||
|
||||
<table class='list'>
|
||||
<thead>
|
||||
<td></td>
|
||||
<td>Id</td>
|
||||
<td>Intitulé</td>
|
||||
<td>Date d'inscription</td>
|
||||
<td>Expiration d'expiration</td>
|
||||
<td>Tarif</td>
|
||||
<td>Montant</td>
|
||||
<td>Somme payée</td>
|
||||
</thead>
|
||||
|
||||
{foreach from=$liste item=cotis key=i}
|
||||
{if !$cotis.paid}
|
||||
{continue}
|
||||
{/if}
|
||||
<tr>
|
||||
<td>
|
||||
{input type="radio" name="cotisation" value="%s"|args:$i}
|
||||
</td>
|
||||
{foreach from=$cotis item=element key=key}
|
||||
{if $key == 'paid'}
|
||||
{continue}
|
||||
{/if}
|
||||
<td>
|
||||
<label for="f_cotisation_{$i}">
|
||||
{if ($key == 'date' || $key == 'expiry') && $element > 0}
|
||||
{$element|date_short}
|
||||
{elseif $key == 'amount' OR $key == 'paid_amount'}
|
||||
{$element|raw|money_currency}
|
||||
{else}
|
||||
{$element}
|
||||
{/if}
|
||||
|
||||
<input type="hidden" name="{$key}_{$i}" value="{$element}">
|
||||
</label>
|
||||
</td>
|
||||
{/foreach}
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
<p class="submit" data-types="t3">
|
||||
{csrf_field key="add_cotis_2"}
|
||||
{button type="submit" name="add_cotis" label="Enregistrer" shape="right" class="main"}
|
||||
</p>
|
||||
{else}
|
||||
<p>Ce membre n'a aucune cotisation payée.</p>
|
||||
</fieldset>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</form>
|
||||
|
||||
{include file="%s/templates/_js.tpl"|args:$plugin_root}
|
||||
{include file="%s/templates/_form.tpl"|args:$plugin_root}
|
||||
|
||||
{include file="admin/_foot.tpl"}
|
||||
|
@ -1,19 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Garradin;
|
||||
namespace Garradin\Plugin\Facturation;
|
||||
|
||||
use Garradin\Config;
|
||||
use Garradin\Utils;
|
||||
|
||||
define('DEVIS', 0);
|
||||
define('FACT', 1);
|
||||
define('CERFA', 2);
|
||||
define('COTIS', 3);
|
||||
|
||||
use Garradin\Plugin\Facturation\Facture;
|
||||
use Garradin\Plugin\Facturation\Client;
|
||||
const PATTERNS_LIST = [
|
||||
null => 'Aucun, le numéro sera à spécifier manuellement pour chaque document',
|
||||
'%{type}-%{year}-%{ynumber}' => 'Type-Année-Numéro du document par année ("FACT-2021-42")',
|
||||
'%{year}-%{type}-%04{ynumber}' => 'Année-Type-Numéro du document par année ("2021-DEVIS-0042")',
|
||||
'%{t}-%{year}-%{ynumber}' => 'Type court-Année-Numéro du document par année ("F-2021-42")',
|
||||
'%{y}%{t}%{ynumber}' => 'Année courte-Type court-Numéro du document par année ("21D42")',
|
||||
'%{type}-%{id}' => 'Type - Numéro unique du document ("FACT-42")',
|
||||
'%{t}%{id}' => 'Type court et numéro unique du document ("F42")',
|
||||
'%{id}' => 'Numéro unique du document ("42"))',
|
||||
'%06{id}' => 'Numéro unique du document sur 6 chiffres ("000042")',
|
||||
];
|
||||
|
||||
$client = new Client;
|
||||
$facture = new Facture;
|
||||
|
||||
$tpl->assign('www_url', WWW_URL);
|
||||
$tpl->assign('www_url', \Garradin\WWW_URL);
|
||||
$tpl->assign('f_obj', $facture);
|
||||
$tpl->assign('plugin_url', Utils::plugin_url());
|
||||
|
||||
|
@ -29,6 +29,8 @@ if (f('save') && $form->check('facturation_config'))
|
||||
$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)
|
||||
@ -122,6 +124,8 @@ else
|
||||
|
||||
$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');
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace Garradin;
|
||||
|
||||
use const \Garradin\Plugin\Facturation\PATTERNS_LIST;
|
||||
|
||||
require_once __DIR__ . '/_inc.php';
|
||||
|
||||
$session->requireAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE);
|
||||
@ -13,17 +15,39 @@ $db = DB::getInstance();
|
||||
|
||||
$step = $radio = false;
|
||||
$liste = [];
|
||||
$designations = [];
|
||||
$prix = [];
|
||||
|
||||
$csrf_key = 'ajout_facture';
|
||||
$fields = $facture->recu_fields;
|
||||
|
||||
$tpl->assign('moyens_paiement', $facture->listMoyensPaiement());
|
||||
$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;
|
||||
}
|
||||
|
||||
$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');
|
||||
|
||||
if (f('add'))
|
||||
if (f('save'))
|
||||
{
|
||||
$form->check('ajout_facture', [
|
||||
$form->check($csrf_key, [
|
||||
'type' => 'required|in:'.implode(',', [DEVIS, FACT, CERFA]),
|
||||
'numero_facture' => 'required|string',
|
||||
'numero_facture' => $require_number ? 'required|string' : 'string',
|
||||
'date_emission' => 'required|date_format:d/m/Y',
|
||||
'date_echeance' => 'required|date_format:d/m/Y',
|
||||
// 'reglee' => '',
|
||||
@ -31,7 +55,7 @@ if (f('add'))
|
||||
'base_receveur' => 'required|in:membre,client',
|
||||
// 'client' => '',
|
||||
// 'membre' => '',
|
||||
'moyen_paiement' => 'required|in:' . implode(',', array_keys($facture->listMoyensPaiement())),
|
||||
'moyen_paiement' => 'required|in:' . implode(',', array_keys($moyens_paiement)),
|
||||
'designation' => 'array|required',
|
||||
'prix' => 'array|required'
|
||||
]);
|
||||
@ -43,10 +67,10 @@ if (f('add'))
|
||||
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'),
|
||||
'numero' => f('numero_facture'),
|
||||
'date_emission' => f('date_emission'),
|
||||
'date_echeance' => f('date_echeance'),
|
||||
'reglee' => f('reglee') == 1?1:0,
|
||||
@ -80,7 +104,7 @@ if (f('add'))
|
||||
$truc['receveur_id'] = f('membre');
|
||||
}
|
||||
|
||||
$id = $facture->add($truc);
|
||||
$id = $facture->add($truc, $plugin->getConfig('pattern'));
|
||||
|
||||
Utils::redirect(PLUGIN_URL . 'facture.php?id='.(int)$id);
|
||||
|
||||
@ -140,7 +164,7 @@ elseif (f('add_cotis'))
|
||||
'expiration' => $cotis['expiry'] ]
|
||||
];
|
||||
|
||||
$id = $facture->add($data);
|
||||
$id = $facture->add($data, $plugin->getConfig('pattern'));
|
||||
|
||||
Utils::redirect(PLUGIN_URL . 'facture.php?id='.(int)$id);
|
||||
}
|
||||
@ -176,6 +200,9 @@ elseif (null !== f('type'))
|
||||
{
|
||||
$radio['type'] = f('type');
|
||||
}
|
||||
elseif (isset($doc['type'])) {
|
||||
$radio['type'] = $doc['type'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$radio['type'] = FACT;
|
||||
@ -187,8 +214,6 @@ $tpl->assign('types_details', $facture->types);
|
||||
$tpl->assign('client_id', f('client') ?: -1);
|
||||
$tpl->assign('membre_id', f('membre') ?: -1);
|
||||
|
||||
$designations = [];
|
||||
$prix = [];
|
||||
$from_user = false;
|
||||
if (($d = f('designation')) && ($p = f('prix')) && implode($d))
|
||||
{
|
||||
@ -203,6 +228,17 @@ if (($d = f('designation')) && ($p = f('prix')) && implode($d))
|
||||
}
|
||||
$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];
|
||||
@ -214,7 +250,7 @@ $date = new \DateTime;
|
||||
$date->setTimestamp(time());
|
||||
$tpl->assign('date', $date->format('d/m/Y'));
|
||||
|
||||
$tpl->assign(compact('designations', 'prix', 'from_user', 'identite'));
|
||||
$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;'));
|
||||
|
||||
|
@ -13,9 +13,9 @@ $db = DB::getInstance();
|
||||
$step = false;
|
||||
$liste = [];
|
||||
|
||||
$fields = $facture->recu_fields;
|
||||
$moyens_paiement = $facture->listMoyensPaiement(true);
|
||||
|
||||
$tpl->assign('moyens_paiement', $facture->listMoyensPaiement());
|
||||
$tpl->assign('moyens_paiement', $moyens_paiement);
|
||||
$tpl->assign('moyen_paiement', f('moyen_paiement') ?: 'ES');
|
||||
|
||||
qv(['id' => 'required|numeric']);
|
||||
@ -26,11 +26,13 @@ if (!$f = $facture->get($id))
|
||||
throw new UserException("Ce document n'existe pas.");
|
||||
}
|
||||
|
||||
$csrf_key = 'modifier_facture';
|
||||
|
||||
// Traitement
|
||||
|
||||
if(f('save'))
|
||||
{
|
||||
$form->check('modifier_facture', [
|
||||
$form->check($csrf_key, [
|
||||
'type' => 'required|in:'.implode(',', [DEVIS, FACT, CERFA]),
|
||||
'numero_facture' => 'required|string',
|
||||
'date_emission' => 'required|date_format:d/m/Y',
|
||||
@ -40,7 +42,7 @@ if(f('save'))
|
||||
'base_receveur' => 'required|in:membre,client',
|
||||
// 'client' => '',
|
||||
// 'membre' => '',
|
||||
'moyen_paiement' => 'required|in:' . implode(',', array_keys($facture->listMoyensPaiement())),
|
||||
'moyen_paiement' => 'required|in:' . implode(',', array_keys($moyens_paiement)),
|
||||
'designation' => 'array|required',
|
||||
'prix' => 'array|required'
|
||||
]);
|
||||
@ -193,7 +195,6 @@ if ($step)
|
||||
|
||||
// Affichage
|
||||
|
||||
$doc['moyens_paiement'] = $facture->listMoyensPaiement(true);
|
||||
// $doc['moyen_paiement'] = $doc['moyens_paiement'][$f->moyen_paiement];
|
||||
$doc['moyen_paiement'] = $f->moyen_paiement;
|
||||
$doc['type'] = $f->type_facture;
|
||||
@ -253,7 +254,7 @@ if ($f->type_facture != COTIS)
|
||||
}
|
||||
|
||||
|
||||
$tpl->assign(compact('designations', 'prix', 'from_user', 'identite'));
|
||||
$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;'));
|
||||
|
||||
@ -261,4 +262,6 @@ $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');
|
Loading…
Reference in New Issue
Block a user