Overview
Comment: | Add ability to link a fee to a project, fix [fde0ebd9e938a3496720c1974dcd2d0f47275c5f] |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
900e9cdb36bed0edb1850fc56574285d |
User & Date: | bohwaz on 2022-02-07 22:54:45 |
Other Links: | manifest | tags |
References
2022-02-07
| ||
22:55 | • Fixed ticket [fde0ebd9e9]: Saisie du projet lors du règlement de cotisation plus 5 other changes artifact: 898ed79235 user: bohwaz | |
Context
2022-02-07
| ||
23:15 | Fix access to content.css when access to website is not allowed check-in: 0662a80e28 user: bohwaz tags: trunk | |
22:54 | Add ability to link a fee to a project, fix [fde0ebd9e938a3496720c1974dcd2d0f47275c5f] check-in: 900e9cdb36 user: bohwaz tags: trunk | |
2022-02-05
| ||
00:25 | Fix PHP 8.1 errors check-in: 38ca403881 user: bohwaz tags: trunk | |
Changes
Modified src/VERSION from [537741541b] to [ada4464a06].
|
| | | 1 | 1.1.21 |
Added src/include/data/1.1.21_migration.sql version [d1d671e595].
> | 1 | ALTER TABLE services_fees ADD COLUMN id_analytical INTEGER NULL REFERENCES acc_accounts (id) ON DELETE SET NULL; |
Modified src/include/data/schema.sql from [7141d7dc46] to [305bf6fd27].
︙ | ︙ | |||
60 61 62 63 64 65 66 | description TEXT NULL, amount INTEGER NULL, formula TEXT NULL, -- Formule de calcul du montant de la cotisation, si cotisation dynamique (exemple : membres.revenu_imposable * 0.01) id_service INTEGER NOT NULL REFERENCES services (id) ON DELETE CASCADE, id_account INTEGER NULL REFERENCES acc_accounts (id) ON DELETE SET NULL CHECK (id_account IS NULL OR id_year IS NOT NULL), -- NULL if fee is not linked to accounting, this is reset using a trigger if the year is deleted | | > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | description TEXT NULL, amount INTEGER NULL, formula TEXT NULL, -- Formule de calcul du montant de la cotisation, si cotisation dynamique (exemple : membres.revenu_imposable * 0.01) id_service INTEGER NOT NULL REFERENCES services (id) ON DELETE CASCADE, id_account INTEGER NULL REFERENCES acc_accounts (id) ON DELETE SET NULL CHECK (id_account IS NULL OR id_year IS NOT NULL), -- NULL if fee is not linked to accounting, this is reset using a trigger if the year is deleted id_year INTEGER NULL REFERENCES acc_years (id) ON DELETE SET NULL, -- NULL if fee is not linked to accounting id_analytical INTEGER NULL REFERENCES acc_accounts (id) ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS services_users -- Enregistrement des cotisations et activités ( id INTEGER NOT NULL PRIMARY KEY, id_user INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Services/Fee.php from [7491493b33] to [af385c884c].
︙ | ︙ | |||
12 13 14 15 16 17 18 | use Garradin\Entities\Accounting\Year; use KD2\DB\EntityManager; class Fee extends Entity { const TABLE = 'services_fees'; | | | | | | | | | < | < < < < < < < < < > > > > | 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | use Garradin\Entities\Accounting\Year; use KD2\DB\EntityManager; class Fee extends Entity { const TABLE = 'services_fees'; protected int $id; protected string $label; protected ?string $description; protected ?int $amount; protected ?string $formula; protected int $id_service; protected ?int $id_account; protected ?int $id_year; protected ?int $id_analytical; public function filterUserValue(string $type, $value, string $key) { if ($key == 'amount' && $value !== null) { $value = Utils::moneyToInteger($value); } return $value; } public function importForm(array $source = null) { if (null === $source) { $source = $_POST; } if (isset($source['account']) && is_array($source['account'])) { $source['id_account'] = (int)key($source['account']); } if (isset($source['analytical']) && is_array($source['analytical'])) { $source['id_analytical'] = (int)key($source['analytical']); } if (isset($source['amount_type'])) { if ($source['amount_type'] == 2) { $source['amount'] = null; } elseif ($source['amount_type'] == 1) { $source['formula'] = null; |
︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 | $this->assert(null === $this->amount || $this->amount > 0, 'Le montant est invalide : ' . $this->amount); $this->assert($this->id_service, 'Aucun service n\'a été indiqué pour ce tarif.'); $this->assert((null === $this->id_account && null === $this->id_year) || (null !== $this->id_account && null !== $this->id_year), 'Le compte doit être indiqué avec l\'exercice'); $this->assert(null === $this->id_account || $db->test(Account::TABLE, 'id = ?', $this->id_account), 'Le compte indiqué n\'existe pas'); $this->assert(null === $this->id_year || $db->test(Year::TABLE, 'id = ?', $this->id_year), 'L\'exercice indiqué n\'existe pas'); $this->assert(null === $this->id_account || $db->test(Account::TABLE, 'id = ? AND id_chart = (SELECT id_chart FROM acc_years WHERE id = ?)', $this->id_account, $this->id_year), 'Le compte sélectionné ne correspond pas à l\'exercice'); $this->assert(null === $this->formula || $this->checkFormula(), 'Formule de calcul invalide'); $this->assert(null === $this->amount || null === $this->formula, 'Il n\'est pas possible de spécifier à la fois une formule et un montant'); } public function getAmountForUser(int $user_id): ?int { if ($this->amount) { | > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | $this->assert(null === $this->amount || $this->amount > 0, 'Le montant est invalide : ' . $this->amount); $this->assert($this->id_service, 'Aucun service n\'a été indiqué pour ce tarif.'); $this->assert((null === $this->id_account && null === $this->id_year) || (null !== $this->id_account && null !== $this->id_year), 'Le compte doit être indiqué avec l\'exercice'); $this->assert(null === $this->id_account || $db->test(Account::TABLE, 'id = ?', $this->id_account), 'Le compte indiqué n\'existe pas'); $this->assert(null === $this->id_year || $db->test(Year::TABLE, 'id = ?', $this->id_year), 'L\'exercice indiqué n\'existe pas'); $this->assert(null === $this->id_account || $db->test(Account::TABLE, 'id = ? AND id_chart = (SELECT id_chart FROM acc_years WHERE id = ?)', $this->id_account, $this->id_year), 'Le compte sélectionné ne correspond pas à l\'exercice'); $this->assert(null === $this->id_analytical || $db->test(Account::TABLE, 'id = ? AND id_chart = (SELECT id_chart FROM acc_years WHERE id = ?)', $this->id_analytical, $this->id_year), 'Le projet sélectionné ne correspond pas à l\'exercice'); $this->assert(null === $this->formula || $this->checkFormula(), 'Formule de calcul invalide'); $this->assert(null === $this->amount || null === $this->formula, 'Il n\'est pas possible de spécifier à la fois une formule et un montant'); } public function getAmountForUser(int $user_id): ?int { if ($this->amount) { |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Services/Service_User.php from [4230a71808] to [2bb10f99d8].
︙ | ︙ | |||
153 154 155 156 157 158 159 160 161 162 163 164 165 166 | if ($this->fee()->label != $label) { $label .= ' - ' . $this->fee()->label; } $label .= sprintf(' (%s)', (new Membres)->getNom($this->id_user)); $source['label'] = $label; $transaction->importFromNewForm($source); $transaction->save(); $transaction->linkToUser($this->id_user, $this->id()); return $transaction; } | > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | if ($this->fee()->label != $label) { $label .= ' - ' . $this->fee()->label; } $label .= sprintf(' (%s)', (new Membres)->getNom($this->id_user)); $source['label'] = $label; $source['id_analytical'] = $this->fee()->id_analytical; $transaction->importFromNewForm($source); $transaction->save(); $transaction->linkToUser($this->id_user, $this->id()); return $transaction; } |
︙ | ︙ |
Modified src/include/lib/Garradin/Upgrade.php from [66c8d5b4d2] to [1495a95c06].
︙ | ︙ | |||
400 401 402 403 404 405 406 407 408 409 410 411 412 413 | $db->exec('DROP TABLE membres_old;'); // Set new types for accounts $db->import(ROOT . '/include/data/1.1.19_migration.sql'); $db->commitSchemaUpdate(); } // Vérification de la cohérence des clés étrangères $db->foreignKeyCheck(); // Delete local cached files Utils::resetCache(USER_TEMPLATES_CACHE_ROOT); Utils::resetCache(STATIC_CACHE_ROOT); | > > > > > > > | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | $db->exec('DROP TABLE membres_old;'); // Set new types for accounts $db->import(ROOT . '/include/data/1.1.19_migration.sql'); $db->commitSchemaUpdate(); } if (version_compare($v, '1.1.21', '<')) { $db->begin(); // Add id_analytical column to services_fees $db->import(ROOT . '/include/data/1.1.21_migration.sql'); $db->commit(); } // Vérification de la cohérence des clés étrangères $db->foreignKeyCheck(); // Delete local cached files Utils::resetCache(USER_TEMPLATES_CACHE_ROOT); Utils::resetCache(STATIC_CACHE_ROOT); |
︙ | ︙ |
Modified src/templates/services/fees/_fee_form.tpl from [3b93d6fde1] to [5d079b874c].
1 2 3 4 5 6 7 8 9 10 11 12 | <?php assert(isset($legend)); assert(isset($csrf_key)); assert(isset($submit_label)); $targets = Entities\Accounting\Account::TYPE_REVENUE; ?> {form_errors} <form method="post" action="{$self_url}" data-focus="1"> <fieldset> | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php assert(isset($legend)); assert(isset($csrf_key)); assert(isset($submit_label)); $targets = Entities\Accounting\Account::TYPE_REVENUE; $analytical_targets = Entities\Accounting\Account::TYPE_ANALYTICAL; ?> {form_errors} <form method="post" action="{$self_url}" data-focus="1"> <fieldset> |
︙ | ︙ | |||
50 51 52 53 54 55 56 | <select id="f_id_year" name="id_year"> <option value="">-- Sélectionner un exercice</option> {foreach from=$years item="year"} <option value="{$year.id}"{if $year.id == $fee.id_year} selected="selected"{/if}>{$year.label} — {$year.start_date|date_short} au {$year.end_date|date_short}</option> {/foreach} </select> </dd> | | > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <select id="f_id_year" name="id_year"> <option value="">-- Sélectionner un exercice</option> {foreach from=$years item="year"} <option value="{$year.id}"{if $year.id == $fee.id_year} selected="selected"{/if}>{$year.label} — {$year.start_date|date_short} au {$year.end_date|date_short}</option> {/foreach} </select> </dd> {input type="list" target="!acc/charts/accounts/selector.php?targets=%s&year=%d"|args:$targets,$fee.id_year name="account" label="Compte de recettes à utiliser" default=$account required=true} {input type="list" target="!acc/charts/accounts/selector.php?targets=%s&year=%d"|args:$analytical_targets,$fee.id_year name="analytical" label="Associer les écritures à ce projet" default=$analytical_account required=false} </dl> {/if} </fieldset> <p class="submit"> {csrf_field key=$csrf_key} {button type="submit" name="save" label="Enregistrer" shape="right" class="main"} |
︙ | ︙ |
Modified src/www/admin/services/fees/edit.php from [545ab428a4] to [ea164cf904].
︙ | ︙ | |||
34 35 36 37 38 39 40 41 | } $accounting_enabled = (bool) $fee->id_account; $years = Years::listOpen(); $account = $fee->id_account ? [$fee->id_account => Accounts::getSelectorLabel($fee->id_account)] : null; | > | | 34 35 36 37 38 39 40 41 42 43 44 45 | } $accounting_enabled = (bool) $fee->id_account; $years = Years::listOpen(); $account = $fee->id_account ? [$fee->id_account => Accounts::getSelectorLabel($fee->id_account)] : null; $analytical_account = $fee->id_analytical ? [$fee->id_analytical => Accounts::getSelectorLabel($fee->id_analytical)] : null; $tpl->assign(compact('service', 'amount_type', 'fee', 'csrf_key', 'account', 'accounting_enabled', 'years', 'analytical_account')); $tpl->display('services/fees/edit.tpl'); |
Modified src/www/admin/services/fees/index.php from [853d7be879] to [8cf8f06ec6].
︙ | ︙ | |||
19 20 21 22 23 24 25 | $form->runIf($session->canAccess($session::SECTION_USERS, $session::ACCESS_ADMIN) && f('save'), function () use ($service) { $fee = new Fee; $fee->id_service = $service->id(); $fee->importForm(); $fee->save(); }, 'fee_add', ADMIN_URL . 'services/fees/?id=' . $service->id()); | < < > | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | $form->runIf($session->canAccess($session::SECTION_USERS, $session::ACCESS_ADMIN) && f('save'), function () use ($service) { $fee = new Fee; $fee->id_service = $service->id(); $fee->importForm(); $fee->save(); }, 'fee_add', ADMIN_URL . 'services/fees/?id=' . $service->id()); $accounting_enabled = false; $years = Years::listOpen(); $analytical_account = null; $tpl->assign(compact('service', 'accounting_enabled', 'years', 'analytical_account')); $tpl->assign('list', $fees->listWithStats()); $tpl->display('services/fees/index.tpl'); |