14 public function importPlan($file = NULL)
16 $plan = json_decode(file_get_contents($file ?
$file : ROOT
.'/include/data/plan_comptable.json'), true);
18 $db = DB
::getInstance();
22 foreach ($plan as $id=>$compte)
26 if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $id))
28 $db->simpleUpdate('compta_comptes', [
29 'parent' => $compte['parent'],
30 'libelle' => $compte['nom'],
31 'position' => $compte['position'],
32 'plan_comptable' => 1,
33 ], 'id = \''.$db->escapeString($id).'\'');
37 $db->simpleInsert('compta_comptes', [
39 'parent' => $compte['parent'],
40 'libelle' => $compte['nom'],
41 'position' => $compte['position'],
42 'plan_comptable' => 1,
47 //$db->exec('DELETE FROM compta_comptes WHERE id NOT IN(\''.implode('\', \'', $ids).'\') AND plan_comptable = 1;');
54 public function add($data)
56 $this->_checkFields($data, true);
58 $db = DB
::getInstance();
60 if (empty($data['id']))
62 $new_id = $data['parent'];
63 $nb_sous_comptes = $db->simpleQuerySingle('SELECT COUNT(*) FROM compta_comptes WHERE parent = ?;', false, $new_id);
65 // Pas plus de 26 sous-comptes par compte, parce que l'alphabet s'arrête à 26 lettres
66 if ($nb_sous_comptes >= 26)
68 throw new UserException('Nombre de sous-comptes maximal atteint pour ce compte parent-ci.');
71 $new_id .= chr(65+
(int)$nb_sous_comptes);
75 $new_id = $data['id'];
78 if (isset($data['position']))
80 $position = (int) $data['position'];
84 $position = $db->simpleQuerySingle('SELECT position FROM compta_comptes WHERE id = ?;', false, $data['parent']);
87 $db->simpleInsert('compta_comptes', [
89 'libelle' => trim($data['libelle']),
90 'parent' => $data['parent'],
91 'plan_comptable' => 0,
92 'position' => (int)$position,
98 public function edit($id, $data)
100 $db = DB
::getInstance();
102 // Vérification que l'on peut éditer ce compte
103 if ($db->simpleQuerySingle('SELECT plan_comptable FROM compta_comptes WHERE id = ?;', false, $id))
105 throw new UserException('Ce compte fait partie du plan comptable et n\'est pas modifiable.');
108 if (isset($data['position']) && empty($data['position']))
110 throw new UserException('Aucune position du compte n\'a été indiquée.');
113 $this->_checkFields($data);
116 'libelle' => trim($data['libelle']),
119 if (isset($data['position']))
121 $update['position'] = (int) trim($data['position']);
124 $db->simpleUpdate('compta_comptes', $update, 'id = \''.$db->escapeString(trim($id)).'\'');
129 public function delete($id)
131 $db = DB
::getInstance();
133 // Ne pas supprimer un compte qui est utilisé !
134 if ($db->simpleQuerySingle('SELECT 1 FROM compta_flux WHERE compte = ? LIMIT 1;', false, $id))
136 throw new UserException('Ce compte ne peut être supprimé car des opérations comptables y sont liées.');
139 if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes_bancaires WHERE id = ? LIMIT 1;', false, $id))
141 throw new UserException('Ce compte ne peut être supprimé car il est lié à un compte bancaire.');
144 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
146 throw new UserException('Ce compte ne peut être supprimé car des catégories y sont liées.');
149 $db->simpleExec('DELETE FROM compta_comptes WHERE id = ?;', trim($id));
155 * Peut-on supprimer ce compte ? (OUI s'il n'a pas d'écriture liée)
156 * @param string $id Numéro du compte
157 * @return boolean TRUE si le compte n'a pas d'écriture liée
159 public function canDelete($id)
161 $db = DB
::getInstance();
163 if ($db->simpleQuerySingle('SELECT 1 FROM compta_flux
164 WHERE compte = ? LIMIT 1;', false, $id))
169 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
178 * Peut-on désactiver ce compte ? (OUI s'il n'a pas d'écriture liée dans l'exercice courant)
179 * @param string $id Numéro du compte
180 * @return boolean TRUE si le compte n'a pas d'écriture liée dans l'exercice courant
182 public function canDisable($id)
184 $db = DB
::getInstance();
186 if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
187 LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
188 WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
189 AND compte = ? LIMIT 1;', false, $id))
194 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
203 * Désactiver un compte
204 * Le compte ne sera plus utilisable pour les écritures ou les catégories mais restera en base de données
205 * @param string $id Numéro du compte
206 * @return boolean TRUE si la désactivation a fonctionné, une exception utilisateur si
207 * la désactivation n'est pas possible.
209 public function disable($id)
211 $db = DB
::getInstance();
213 // Ne pas désactiver un compte utilisé dans l'exercice courant
214 if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
215 LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
216 WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
217 AND compte = ? LIMIT 1;', false, $id))
219 throw new UserException('Ce compte ne peut être désactivé car des écritures y sont liées sur l\'exercice courant. '
220 . 'Il faut supprimer ou ré-attribuer ces écritures avant de pouvoir supprimer le compte.');
223 // Ne pas désactiver un compte utilisé pour une catégorie
224 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
226 throw new UserException('Ce compte ne peut être désactivé car des catégories y sont liées.');
229 return $db->simpleUpdate('compta_comptes', ['desactive' => 1], 'id = \''.$db->escapeString(trim($id)).'\'');
232 public function get($id)
234 $db = DB
::getInstance();
235 return $db->simpleQuerySingle('SELECT * FROM compta_comptes WHERE id = ?;', true, trim($id));
238 public function getList($parent = 0)
240 $db = DB
::getInstance();
241 return $db->simpleStatementFetchAssocKey('SELECT id, * FROM compta_comptes WHERE parent = ? ORDER BY id;', SQLITE3_ASSOC
, $parent);
244 public function getListAll($parent = 0)
246 $db = DB
::getInstance();
247 return $db->queryFetchAssoc('SELECT id, libelle FROM compta_comptes ORDER BY id;');
250 public function listTree($parent = 0, $include_children = true)
252 $db = DB
::getInstance();
254 if ($include_children)
256 $parent = $parent ?
'WHERE parent LIKE \''.$db->escapeString($parent).'%\' ' : '';
260 $parent = $parent ?
'WHERE parent = \''.$db->escapeString($parent).'\' ' : 'WHERE parent = 0';
263 return $db->simpleStatementFetch('SELECT * FROM compta_comptes '.$parent.' ORDER BY id;');
266 protected function _checkFields(&$data, $force_parent_check = false)
268 $db = DB
::getInstance();
270 if (empty($data['libelle']) ||
!trim($data['libelle']))
272 throw new UserException('Le libellé ne peut rester vide.');
275 $data['libelle'] = trim($data['libelle']);
277 if (isset($data['id']))
279 $force_parent_check = true;
280 $data['id'] = trim($data['id']);
282 if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $data['id']))
284 throw new UserException('Le compte numéro '.$data['id'].' existe déjà.');
288 if (isset($data['parent']) ||
$force_parent_check)
290 if (empty($data['parent']) && !trim($data['parent']))
292 throw new UserException('Le compte ne peut pas ne pas avoir de compte parent.');
295 if (!($id = $db->simpleQuerySingle('SELECT id FROM compta_comptes WHERE id = ?;', false, $data['parent'])))
297 throw new UserException('Le compte parent indiqué n\'existe pas.');
300 $data['parent'] = trim($id);
303 if (isset($data['id']))
305 if (strncmp($data['id'], $data['parent'], strlen($data['parent'])) !== 0)
307 throw new UserException('Le compte '.$data['id'].' n\'est pas un sous-compte de '.$data['parent'].'.');
314 public function getPositions()
317 self
::ACTIF
=> 'Actif',
318 self
::PASSIF
=> 'Passif',
319 self
::ACTIF | self
::PASSIF
=> 'Actif ou passif (déterminé automatiquement au bilan selon le solde du compte)',
320 self
::CHARGE
=> 'Charge',
321 self
::PRODUIT
=> 'Produit',
322 self
::CHARGE | self
::PRODUIT
=> 'Charge et produit',