Overview
Comment: | Renommer les entités de compta, passer à l'anglais, simplifier (suppression des moyens de paiement, possibilité d'avoir plusieurs plans comptables, etc.) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | dev |
Files: | files | file ages | folders |
SHA1: |
9c856dd92cfea39a2e1d817dc37a269e |
User & Date: | bohwaz on 2020-04-20 01:05:06 |
Other Links: | branch diff | manifest | tags |
Context
2020-04-21
| ||
00:58 | Renommer le namespace Compta -> Accounting check-in: 1eec72f23b user: bohwaz tags: dev | |
2020-04-20
| ||
01:05 | Renommer les entités de compta, passer à l'anglais, simplifier (suppression des moyens de paiement, possibilité d'avoir plusieurs plans comptables, etc.) check-in: 9c856dd92c user: bohwaz tags: dev | |
01:03 | Suppression clés de config non utilisées check-in: 09e570ec23 user: bohwaz tags: dev | |
Changes
Modified src/include/data/1.0.0_migration.sql from [f261086c64] to [214a92ada1].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ALTER TABLE compta_journal RENAME TO compta_journal_old; ALTER TABLE compta_comptes RENAME TO compta_comptes_old; ALTER TABLE compta_categories RENAME TO compta_categories_old; ALTER TABLE compta_exercices RENAME TO compta_exercices_old; ALTER TABLE membres_operations RENAME TO membres_operations_old; ALTER TABLE membres_categories RENAME TO membres_categories_old; DROP TABLE fichiers_compta_journal; -- Inutilisé à ce jour .read 1.0.0_schema.sql -- Migration comptes de code comme identifiant à ID unique INSERT INTO compta_comptes (id, code, parent, libelle, position, plan_comptable, id_exercice) SELECT NULL, id, NULL, libelle, position, plan_comptable, NULL FROM compta_comptes_old; -- Migration de la hiérarchie UPDATE compta_comptes AS a SET parent = (SELECT id FROM compta_comptes AS b WHERE code = (SELECT parent FROM compta_comptes_old AS c WHERE id = b.code)); | > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ALTER TABLE compta_journal RENAME TO compta_journal_old; ALTER TABLE compta_comptes RENAME TO compta_comptes_old; ALTER TABLE compta_categories RENAME TO compta_categories_old; ALTER TABLE compta_exercices RENAME TO compta_exercices_old; ALTER TABLE membres_operations RENAME TO membres_operations_old; ALTER TABLE membres_categories RENAME TO membres_categories_old; DROP TABLE fichiers_compta_journal; -- Inutilisé à ce jour -- N'est pas utilisé DELETE FROM config WHERE cle = 'categorie_dons' OR cle = 'categorie_cotisations'; .read 1.0.0_schema.sql -- FIXME: insertion en comptes analytiques des projets et associations dans transactions -- FIXME: création plan comptable -- Migration comptes de code comme identifiant à ID unique INSERT INTO compta_comptes (id, code, parent, libelle, position, plan_comptable, id_exercice) SELECT NULL, id, NULL, libelle, position, plan_comptable, NULL FROM compta_comptes_old; -- Migration de la hiérarchie UPDATE compta_comptes AS a SET parent = (SELECT id FROM compta_comptes AS b WHERE code = (SELECT parent FROM compta_comptes_old AS c WHERE id = b.code)); |
︙ | ︙ | |||
64 65 66 67 68 69 70 71 | -- CREATE TRIGGER IF NOT EXISTS ON compta_journal_ecritures -- Transfert des rapprochements UPDATE compta_mouvements_lignes SET rapprochement = 1 WHERE id_mouvement IN (SELECT id_operation FROM compta_rapprochement); -- Suppression de la table rapprochements DROP TABLE compta_rapprochement; | > > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | -- CREATE TRIGGER IF NOT EXISTS ON compta_journal_ecritures -- Transfert des rapprochements UPDATE compta_mouvements_lignes SET rapprochement = 1 WHERE id_mouvement IN (SELECT id_operation FROM compta_rapprochement); -- Suppression de la table rapprochements DROP TABLE compta_rapprochement; -- Suppression inutilisées DROP TABLE compta_projets; DROP TABLE compta_comptes_bancaires; DROP TABLE compta_moyens_paiements; |
Modified src/include/data/1.0.0_schema.sql from [9e284814b8] to [fcd675e17c].
1 2 3 4 5 6 | CREATE TABLE IF NOT EXISTS config ( -- Configuration de Garradin cle TEXT PRIMARY KEY NOT NULL, valeur TEXT ); | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 | CREATE TABLE IF NOT EXISTS config ( -- Configuration de Garradin cle TEXT PRIMARY KEY NOT NULL, valeur TEXT ); CREATE TABLE IF NOT EXISTS membres_categories -- Catégories de membres ( id INTEGER PRIMARY KEY NOT NULL, nom TEXT NOT NULL, droit_wiki INTEGER NOT NULL DEFAULT 1, |
︙ | ︙ | |||
38 39 40 41 42 43 44 | PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS cotisations -- Types de cotisations et activités ( id INTEGER PRIMARY KEY NOT NULL, | < < > > > > > > > > > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS cotisations -- Types de cotisations et activités ( id INTEGER PRIMARY KEY NOT NULL, intitule TEXT NOT NULL, description TEXT NULL, duree INTEGER NULL, -- En jours debut TEXT NULL, -- timestamp fin TEXT NULL ); CREATE TABLE IF NOT EXISTS cotisations_tarifs ( id INTEGER PRIMARY KEY NOT NULL, label TEXT NOT NULL, description TEXT NULL, amount INTEGER NULL, formula TEXT NULL, id_category INTEGER NULL REFERENCES acc_categories (id) ON DELETE SET NULL, -- NULL si le type n'est pas associé automatiquement à la compta ); CREATE TABLE IF NOT EXISTS cotisations_membres -- Enregistrement des cotisations et activités ( id INTEGER NOT NULL PRIMARY KEY, id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE, |
︙ | ︙ | |||
172 173 174 175 176 177 178 | UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; -- -- COMPTA -- | | | | | | > > > > | > > > > > > | | > > | > | < < < | | < < < < < < < < < < < < < | < < < < < < < < | | | < < | < | | < < < < | < < < | | < < < < < < < < < < < < < < < < < < < < < < < < | | | > < | > | | < | < < | < < < < < < < < < < < < < | | | | 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 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; -- -- COMPTA -- CREATE TABLE IF NOT EXISTS acc_years -- Exercices ( id INTEGER NOT NULL PRIMARY KEY, label TEXT NOT NULL, start_date TEXT NOT NULL CHECK (date(debut) IS NOT NULL AND date(debut) = debut), end_date TEXT NOT NULL CHECK (date(fin) IS NOT NULL AND date(fin) = fin), closed INTEGER NOT NULL DEFAULT 0, id_plan INTEGER NOT NULL REFERENCES acc_plans (id) ); CREATE TABLE IF NOT EXISTS acc_plans -- Plans comptables : il peut y en avoir plusieurs ( id INTEGER NOT NULL PRIMARY KEY, country TEXT NOT NULL, code TEXT NULL, -- NULL = plan comptable créé par l'utilisateur label TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS acc_accounts -- Comptes des plans comptables ( id INTEGER NOT NULL PRIMARY KEY, id_plan INTEGER NOT NULL REFERENCES compta_plans, code TEXT NOT NULL, -- peut contenir des lettres, eg. 53A, 53B, etc. parent INTEGER NULL REFERENCES compta_comptes(id), label TEXT NOT NULL, position INTEGER NOT NULL, -- position actif/passif/charge/produit type INTEGER NOT NULL DEFAULT 0, -- compte spécial : banque, caisse, en attente d'encaissement user INTEGER NOT NULL DEFAULT 1 -- 1 = fait partie du plan comptable original, 0 = a été ajouté par l'utilisateur ); CREATE UNIQUE INDEX IF NOT EXISTS acc_accounts_codes ON acc_accounts (code, id_plan); CREATE INDEX IF NOT EXISTS acc_accounts_parent ON acc_accounts (parent); CREATE TABLE IF NOT EXISTS acc_transactions -- Opérations comptables ( id INTEGER PRIMARY KEY NOT NULL, label TEXT NOT NULL, notes TEXT NULL, reference TEXT NULL, -- N° de pièce comptable date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), validated INTEGER NOT NULL DEFAULT 0, -- 1 = écriture validée, non modifiable hash TEXT NULL, prev_hash TEXT NULL, id_year INTEGER NOT NULL REFERENCES acc_years(id), id_category INTEGER NULL REFERENCES acc_categories(id) ON DELETE SET NULL, -- Numéro de catégorie (en mode simple) id_analytical INTEGER NULL REFERENCES acc_accounts(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS acc_transactions_year ON acc_transactions (id_year); CREATE INDEX IF NOT EXISTS acc_transactions_date ON acc_transactions (date); CREATE TABLE IF NOT EXISTS acc_transactions_lines -- Lignes d'écritures d'une opération ( id INTEGER PRIMARY KEY NOT NULL, id_transaction INTEGER NOT NULL REFERENCES acc_transactions (id) ON DELETE CASCADE, id_account INTEGER NOT NULL REFERENCES acc_accounts (id), -- N° du compte dans le plan comptable credit INTEGER NOT NULL, debit INTEGER NOT NULL, reconcilied INTEGER NOT NULL DEFAULT 0, payment_reference TEXT NULL, -- Référence de paiement, eg. numéro de chèque CONSTRAINT line_check1 CHECK ((credit * debit) = 0), CONSTRAINT line_check2 CHECK ((credit + debit) > 0) ); CREATE INDEX IF NOT EXISTS acc_transactions_lines_account ON acc_transactions_lines (id_account); CREATE TABLE IF NOT EXISTS acc_categories -- Catégories pour simplifier le plan comptable ( id INTEGER NOT NULL PRIMARY KEY, type INTEGER NOT NULL DEFAULT 1, -- 1 = recette, -1 = dépense, 0 = autre (utilisé uniquement pour l'interface) label TEXT NOT NULL, description TEXT NULL, id_account INTEGER NULL REFERENCES acc_accounts(id) ON DELETE CASCADE -- Compte affecté par cette catégorie ); CREATE TABLE IF NOT EXISTS plugins ( id TEXT NOT NULL PRIMARY KEY, officiel INTEGER NOT NULL DEFAULT 0, nom TEXT NOT NULL, |
︙ | ︙ | |||
394 395 396 397 398 399 400 | -- Associations entre fichiers et pages du wiki ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES wiki_pages (id), PRIMARY KEY(fichier, id) ); | | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | -- Associations entre fichiers et pages du wiki ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES wiki_pages (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS fichiers_acc_transactions -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES acc_transactions (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS recherches -- Recherches enregistrées ( id INTEGER NOT NULL PRIMARY KEY, |
︙ | ︙ |
Deleted src/include/lib/Garradin/Compta/Compte_Bancaire.php version [03377fbdd1].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Comptes_Bancaires.php version [c2ddfadd03].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Modified src/include/lib/Garradin/Entities/Compta/Account.php from [ec757b0335] to [ca23ed40e3].
1 2 3 4 5 6 7 8 9 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; | | | | | | > > > | > | | | > | | | | > | | > | < | 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; class Account extends Entity { const TABLE = 'acc_accounts'; const PASSIF = 1; const ACTIF = 2; const ACTIF_PASSIF = 3; const PRODUIT = 4; const CHARGE = 5; const PRODUIT_CHARGE = 6; const TYPE_NONE = 0; const TYPE_BANK = 1; const TYPE_CASH = 2; /** * Outstanding transaction accounts (like cheque or card payments) */ const TYPE_OUTSTANDING = 3; protected $id; protected $id_plan; protected $code; protected $parent; protected $label; protected $position; protected $type; protected $user; protected $_types = [ 'id_plan' => 'int', 'code' => 'string', 'parent' => '?int', 'label' => 'string', 'type' => 'int', 'special' => 'int', 'user' => 'int', ]; protected $_validation_rules = [ 'id' => 'required|integer', 'libelle' => 'required|string', 'parent' => 'required|nullable|integer|in_table:acc_accounts,id', 'id_plan' => 'required|integer|in_table:acc_plans,id', 'type' => 'required|integer', 'special' => 'required|integer', 'user' => 'integer|min:0|max:1', ]; } |
Modified src/include/lib/Garradin/Entities/Compta/Line.php from [820ffb3e7d] to [a3e700e1fa].
1 2 3 4 5 6 7 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\ValidationException; | | | > | > | | > > | | | | > > | 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 37 38 39 40 41 42 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\ValidationException; class Line extends Entity { const TABLE = 'acc_transactions_lines'; protected $id; protected $id_transaction; protected $id_account; protected $credit = 0; protected $debit = 0; protected $payment_reference; protected $reconciled; protected $_types = [ 'id_transaction' => 'int', 'id_account' => 'int', 'credit' => 'int', 'debit' => 'int', 'payment_reference' => '?string', 'reconcilied' => 'int', ]; protected $_validation_rules = [ 'id_transaction' => 'required|integer|in_table:acc_transactions,id', 'id_account' => 'required|integer|in_table:acc_accounts,id', 'credit' => 'required|integer|min:0', 'debit' => 'required|integer|min:0', 'payment_reference' => 'string|max:200', 'reconcilied' => 'int|min:0|max:1', ]; public function filterUserValue(string $key, $value, array $source) { $value = parent::filterUserValue($key, $value); if ($key == 'credit' || $key == 'debit') |
︙ | ︙ | |||
47 48 49 50 51 52 53 | } public function selfCheck() { parent::selfCheck(); $this->assert($this->credit || $this->debit, 'Aucun montant au débit ou au crédit.'); $this->assert(($this->credit * $this->debit) === 0 && ($this->credit + $this->debit) > 0, 'Ligne non équilibrée : crédit ou débit doit valoir zéro.'); | | | 53 54 55 56 57 58 59 60 61 62 | } public function selfCheck() { parent::selfCheck(); $this->assert($this->credit || $this->debit, 'Aucun montant au débit ou au crédit.'); $this->assert(($this->credit * $this->debit) === 0 && ($this->credit + $this->debit) > 0, 'Ligne non équilibrée : crédit ou débit doit valoir zéro.'); $this->assert($this->id_transaction, 'Aucun mouvement n\'a été indiqué pour cette ligne.'); } } |
Modified src/include/lib/Garradin/Entities/Compta/Transaction.php from [d018180264] to [71f26cd748].
1 2 3 4 5 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; | | | | | | | < < | | | < | | | | < < | | | | < | | < | > < < | | | < | | | | | | | | | | | < < | | | | < | | 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\validatedException; use Garradin\DB; use Garradin\Config; class Transaction extends Entity { const TABLE = 'acc_transactions'; protected $id; protected $label; protected $notes; protected $reference; protected $date; protected $validated; protected $hash; protected $prev_hash; protected $id_year; protected $id_category; protected $id_analytical; protected $_types = [ 'label' => 'string', 'notes' => '?string', 'reference' => '?string', 'date' => 'date', 'validated' => 'bool', 'hash' => '?string', 'prev_hash' => '?string', 'id_year' => 'int', 'id_category' => '?int', 'id_analytical' => '?int', ]; protected $_validated_rules = [ 'label' => 'required|string|max:200', 'notes' => 'string|max:20000', 'reference' => 'string|max:200', 'date' => 'required|date', 'validated' => 'bool', 'id_year' => 'integer|in_table:acc_years,id', 'id_category' => 'integer|in_table:acc_categories,id', 'id_analytical' => 'integer|in_table:acc_accounts,id' ]; protected $lines; public function getLines() { if (null === $this->lines && $this->exists()) { $db = DB::getInstance(); $this->lines = $db->toObject($db->get('SELECT * FROM acc_transactions_lines WHERE id_transaction = ? ORDER BY id;', $this->id), Ligne::class); } else { $this->lines = []; } return $this->lines; } /* public function getHash() { if (!$this->id_year) { throw new \LogicException('Il n\'est pas possible de hasher un mouvement qui n\'est pas associé à un exercice'); } static $keep_keys = [ 'label', 'notes', 'reference', 'date', 'validated', 'prev_hash', ]; $hash = hash_init('sha256'); $values = $this->asArray(); $values = array_intersect_key($values, $keep_keys); hash_update($hash, implode(',', array_keys($values))); hash_update($hash, implode(',', $values)); foreach ($this->getLines() as $ligne) { hash_update($hash, implode(',', [$ligne->compte, $ligne->debit, $ligne->credit])); } return hash_final($hash, false); } public function checkHash() { return hash_equals($this->getHash(), $this->hash); } */ public function add(Ligne $ligne) { $this->lines[] = $ligne; } public function simple($montant, $compte) { $categorie = new Categorie($this->id_category); if ($categorie->type == Categorie::DEPENSE) { $from = $categorie->compte; $to = $compte; } else |
︙ | ︙ | |||
150 151 152 153 154 155 156 | $ligne1->credit = $amount; return $this->add($ligne1) && $this->add($ligne2); } public function save() { | | | | | | | < < < < < < < < < < < < | < | | | | | | | | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 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 | $ligne1->credit = $amount; return $this->add($ligne1) && $this->add($ligne2); } public function save() { if ($this->validated && !isset($this->_modified['validated'])) { throw new validatedException('Il n\'est pas possible de modifier un mouvement qui a été validé'); } if (!parent::save()) { return false; } foreach ($this->lines as $ligne) { $ligne->id_transaction = $this->id; $ligne->save(); } } public function delete() { if ($this->validated) { throw new validatedException('Il n\'est pas possible de supprimer un mouvement qui a été validé'); } parent::delete(); } public function selfCheck() { parent::selfCheck(); $db = DB::getInstance(); $config = Config::getInstance(); // ID d'exercice obligatoire s'il existe déjà des exercices if (null === $this->id_year && $db->firstColumn('SELECT 1 FROM acc_years LIMIT 1;')) { throw new validatedException('Aucun exercice spécifié.'); } if (null !== $this->id_year && !$db->test('acc_years', 'id = ? AND start_date <= ? AND end_date >= ?;', $this->id_year, $this->date, $this->date)) { throw new validatedException('La date ne correspond pas à l\'exercice sélectionné.'); } $total = 0; $lines = $this->getLines(); foreach ($lines as $line) { $total += $line->credit; $total -= $line->debit; } if (0 !== $total) { throw new validatedException('Mouvement non équilibré : déséquilibre entre débits et crédits'); } } } |
Modified src/include/lib/Garradin/Entities/Compta/Year.php from [d63b31b5b9] to [7f892d19e6].
1 2 3 4 5 6 7 8 9 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | <?php namespace Garradin\Entities\Compta; use Garradin\Entity; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; class Year extends Entity { const TABLE = 'acc_years'; protected $id; protected $label; protected $start_date; protected $end_date; protected $closed = 0; protected $_types = [ 'id' => 'integer', 'label' => 'string', 'start_date' => 'date', 'end_date' => 'date', 'closed' => 'integer', ]; protected $_validation_rules = [ 'label' => 'required|string|max:200', 'start_date' => 'required|date|before:end_date', 'end_date' => 'required|date|after:start_date', 'closed' => 'int|min:0|max:1', ]; public function selfCheck(): void { parent::selfCheck(); $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 == 1 || !isset($this->_modified['closed']), 'Il est interdit de réouvrir un exercice clôturé'); $db = DB::getInstance(); // Vérifier qu'on ne crée pas 2 exercices qui se recoupent if ($this->exists()) { $this->assert( !$db->test(self::TABLE, 'id != :id AND ((start_date <= :start_date AND end_date >= :start_date) OR (start_date <= :end_date AND end_date >= :start_date))', ['id' => $this->id(), 'start_date' => $this->start_date, 'end_date' => $this->end_date]), 'La date de début ou de fin se recoupe avec un exercice existant.' ); $this->assert( !$db->test(Transaction::TABLE, 'id_year = ? AND date < ?', $this->id(), $this->start_date), 'Des mouvements de cet exercice ont une date antérieure à la date de début de l\'exercice.' ); $this->assert( !$db->test(Transaction::TABLE, 'id_year = ? AND date > ?', $this->id(), $this->end_date), 'Des mouvements de cet exercice ont une date postérieure à la date de fin de l\'exercice.' ); } else { $this->assert( !$db->test(self::TABLE, '(start_date <= :start_date AND end_date >= :start_date) OR (start_date <= :end_date AND end_date >= :start_date)', ['start_date' => $this->start_date, 'end_date' => $this->end_date]), 'La date de début ou de fin se recoupe avec un exercice existant.' ); } } public function close() { if ($this->closed) { throw new \LogicException('Cet exercice est déjà clôturé'); } $this->set('closed', 1); } public function delete(): bool { $db = DB::getInstance(); // Ne pas supprimer un compte qui est utilisé ! if ($db->test(Transaction::TABLE, $db->where('id_year', $this->id()))) { throw new UserException('Cet exercice ne peut être supprimé car des mouvements y sont liés.'); } return parent::delete(); } } |