Overview
Comment: | Remove _form_rules feature in entities, improve and fix bugs in account add from transaction |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk | stable |
Files: | files | file ages | folders |
SHA3-256: |
4e2775ba8e7ab85a987914be48e6bdf9 |
User & Date: | bohwaz on 2022-07-30 18:23:12 |
Other Links: | manifest | tags |
Context
2022-07-30
| ||
19:33 | Implement create and edit transactions in API check-in: b7cb001be2 user: bohwaz tags: trunk, stable | |
18:23 | Remove _form_rules feature in entities, improve and fix bugs in account add from transaction check-in: 4e2775ba8e user: bohwaz tags: trunk, stable | |
17:41 | Fix small issues and inconsistencies after refactoring of transaction code check-in: 863d48d3ba user: bohwaz tags: trunk | |
Changes
Modified src/include/lib/Garradin/Entities/Accounting/Account.php from [24f3d17de8] to [25dbc99537].
︙ | ︙ | |||
166 167 168 169 170 171 172 | 'label' => 'string', 'description' => '?string', 'position' => 'int', 'type' => 'int', 'user' => 'int', ]; | < < < < < < > > > > > > > > | | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | 'label' => 'string', 'description' => '?string', 'position' => 'int', 'type' => 'int', 'user' => 'int', ]; protected $_position = []; public function selfCheck(): void { $db = DB::getInstance(); $this->assert(trim($this->code) !== '', 'Le numéro de compte ne peut rester vide.'); $this->assert(trim($this->label) !== '', 'L\'intitulé de compte ne peut rester vide.'); $this->assert(strlen($this->code) <= 20, 'Le numéro de compte ne peut faire plus de 20 caractères.'); $this->assert(preg_match('/^[a-z0-9_]+$/i', $this->code), 'Le numéro de compte ne peut comporter que des lettres et des chiffres.'); $this->assert(strlen($this->label) <= 200, 'L\'intitulé de compte ne peut faire plus de 200 caractères.'); $this->assert(!isset($this->description) || strlen($this->description) <= 2000, 'La description de compte ne peut faire plus de 2000 caractères.'); $this->assert(!empty($this->id_chart), 'Aucun plan comptable lié'); $where = 'code = ? AND id_chart = ?'; $where .= $this->exists() ? sprintf(' AND id != %d', $this->id()) : ''; if ($db->test(self::TABLE, $where, $this->code, $this->id_chart)) { throw new ValidationException(sprintf('Le code "%s" est déjà utilisé par un autre compte.', $this->code)); } $this->assert(array_key_exists($this->type, self::TYPES_NAMES), 'Type invalide: ' . $this->type); $this->assert(array_key_exists($this->position, self::POSITIONS_NAMES), 'Position invalide'); $this->assert($this->user === 0 || $this->user === 1); parent::selfCheck(); } public function listJournal(int $year_id, bool $simple = false, ?DateTimeInterface $start = null, ?DateTimeInterface $end = null) |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Accounting/Chart.php from [297b8e2f31] to [83c4d84edf].
︙ | ︙ | |||
23 24 25 26 27 28 29 | 'id' => 'int', 'label' => 'string', 'country' => 'string', 'code' => '?string', 'archived' => 'int', ]; | < < < < < < > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 'id' => 'int', 'label' => 'string', 'country' => 'string', 'code' => '?string', 'archived' => 'int', ]; public function selfCheck(): void { parent::selfCheck(); $this->assert(trim($this->label) !== '', 'Le libellé ne peut rester vide.'); $this->assert(strlen($this->label) <= 200, 'Le libellé ne peut faire plus de 200 caractères.'); $this->assert(trim($this->country) !== '', 'Le pays ne peut rester vide.'); $this->assert(Utils::getCountryName($this->country), 'Le code pays doit être un code ISO valide'); $this->assert($this->archived === 0 || $this->archived === 1); } public function accounts() { return new Accounts($this->id()); |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Accounting/Year.php from [215a66eaee] to [76ca394f08].
︙ | ︙ | |||
27 28 29 30 31 32 33 | 'label' => 'string', 'start_date' => 'date', 'end_date' => 'date', 'closed' => 'int', 'id_chart' => 'int', ]; | < < < < < < > > > > | > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 'label' => 'string', 'start_date' => 'date', 'end_date' => 'date', 'closed' => 'int', 'id_chart' => 'int', ]; public function selfCheck(): void { $this->assert(trim($this->label) !== '', 'Le libellé ne peut rester vide.'); $this->assert(strlen($this->label) <= 200, 'Le libellé ne peut faire plus de 200 caractères.'); $this->assert($this->start_date instanceof \DateTime, 'La date de début de l\'exercice n\'est pas définie.'); $this->assert($this->end_date instanceof \DateTime, 'La date de début de l\'exercice n\'est pas définie.'); $this->assert($this->start_date < $this->end_date, 'La date de fin doit être postérieure à la date de début'); $this->assert($this->closed === 0 || $this->closed === 1); $db = DB::getInstance(); $this->assert($this->id_chart !== null); parent::selfCheck(); if ($this->exists()) { $this->assert( !$db->test(Transaction::TABLE, 'id_year = ? AND date < ?', $this->id(), $this->start_date->format('Y-m-d')), 'Des écritures de cet exercice ont une date antérieure à la date de début de l\'exercice.' ); |
︙ | ︙ |
Modified src/include/lib/Garradin/Entity.php from [d7f5ff09d1] to [8d420902ea].
1 2 3 4 5 6 7 8 9 | <?php namespace Garradin; use Garradin\Form; use KD2\DB\AbstractEntity; class Entity extends AbstractEntity { | < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?php namespace Garradin; use Garradin\Form; use KD2\DB\AbstractEntity; class Entity extends AbstractEntity { /** * Valider les champs avant enregistrement * @throws ValidationException Si une erreur de validation survient */ public function importForm(array $source = null) { if (null === $source) { $source = $_POST; } return $this->import($source); } static public function filterUserDateValue(?string $value): ?\DateTime { if (!trim((string) $value)) { return null; |
︙ | ︙ |
Modified src/templates/acc/charts/accounts/_account_form.tpl from [adc16430f8] to [4c02e8d69a].
1 2 3 4 5 6 7 | <dl> {if !$account.type || !$create} {input type="select" label="Type de compte usuel" name="type" source=$account required=true options=$types} <dd class="help">Le statut de compte usuel est utilisé pour les écritures <em>« simplifiées »</em> (recettes, dépenses, dettes, créances, virements), pour la liste des comptes, et également pour proposer certaines fonctionnalités (rapprochement pour les comptes bancaires, règlement rapide de dette et créance, dépôt de chèques).</dd> <dd class="help">Un compte qui n'a pas de type usuel ne pourra être utilisé que dans une saisie avancée, et ne sera visible que dans les rapports de l'exercice.</dd> {else} <dt>Type de compte</dt> | > | > > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <dl> {if !$account.type || !$create} {input type="select" label="Type de compte usuel" name="type" source=$account required=true options=$types} <dd class="help">Le statut de compte usuel est utilisé pour les écritures <em>« simplifiées »</em> (recettes, dépenses, dettes, créances, virements), pour la liste des comptes, et également pour proposer certaines fonctionnalités (rapprochement pour les comptes bancaires, règlement rapide de dette et créance, dépôt de chèques).</dd> <dd class="help">Un compte qui n'a pas de type usuel ne pourra être utilisé que dans une saisie avancée, et ne sera visible que dans les rapports de l'exercice.</dd> {else} <dt>Type de compte</dt> <dd> <?php $t = $types[$account->type]; ?> {$t} <input type="hidden" name="type" value="{$account.type}" /> </dd> {/if} {if !$account.type || $account.type == $account::TYPE_VOLUNTEERING} <dt><label for="f_position_0">Position au bilan ou résultat</label>{if !$edit_disabled} <b>(obligatoire)</b>{/if}</dt> <dd class="help">La position permet d'indiquer dans quelle partie du bilan ou du résultat doit figurer le compte.</dd> <dd class="help">Les comptes inscrits en actif ou passif figureront dans le bilan, alors que ceux inscrits en produit ou charge figureront au compte de résultat.</dd> {input type="radio" label="Ne pas utiliser ce compte au bilan ni au résultat" name="position" value=0 source=$account disabled=$edit_disabled} {if $account.type != $account::TYPE_VOLUNTEERING} {input type="radio" label="Bilan : actif" name="position" value=Entities\Accounting\Account::ASSET source=$account help="ce que possède l'association : stocks, locaux, soldes bancaires, etc." disabled=$edit_disabled} {input type="radio" label="Bilan : passif" name="position" value=Entities\Accounting\Account::LIABILITY source=$account help="ce que l'association doit : dettes, provisions, réserves, etc." disabled=$edit_disabled} {input type="radio" label="Bilan : actif ou passif" name="position" value=Entities\Accounting\Account::ASSET_OR_LIABILITY source=$account help="le compte sera placé à l'actif si son solde est débiteur, ou au passif s'il est créditeur" disabled=$edit_disabled} {/if} {input type="radio" label="Résultat : charge" name="position" value=Entities\Accounting\Account::EXPENSE source=$account help="dépenses" disabled=$edit_disabled} {input type="radio" label="Résultat : produit" name="position" value=Entities\Accounting\Account::REVENUE source=$account help="recettes" disabled=$edit_disabled} {/if} {input type="text" label="Numéro" maxlength="20" pattern="[A-Z0-9]+" name="code" source=$account required=true help="Le numéro du compte sert à trier le compte dans le plan comptable, attention à choisir un numéro qui correspond au plan comptable." disabled=$edit_disabled} <dd class="help">Le numéro ne doit contenir que des chiffres et des lettres majuscules.</dd> {input type="text" label="Libellé" name="label" source=$account required=true disabled=$edit_disabled} {input type="textarea" label="Description" name="description" source=$account} {if $create && in_array($account.type, [$account::TYPE_BANK, $account::TYPE_CASH, $account::TYPE_OUTSTANDING, $account::TYPE_THIRD_PARTY]) && !empty($current_year)} {input type="money" name="opening_amount" label="Solde d'ouverture" help="Si renseigné, ce solde sera inscrit dans l'exercice « %s »."|args:$current_year.label} {/if} </dl> |
Modified src/templates/acc/charts/accounts/_nav.tpl from [26818190bb] to [aee27c26ea].
1 2 3 | <nav class="tabs"> {if $dialog} {* JS trick to get back to the original iframe URL! *} | > > > > | > < > | | | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <nav class="tabs"> {if $dialog} {* JS trick to get back to the original iframe URL! *} <aside> {if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)} {linkbutton href="!acc/charts/accounts/new.php?id=%d"|args:$chart.id label="Ajouter un compte" shape="plus"} {/if} {linkbutton shape="left" label="Retour à la sélection de compte" href="#" onclick="g.reloadParentDialog(); return false;"} </aside> <ul> {else} <ul> <li class="current">{link href="!acc/charts/" label="Plans comptables"}</li> </ul> {if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN)} <aside>{linkbutton href="!acc/charts/accounts/new.php?id=%d"|args:$chart.id label="Ajouter un compte" shape="plus"}</aside> {/if} <ul class="sub"> <li class="title">{$chart.label}</li> {/if} <li{if $current == 'favorites'} class="current"{/if}>{link href="!acc/charts/accounts/?id=%d"|args:$chart.id label="Comptes usuels"}</li> <li{if $current == 'all'} class="current"{/if}>{link href="!acc/charts/accounts/all.php?id=%d"|args:$chart.id label="Tous les comptes"}</li> </ul> </nav> |
Modified src/templates/acc/charts/accounts/new.tpl from [da7b7cc99e] to [7f64222281].
1 2 3 4 5 6 | {include file="admin/_head.tpl" title="Nouveau compte" current="acc/charts"} {include file="acc/charts/accounts/_nav.tpl" current="new"} {form_errors} | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | {include file="admin/_head.tpl" title="Nouveau compte" current="acc/charts"} {include file="acc/charts/accounts/_nav.tpl" current="new"} {form_errors} {if !isset($account->type)} <form method="post" action="{$self_url}" data-focus="1"> <fieldset> <legend>Créer un nouveau compte</legend> <dl><label for="f_type">Type de compte</label></dl> {foreach from=$types_create item="t" key="v"} {input type="radio-btn" name="type" value=$v label=$t.label help=$t.help} {/foreach} </fieldset> |
︙ | ︙ |
Modified src/www/admin/acc/charts/accounts/new.php from [427dda7d05] to [78ea9bc506].
︙ | ︙ | |||
27 28 29 30 31 32 33 | $account = new Account; $account->position = Account::ASSET_OR_LIABILITY; $types = $account::TYPES_NAMES; $types[0] = '-- Pas un compte usuel'; // Simple creation with pre-determined account type | | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | $account = new Account; $account->position = Account::ASSET_OR_LIABILITY; $types = $account::TYPES_NAMES; $types[0] = '-- Pas un compte usuel'; // Simple creation with pre-determined account type if (f('type') !== null) { $account->type = (int)f('type'); $account->position = Accounts::getPositionFromType($account->type); $account->code = $accounts->getNextCodeForType($account->type); } $form->runIf('save', function () use ($account, $accounts, $chart, $current_year) { $db = DB::getInstance(); |
︙ | ︙ | |||
69 70 71 72 73 74 75 | $page = ''; if (!$account->type) { $page = 'all.php'; } | > | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | $page = ''; if (!$account->type) { $page = 'all.php'; } $url = sprintf('!acc/charts/accounts/%s?id=%d', $page, $account->id_chart); Utils::redirect($url); }, 'acc_accounts_new'); $types_create = [ Account::TYPE_BANK => [ 'label' => Account::TYPES_NAMES[Account::TYPE_BANK], 'help' => 'Compte bancaire, livret, ou intermédiaire financier (type HelloAsso, Paypal, Stripe, SumUp, etc.)', ], |
︙ | ︙ | |||
112 113 114 115 116 117 118 | Account::TYPE_NONE => [ 'label' => 'Autre type de compte', ], ]; $type = $account->type; | | | 113 114 115 116 117 118 119 120 121 122 | Account::TYPE_NONE => [ 'label' => 'Autre type de compte', ], ]; $type = $account->type; $tpl->assign(compact('types', 'types_create', 'account', 'chart')); $tpl->display('acc/charts/accounts/new.tpl'); |