public function getStats($query) { $db = DB::getInstance(); $data = $db->simpleStatementFetchAssoc($query); $e = $db->querySingle('SELECT *, strftime(\'%s\', debut) AS debut, strftime(\'%s\', fin) AS fin FROM compta_exercices WHERE cloture = 0;', true); if (!$e) { return []; } $y = date('Y', $e['debut']); $m = date('m', $e['debut']); $max = date('Ym', $e['fin']); while ($y . $m <= $max) { if (!isset($data[$y . $m])) { $data[$y . $m] = 0; } if ($m == 12) { $m = '01'; $y++; } else { $m++; $m = str_pad((int) $m, 2, '0', STR_PAD_LEFT); } } ksort($data); return $data; }
public function getList($parent = false) { $db = DB::getInstance(); return $db->simpleStatementFetchAssocKey('SELECT c.id AS id, * FROM compta_comptes AS c INNER JOIN compta_comptes_bancaires AS cc ON c.id = cc.id WHERE c.parent = ' . self::NUMERO_PARENT_COMPTES . ' ORDER BY c.id;'); }
public function record($compte, $journal, $cases, $auteur) { if (!is_array($journal)) { throw new \UnexpectedValueException('$journal doit être un tableau.'); } if (!is_array($cases) && empty($cases)) { $cases = []; } $db = DB::getInstance(); $db->exec('BEGIN;'); // Synchro des trucs cochés $st = $db->prepare('INSERT OR REPLACE INTO compta_rapprochement (operation, auteur) VALUES (:operation, :auteur);'); $st->bindValue(':auteur', (int) $auteur, \SQLITE3_INTEGER); foreach ($journal as $row) { if (!array_key_exists($row['id'], $cases)) { continue; } $st->bindValue(':operation', (int) $row['id'], \SQLITE3_INTEGER); $st->execute(); } // Synchro des trucs NON cochés $st = $db->prepare('DELETE FROM compta_rapprochement WHERE operation = :id;'); foreach ($journal as $row) { if (array_key_exists($row['id'], $cases)) { continue; } $st->bindValue(':id', (int) $row['id'], \SQLITE3_INTEGER); $st->execute(); } $db->exec('END;'); return true; }
public function getMoyenPaiement($code) { $db = DB::getInstance(); return $db->simpleQuerySingle('SELECT nom FROM compta_moyens_paiement WHERE code = ?;', false, $code); }
/** * Calculer le bilan comptable pour l'exercice $exercice * @param integer $exercice ID de l'exercice dont il faut produire le bilan * @param boolean $resultat true s'il faut calculer le résultat de l'exercice (utile pour un exercice en cours) * @return array Un tableau multi-dimensionnel avec deux clés : actif et passif */ public function getBilan($exercice) { $db = DB::getInstance(); $include = [Comptes::ACTIF, Comptes::PASSIF, Comptes::PASSIF | Comptes::ACTIF]; $actif = ['comptes' => [], 'total' => 0.0]; $passif = ['comptes' => [], 'total' => 0.0]; $actif_ou_passif = ['comptes' => [], 'total' => 0.0]; $resultat = $this->getCompteResultat($exercice); if ($resultat['resultat'] >= 0) { $passif['comptes']['12'] = ['comptes' => ['120' => $resultat['resultat']], 'solde' => $resultat['resultat']]; $passif['total'] = $resultat['resultat']; } else { $passif['comptes']['12'] = ['comptes' => ['129' => $resultat['resultat']], 'solde' => $resultat['resultat']]; $passif['total'] = $resultat['resultat']; } // Y'a sûrement moyen d'améliorer tout ça pour que le maximum de travail // soit fait au niveau du SQL, mais pour le moment ça marche $res = $db->prepare('SELECT compte, debit, credit, (SELECT position FROM compta_comptes WHERE id = compte) AS position FROM (SELECT compte_debit AS compte, SUM(montant) AS debit, NULL AS credit FROM compta_journal WHERE id_exercice = ' . (int) $exercice . ' GROUP BY compte_debit UNION SELECT compte_credit AS compte, NULL AS debit, SUM(montant) AS credit FROM compta_journal WHERE id_exercice = ' . (int) $exercice . ' GROUP BY compte_credit) WHERE compte IN (SELECT id FROM compta_comptes WHERE position IN (' . implode(', ', $include) . ')) ORDER BY compte ASC;')->execute(); while ($row = $res->fetchArray(SQLITE3_NUM)) { list($compte, $debit, $credit, $position) = $row; $parent = substr($compte, 0, 2); $classe = $compte[0]; if ($position & Comptes::ACTIF && $position & Comptes::PASSIF) { $position = 'actif_ou_passif'; $solde = $debit - $credit; } else { if ($position & Comptes::ACTIF) { $position = 'actif'; $solde = $debit - $credit; } else { if ($position & Comptes::PASSIF) { $position = 'passif'; $solde = $credit - $debit; } else { continue; } } } if (!isset(${$position}['comptes'][$parent])) { ${$position}['comptes'][$parent] = ['comptes' => [], 'solde' => 0]; } if (!isset(${$position}['comptes'][$parent]['comptes'][$compte])) { ${$position}['comptes'][$parent]['comptes'][$compte] = 0; } $solde = round($solde, 2); ${$position}['comptes'][$parent]['comptes'][$compte] += $solde; ${$position}['total'] += $solde; ${$position}['comptes'][$parent]['solde'] += $solde; } $res->finalize(); foreach ($actif_ou_passif['comptes'] as $parent => $p) { foreach ($p['comptes'] as $compte => $solde) { if ($solde > 0) { $position = 'actif'; } else { if ($solde < 0) { $position = 'passif'; $solde = -$solde; } else { continue; } } if (!isset(${$position}['comptes'][$parent])) { ${$position}['comptes'][$parent] = ['comptes' => [], 'solde' => 0]; } if (!isset(${$position}['comptes'][$parent]['comptes'][$compte])) { ${$position}['comptes'][$parent]['comptes'][$compte] = 0; } ${$position}['comptes'][$parent]['comptes'][$compte] += $solde; ${$position}['total'] += $solde; ${$position}['comptes'][$parent]['solde'] += $solde; } } // Suppression des soldes nuls foreach ($passif['comptes'] as $parent => $p) { if ($p['solde'] == 0) { unset($passif['comptes'][$parent]); continue; } foreach ($p['comptes'] as $id => $solde) { if ($solde == 0) { unset($passif['comptes'][$parent]['comptes'][$id]); } } } foreach ($actif['comptes'] as $parent => $p) { if (empty($p['solde'])) { unset($actif['comptes'][$parent]); continue; } foreach ($p['comptes'] as $id => $solde) { if (empty($solde)) { unset($actif['comptes'][$parent]['comptes'][$id]); } } } return ['actif' => $actif, 'passif' => $passif]; }
public function countForMember($id) { $db = DB::getInstance(); return $db->simpleQuerySingle('SELECT COUNT(DISTINCT id_cotisation) FROM cotisations_membres WHERE id_membre = ?;', false, (int) $id); }
public function schemaSQL() { $db = DB::getInstance(); $tables = ['journal' => $db->querySingle('SELECT sql FROM sqlite_master WHERE type = \'table\' AND name = \'compta_journal\';')]; return $tables; }
public function fromCitizen($path) { if (!file_exists($path) || !is_readable($path)) { throw new \RuntimeException('Fichier inconnu : ' . $path); } $fp = fopen($path, 'r'); if (!$fp) { return false; } $db = DB::getInstance(); $db->exec('BEGIN;'); $comptes = new Comptes(); $banques = new Comptes_Bancaires(); $cats = new Categories(); $journal = new Journal(); $columns = []; $liste_comptes = $db->simpleStatementFetchAssoc('SELECT id, id FROM compta_comptes;'); $liste_cats = $db->simpleStatementFetchAssoc('SELECT intitule, id FROM compta_categories;'); $liste_moyens = $cats->listMoyensPaiement(); $get_compte = function ($compte, $intitule) use(&$liste_comptes, &$comptes, &$banques) { if (substr($compte, 0, 2) == '51') { $compte = '512' . substr($compte, -1); } // Création comptes if (!array_key_exists($compte, $liste_comptes)) { if (substr($compte, 0, 3) == '512') { $liste_comptes[$compte] = $banques->add(['libelle' => $intitule, 'banque' => 'Inconnue']); } else { $liste_comptes[$compte] = $comptes->add(['id' => $compte, 'libelle' => $intitule, 'parent' => substr($compte, 0, -1)]); } } return $compte; }; $col = function ($column) use(&$row, &$columns) { if (!isset($columns[$column])) { return null; } if (!isset($row[$columns[$column]])) { return null; } return $row[$columns[$column]]; }; $line = 0; $delim = Utils::find_csv_delim($fp); while (!feof($fp)) { $row = fgetcsv($fp, 4096, $delim); $line++; if (empty($row)) { continue; } if (empty($columns)) { $columns = $row; $columns = array_flip($columns); continue; } $date = $col('Date'); if (!preg_match('!^\\d{2}/\\d{2}/\\d{4}$!', $date)) { $db->exec('ROLLBACK;'); throw new UserException('Erreur sur la ligne ' . $line . ' : la date n\'est pas au format jj/mm/aaaa.'); } $date = explode('/', $date); $date = $date[2] . '-' . $date[1] . '-' . $date[0]; if ($db->simpleQuerySingle('SELECT 1 FROM compta_exercices WHERE (? < debut OR ? > fin) AND cloture = 0;', false, $date, $date)) { continue; } $debit = $get_compte($col('Compte débité - Numéro'), $col('Compte débité - Intitulé')); $credit = $get_compte($col('Compte crédité - Numéro'), $col('Compte crédité - Intitulé')); $cat = $col('Rubrique'); $moyen = strtoupper(substr($col('Moyen de paiement'), 0, 2)); if (!$moyen || !array_key_exists($moyen, $liste_moyens)) { $moyen = false; $cat = false; } if ($cat && !array_key_exists($cat, $liste_cats)) { if ($col('Nature') == 'Recette') { $type = $cats::RECETTES; $compte = $credit; } elseif ($col('Nature') == 'Dépense') { $type = $cats::DEPENSES; $compte = $debit; } else { $type = $cats::AUTRES; $cat = false; } if ($type != $cats::AUTRES) { $liste_cats[$cat] = $cats->add(['intitule' => $cat, 'type' => $type, 'compte' => $compte]); } } $data = ['libelle' => $col('Libellé'), 'montant' => $col('Montant'), 'date' => $date, 'compte_credit' => $credit, 'compte_debit' => $debit, 'numero_piece' => $col('Numéro de pièce'), 'remarques' => $col('Remarques')]; if ($cat) { $data['moyen_paiement'] = $moyen; $data['numero_cheque'] = $col('Numéro de chèque'); $data['id_categorie'] = $liste_cats[$cat]; } $journal->add($data); } $db->exec('END;'); fclose($fp); return true; }
public function listNotHidden() { $db = DB::getInstance(); return $db->queryFetchAssoc('SELECT id, nom FROM membres_categories WHERE cacher = 0;'); }
public function toCSV() { $db = DB::getInstance(); $res = $db->prepare('SELECT m.id, c.nom AS categorie, m.* FROM membres AS m LEFT JOIN membres_categories AS c ON m.id_categorie = c.id ORDER BY c.id;')->execute(); $fp = fopen('php://output', 'w'); $header = false; while ($row = $res->fetchArray(SQLITE3_ASSOC)) { unset($row['passe']); if (!$header) { fputcsv($fp, array_keys($row)); $header = true; } fputcsv($fp, $row); } fclose($fp); return true; }
protected function _checkFields(&$data, $force_parent_check = false) { $db = DB::getInstance(); if (empty($data['libelle']) || !trim($data['libelle'])) { throw new UserException('Le libellé ne peut rester vide.'); } $data['libelle'] = trim($data['libelle']); if (isset($data['id'])) { $force_parent_check = true; $data['id'] = trim($data['id']); if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $data['id'])) { throw new UserException('Le compte numéro ' . $data['id'] . ' existe déjà.'); } } if (isset($data['parent']) || $force_parent_check) { if (empty($data['parent']) && !trim($data['parent'])) { throw new UserException('Le compte ne peut pas ne pas avoir de compte parent.'); } if (!($id = $db->simpleQuerySingle('SELECT id FROM compta_comptes WHERE id = ?;', false, $data['parent']))) { throw new UserException('Le compte parent indiqué n\'existe pas.'); } $data['parent'] = trim($id); } if (isset($data['id'])) { if (strncmp($data['id'], $data['parent'], strlen($data['parent'])) !== 0) { throw new UserException('Le compte ' . $data['id'] . ' n\'est pas un sous-compte de ' . $data['parent'] . '.'); } } return true; }
/** * Enregistre les changements de champs en base de données * @param boolean $enable_copy Recopier les anciennes champs dans les nouveaux ? * @return boolean true */ public function save($enable_copy = true) { $db = DB::getInstance(); $config = Config::getInstance(); // Champs à créer $create = ['id INTEGER PRIMARY KEY, -- Numéro attribué automatiquement', 'id_categorie INTEGER NOT NULL, -- Numéro de catégorie', 'date_connexion TEXT NULL, -- Date de dernière connexion', 'date_inscription TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d\'inscription']; $create_keys = ['FOREIGN KEY (id_categorie) REFERENCES membres_categories (id)']; // Champs à recopier $copy = ['id', 'id_categorie', 'date_connexion', 'date_inscription']; $anciens_champs = $config->get('champs_membres'); $anciens_champs = is_null($anciens_champs) ? $this->champs : $anciens_champs->getAll(); foreach ($this->champs as $key => $cfg) { if ($cfg['type'] == 'number') { $type = 'FLOAT'; } elseif ($cfg['type'] == 'multiple' || $cfg['type'] == 'checkbox') { $type = 'INTEGER'; } elseif ($cfg['type'] == 'file') { $type = 'BLOB'; } else { $type = 'TEXT'; } $line = $key . ' ' . $type . ','; if (!empty($cfg['title'])) { $line .= ' -- ' . str_replace(["\n", "\r"], '', $cfg['title']); } $create[] = $line; if (array_key_exists($key, $anciens_champs)) { $copy[] = $key; } } $create = array_merge($create, $create_keys); $create = 'CREATE TABLE membres_tmp (' . "\n\t" . implode("\n\t", $create) . "\n);"; $copy = 'INSERT INTO membres_tmp (' . implode(', ', $copy) . ') SELECT ' . implode(', ', $copy) . ' FROM membres;'; $db->exec('PRAGMA foreign_keys = OFF;'); $db->exec('BEGIN;'); $db->exec($create); if ($enable_copy) { $db->exec($copy); } $db->exec('DROP TABLE IF EXISTS membres;'); $db->exec('ALTER TABLE membres_tmp RENAME TO membres;'); $db->exec('CREATE INDEX membres_id_categorie ON membres (id_categorie);'); // Index if ($config->get('champ_identifiant')) { // Mettre les champs identifiant vides à NULL pour pouvoir créer un index unique $db->exec('UPDATE membres SET ' . $config->get('champ_identifiant') . ' = NULL WHERE ' . $config->get('champ_identifiant') . ' = "";'); // Création de l'index unique $db->exec('CREATE UNIQUE INDEX membres_identifiant ON membres (' . $config->get('champ_identifiant') . ');'); } // Création des index pour les champs affichés dans la liste des membres $listed_fields = array_keys($this->getListedFields()); foreach ($listed_fields as $field) { if ($field === $config->get('champ_identifiant')) { // Il y a déjà un index continue; } $db->exec('CREATE INDEX membres_liste_' . $field . ' ON membres (' . $field . ');'); } $db->exec('END;'); $db->exec('PRAGMA foreign_keys = ON;'); $config->set('champs_membres', $this); $config->save(); return true; }