コード例 #1
0
ファイル: Stats.php プロジェクト: kd2org/garradin
    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;
    }
コード例 #2
0
ファイル: Comptes_Bancaires.php プロジェクト: kd2org/garradin
 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;');
 }
コード例 #3
0
ファイル: Rapprochement.php プロジェクト: kd2org/garradin
 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;
 }
コード例 #4
0
ファイル: Categories.php プロジェクト: kd2org/garradin
 public function getMoyenPaiement($code)
 {
     $db = DB::getInstance();
     return $db->simpleQuerySingle('SELECT nom FROM compta_moyens_paiement WHERE code = ?;', false, $code);
 }
コード例 #5
0
ファイル: Exercices.php プロジェクト: kd2org/garradin
 /**
  * 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];
 }
コード例 #6
0
ファイル: Cotisations.php プロジェクト: kd2org/garradin
    public function countForMember($id)
    {
        $db = DB::getInstance();
        return $db->simpleQuerySingle('SELECT COUNT(DISTINCT id_cotisation) FROM cotisations_membres 
			WHERE id_membre = ?;', false, (int) $id);
    }
コード例 #7
0
ファイル: Journal.php プロジェクト: kd2org/garradin
 public function schemaSQL()
 {
     $db = DB::getInstance();
     $tables = ['journal' => $db->querySingle('SELECT sql FROM sqlite_master WHERE type = \'table\' AND name = \'compta_journal\';')];
     return $tables;
 }
コード例 #8
0
ファイル: Import.php プロジェクト: kd2org/garradin
    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;
    }
コード例 #9
0
ファイル: Categories.php プロジェクト: kd2org/garradin
 public function listNotHidden()
 {
     $db = DB::getInstance();
     return $db->queryFetchAssoc('SELECT id, nom FROM membres_categories WHERE cacher = 0;');
 }
コード例 #10
0
ファイル: Import.php プロジェクト: kd2org/garradin
 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;
 }
コード例 #11
0
ファイル: Comptes.php プロジェクト: kd2org/garradin
 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;
 }
コード例 #12
0
ファイル: Champs.php プロジェクト: kd2org/garradin
 /**
  * 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;
 }