Comment: | Merge dev into trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both |
Files: | files | file ages | folders |
SHA1: |
81dd73fb2691422def62be69a2ce9be1 |
User & Date: | bohwaz on 2020-12-06 18:40:08 |
Other Links: | manifest | tags |
2020-12-06
| ||
18:41 | New release check-in: e45b645e78 user: bohwaz tags: trunk, stable, 1.0.0-rc8 | |
18:40 | Merge dev into trunk check-in: 81dd73fb26 user: bohwaz | |
14:57 | Transfer was reversed check-in: 3af5abf868 user: bohwaz tags: dev | |
2020-09-08
| ||
18:53 | Limiter la longueur du champ de recherche check-in: 0277842dc6 user: bohwaz tags: trunk, stable | |
Modified .travis.yml from [ab9c965cec] to [4da8c0eef1].
1 2 | language: php php: | < < < | 1 2 3 4 5 6 7 8 9 | language: php php: - '7.2' - '7.3' - '7.4' install: - make -C src deps |
︙ | ︙ |
Name change from src/COPYING to COPYING.
︙ | ︙ |
Modified README.md from [b24af5ed67] to [b535b9dd6a].
|
| | | > > | > > | > | > | > | > > | > | > > > > | > | 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 | # Garradin - Le gestionnaire d'association Garradin est un logiciel de gestion de petite et moyenne association. Plus d'infos sur le site de développement ici : [fossil.kd2.org/garradin](https://fossil.kd2.org/garradin/) [Documentation développeuse⋅développeur](https://fossil.kd2.org/garradin/wiki?name=Documentation+d%C3%A9veloppeur) Il est possible d'essayer et utiliser gratuitement Garradin sur la plateforme [Garradin.eu](https://garradin.eu/). Le code sur Github, n'est qu'un miroir, le développement principal se passe sur Fossil. ## Licence GNU Affero GPL v3 (voir fichier COPYING) Cette licence permet la libre redistribution, utilisation et modification du logiciel. La seule condition est de re-partager les éventuelles modifications apportées. Cette clause s'applique même si le logiciel n'est pas distribué et simplement installé sur un serveur. ## Code utilisé Inclus les bibliothèques suivantes : * [KD2fw](https://fossil.kd2.org/kd2fw/) - Copyright : 2001-2020+ BohwaZ - Licence : GNU AGPL v3 * [Gibberish AES](https://github.com/mdp/gibberish-aes) - Copyright : Mark Percival 2008 - http://markpercival.us -Licence : MIT |
Name change from src/include/data/0.7.0.sql to archives/0.7.0_migration.sql.
︙ | ︙ |
Name change from src/include/data/0.7.2.sql to archives/0.7.2_migration.sql.
︙ | ︙ |
Modified archives/0.8.0_migration.sql from [34e1625504] to [b56b968950].
︙ | ︙ | |||
47 48 49 50 51 52 53 | -- Sinon les nouveaux ne seront pas créés sur la nouvelle table DROP TRIGGER wiki_recherche_delete; DROP TRIGGER wiki_recherche_update; DROP TRIGGER wiki_recherche_contenu_insert; DROP TRIGGER wiki_recherche_contenu_chiffre; -- Création des tables mises à jour (et de leurs index) | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | -- Sinon les nouveaux ne seront pas créés sur la nouvelle table DROP TRIGGER wiki_recherche_delete; DROP TRIGGER wiki_recherche_update; DROP TRIGGER wiki_recherche_contenu_insert; DROP TRIGGER wiki_recherche_contenu_chiffre; -- Création des tables mises à jour (et de leurs index) .read 0.8.0_schema.sql -- Copie des données INSERT INTO cotisations_membres SELECT * FROM cotisations_membres_old; INSERT INTO rappels SELECT * FROM rappels_old; INSERT INTO rappels_envoyes SELECT id, id_membre, id_cotisation, id_rappel, date, media FROM rappels_envoyes_old; INSERT INTO wiki_pages SELECT * FROM wiki_pages_old; INSERT INTO wiki_revisions SELECT * FROM wiki_revisions_old; |
︙ | ︙ |
Added archives/0.8.0_schema.sql version [1c0ae41b79].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | CREATE TABLE IF NOT EXISTS config ( -- Configuration de Garradin cle TEXT PRIMARY KEY NOT NULL, valeur TEXT ); -- On stocke ici les ID de catégorie de compta correspondant aux types spéciaux -- compta_categorie_cotisations => id_categorie -- compta_categorie_dons => id_categorie CREATE TABLE IF NOT EXISTS membres_categories -- Catégories de membres ( id INTEGER PRIMARY KEY NOT NULL, nom TEXT NOT NULL, description TEXT NULL, droit_wiki INTEGER NOT NULL DEFAULT 1, droit_membres INTEGER NOT NULL DEFAULT 1, droit_compta INTEGER NOT NULL DEFAULT 1, droit_inscription INTEGER NOT NULL DEFAULT 0, droit_connexion INTEGER NOT NULL DEFAULT 1, droit_config INTEGER NOT NULL DEFAULT 0, cacher INTEGER NOT NULL DEFAULT 0, id_cotisation_obligatoire INTEGER NULL REFERENCES cotisations (id) ON DELETE SET NULL ); -- Membres de l'asso -- Table dynamique générée par l'application -- voir Garradin\Membres\Champs.php CREATE TABLE IF NOT EXISTS membres_sessions -- Sessions ( selecteur TEXT NOT NULL, hash TEXT NOT NULL, id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, expire INT NOT NULL, PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS cotisations -- Types de cotisations et activités ( id INTEGER PRIMARY KEY NOT NULL, id_categorie_compta INTEGER NULL, -- NULL si le type n'est pas associé automatiquement à la compta intitule TEXT NOT NULL, description TEXT NULL, montant REAL NOT NULL, duree INTEGER NULL, -- En jours debut TEXT NULL, -- timestamp fin TEXT NULL, FOREIGN KEY (id_categorie_compta) REFERENCES compta_categories (id) ); 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, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date) ); CREATE UNIQUE INDEX IF NOT EXISTS cm_unique ON cotisations_membres (id_membre, id_cotisation, date); CREATE TABLE IF NOT EXISTS membres_operations -- Liaision des enregistrement des paiements en compta ( id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_operation INTEGER NOT NULL REFERENCES compta_journal (id) ON DELETE CASCADE, id_cotisation INTEGER NULL REFERENCES cotisations_membres (id) ON DELETE SET NULL, PRIMARY KEY (id_membre, id_operation) ); CREATE TABLE IF NOT EXISTS rappels -- Rappels de devoir renouveller une cotisation ( id INTEGER NOT NULL PRIMARY KEY, id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE, delai INTEGER NOT NULL, -- Délai en jours pour envoyer le rappel sujet TEXT NOT NULL, texte TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS rappels_envoyes -- Enregistrement des rappels envoyés à qui et quand ( 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, id_rappel INTEGER NULL REFERENCES rappels (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), media INTEGER NOT NULL -- Média utilisé pour le rappel : 1 = email, 2 = courrier, 3 = autre ); -- -- WIKI -- CREATE TABLE IF NOT EXISTS wiki_pages -- Pages du wiki ( id INTEGER PRIMARY KEY NOT NULL, uri TEXT NOT NULL, -- URI unique (équivalent NomPageWiki) titre TEXT NOT NULL, date_creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_creation) IS NOT NULL AND datetime(date_creation) = date_creation), date_modification TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_modification) IS NOT NULL AND datetime(date_modification) = date_modification), parent INTEGER NOT NULL DEFAULT 0, -- ID de la page parent revision INTEGER NOT NULL DEFAULT 0, -- Numéro de révision (commence à 0 si pas de texte, +1 à chaque changement du texte) droit_lecture INTEGER NOT NULL DEFAULT 0, -- Accès en lecture (-1 = public [site web], 0 = tous ceux qui ont accès en lecture au wiki, 1+ = ID de groupe) droit_ecriture INTEGER NOT NULL DEFAULT 0 -- Accès en écriture (0 = tous ceux qui ont droit d'écriture sur le wiki, 1+ = ID de groupe) ); CREATE UNIQUE INDEX IF NOT EXISTS wiki_uri ON wiki_pages (uri); CREATE VIRTUAL TABLE IF NOT EXISTS wiki_recherche USING fts4 -- Table dupliquée pour chercher une page ( id INT PRIMARY KEY NOT NULL, -- Clé externe obligatoire titre TEXT NOT NULL, contenu TEXT NULL, -- Contenu de la dernière révision FOREIGN KEY (id) REFERENCES wiki_pages(id) ); CREATE TABLE IF NOT EXISTS wiki_revisions -- Révisions du contenu des pages ( id_page INTEGER NOT NULL REFERENCES wiki_pages (id) ON DELETE CASCADE, revision INTEGER NULL, id_auteur INTEGER NULL REFERENCES membres (id) ON DELETE SET NULL, contenu TEXT NOT NULL, modification TEXT NULL, -- Description des modifications effectuées chiffrement INTEGER NOT NULL DEFAULT 0, -- 1 si le contenu est chiffré, 0 sinon date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), PRIMARY KEY(id_page, revision) ); CREATE INDEX IF NOT EXISTS wiki_revisions_id_page ON wiki_revisions (id_page); CREATE INDEX IF NOT EXISTS wiki_revisions_id_auteur ON wiki_revisions (id_auteur); -- Triggers pour synchro avec table wiki_pages CREATE TRIGGER IF NOT EXISTS wiki_recherche_delete AFTER DELETE ON wiki_pages BEGIN DELETE FROM wiki_recherche WHERE id = old.id; END; CREATE TRIGGER IF NOT EXISTS wiki_recherche_update AFTER UPDATE OF id, titre ON wiki_pages BEGIN UPDATE wiki_recherche SET id = new.id, titre = new.titre WHERE id = old.id; END; -- Trigger pour mettre à jour le contenu de la table de recherche lors d'une nouvelle révision CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_insert AFTER INSERT ON wiki_revisions WHEN new.chiffrement != 1 BEGIN UPDATE wiki_recherche SET contenu = new.contenu WHERE id = new.id_page; END; -- Si le contenu est chiffré, la recherche n'affiche pas de contenu CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_chiffre AFTER INSERT ON wiki_revisions WHEN new.chiffrement = 1 BEGIN UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; /* CREATE TABLE wiki_suivi -- Suivi des pages ( id_membre INTEGER NOT NULL, id_page INTEGER NOT NULL, PRIMARY KEY (id_membre, id_page), FOREIGN KEY (id_page) REFERENCES wiki_pages (id), -- Clé externe obligatoire FOREIGN KEY (id_membre) REFERENCES membres (id) -- Clé externe obligatoire ); */ -- -- COMPTA -- CREATE TABLE IF NOT EXISTS compta_exercices -- Exercices ( id INTEGER NOT NULL PRIMARY KEY, libelle TEXT NOT NULL, debut TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(debut) IS NOT NULL AND date(debut) = debut), fin TEXT NULL DEFAULT NULL CHECK (fin IS NULL OR (date(fin) IS NOT NULL AND date(fin) = fin)), cloture INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS compta_comptes -- Plan comptable ( id TEXT NOT NULL PRIMARY KEY, -- peut contenir des lettres, eg. 53A, 53B, etc. parent TEXT NOT NULL DEFAULT 0, libelle TEXT NOT NULL, position INTEGER NOT NULL, -- position actif/passif/charge/produit plan_comptable INTEGER NOT NULL DEFAULT 1, -- 1 = fait partie du plan comptable, 0 = a été ajouté par l'utilisateur desactive INTEGER NOT NULL DEFAULT 0 -- 1 = compte historique désactivé ); CREATE INDEX IF NOT EXISTS compta_comptes_parent ON compta_comptes (parent); CREATE TABLE IF NOT EXISTS compta_comptes_bancaires -- Comptes bancaires ( id TEXT NOT NULL PRIMARY KEY, banque TEXT NOT NULL, iban TEXT NULL, bic TEXT NULL, FOREIGN KEY(id) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS compta_projets -- Projets (compta analytique) ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS compta_journal -- Journal des opérations comptables ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL, remarques TEXT NULL, numero_piece TEXT NULL, -- N° de pièce comptable montant REAL NOT NULL, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), moyen_paiement TEXT NULL, numero_cheque TEXT NULL, compte_debit TEXT NULL, -- N° du compte dans le plan, NULL est utilisé pour une opération qui vient d'un exercice précédent compte_credit TEXT NULL, -- N° du compte dans le plan id_exercice INTEGER NULL DEFAULT NULL, -- En cas de compta simple, l'exercice est permanent (NULL) id_auteur INTEGER NULL, id_categorie INTEGER NULL, -- Numéro de catégorie (en mode simple) id_projet INTEGER NULL, FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code), FOREIGN KEY(compte_debit) REFERENCES compta_comptes(id), FOREIGN KEY(compte_credit) REFERENCES compta_comptes(id), FOREIGN KEY(id_exercice) REFERENCES compta_exercices(id), FOREIGN KEY(id_auteur) REFERENCES membres(id) ON DELETE SET NULL, FOREIGN KEY(id_categorie) REFERENCES compta_categories(id) ON DELETE SET NULL, FOREIGN KEY(id_projet) REFERENCES compta_projets(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS compta_operations_exercice ON compta_journal (id_exercice); CREATE INDEX IF NOT EXISTS compta_operations_date ON compta_journal (date); CREATE INDEX IF NOT EXISTS compta_operations_comptes ON compta_journal (compte_debit, compte_credit); CREATE INDEX IF NOT EXISTS compta_operations_auteur ON compta_journal (id_auteur); CREATE TABLE IF NOT EXISTS compta_moyens_paiement -- Moyens de paiement ( code TEXT NOT NULL PRIMARY KEY, nom TEXT NOT NULL ); --INSERT INTO compta_moyens_paiement (code, nom) VALUES ('AU', 'Autre'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CB', 'Carte bleue'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CH', 'Chèque'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('ES', 'Espèces'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('PR', 'Prélèvement'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('TI', 'TIP'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('VI', 'Virement'); CREATE TABLE IF NOT EXISTS compta_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) intitule TEXT NOT NULL, description TEXT NULL, compte TEXT NOT NULL, -- Compte affecté par cette catégorie FOREIGN KEY(compte) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS plugins ( id TEXT NOT NULL PRIMARY KEY, officiel INTEGER NOT NULL DEFAULT 0, nom TEXT NOT NULL, description TEXT NULL, auteur TEXT NULL, url TEXT NULL, version TEXT NOT NULL, menu INTEGER NOT NULL DEFAULT 0, config TEXT NULL ); CREATE TABLE IF NOT EXISTS plugins_signaux -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE IF NOT EXISTS compta_rapprochement -- Rapprochement entre compta et relevés de comptes ( id_operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), id_auteur INTEGER NULL REFERENCES membres (id) ); CREATE TABLE IF NOT EXISTS fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue datetime TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(datetime) IS NOT NULL AND datetime(datetime) = datetime), -- Date d'ajout ou mise à jour du fichier id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS fichiers_date ON fichiers (datetime); CREATE TABLE IF NOT EXISTS fichiers_contenu -- Contenu des fichiers ( id INTEGER NOT NULL PRIMARY KEY, hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL, -- Taille en octets contenu BLOB NULL ); CREATE UNIQUE INDEX IF NOT EXISTS fichiers_hash ON fichiers_contenu (hash); CREATE TABLE IF NOT EXISTS fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES membres (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS fichiers_wiki_pages -- 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_compta_journal -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES compta_journal (id), PRIMARY KEY(fichier, id) ); |
Modified archives/0.8.3_migration.sql from [68c67cd1a9] to [78f64dc820].
1 2 3 4 | -- Ajout d'une clause ON DELETE SET NULL sur la table cotisations ALTER TABLE cotisations_membres RENAME TO cotisations_membres_old; -- Création des tables mises à jour (et de leurs index) | | | 1 2 3 4 5 6 7 8 9 10 11 | -- Ajout d'une clause ON DELETE SET NULL sur la table cotisations ALTER TABLE cotisations_membres RENAME TO cotisations_membres_old; -- Création des tables mises à jour (et de leurs index) .read 0.8.3_schema.sql -- Copie des données INSERT INTO cotisations_membres SELECT * FROM cotisations_membres_old; -- Suppression des anciennes tables DROP TABLE cotisations_membres_old; |
Added archives/0.8.3_schema.sql version [80be656e5d].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | CREATE TABLE IF NOT EXISTS config ( -- Configuration de Garradin cle TEXT PRIMARY KEY NOT NULL, valeur TEXT ); -- On stocke ici les ID de catégorie de compta correspondant aux types spéciaux -- compta_categorie_cotisations => id_categorie -- compta_categorie_dons => id_categorie CREATE TABLE IF NOT EXISTS membres_categories -- Catégories de membres ( id INTEGER PRIMARY KEY NOT NULL, nom TEXT NOT NULL, description TEXT NULL, droit_wiki INTEGER NOT NULL DEFAULT 1, droit_membres INTEGER NOT NULL DEFAULT 1, droit_compta INTEGER NOT NULL DEFAULT 1, droit_inscription INTEGER NOT NULL DEFAULT 0, droit_connexion INTEGER NOT NULL DEFAULT 1, droit_config INTEGER NOT NULL DEFAULT 0, cacher INTEGER NOT NULL DEFAULT 0, id_cotisation_obligatoire INTEGER NULL REFERENCES cotisations (id) ON DELETE SET NULL ); -- Membres de l'asso -- Table dynamique générée par l'application -- voir Garradin\Membres\Champs.php CREATE TABLE IF NOT EXISTS membres_sessions -- Sessions ( selecteur TEXT NOT NULL, hash TEXT NOT NULL, id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, expire INT NOT NULL, PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS cotisations -- Types de cotisations et activités ( id INTEGER PRIMARY KEY NOT NULL, id_categorie_compta INTEGER NULL REFERENCES compta_categories (id) ON DELETE SET NULL, -- NULL si le type n'est pas associé automatiquement à la compta intitule TEXT NOT NULL, description TEXT NULL, montant REAL NOT NULL, duree INTEGER NULL, -- En jours debut TEXT NULL, -- timestamp fin TEXT NULL ); 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, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date) ); CREATE UNIQUE INDEX IF NOT EXISTS cm_unique ON cotisations_membres (id_membre, id_cotisation, date); CREATE TABLE IF NOT EXISTS membres_operations -- Liaison des enregistrement des paiements en compta ( id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_operation INTEGER NOT NULL REFERENCES compta_journal (id) ON DELETE CASCADE, id_cotisation INTEGER NULL REFERENCES cotisations_membres (id) ON DELETE SET NULL, PRIMARY KEY (id_membre, id_operation) ); CREATE TABLE IF NOT EXISTS rappels -- Rappels de devoir renouveller une cotisation ( id INTEGER NOT NULL PRIMARY KEY, id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE, delai INTEGER NOT NULL, -- Délai en jours pour envoyer le rappel sujet TEXT NOT NULL, texte TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS rappels_envoyes -- Enregistrement des rappels envoyés à qui et quand ( 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, id_rappel INTEGER NULL REFERENCES rappels (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), media INTEGER NOT NULL -- Média utilisé pour le rappel : 1 = email, 2 = courrier, 3 = autre ); -- -- WIKI -- CREATE TABLE IF NOT EXISTS wiki_pages -- Pages du wiki ( id INTEGER PRIMARY KEY NOT NULL, uri TEXT NOT NULL, -- URI unique (équivalent NomPageWiki) titre TEXT NOT NULL, date_creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_creation) IS NOT NULL AND datetime(date_creation) = date_creation), date_modification TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_modification) IS NOT NULL AND datetime(date_modification) = date_modification), parent INTEGER NOT NULL DEFAULT 0, -- ID de la page parent revision INTEGER NOT NULL DEFAULT 0, -- Numéro de révision (commence à 0 si pas de texte, +1 à chaque changement du texte) droit_lecture INTEGER NOT NULL DEFAULT 0, -- Accès en lecture (-1 = public [site web], 0 = tous ceux qui ont accès en lecture au wiki, 1+ = ID de groupe) droit_ecriture INTEGER NOT NULL DEFAULT 0 -- Accès en écriture (0 = tous ceux qui ont droit d'écriture sur le wiki, 1+ = ID de groupe) ); CREATE UNIQUE INDEX IF NOT EXISTS wiki_uri ON wiki_pages (uri); CREATE VIRTUAL TABLE IF NOT EXISTS wiki_recherche USING fts4 -- Table dupliquée pour chercher une page ( id INT PRIMARY KEY NOT NULL, -- Clé externe obligatoire titre TEXT NOT NULL, contenu TEXT NULL, -- Contenu de la dernière révision FOREIGN KEY (id) REFERENCES wiki_pages(id) ); CREATE TABLE IF NOT EXISTS wiki_revisions -- Révisions du contenu des pages ( id_page INTEGER NOT NULL REFERENCES wiki_pages (id) ON DELETE CASCADE, revision INTEGER NULL, id_auteur INTEGER NULL REFERENCES membres (id) ON DELETE SET NULL, contenu TEXT NOT NULL, modification TEXT NULL, -- Description des modifications effectuées chiffrement INTEGER NOT NULL DEFAULT 0, -- 1 si le contenu est chiffré, 0 sinon date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), PRIMARY KEY(id_page, revision) ); CREATE INDEX IF NOT EXISTS wiki_revisions_id_page ON wiki_revisions (id_page); CREATE INDEX IF NOT EXISTS wiki_revisions_id_auteur ON wiki_revisions (id_auteur); -- Triggers pour synchro avec table wiki_pages CREATE TRIGGER IF NOT EXISTS wiki_recherche_delete AFTER DELETE ON wiki_pages BEGIN DELETE FROM wiki_recherche WHERE id = old.id; END; CREATE TRIGGER IF NOT EXISTS wiki_recherche_update AFTER UPDATE OF id, titre ON wiki_pages BEGIN UPDATE wiki_recherche SET id = new.id, titre = new.titre WHERE id = old.id; END; -- Trigger pour mettre à jour le contenu de la table de recherche lors d'une nouvelle révision CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_insert AFTER INSERT ON wiki_revisions WHEN new.chiffrement != 1 BEGIN UPDATE wiki_recherche SET contenu = new.contenu WHERE id = new.id_page; END; -- Si le contenu est chiffré, la recherche n'affiche pas de contenu CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_chiffre AFTER INSERT ON wiki_revisions WHEN new.chiffrement = 1 BEGIN UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; /* CREATE TABLE wiki_suivi -- Suivi des pages ( id_membre INTEGER NOT NULL, id_page INTEGER NOT NULL, PRIMARY KEY (id_membre, id_page), FOREIGN KEY (id_page) REFERENCES wiki_pages (id), -- Clé externe obligatoire FOREIGN KEY (id_membre) REFERENCES membres (id) -- Clé externe obligatoire ); */ -- -- COMPTA -- CREATE TABLE IF NOT EXISTS compta_exercices -- Exercices ( id INTEGER NOT NULL PRIMARY KEY, libelle TEXT NOT NULL, debut TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(debut) IS NOT NULL AND date(debut) = debut), fin TEXT NULL DEFAULT NULL CHECK (fin IS NULL OR (date(fin) IS NOT NULL AND date(fin) = fin)), cloture INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS compta_comptes -- Plan comptable ( id TEXT NOT NULL PRIMARY KEY, -- peut contenir des lettres, eg. 53A, 53B, etc. parent TEXT NOT NULL DEFAULT 0, libelle TEXT NOT NULL, position INTEGER NOT NULL, -- position actif/passif/charge/produit plan_comptable INTEGER NOT NULL DEFAULT 1, -- 1 = fait partie du plan comptable, 0 = a été ajouté par l'utilisateur desactive INTEGER NOT NULL DEFAULT 0 -- 1 = compte historique désactivé ); CREATE INDEX IF NOT EXISTS compta_comptes_parent ON compta_comptes (parent); CREATE TABLE IF NOT EXISTS compta_comptes_bancaires -- Comptes bancaires ( id TEXT NOT NULL PRIMARY KEY, banque TEXT NOT NULL, iban TEXT NULL, bic TEXT NULL, FOREIGN KEY(id) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS compta_projets -- Projets (compta analytique) ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS compta_journal -- Journal des opérations comptables ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL, remarques TEXT NULL, numero_piece TEXT NULL, -- N° de pièce comptable montant REAL NOT NULL, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), moyen_paiement TEXT NULL, numero_cheque TEXT NULL, compte_debit TEXT NULL, -- N° du compte dans le plan, NULL est utilisé pour une opération qui vient d'un exercice précédent compte_credit TEXT NULL, -- N° du compte dans le plan id_exercice INTEGER NULL DEFAULT NULL, -- En cas de compta simple, l'exercice est permanent (NULL) id_auteur INTEGER NULL, id_categorie INTEGER NULL, -- Numéro de catégorie (en mode simple) id_projet INTEGER NULL, FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code), FOREIGN KEY(compte_debit) REFERENCES compta_comptes(id), FOREIGN KEY(compte_credit) REFERENCES compta_comptes(id), FOREIGN KEY(id_exercice) REFERENCES compta_exercices(id), FOREIGN KEY(id_auteur) REFERENCES membres(id) ON DELETE SET NULL, FOREIGN KEY(id_categorie) REFERENCES compta_categories(id) ON DELETE SET NULL, FOREIGN KEY(id_projet) REFERENCES compta_projets(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS compta_operations_exercice ON compta_journal (id_exercice); CREATE INDEX IF NOT EXISTS compta_operations_date ON compta_journal (date); CREATE INDEX IF NOT EXISTS compta_operations_comptes ON compta_journal (compte_debit, compte_credit); CREATE INDEX IF NOT EXISTS compta_operations_auteur ON compta_journal (id_auteur); CREATE TABLE IF NOT EXISTS compta_moyens_paiement -- Moyens de paiement ( code TEXT NOT NULL PRIMARY KEY, nom TEXT NOT NULL ); --INSERT INTO compta_moyens_paiement (code, nom) VALUES ('AU', 'Autre'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CB', 'Carte bleue'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CH', 'Chèque'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('ES', 'Espèces'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('PR', 'Prélèvement'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('TI', 'TIP'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('VI', 'Virement'); CREATE TABLE IF NOT EXISTS compta_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) intitule TEXT NOT NULL, description TEXT NULL, compte TEXT NOT NULL, -- Compte affecté par cette catégorie FOREIGN KEY(compte) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS plugins ( id TEXT NOT NULL PRIMARY KEY, officiel INTEGER NOT NULL DEFAULT 0, nom TEXT NOT NULL, description TEXT NULL, auteur TEXT NULL, url TEXT NULL, version TEXT NOT NULL, menu INTEGER NOT NULL DEFAULT 0, config TEXT NULL ); CREATE TABLE IF NOT EXISTS plugins_signaux -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE IF NOT EXISTS compta_rapprochement -- Rapprochement entre compta et relevés de comptes ( id_operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), id_auteur INTEGER NULL REFERENCES membres (id) ); CREATE TABLE IF NOT EXISTS fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue datetime TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(datetime) IS NOT NULL AND datetime(datetime) = datetime), -- Date d'ajout ou mise à jour du fichier id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS fichiers_date ON fichiers (datetime); CREATE TABLE IF NOT EXISTS fichiers_contenu -- Contenu des fichiers ( id INTEGER NOT NULL PRIMARY KEY, hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL, -- Taille en octets contenu BLOB NULL ); CREATE UNIQUE INDEX IF NOT EXISTS fichiers_hash ON fichiers_contenu (hash); CREATE TABLE IF NOT EXISTS fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES membres (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS fichiers_wiki_pages -- 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_compta_journal -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES compta_journal (id), PRIMARY KEY(fichier, id) ); |
Name change from src/include/data/0.8.4.sql to archives/0.8.4_migration.sql.
Modified archives/0.9.0_migration.sql from [9f23495ff4] to [90ab72f7f4].
1 2 3 4 5 6 7 8 9 10 11 12 13 | -- Désactivation de l'accès aux membres, pour les groupes qui n'avaient que le droit de lecture -- car maintenant ce droit permet de voir les fiches de membres complètes UPDATE membres_categories SET droit_membres = 0 WHERE droit_membres = 1; -- Suppression de la colonne description des catégories ALTER TABLE membres_categories RENAME TO membres_categories_old; -- Mise à jour table compta_rapprochement: la foreign key sur membres est passée -- à ON DELETE SET NULL ALTER TABLE compta_rapprochement RENAME TO compta_rapprochement_old; -- Re-créer la table -- Créer également les nouvelles tables email | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | -- Désactivation de l'accès aux membres, pour les groupes qui n'avaient que le droit de lecture -- car maintenant ce droit permet de voir les fiches de membres complètes UPDATE membres_categories SET droit_membres = 0 WHERE droit_membres = 1; -- Suppression de la colonne description des catégories ALTER TABLE membres_categories RENAME TO membres_categories_old; -- Mise à jour table compta_rapprochement: la foreign key sur membres est passée -- à ON DELETE SET NULL ALTER TABLE compta_rapprochement RENAME TO compta_rapprochement_old; -- Re-créer la table -- Créer également les nouvelles tables email .read 0.9.0_schema.sql -- Copie des données, sauf la colonne description INSERT INTO membres_categories SELECT id, nom, droit_wiki, droit_membres, droit_compta, droit_inscription, droit_connexion, droit_config, cacher, id_cotisation_obligatoire FROM membres_categories_old; |
︙ | ︙ |
Added archives/0.9.0_schema.sql version [9f23495ff4].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | -- Désactivation de l'accès aux membres, pour les groupes qui n'avaient que le droit de lecture -- car maintenant ce droit permet de voir les fiches de membres complètes UPDATE membres_categories SET droit_membres = 0 WHERE droit_membres = 1; -- Suppression de la colonne description des catégories ALTER TABLE membres_categories RENAME TO membres_categories_old; -- Mise à jour table compta_rapprochement: la foreign key sur membres est passée -- à ON DELETE SET NULL ALTER TABLE compta_rapprochement RENAME TO compta_rapprochement_old; -- Re-créer la table -- Créer également les nouvelles tables email .read schema.sql -- Copie des données, sauf la colonne description INSERT INTO membres_categories SELECT id, nom, droit_wiki, droit_membres, droit_compta, droit_inscription, droit_connexion, droit_config, cacher, id_cotisation_obligatoire FROM membres_categories_old; -- Suppression des anciennes tables DROP TABLE membres_categories_old; -- Migration des données INSERT INTO compta_rapprochement SELECT * FROM compta_rapprochement_old; DROP TABLE compta_rapprochement_old; -- Cette variable n'est plus utilisée DELETE FROM config WHERE cle = 'email_envoi_automatique'; ALTER TABLE plugins ADD COLUMN menu_condition TEXT NULL; -- Supprimer le début dans le nom des plugins UPDATE plugins_signaux SET callback = replace(callback, 'Garradin\Plugin\', ''); |
Modified archives/0.9.1_migration.sql from [8d911832a5] to [6227606b97].
1 2 3 4 5 | -- Il manquait une clause ON DELETE SET NULL sur la foreign key -- de cotisations quand on faisait une mise à jour depuis une -- ancienne version ALTER TABLE cotisations RENAME TO cotisations_old; | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | -- Il manquait une clause ON DELETE SET NULL sur la foreign key -- de cotisations quand on faisait une mise à jour depuis une -- ancienne version ALTER TABLE cotisations RENAME TO cotisations_old; .read 0.9.1_schema.sql INSERT INTO cotisations SELECT * FROM cotisations_old; DROP TABLE cotisations_old; -- Changer le compte des reports automatiques UPDATE compta_journal SET compte_debit = '890' WHERE compte_debit IS NULL; UPDATE compta_journal SET compte_credit = '890' WHERE compte_credit IS NULL; |
Added archives/0.9.1_schema.sql version [efe750515a].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | CREATE TABLE IF NOT EXISTS config ( -- Configuration de Garradin cle TEXT PRIMARY KEY NOT NULL, valeur TEXT ); -- On stocke ici les ID de catégorie de compta correspondant aux types spéciaux -- compta_categorie_cotisations => id_categorie -- compta_categorie_dons => id_categorie 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, droit_membres INTEGER NOT NULL DEFAULT 1, droit_compta INTEGER NOT NULL DEFAULT 1, droit_inscription INTEGER NOT NULL DEFAULT 0, droit_connexion INTEGER NOT NULL DEFAULT 1, droit_config INTEGER NOT NULL DEFAULT 0, cacher INTEGER NOT NULL DEFAULT 0, id_cotisation_obligatoire INTEGER NULL REFERENCES cotisations (id) ON DELETE SET NULL ); -- Membres de l'asso -- Table dynamique générée par l'application -- voir Garradin\Membres\Champs.php CREATE TABLE IF NOT EXISTS membres_sessions -- Sessions ( selecteur TEXT NOT NULL, hash TEXT NOT NULL, id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, expire INT NOT NULL, PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS cotisations -- Types de cotisations et activités ( id INTEGER PRIMARY KEY NOT NULL, id_categorie_compta INTEGER NULL REFERENCES compta_categories (id) ON DELETE SET NULL, -- NULL si le type n'est pas associé automatiquement à la compta intitule TEXT NOT NULL, description TEXT NULL, montant REAL NOT NULL, duree INTEGER NULL, -- En jours debut TEXT NULL, -- timestamp fin TEXT NULL ); 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, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date) ); CREATE UNIQUE INDEX IF NOT EXISTS cm_unique ON cotisations_membres (id_membre, id_cotisation, date); CREATE TABLE IF NOT EXISTS membres_operations -- Liaison des enregistrement des paiements en compta ( id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_operation INTEGER NOT NULL REFERENCES compta_journal (id) ON DELETE CASCADE, id_cotisation INTEGER NULL REFERENCES cotisations_membres (id) ON DELETE SET NULL, PRIMARY KEY (id_membre, id_operation) ); CREATE TABLE IF NOT EXISTS rappels -- Rappels de devoir renouveller une cotisation ( id INTEGER NOT NULL PRIMARY KEY, id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE, delai INTEGER NOT NULL, -- Délai en jours pour envoyer le rappel sujet TEXT NOT NULL, texte TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS rappels_envoyes -- Enregistrement des rappels envoyés à qui et quand ( 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, id_rappel INTEGER NULL REFERENCES rappels (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), media INTEGER NOT NULL -- Média utilisé pour le rappel : 1 = email, 2 = courrier, 3 = autre ); -- -- WIKI -- CREATE TABLE IF NOT EXISTS wiki_pages -- Pages du wiki ( id INTEGER PRIMARY KEY NOT NULL, uri TEXT NOT NULL, -- URI unique (équivalent NomPageWiki) titre TEXT NOT NULL, date_creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_creation) IS NOT NULL AND datetime(date_creation) = date_creation), date_modification TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_modification) IS NOT NULL AND datetime(date_modification) = date_modification), parent INTEGER NOT NULL DEFAULT 0, -- ID de la page parent revision INTEGER NOT NULL DEFAULT 0, -- Numéro de révision (commence à 0 si pas de texte, +1 à chaque changement du texte) droit_lecture INTEGER NOT NULL DEFAULT 0, -- Accès en lecture (-1 = public [site web], 0 = tous ceux qui ont accès en lecture au wiki, 1+ = ID de groupe) droit_ecriture INTEGER NOT NULL DEFAULT 0 -- Accès en écriture (0 = tous ceux qui ont droit d'écriture sur le wiki, 1+ = ID de groupe) ); CREATE UNIQUE INDEX IF NOT EXISTS wiki_uri ON wiki_pages (uri); CREATE VIRTUAL TABLE IF NOT EXISTS wiki_recherche USING fts4 -- Table dupliquée pour chercher une page ( id INT PRIMARY KEY NOT NULL, -- Clé externe obligatoire titre TEXT NOT NULL, contenu TEXT NULL, -- Contenu de la dernière révision FOREIGN KEY (id) REFERENCES wiki_pages(id) ); CREATE TABLE IF NOT EXISTS wiki_revisions -- Révisions du contenu des pages ( id_page INTEGER NOT NULL REFERENCES wiki_pages (id) ON DELETE CASCADE, revision INTEGER NULL, id_auteur INTEGER NULL REFERENCES membres (id) ON DELETE SET NULL, contenu TEXT NOT NULL, modification TEXT NULL, -- Description des modifications effectuées chiffrement INTEGER NOT NULL DEFAULT 0, -- 1 si le contenu est chiffré, 0 sinon date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), PRIMARY KEY(id_page, revision) ); CREATE INDEX IF NOT EXISTS wiki_revisions_id_page ON wiki_revisions (id_page); CREATE INDEX IF NOT EXISTS wiki_revisions_id_auteur ON wiki_revisions (id_auteur); -- Triggers pour synchro avec table wiki_pages CREATE TRIGGER IF NOT EXISTS wiki_recherche_delete AFTER DELETE ON wiki_pages BEGIN DELETE FROM wiki_recherche WHERE id = old.id; END; CREATE TRIGGER IF NOT EXISTS wiki_recherche_update AFTER UPDATE OF id, titre ON wiki_pages BEGIN UPDATE wiki_recherche SET id = new.id, titre = new.titre WHERE id = old.id; END; -- Trigger pour mettre à jour le contenu de la table de recherche lors d'une nouvelle révision CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_insert AFTER INSERT ON wiki_revisions WHEN new.chiffrement != 1 BEGIN UPDATE wiki_recherche SET contenu = new.contenu WHERE id = new.id_page; END; -- Si le contenu est chiffré, la recherche n'affiche pas de contenu CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_chiffre AFTER INSERT ON wiki_revisions WHEN new.chiffrement = 1 BEGIN UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; /* CREATE TABLE wiki_suivi -- Suivi des pages ( id_membre INTEGER NOT NULL, id_page INTEGER NOT NULL, PRIMARY KEY (id_membre, id_page), FOREIGN KEY (id_page) REFERENCES wiki_pages (id), -- Clé externe obligatoire FOREIGN KEY (id_membre) REFERENCES membres (id) -- Clé externe obligatoire ); */ -- -- COMPTA -- CREATE TABLE IF NOT EXISTS compta_exercices -- Exercices ( id INTEGER NOT NULL PRIMARY KEY, libelle TEXT NOT NULL, debut TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(debut) IS NOT NULL AND date(debut) = debut), fin TEXT NULL DEFAULT NULL CHECK (fin IS NULL OR (date(fin) IS NOT NULL AND date(fin) = fin)), cloture INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS compta_comptes -- Plan comptable ( id TEXT NOT NULL PRIMARY KEY, -- peut contenir des lettres, eg. 53A, 53B, etc. parent TEXT NOT NULL DEFAULT 0, libelle TEXT NOT NULL, position INTEGER NOT NULL, -- position actif/passif/charge/produit plan_comptable INTEGER NOT NULL DEFAULT 1, -- 1 = fait partie du plan comptable, 0 = a été ajouté par l'utilisateur desactive INTEGER NOT NULL DEFAULT 0 -- 1 = compte historique désactivé ); CREATE INDEX IF NOT EXISTS compta_comptes_parent ON compta_comptes (parent); CREATE TABLE IF NOT EXISTS compta_comptes_bancaires -- Comptes bancaires ( id TEXT NOT NULL PRIMARY KEY, banque TEXT NOT NULL, iban TEXT NULL, bic TEXT NULL, FOREIGN KEY(id) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS compta_projets -- Projets (compta analytique) ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS compta_journal -- Journal des opérations comptables ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL, remarques TEXT NULL, numero_piece TEXT NULL, -- N° de pièce comptable montant REAL NOT NULL, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), moyen_paiement TEXT NULL, numero_cheque TEXT NULL, compte_debit TEXT NULL, -- N° du compte dans le plan, NULL est utilisé pour une opération qui vient d'un exercice précédent compte_credit TEXT NULL, -- N° du compte dans le plan id_exercice INTEGER NULL DEFAULT NULL, -- En cas de compta simple, l'exercice est permanent (NULL) id_auteur INTEGER NULL, id_categorie INTEGER NULL, -- Numéro de catégorie (en mode simple) id_projet INTEGER NULL, FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code), FOREIGN KEY(compte_debit) REFERENCES compta_comptes(id), FOREIGN KEY(compte_credit) REFERENCES compta_comptes(id), FOREIGN KEY(id_exercice) REFERENCES compta_exercices(id), FOREIGN KEY(id_auteur) REFERENCES membres(id) ON DELETE SET NULL, FOREIGN KEY(id_categorie) REFERENCES compta_categories(id) ON DELETE SET NULL, FOREIGN KEY(id_projet) REFERENCES compta_projets(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS compta_operations_exercice ON compta_journal (id_exercice); CREATE INDEX IF NOT EXISTS compta_operations_date ON compta_journal (date); CREATE INDEX IF NOT EXISTS compta_operations_comptes ON compta_journal (compte_debit, compte_credit); CREATE INDEX IF NOT EXISTS compta_operations_auteur ON compta_journal (id_auteur); CREATE TABLE IF NOT EXISTS compta_moyens_paiement -- Moyens de paiement ( code TEXT NOT NULL PRIMARY KEY, nom TEXT NOT NULL ); --INSERT INTO compta_moyens_paiement (code, nom) VALUES ('AU', 'Autre'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CB', 'Carte bleue'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CH', 'Chèque'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('ES', 'Espèces'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('PR', 'Prélèvement'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('TI', 'TIP'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('VI', 'Virement'); CREATE TABLE IF NOT EXISTS compta_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) intitule TEXT NOT NULL, description TEXT NULL, compte TEXT NOT NULL, -- Compte affecté par cette catégorie FOREIGN KEY(compte) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS plugins ( id TEXT NOT NULL PRIMARY KEY, officiel INTEGER NOT NULL DEFAULT 0, nom TEXT NOT NULL, description TEXT NULL, auteur TEXT NULL, url TEXT NULL, version TEXT NOT NULL, menu INTEGER NOT NULL DEFAULT 0, menu_condition TEXT NULL, config TEXT NULL ); CREATE TABLE IF NOT EXISTS plugins_signaux -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE IF NOT EXISTS compta_rapprochement -- Rapprochement entre compta et relevés de comptes ( id_operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), id_auteur INTEGER NULL REFERENCES membres (id) ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue datetime TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(datetime) IS NOT NULL AND datetime(datetime) = datetime), -- Date d'ajout ou mise à jour du fichier id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS fichiers_date ON fichiers (datetime); CREATE TABLE IF NOT EXISTS fichiers_contenu -- Contenu des fichiers ( id INTEGER NOT NULL PRIMARY KEY, hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL, -- Taille en octets contenu BLOB NULL ); CREATE UNIQUE INDEX IF NOT EXISTS fichiers_hash ON fichiers_contenu (hash); CREATE TABLE IF NOT EXISTS fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES membres (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS fichiers_wiki_pages -- 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_compta_journal -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES compta_journal (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS recherches -- Recherches enregistrées ( id INTEGER NOT NULL PRIMARY KEY, id_membre INTEGER NULL REFERENCES membres (id) ON DELETE CASCADE, -- Si non NULL, alors la recherche ne sera visible que par le membre associé intitule TEXT NOT NULL, creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(creation) IS NOT NULL AND datetime(creation) = creation), cible TEXT NOT NULL, -- "membres" ou "compta_journal" type TEXT NOT NULL, -- "json" ou "sql" contenu TEXT NOT NULL ); |
Added archives/0.9.5_schema.sql version [c8df01c2dd].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | CREATE TABLE IF NOT EXISTS config ( -- Configuration de Garradin cle TEXT PRIMARY KEY NOT NULL, valeur TEXT ); -- On stocke ici les ID de catégorie de compta correspondant aux types spéciaux -- compta_categorie_cotisations => id_categorie -- compta_categorie_dons => id_categorie 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, droit_membres INTEGER NOT NULL DEFAULT 1, droit_compta INTEGER NOT NULL DEFAULT 1, droit_inscription INTEGER NOT NULL DEFAULT 0, droit_connexion INTEGER NOT NULL DEFAULT 1, droit_config INTEGER NOT NULL DEFAULT 0, cacher INTEGER NOT NULL DEFAULT 0, id_cotisation_obligatoire INTEGER NULL REFERENCES cotisations (id) ON DELETE SET NULL ); -- Membres de l'asso -- Table dynamique générée par l'application -- voir Garradin\Membres\Champs.php CREATE TABLE IF NOT EXISTS membres_sessions -- Sessions ( selecteur TEXT NOT NULL, hash TEXT NOT NULL, id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, expire INT NOT NULL, PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS cotisations -- Types de cotisations et activités ( id INTEGER PRIMARY KEY NOT NULL, id_categorie_compta INTEGER NULL REFERENCES compta_categories (id) ON DELETE SET NULL, -- NULL si le type n'est pas associé automatiquement à la compta intitule TEXT NOT NULL, description TEXT NULL, montant REAL NOT NULL, duree INTEGER NULL, -- En jours debut TEXT NULL, -- timestamp fin TEXT NULL ); 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, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date) ); CREATE UNIQUE INDEX IF NOT EXISTS cm_unique ON cotisations_membres (id_membre, id_cotisation, date); CREATE TABLE IF NOT EXISTS membres_operations -- Liaison des enregistrement des paiements en compta ( id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_operation INTEGER NOT NULL REFERENCES compta_journal (id) ON DELETE CASCADE, id_cotisation INTEGER NULL REFERENCES cotisations_membres (id) ON DELETE SET NULL, PRIMARY KEY (id_membre, id_operation) ); CREATE TABLE IF NOT EXISTS rappels -- Rappels de devoir renouveller une cotisation ( id INTEGER NOT NULL PRIMARY KEY, id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE, delai INTEGER NOT NULL, -- Délai en jours pour envoyer le rappel sujet TEXT NOT NULL, texte TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS rappels_envoyes -- Enregistrement des rappels envoyés à qui et quand ( 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, id_rappel INTEGER NULL REFERENCES rappels (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), media INTEGER NOT NULL -- Média utilisé pour le rappel : 1 = email, 2 = courrier, 3 = autre ); -- -- WIKI -- CREATE TABLE IF NOT EXISTS wiki_pages -- Pages du wiki ( id INTEGER PRIMARY KEY NOT NULL, uri TEXT NOT NULL, -- URI unique (équivalent NomPageWiki) titre TEXT NOT NULL, date_creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_creation) IS NOT NULL AND datetime(date_creation) = date_creation), date_modification TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date_modification) IS NOT NULL AND datetime(date_modification) = date_modification), parent INTEGER NOT NULL DEFAULT 0, -- ID de la page parent revision INTEGER NOT NULL DEFAULT 0, -- Numéro de révision (commence à 0 si pas de texte, +1 à chaque changement du texte) droit_lecture INTEGER NOT NULL DEFAULT 0, -- Accès en lecture (-1 = public [site web], 0 = tous ceux qui ont accès en lecture au wiki, 1+ = ID de groupe) droit_ecriture INTEGER NOT NULL DEFAULT 0 -- Accès en écriture (0 = tous ceux qui ont droit d'écriture sur le wiki, 1+ = ID de groupe) ); CREATE UNIQUE INDEX IF NOT EXISTS wiki_uri ON wiki_pages (uri); CREATE VIRTUAL TABLE IF NOT EXISTS wiki_recherche USING fts4 -- Table dupliquée pour chercher une page ( id INT PRIMARY KEY NOT NULL, -- Clé externe obligatoire titre TEXT NOT NULL, contenu TEXT NULL, -- Contenu de la dernière révision FOREIGN KEY (id) REFERENCES wiki_pages(id) ); CREATE TABLE IF NOT EXISTS wiki_revisions -- Révisions du contenu des pages ( id_page INTEGER NOT NULL REFERENCES wiki_pages (id) ON DELETE CASCADE, revision INTEGER NULL, id_auteur INTEGER NULL REFERENCES membres (id) ON DELETE SET NULL, contenu TEXT NOT NULL, modification TEXT NULL, -- Description des modifications effectuées chiffrement INTEGER NOT NULL DEFAULT 0, -- 1 si le contenu est chiffré, 0 sinon date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), PRIMARY KEY(id_page, revision) ); CREATE INDEX IF NOT EXISTS wiki_revisions_id_page ON wiki_revisions (id_page); CREATE INDEX IF NOT EXISTS wiki_revisions_id_auteur ON wiki_revisions (id_auteur); -- Triggers pour synchro avec table wiki_pages CREATE TRIGGER IF NOT EXISTS wiki_recherche_delete AFTER DELETE ON wiki_pages BEGIN DELETE FROM wiki_recherche WHERE id = old.id; END; CREATE TRIGGER IF NOT EXISTS wiki_recherche_update AFTER UPDATE OF id, titre ON wiki_pages BEGIN UPDATE wiki_recherche SET id = new.id, titre = new.titre WHERE id = old.id; END; -- Trigger pour mettre à jour le contenu de la table de recherche lors d'une nouvelle révision CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_insert AFTER INSERT ON wiki_revisions WHEN new.chiffrement != 1 BEGIN UPDATE wiki_recherche SET contenu = new.contenu WHERE id = new.id_page; END; -- Si le contenu est chiffré, la recherche n'affiche pas de contenu CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_chiffre AFTER INSERT ON wiki_revisions WHEN new.chiffrement = 1 BEGIN UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; /* CREATE TABLE wiki_suivi -- Suivi des pages ( id_membre INTEGER NOT NULL, id_page INTEGER NOT NULL, PRIMARY KEY (id_membre, id_page), FOREIGN KEY (id_page) REFERENCES wiki_pages (id), -- Clé externe obligatoire FOREIGN KEY (id_membre) REFERENCES membres (id) -- Clé externe obligatoire ); */ -- -- COMPTA -- CREATE TABLE IF NOT EXISTS compta_exercices -- Exercices ( id INTEGER NOT NULL PRIMARY KEY, libelle TEXT NOT NULL, debut TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(debut) IS NOT NULL AND date(debut) = debut), fin TEXT NULL DEFAULT NULL CHECK (fin IS NULL OR (date(fin) IS NOT NULL AND date(fin) = fin)), cloture INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS compta_comptes -- Plan comptable ( id TEXT NOT NULL PRIMARY KEY, -- peut contenir des lettres, eg. 53A, 53B, etc. parent TEXT NOT NULL DEFAULT 0, libelle TEXT NOT NULL, position INTEGER NOT NULL, -- position actif/passif/charge/produit plan_comptable INTEGER NOT NULL DEFAULT 1, -- 1 = fait partie du plan comptable, 0 = a été ajouté par l'utilisateur desactive INTEGER NOT NULL DEFAULT 0 -- 1 = compte historique désactivé ); CREATE INDEX IF NOT EXISTS compta_comptes_parent ON compta_comptes (parent); CREATE TABLE IF NOT EXISTS compta_comptes_bancaires -- Comptes bancaires ( id TEXT NOT NULL PRIMARY KEY, banque TEXT NOT NULL, iban TEXT NULL, bic TEXT NULL, FOREIGN KEY(id) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS compta_projets -- Projets (compta analytique) ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS compta_journal -- Journal des opérations comptables ( id INTEGER PRIMARY KEY NOT NULL, libelle TEXT NOT NULL, remarques TEXT NULL, numero_piece TEXT NULL, -- N° de pièce comptable montant REAL NOT NULL, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), moyen_paiement TEXT NULL, numero_cheque TEXT NULL, compte_debit TEXT NULL, -- N° du compte dans le plan, NULL est utilisé pour une opération qui vient d'un exercice précédent compte_credit TEXT NULL, -- N° du compte dans le plan id_exercice INTEGER NULL DEFAULT NULL, -- En cas de compta simple, l'exercice est permanent (NULL) id_auteur INTEGER NULL, id_categorie INTEGER NULL, -- Numéro de catégorie (en mode simple) id_projet INTEGER NULL, FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code), FOREIGN KEY(compte_debit) REFERENCES compta_comptes(id), FOREIGN KEY(compte_credit) REFERENCES compta_comptes(id), FOREIGN KEY(id_exercice) REFERENCES compta_exercices(id), FOREIGN KEY(id_auteur) REFERENCES membres(id) ON DELETE SET NULL, FOREIGN KEY(id_categorie) REFERENCES compta_categories(id) ON DELETE SET NULL, FOREIGN KEY(id_projet) REFERENCES compta_projets(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS compta_operations_exercice ON compta_journal (id_exercice); CREATE INDEX IF NOT EXISTS compta_operations_date ON compta_journal (date); CREATE INDEX IF NOT EXISTS compta_operations_comptes ON compta_journal (compte_debit, compte_credit); CREATE INDEX IF NOT EXISTS compta_operations_auteur ON compta_journal (id_auteur); CREATE TABLE IF NOT EXISTS compta_moyens_paiement -- Moyens de paiement ( code TEXT NOT NULL PRIMARY KEY, nom TEXT NOT NULL ); --INSERT INTO compta_moyens_paiement (code, nom) VALUES ('AU', 'Autre'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CB', 'Carte bleue'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('CH', 'Chèque'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('ES', 'Espèces'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('PR', 'Prélèvement'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('TI', 'TIP'); INSERT OR IGNORE INTO compta_moyens_paiement (code, nom) VALUES ('VI', 'Virement'); CREATE TABLE IF NOT EXISTS compta_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) intitule TEXT NOT NULL, description TEXT NULL, compte TEXT NOT NULL, -- Compte affecté par cette catégorie FOREIGN KEY(compte) REFERENCES compta_comptes(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS plugins ( id TEXT NOT NULL PRIMARY KEY, officiel INTEGER NOT NULL DEFAULT 0, nom TEXT NOT NULL, description TEXT NULL, auteur TEXT NULL, url TEXT NULL, version TEXT NOT NULL, menu INTEGER NOT NULL DEFAULT 0, menu_condition TEXT NULL, config TEXT NULL ); CREATE TABLE IF NOT EXISTS plugins_signaux -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE IF NOT EXISTS compta_rapprochement -- Rapprochement entre compta et relevés de comptes ( id_operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(date) IS NOT NULL AND datetime(date) = date), id_auteur INTEGER NULL REFERENCES membres (id) ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue datetime TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(datetime) IS NOT NULL AND datetime(datetime) = datetime), -- Date d'ajout ou mise à jour du fichier id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS fichiers_date ON fichiers (datetime); CREATE TABLE IF NOT EXISTS fichiers_contenu -- Contenu des fichiers ( id INTEGER NOT NULL PRIMARY KEY, hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL, -- Taille en octets contenu BLOB NULL ); CREATE UNIQUE INDEX IF NOT EXISTS fichiers_hash ON fichiers_contenu (hash); CREATE TABLE IF NOT EXISTS fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES membres (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS fichiers_wiki_pages -- 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_compta_journal -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES compta_journal (id), PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS recherches -- Recherches enregistrées ( id INTEGER NOT NULL PRIMARY KEY, id_membre INTEGER NULL REFERENCES membres (id) ON DELETE CASCADE, -- Si non NULL, alors la recherche ne sera visible que par le membre associé intitule TEXT NOT NULL, creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(creation) IS NOT NULL AND datetime(creation) = creation), cible TEXT NOT NULL, -- "membres" ou "compta_journal" type TEXT NOT NULL, -- "json" ou "sql" contenu TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS compromised_passwords_cache -- Cache des hash de mots de passe compromis ( hash TEXT NOT NULL PRIMARY KEY ); CREATE TABLE IF NOT EXISTS compromised_passwords_cache_ranges -- Cache des préfixes de mots de passe compromis ( prefix TEXT NOT NULL PRIMARY KEY, date INTEGER NOT NULL ); |
Modified archives/plan_comptable.json from [4d7e33a414] to [c496246466].
︙ | ︙ | |||
1741 1742 1743 1744 1745 1746 1747 | }, "890": { "code": 890, "nom": "Bilan d'ouverture", "parent": 89, "position": 3 }, | | | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 | }, "890": { "code": 890, "nom": "Bilan d'ouverture", "parent": 89, "position": 3 }, "891": { "code": 891, "nom": "Bilan de clôture", "parent": 89, "position": 3 }, "9": { "code": 9, "nom": "Classe 9 \u2014 Comptes analytiques", "parent": 0, "position": 12 } } |
Modified debian/config.debian.php from [2a98e1b5ea] to [1cd45bbd87].
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | $_ENV['XDG_CONFIG_HOME'] = $home . '/.config'; } if (!file_exists($_ENV['XDG_CONFIG_HOME'] . '/garradin')) { mkdir($_ENV['XDG_CONFIG_HOME'] . '/garradin', 0700, true); } // Data directory: where the data will go if (empty($_ENV['XDG_DATA_HOME'])) { $_ENV['XDG_DATA_HOME'] = $home . '/.local/share'; } if (!file_exists($_ENV['XDG_DATA_HOME'] . '/garradin')) { mkdir($_ENV['XDG_DATA_HOME'] . '/garradin', 0700, true); } | > > > > > | > > | | > > | | | | | | | | | | | | | | | | < | > > > > > | > > | > > | | > > | > > > | | < > | > > | 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 | $_ENV['XDG_CONFIG_HOME'] = $home . '/.config'; } if (!file_exists($_ENV['XDG_CONFIG_HOME'] . '/garradin')) { mkdir($_ENV['XDG_CONFIG_HOME'] . '/garradin', 0700, true); } if (file_exists($_ENV['XDG_CONFIG_HOME'] . '/garradin/config.local.php')) { require_once $_ENV['XDG_CONFIG_HOME'] . '/garradin/config.local.php'; } // Data directory: where the data will go if (empty($_ENV['XDG_DATA_HOME'])) { $_ENV['XDG_DATA_HOME'] = $home . '/.local/share'; } if (!file_exists($_ENV['XDG_DATA_HOME'] . '/garradin')) { mkdir($_ENV['XDG_DATA_HOME'] . '/garradin', 0700, true); } if (!defined('Garradin\DATA_ROOT')) { define('Garradin\DATA_ROOT', $_ENV['XDG_DATA_HOME'] . '/garradin'); } // Cache directory: temporary stuff if (empty($_ENV['XDG_CACHE_HOME'])) { $_ENV['XDG_CACHE_HOME'] = $home . '/.cache'; } if (!file_exists($_ENV['XDG_CACHE_HOME'] . '/garradin')) { mkdir($_ENV['XDG_CACHE_HOME'] . '/garradin', 0700, true); } if (!defined('Garradin\CACHE_ROOT')) { define('Garradin\CACHE_ROOT', $_ENV['XDG_CACHE_HOME'] . '/garradin'); } if (!defined('Garradin\DB_FILE')) { $last_file = $_ENV['XDG_CONFIG_HOME'] . '/garradin/last'; if ($_ENV['GARRADIN_STANDALONE'] != 1) { $last_sqlite = trim($_ENV['GARRADIN_STANDALONE']); } else if (file_exists($last_file)) { $last_sqlite = trim(file_get_contents($last_file)); } else { $last_sqlite = $_ENV['XDG_DATA_HOME'] . '/garradin/association.sqlite'; } file_put_contents($last_file, $last_sqlite); define('Garradin\DB_FILE', $last_sqlite); } if (!defined('Garradin\LOCAL_LOGIN')) { define('Garradin\LOCAL_LOGIN', true); } } elseif (isset($_SERVER['SERVER_NAME'])) { if (file_exists('/etc/garradin/config.php')) { require_once '/etc/garradin/config.php'; } if (!defined('Garradin\DATA_ROOT')) { define('Garradin\DATA_ROOT', '/var/lib/garradin'); } if (!defined('Garradin\CACHE_ROOT')) { define('Garradin\CACHE_ROOT', '/var/cache/garradin'); } } if (!defined('Garradin\SECRET_KEY')) { if (file_exists(CACHE_ROOT . '/key')) { define('Garradin\SECRET_KEY', trim(file_get_contents(CACHE_ROOT . '/key'))); } else { define('Garradin\SECRET_KEY', base64_encode(random_bytes(64))); file_put_contents(CACHE_ROOT . '/key', SECRET_KEY); } } |
Modified debian/makedeb.sh from [242f467b69] to [e75e803576].
︙ | ︙ | |||
34 35 36 37 38 39 40 | mkdir -p "${DEBLOCALPREFIX}/share/applications" cp ${THISDIR}/garradin.desktop "${DEBLOCALPREFIX}/share/applications/" CODEDIR=${DEBLOCALPREFIX}/share/${PACKAGE_DEBNAME} mkdir -p ${CODEDIR} cp -r ${SRCDIR}/* ${CODEDIR} cp ${THISDIR}/config.debian.php ${CODEDIR}/config.local.php | | > > > > | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | mkdir -p "${DEBLOCALPREFIX}/share/applications" cp ${THISDIR}/garradin.desktop "${DEBLOCALPREFIX}/share/applications/" CODEDIR=${DEBLOCALPREFIX}/share/${PACKAGE_DEBNAME} mkdir -p ${CODEDIR} cp -r ${SRCDIR}/* ${CODEDIR} cp ${THISDIR}/config.debian.php ${CODEDIR}/config.local.php rm -rf ${CODEDIR}/*.sqlite ${CODEDIR}/cache ${CODEDIR}/www/squelettes ${CODEDIR}/www/plugins/* cp ${THISDIR}/garradin.png "${CODEDIR}" mkdir -p "${DEBROOT}/var/lib/${PACKAGE_DEBNAME}" mkdir -p "${DEBROOT}/var/cache/${PACKAGE_DEBNAME}" mkdir -p "${DEBROOT}/etc/${PACKAGE_DEBNAME}" # Cleaning files that will be copied to /usr/share/doc #rm -f ${CODEDIR}/../{README.md,COPYING} cd $DEBROOT || { echo "Debian dest dir [$DEBROOT] not found. :(" exit 2 } rm -fr DEBIAN |
︙ | ︙ | |||
60 61 62 63 64 65 66 | echo "Creating .deb package [${DEBFILE}]..." echo "Generating md5 sums..." find ${DEBLOCALPREFIX} -type f -exec md5sum {} \; > DEBIAN/md5sums true && { echo "Generating Debian-specific files..." | | > > > > > > > > > > > > > > | 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 | echo "Creating .deb package [${DEBFILE}]..." echo "Generating md5 sums..." find ${DEBLOCALPREFIX} -type f -exec md5sum {} \; > DEBIAN/md5sums true && { echo "Generating Debian-specific files..." cp ${THISDIR}/../COPYING ${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME}/copyright } || { echo "Fail." exit 1 } true && { cat <<EOF > DEBIAN/postinst #!/bin/sh chown www-data:www-data /var/lib/garradin /var/cache/garradin chown root:www-data /etc/garradin chmod g=rX,o= /etc/garradin chmod ug=rwX,o= /var/lib/garradin /var/cache/garradin EOF chmod +x DEBIAN/postinst } true && { CHANGELOG=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME}/changelog.gz cat <<EOF | gzip -c > ${CHANGELOG} ${PACKAGE_DEBNAME} ${PACKAGE_DEB_VERSION}; urgency=low |
︙ | ︙ | |||
86 87 88 89 90 91 92 | } # doc. DOCDIR=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME} true && { echo "Generating doc..." | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | } # doc. DOCDIR=${DEBLOCALPREFIX}/share/doc/${PACKAGE_DEBNAME} true && { echo "Generating doc..." cp ${THISDIR}/../README.md ${DOCDIR} a2x --doctype manpage --format manpage ${THISDIR}/manpage.txt mkdir -p ${DEBLOCALPREFIX}/share/man/man1 gzip -c ${THISDIR}/garradin.1 > ${DEBLOCALPREFIX}/share/man/man1/${PACKAGE_DEBNAME}.1.gz rm -f ${THISDIR}/garradin.1 } || { echo "Fail." exit 1 } true && { CONTROL=DEBIAN/control echo "Generating ${CONTROL}..." cat <<EOF > ${CONTROL} Package: ${PACKAGE_DEBNAME} Section: web Priority: optional Maintainer: Garradin <garradin@kd2.org> Architecture: ${DEB_ARCH_NAME} Depends: dash | bash, php-cli (>=7.2), php-sqlite3 Version: ${PACKAGE_DEB_VERSION} Suggests: www-browser, php-gd Homepage: http://dev.kd2.org/garradin/ Description: Garradin is a tool to manage non-profit organizations. It's only available in french. Description-fr: Gestionnaire d'association en interface web ou CLI. Garradin est un gestionnaire d'association à but non lucratif. |
︙ | ︙ |
Added doc/dev/odoo_accounts.sql version [6c994995cd].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | -- Schéma Odoo (PgSQL) pour info sur la compta -- Pour les écritures, deux tables : move et move_line -- Utilisation de deux colonnes "debit" et "credit" -- https://github.com/odoo/odoo/blob/11.0/addons/account/data/data_account_type.xml -- https://www.odoo.com/documentation/11.0/webservices/localization.html CREATE TABLE public.account_account_type ( id integer NOT NULL, name character varying NOT NULL, include_initial_balance boolean, type character varying NOT NULL, note text, create_uid integer, create_date timestamp without time zone, write_uid integer, write_date timestamp without time zone ); COPY public.account_account_type (id, name, include_initial_balance, type, note, create_uid, create_date, write_uid, write_date) FROM stdin; 1 Receivable t receivable \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 2 Payable t payable \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 3 Bank and Cash t liquidity \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 4 Credit Card t liquidity \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 5 Current Assets t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 6 Non-current Assets t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 7 Prepayments t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 8 Fixed Assets t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 9 Current Liabilities t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 10 Non-current Liabilities t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 11 Equity t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 12 Current Year Earnings t other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 13 Other Income f other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 14 Income f other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 15 Depreciation f other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 16 Expenses f other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 17 Cost of Revenue f other \N 1 2019-02-14 15:05:35.697512 1 2019-02-14 15:05:35.697512 \. COPY public.account_account (id, name, currency_id, code, deprecated, user_type_id, internal_type, last_time_entries_checked, reconcile, note, company_id, group_id, create_uid, create_date, write_uid, write_date) FROM stdin; 1 Virements Internes \N 580000 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 2 Capital souscrit - non appelé \N 101100 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 3 Capital souscrit - appelé non versé \N 101200 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 4 Capital non amorti \N 101310 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 5 Capital amorti \N 101320 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 6 Capital souscrit soumis à des réglementations particulières \N 101800 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 7 Primes d'émission \N 104100 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 8 Primes de fusion \N 104200 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 10 Primes de conversion d'obligations en actions \N 104400 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 11 Bons de souscription d'actions \N 104500 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 12 Réserve spéciale de réévaluation \N 105100 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 13 Écart de réévaluation libre \N 105200 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 15 Écarts de réévaluation (autres opérations légales) \N 105500 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 16 Autres écarts de réévaluation en France \N 105700 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 17 Autres écarts de réévaluation à l'étranger \N 105800 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 18 Réserve légale proprement dite \N 106110 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 19 Plus-values nettes à long terme \N 106120 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 20 Réserves indisponibles \N 106200 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 22 Plus-values nettes à long terme \N 106410 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 23 Réserves consécutives à l'octroi de subventions d'investissement \N 106430 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 24 Autres réserves réglementées \N 106480 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 25 Réserve de propre assureur \N 106810 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 26 Réserves diverses \N 106880 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 27 Écarts d'équivalence \N 107000 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 28 Compte de l'exploitant \N 108000 f 11 other \N f Capital pour une Entreprise Individuelle 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 29 Actionnaires : capital souscrit - non appelé \N 109000 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 31 Report à nouveau (solde débiteur) \N 119000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 30 Report à nouveau (solde créditeur) \N 110000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 9 Primes d'apport \N 104300 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 14 Réserve de réévaluation \N 105300 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 21 Réserves statutaires ou contractuelles \N 106300 f 11 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 32 Résultat de l'exercice (bénéfice) \N 120000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 33 Résultat de l'exercice (perte) \N 129000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 34 Subventions d'équipement - État \N 131100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 35 Subventions d'équipement - Régions \N 131200 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 37 Subventions d'équipement - Communes \N 131400 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 38 Subventions d'équipement - Collectivités publiques \N 131500 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 39 Subventions d'équipement - Entreprises publiques \N 131600 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 40 Subventions d'équipement - Entreprises et organismes privés \N 131700 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 41 Subventions d'équipement - Autres \N 131800 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 42 Autres subventions d'investissement (même ventilation que celle du compte 131) \N 138000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 43 Subventions d'équipement inscrites au compte de résultat - État \N 139110 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 44 Subventions d'équipement inscrites au compte de résultat - Régions \N 139120 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 45 Subventions d'équipement inscrites au compte de résultat - Départements \N 139130 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 46 Subventions d'équipement inscrites au compte de résultat - Communes \N 139140 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 47 Subventions d'équipement inscrites au compte de résultat - Collectivités publiques \N 139150 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 48 Subventions d'équipement inscrites au compte de résultat - Entreprises publiques \N 139160 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 49 Subventions d'équipement inscrites au compte de résultat - Entreprises et organismes privés \N 139170 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 50 Subventions d'équipement inscrites au compte de résultat - Autres \N 139180 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 51 Autres subventions d'investissement (même ventilation que celle du compte 1391) \N 139800 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 53 Provisions pour investissement (participation des salariés) \N 142400 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 54 Provisions réglementées relatives aux stocks - Hausse de prix \N 143100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 55 Provisions réglementées relatives aux stocks - Fluctuation des cours \N 143200 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 56 Provisions réglementées relatives aux autres éléments de l'actif \N 144000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 57 Amortissements dérogatoires \N 145000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 58 Provision spéciale de réévaluation \N 146000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 36 Subventions d'équipement - Départements \N 131300 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 52 Provisions reconstitution des gisements miniers et pétroliers \N 142300 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 719 Bla bla \N 512002 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:11:18.063543 1 2019-02-14 15:11:18.063543 59 Plus-values réinvesties \N 147000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 60 Autres provisions réglementées \N 148000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 61 Provisions pour litiges \N 151100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 62 Provisions pour garanties données aux clients \N 151200 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 64 Provisions pour amendes et pénalités \N 151400 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 65 Provisions pour pertes de change \N 151500 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 66 Provisions pour pertes sur contrats \N 151600 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 67 Autres provisions pour risques \N 151800 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 69 Provisions pour restructurations \N 154000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 70 Provisions pour impôts \N 155000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 71 Provisions pour renouvellement des immobilisations (entreprises concessionnaires) \N 156000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 72 Provisions pour charges à répartir sur plusieurs exercices - Gros entretien ou grandes révisions \N 157200 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 73 Provisions pour remises en état \N 158100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 76 Emprunts auprès des établissements de crédit \N 164000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 77 Dépôts \N 165100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 78 Cautionnements \N 165500 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 79 Participation des salariés aux résultats - Comptes bloqués \N 166100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 80 Participation des salariés aux résultats - Fonds de participation \N 166200 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 81 Emprunts et dettes assortis de conditions particulières - Emissions de titres participatifs \N 167100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 82 Emprunts et dettes assortis de conditions particulières - Avances conditionnées de l'État \N 167400 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 83 Emprunts et dettes assortis de conditions particulières - Emprunts participatifs \N 167500 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 84 Autres emprunts et dettes assimilées - Autres emprunts \N 168100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 85 Autres emprunts et dettes assimilées - Rentes viagères capitalisées \N 168500 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 86 Autres emprunts et dettes assimilées - Autres dettes \N 168700 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 74 Emprunts obligataires convertibles \N 161000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 63 Provisions pour pertes sur marchés à terme \N 151300 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 68 Provisions pour pensions et obligations similaires \N 153000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 75 Autres emprunts obligataires \N 163000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 87 Intérêts courus sur emprunts obligataires convertibles \N 168810 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 88 Intérêts courus sur autres emprunts obligataires \N 168830 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 89 Intérêts courus sur emprunts auprès des établissements de crédit \N 168840 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 90 Intérêts courus sur dépôts et cautionnements reçus \N 168850 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 91 Intérêts courus sur participation des salariés aux résultats \N 168860 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 92 Intérêts courus sur emprunts et dettes assortis de conditions particulières \N 168870 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 93 Intérêts courus sur autres emprunts et dettes assimilées \N 168880 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 94 Primes de remboursement des obligations \N 169000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 96 Dettes rattachées à des participations (hors groupe) \N 174000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 97 Dettes rattachées à des sociétés en participation - Principal \N 178100 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 98 Dettes rattachées à des sociétés en participation - Intérêts courus \N 178800 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 100 Biens et prestations de services échangés entre établissements (charges) \N 186000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 101 Biens et prestations de services échangés entre établissements (produits) \N 187000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 102 Comptes de liaison des sociétés en participation \N 188000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 103 Immobilisations incorporelles - Frais d'établissement - Frais de constitution \N 201100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 104 Immobilisations incorporelles - Frais d'établissement - Frais de prospection \N 201210 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 105 Immobilisations incorporelles - Frais d'établissement - Frais de publicité \N 201220 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 108 Immobilisations incorporelles - Concessions et droits similaires, brevets, licences, marques, procédés, logiciels, droits et valeurs similaires \N 205000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 109 Immobilisations incorporelles - Droit au bail \N 206000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 110 Immobilisations incorporelles - Fonds commercial \N 207000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 111 Autres immobilisations incorporelles \N 208000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 95 Dettes rattachées à des participations (groupe) \N 171000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 237 Études en cours E 1 \N 341100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 99 Comptes de liaison des établissements \N 181000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 106 Immobilisations incorporelles - Frais d'augmentation de capital et d'opérations diverses (fusions, scissions, transformations) \N 201300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 107 Immobilisations incorporelles - Frais de recherche et de développement \N 203000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 112 Immobilisations corporelles - Terrains nus \N 211100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 113 Immobilisations corporelles - Terrains aménagés \N 211200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 115 Immobilisations corporelles - Carrières \N 211410 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 116 Immobilisations corporelles - Terrains bâtis - Ensembles immobiliers industriels \N 211510 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 117 Immobilisations corporelles - Terrains bâtis - Ensembles immobiliers administratifs et commerciaux \N 211550 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 118 Immobilisations corporelles - Terrains bâtis affectés aux opérations professionnelles \N 211581 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 119 Immobilisations corporelles - Terrains bâtis affectés aux opérations non professionnelles \N 211588 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 120 Immobilisations corporelles - Compte d'ordre sur immobilisations \N 211600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 121 Immobilisations corporelles - Agencements et aménagements de terrains (même ventilation que celle du compte 211) \N 212000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 122 Immobilisations corporelles - Bâtiments - Ensembles immobiliers industriels \N 213110 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 123 Immobilisations corporelles - Bâtiments - Ensembles immobiliers administratifs et commerciaux \N 213150 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 124 Immobilisations corporelles - Bâtiments affectés aux opérations professionnelles \N 213181 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 125 Immobilisations corporelles - Bâtiments affectés aux opérations non professionnelles \N 213188 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 126 Immobilisations corporelles - Installations générales, agencements, aménagements des constructions (même ventilation que celle du compte 2131) \N 213500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 127 Immobilisations corporelles - Ouvrages d'infrastructure - Voies de terre \N 213810 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 128 Immobilisations corporelles - Ouvrages d'infrastructure - Voies de fer \N 213820 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 129 Immobilisations corporelles - Ouvrages d'infrastructure - Voies d'eau \N 213830 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 130 Immobilisations corporelles - Ouvrages d'infrastructure - Barrages \N 213840 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 131 Immobilisations corporelles - Ouvrages d'infrastructure - Pistes d'aérodromes \N 213850 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 132 Immobilisations corporelles - Constructions sur sol d'autrui (même ventilation que celle du compte 213) \N 214000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 133 Immobilisations corporelles - Installations complexes spécialisées sur sol propre \N 215110 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 134 Immobilisations corporelles - Installations complexes spécialisées sur sol d'autrui \N 215140 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 114 Immobilisations corporelles - Sous-sols et sur-sols \N 211300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 135 Immobilisations corporelles - Installations à caractère spécifique sur sol propre \N 215310 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 136 Immobilisations corporelles - Installations à caractère spécifique sur sol d'autrui \N 215340 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 137 Immobilisations corporelles - Matériels industriels \N 215400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 138 Immobilisations corporelles - Outillage industriel \N 215500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 139 Immobilisations corporelles - Agencements et aménagements des matériels et outillage industriels \N 215700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 140 Immobilisations corporelles - Installations générales agencements aménagements divers \N 218100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 141 Immobilisations corporelles - Matériel de transport \N 218200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 143 Immobilisations corporelles - Mobilier \N 218400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 144 Immobilisations corporelles - Cheptel \N 218500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 145 Immobilisations corporelles - Emballages récupérables \N 218600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 146 Immobilisations mises en concession \N 220000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 147 Immobilisations corporelles en cours - Terrains \N 231200 f 5 other \N f Pas d'amortissement sur les terrains 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 149 Immobilisations corporelles en cours - Installations techniques matériel et outillage industriels \N 231500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 150 Autres immobilisations corporelles en cours \N 231800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 151 Immobilisations incorporelles en cours \N 232000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 152 Avances et acomptes versés sur commandes d'immobilisations incorporelles \N 237000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 153 Avances et acomptes versés sur commandes d'immobilisations corporelles - Terrains \N 238200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 155 Avances et acomptes versés sur commandes d'immobilisations corporelles - Installations techniques matériel et outillage industriels \N 238500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 156 Avances et acomptes versés sur commandes d'immobilisations corporelles - Autres immobilisations corporelles \N 238800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 157 Parts dans des entreprises liées et créances sur des entreprises liées \N 250000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 158 Titres de participation - Actions \N 261100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 159 Autres titres de participation \N 261800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 142 Immobilisations corporelles - Matériel de bureau et matériel informatique \N 218300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 148 Immobilisations corporelles en cours - Constructions \N 231300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 154 Avances et acomptes versés sur commandes d'immobilisations corporelles - Constructions \N 238300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 160 Titres évalués par équivalence \N 262000 f 5 other \N f Pas d'amortissement sur les titres évalués par équivalence 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 161 Autres formes de participation \N 266000 f 5 other \N f Pas d'amortissement sur les titres évalués par équivalence 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 162 Créances rattachées à des participations (groupe) \N 267100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 163 Créances rattachées à des participations (hors groupe) \N 267400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 164 Versements représentatifs d'apports non capitalisés (appel de fonds) \N 267500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 166 Autres créances rattachées à des participations \N 267700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 167 Créances rattachées à des participations - Intérêts courus \N 267800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 168 Créances rattachées à des sociétés en participation - Principal \N 268100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 169 Créances rattachées à des sociétés en participation - Intérêts courus \N 268800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 170 Versements restant à effectuer sur titres de participation non libérés \N 269000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 171 Titres immobilisés autres que les titres immobilisés de l'activité de portefeuille - Actions \N 271100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 172 Titres immobilisés autres que les titres immobilisés de l'activité de portefeuille - Autres titres \N 271800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 173 Titres immobilisés - Obligations \N 272100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 174 Titres immobilisés - Bons \N 272200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 176 Prêts participatifs \N 274100 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 177 Prêts aux associés \N 274200 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 179 Autres prêts \N 274800 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 180 Dépôts \N 275100 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 181 Cautionnements \N 275500 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 182 Autres créances immobilisées - Créances diverses \N 276100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 183 Autres créances immobilisées - Intérêts courus sur titres immobilisés (droits de créance) \N 276820 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 184 Autres créances immobilisées - Intérêts courus sur prêts \N 276840 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 185 Autres créances immobilisées - Intérêts courus sur dépôts et cautionnements \N 276850 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 186 Autres créances immobilisées - Intérêts courus sur créances diverses \N 276880 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 187 Actions propres ou parts propres \N 277100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 175 Titres immobilisés de l'activité de portefeuille \N 273000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 178 Prêts au personnel \N 274300 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 165 Avances consolidables \N 267600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 188 Actions propres ou parts propres en voie d'annulation \N 277200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 189 Versements restant à effectuer sur titres immobilisés non libérés \N 279000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 190 Amortissements des immobilisations incorporelles - Frais d'établissement (même ventilation que celle du compte 201) \N 280100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 192 Amortissements des immobilisations incorporelles - Concessions et droits similaires, brevets, licences, logiciels, droits et valeurs similaires \N 280500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 193 Amortissements des immobilisations incorporelles - Fonds commercial \N 280700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 194 Amortissements des autres immobilisations incorporelles \N 280800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 195 Amortissements des immobilisations corporelles - Terrains de gisement \N 281100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 196 Amortissements des immobilisations corporelles - Agencements aménagements de terrains (même ventilation que celle du compte 212) \N 281200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 198 Amortissements des immobilisations corporelles - Constructions sur sol d'autrui (même ventilation que celle du compte 214) \N 281400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 199 Amortissements des immobilisations corporelles - Installations matériel et outillage industriels (même ventilation que celle du compte 215) \N 281500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 200 Amortissements des autres immobilisations corporelles (même ventilation que celle du compte 218) \N 281800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 201 Amortissements des immobilisations mises en concession \N 282000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 202 Dépréciations des immobilisations incorporelles - Marques, procédés, droits et valeurs similaires \N 290500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 203 Dépréciations des immobilisations incorporelles - Droit au bail \N 290600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 204 Dépréciations des immobilisations incorporelles - Fonds commercial \N 290700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 205 Dépréciations des autres immobilisations incorporelles \N 290800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 206 Dépréciations des immobilisations corporelles - Terrains (autres que terrains de gisement) \N 291100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 207 Dépréciations des immobilisations mises en concession \N 292000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 208 Dépréciations des immobilisations corporelles en cours \N 293100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 209 Dépréciations des immobilisations incorporelles en cours \N 293200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 191 Amortissements des immobilisations incorporelles - Frais de recherche et de développement \N 280300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 197 Amortissements des immobilisations corporelles - Constructions (même ventilation que celle du compte 213) \N 281300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 210 Provisions pour dépréciation des titres de participation \N 296100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 211 Provisions pour dépréciation des autres formes de participation \N 296600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 212 Provisions pour dépréciation des créances rattachées à des participations (même ventilation que celle du compte 267) \N 296700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 213 Provisions pour dépréciation des créances rattachées à des sociétés en participation (même ventilation que celle du compte 268) \N 296800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 214 Provisions pour dépréciation des titres immobilisés autres que les titres immobilisés de l'activité de portefeuille - droit de propriété (ventilation : 271) \N 297100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 215 Provisions pour dépréciation des titres immobilisés - droit de créance (même ventilation que celle du compte 272) \N 297200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 217 Provisions pour dépréciation des prêts (même ventilation que celle du compte 274) \N 297400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 218 Provisions pour dépréciation des dépôts et cautionnements versés (même ventilation que celle du compte 275) \N 297500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 221 Matières premières (ou groupe) B \N 312000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 222 Fournitures A, B, C, .. \N 317000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 223 Matières consommables (ou groupe) C \N 321100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 224 Matières consommables (ou groupe) D \N 321200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 225 Combustibles \N 322100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 226 Produits d'entretien \N 322200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 228 Fournitures de magasin \N 322400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 229 Fournitures de bureau \N 322500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 230 Emballages perdus \N 326100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 231 Emballages récupérables non identifiables \N 326500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 232 Emballages à usage mixte \N 326700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 233 Produit en cours P 1 \N 331100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 234 Produit en cours P 2 \N 331200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 235 Travaux en cours T 1 \N 335100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 236 Travaux en cours T 2 \N 335200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 220 Matières premières (ou groupe) A \N 311000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 216 Provisions pour dépréciation des titres immobilisés de l'activité de portefeuille \N 297300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 227 Fournitures d'atelier et d usine \N 322300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 219 Provisions pour dépréciation des autres créances immobilisées (même ventilation que celle du compte 276) \N 297600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 238 Études en cours E 2 \N 341200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 239 Prestations de services en cours S 1 \N 345100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 240 Prestations de services en cours S 2 \N 345200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 241 Stocks produits intermédiaires (ou groupe) A \N 351100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 242 Stocks produits intermédiaires (ou groupe) B \N 351200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 243 Stocks produits finis (ou groupe) A \N 355100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 244 Stocks produits finis (ou groupe) B \N 355200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 245 Stocks produits résiduels - Déchets \N 358100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 246 Stocks produits résiduels - Rebuts \N 358500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 247 Stocks produits résiduels - Matières de récupération \N 358600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 248 Stocks provenant d'immobilisations \N 360000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 250 Stocks de marchandises (ou groupe) B \N 372000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 251 Stocks en voie d'acheminement \N 380000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 252 Provisions pour dépréciation des matières premières (ou groupe) A \N 391100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 253 Provisions pour dépréciation des matières premières (ou groupe) B \N 391200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 254 Provisions pour dépréciation des fournitures A, B, C, .. \N 391700 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 255 Provisions pour dépréciation des matières consommables (même ventilation que celle du compte 321) \N 392100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 256 Provisions pour dépréciation des fournitures consommables (même ventilation que celle du compte 322) \N 392200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 257 Provisions pour dépréciation des emballages (même ventilation que celle du compte 326) \N 392600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 258 Provisions pour dépréciation des produits en cours (même ventilation que celle du compte 331) \N 393100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 259 Provisions pour dépréciation des travaux en cours (même ventilation que celle du compte 335) \N 393500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 260 Provisions pour dépréciation des études en cours (même ventilation que celle du compte 341) \N 394100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 261 Provisions pour dépréciation des prestations de services en cours (même ventilation que celle du compte 345) \N 394500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 262 Provisions pour dépréciation des produits intermédiaires (même ventilation que celle du compte 351) \N 395100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 263 Provisions pour dépréciation des produits finis (même ventilation que celle du compte 355) \N 395500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 249 Stocks de marchandises (ou groupe) A \N 371000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 264 Provisions pour dépréciation des stocks de marchandises (ou groupe) A \N 397100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 265 Provisions pour dépréciation des stocks de marchandises (ou groupe) B \N 397200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 266 Fournisseurs et comptes rattachés \N 400000 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 267 Fournisseurs - Achats de biens et prestations de services \N 401100 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 268 Fournisseurs - Retenues de garantie \N 401700 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 270 Fournisseurs - Achats d'immobilisations \N 404100 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 271 Fournisseurs d'immobilisations - Retenues de garantie \N 404700 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 272 Fournisseurs d'immobilisations - Effets à payer \N 405000 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 273 Factures non parvenues - Fournisseurs \N 408100 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 274 Factures non parvenues - Fournisseurs d'immobilisations \N 408400 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 275 Factures non parvenues - Fournisseurs - Intérêts courus \N 408800 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 276 Fournisseurs débiteurs - Créances pour emballages et matériel à rendre \N 409600 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 277 Fournisseurs débiteurs - Autres avoirs des fournisseurs d'exploitation \N 409710 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 278 Fournisseurs débiteurs - Autres avoirs des fournisseurs d'immobilisations \N 409740 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 279 Fournisseurs débiteurs - Rabais, remises, ristournes à obtenir et autres avoirs non encore reçus \N 409800 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 281 Clients - Ventes de biens ou de prestations de services \N 411100 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 282 Clients - Retenues de garantie \N 411700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 284 Clients douteux ou litigieux \N 416000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 285 Clients - Factures à établir \N 418100 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 286 Clients - Intérêts courus non encore facturés \N 418800 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 287 Clients créditeurs - Avances et acomptes reçus sur commandes \N 419100 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 288 Clients créditeurs - Dettes pour emballages et matériels consignés \N 419600 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 289 Clients créditeurs - Autres avoirs \N 419700 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 290 Clients créditeurs - Rabais, remises, ristournes à accorder et autres avoirs à établir \N 419800 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 280 Clients et comptes rattachés \N 410000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 269 Fournisseurs - Effets à payer \N 403000 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 283 Clients - Effets à recevoir \N 413000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 292 Comités d'entreprise, d'établissement \N 422000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 293 Participation des salariés aux résultats - Réserve spéciale \N 424600 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 294 Participation des salariés aux résultats - Comptes courants \N 424800 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 295 Personnel - Avances et acomptes \N 425000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 296 Personnel - Dépôts \N 426000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 297 Personnel - Oppositions \N 427000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 298 Personnel - Dettes provisionnées pour congés à payer \N 428200 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 299 Personnel - Dettes provisionnées pour participation des salariés aux résultats \N 428400 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 300 Personnel - Autres charges à payer \N 428600 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 301 Personnel - Produits à recevoir \N 428700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 303 Autres organismes sociaux \N 437000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 304 Charges sociales sur congés à payer \N 438200 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 305 Organismes sociaux - Autres charges à payer \N 438600 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 306 Organismes sociaux - Produits à recevoir \N 438700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 307 État - Subventions à recevoir - Subventions d'investissement \N 441100 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 308 État - Subventions à recevoir - Subventions d'exploitation \N 441700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 309 État - Subventions à recevoir - Subventions d'équilibre \N 441800 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 310 État - Subventions à recevoir - Avances sur subventions \N 441900 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 311 État - Impôts et taxes recouvrables sur des tiers - Obligataires \N 442400 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 312 État - Impôts et taxes recouvrables sur des tiers - Associés \N 442500 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 313 Créances sur l'État résultant de la suppression de la règle du décalage d'un mois en matière de TVA \N 443100 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 314 État - Intérêts courus sur créances figurant au compte 4431 \N 443800 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 315 État - Impôts sur les bénéfices \N 444000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 316 TVA due intracommunautaire (Taux Normal) \N 445201 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 317 TVA due intracommunautaire (Taux Intermédiaire) \N 445202 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 318 TVA due intracommunautaire (Autre taux) \N 445203 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 319 TVA due imports \N 445204 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 291 Personnel - Rémunérations dues \N 421000 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 302 Sécurité Sociale \N 431000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 320 TVA à décaisser \N 445510 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 321 Taxes assimilées à la TVA \N 445580 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 322 TVA déductible sur immobilisations \N 445620 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 323 TVA déductible transférée par d'autres entreprises \N 445630 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 324 TVA déductible sur autres biens et services \N 445660 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 325 TVA déductible intracommunautaire \N 445662 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 326 TVA déductible imports \N 445663 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 327 Crédit de TVA à reporter \N 445670 f 5 other \N t Si le remboursement n'a pas été demandé 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 328 Taxes déductibles assimilées à la TVA \N 445680 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 329 TVA collectée (Taux Normal) \N 445711 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 330 TVA collectée (Taux Intermédiaire) \N 445712 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 331 TVA collectée (Autre taux) \N 445713 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 332 Taxes collectées assimilées à la TVA \N 445780 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 333 Taxes sur le chiffre d'affaires à régulariser ou en attente \N 445800 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 334 Acomptes - Régime simplifié d'imposition \N 445810 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 335 Acomptes - Régime du forfait \N 445820 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 336 Remboursement de taxes sur le chiffre d'affaires demandé \N 445830 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 337 TVA récupérée d'avance \N 445840 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 338 Taxes sur le chiffre d'affaires sur factures non parvenues \N 445860 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 339 Taxes sur le chiffre d'affaires sur factures à établir \N 445870 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 340 Obligations cautionnées \N 446000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 341 Autres impôts, taxes et versements assimilés \N 447000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 342 État - Charges fiscales sur congés à payer \N 448200 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 343 État - Charges à payer \N 448600 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 344 État - Produits à recevoir \N 448700 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 345 Quotas d'émission à restituer à l'État \N 449000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 347 Associés - Comptes courants - Principal \N 455100 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 348 Associés - Comptes courants - Intérêts courus \N 455800 f 2 payable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 349 Associés - Comptes d'apport en société - Apports en nature \N 456110 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 346 Groupe \N 451000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 350 Associés - Comptes d'apport en société - Apports en numéraire \N 456150 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 351 Actionnaires - Capital souscrit et appelé, non versé \N 456210 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 352 Associés - Capital appelé, non versé \N 456250 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 354 Associés - Versements anticipés \N 456400 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 355 Actionnaires défaillants \N 456600 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 356 Associés - Capital à rembourser \N 456700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 357 Associés - Dividendes à payer \N 457000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 358 Associés - Opérations faites en commun et en GIE - Opérations courantes \N 458100 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 359 Associés - Opérations faites en commun et en GIE - Intérêts courus \N 458800 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 360 Créances sur cessions d'immobilisations \N 462000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 361 Dettes sur acquisitions de valeurs mobilières de placement \N 464000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 362 Créances sur cessions de valeurs mobilières de placement \N 465000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 363 Autres comptes débiteurs ou créditeurs \N 467000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 364 Charges à payer \N 468600 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 365 Produits à recevoir \N 468700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 367 Différence de conversion - Actif - Diminution des créances \N 476100 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 368 Différence de conversion - Actif - Augmentation des dettes \N 476200 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 369 Différence de conversion - Actif - Différences compensées par couverture de change \N 476800 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 370 Différences de conversion - Passif - Augmentation des créances \N 477100 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 371 Différences de conversion - Passif - Diminution des dettes \N 477200 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 372 Différences de conversion - Passif - Différences compensées par couverture de change \N 477800 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 373 Autres comptes transitoires \N 478000 f 9 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 374 Charges à répartir sur plusieurs exercices - Frais d'émission des emprunts \N 481600 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 375 Charges constatées d'avance \N 486000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 376 Produits constatés d'avance \N 487000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 377 Comptes de répartition périodique des charges \N 488600 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 366 Compte d'attente \N 471000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 353 Associés - Versements reçus sur augmentation de capital \N 456300 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 378 Comptes de répartition périodique des produits \N 488700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 379 Quotas d'émission alloués par l'État \N 489000 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 381 Provisions pour dépréciation des comptes du groupe \N 495100 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 382 Provisions pour dépréciation des comptes courants des associés \N 495500 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 383 Provisions pour dépréciation des opérations faites en commun et en GIE \N 495800 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 384 Provisions pour dépréciation des créances sur cessions d'immobilisations \N 496200 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 385 Provisions pour dépréciation des créances sur cessions de valeurs mobilières de placement \N 496500 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 386 Provisions pour dépréciation - Autres comptes débiteurs \N 496700 f 1 receivable \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 388 Valeurs mobilières de placement - Actions propres \N 502000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 389 Valeurs mobilières de placement - Titres cotés \N 503100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 390 Valeurs mobilières de placement - Titres non cotés \N 503500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 391 Valeurs mobilières de placement - Autres titres conférant un droit de propriété \N 504000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 392 Obligations et bons émis par la société et rachetés par elle \N 505000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 393 Obligations cotés \N 506100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 394 Obligations non cotés \N 506500 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 395 Bons du Trésor et bons de caisse à court terme \N 507000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 396 Autres valeurs mobilières de placement \N 508100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 397 Bons de souscription \N 508200 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 398 Intérêts courus sur obligations, bons et valeurs assimilées \N 508800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 399 Versements restant à effectuer sur valeurs mobilières de placement non libérées \N 509000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 400 Coupons échus à l'encaissement \N 511100 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 401 Chèques à encaisser \N 511200 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 403 Effets à l'escompte \N 511400 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 404 Banques - Comptes en devises \N 512400 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 405 Chèques postaux \N 514000 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 380 Provisions pour dépréciation des comptes de clients \N 491000 f 9 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 387 Valeurs mobilières de placement - Parts dans entreprises liées \N 501000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 402 Effets à l'encaissement \N 511300 f 5 other \N t \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 406 Caisses du Trésor et des établissements publics \N 515000 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 407 Sociétés de bourse \N 516000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 408 Autres organismes financiers \N 517000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 409 Intérêts courus à payer \N 518100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 410 Intérêts courus à recevoir \N 518800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 411 Concours bancaires courants - Crédit de mobilisation de créances commerciales (CMCC) \N 519100 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 413 Concours bancaires courants - Intérêts courus sur concours bancaires courants \N 519800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 414 Instruments de trésorerie \N 520000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 415 Caisse en monnaie nationale \N 531100 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 416 Caisse en devises \N 531400 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 417 Caisse succursale (ou usine) A \N 532000 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 419 Régies d'avances et accréditifs \N 540000 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 421 Provisions pour dépréciation des autres titres conférant un droit de propriété \N 590400 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 422 Provisions pour dépréciation des obligations \N 590600 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 423 Provisions pour dépréciation des autres valeurs mobilières de placement et créances assimilées (provisions) \N 590800 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 424 Achats stockés - Matières premières (ou groupe) A \N 601100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 425 Achats stockés - matières premières (ou groupe) B \N 601200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 426 Achats stockés - Fournitures A, B, C, .. \N 601700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 427 Achats stockés - Matières consommables (ou groupe) C \N 602110 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 428 Achats stockés - Matières consommables (ou groupe) D \N 602120 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 429 Achats stockés - Combustibles \N 602210 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 430 Achats stockés - Produits d'entretien \N 602220 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 431 Achats stockés - Fournitures d'atelier et d'usine \N 602230 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 432 Achats stockés - Fournitures de magasin \N 602240 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 433 Achats stockés - Fournitures de bureau \N 602250 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 434 Achats stockés - Emballages perdus \N 602610 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 412 Concours bancaires courants - Mobilisation de créances nées à l'étranger \N 519300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 418 Caisse succursale (ou usine) B \N 533000 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 420 Provisions pour dépréciation des actions \N 590300 f 5 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 435 Achats stockés - Emballages récupérables non identifiables \N 602650 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 436 Achats stockés - Emballages à usage mixte \N 602670 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 437 Variation des stocks de matières premières (et fournitures) \N 603100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 438 Variation des stocks des autres approvisionnements \N 603200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 439 Variation des stocks de marchandises \N 603700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 440 Achats d'études et prestations de services \N 604000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 441 Achats de matériel équipements et travaux \N 605000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 442 Fournitures non stockables (eau, énergie...) \N 606100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 444 Fournitures administratives \N 606400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 445 Achats autres matières et fournitures \N 606800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 446 Achats de marchandises (ou groupe) A \N 607100 f 16 other \N f Pour achats France 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 447 Achats de marchandises (ou groupe) B \N 607200 f 16 other \N f Pour déclaration TVA intracommunautaire 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 448 Frais accessoires incorporés aux achats \N 608000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 449 Rabais, remises et ristournes obtenus sur achats de matières premières (et fournitures) \N 609100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 450 Rabais, remises et ristournes obtenus sur achats d'autres approvisionnements stockés \N 609200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 451 Rabais, remises et ristournes obtenus sur achats d'études et prestations de services \N 609400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 452 Rabais, remises et ristournes obtenus sur achats de matériel, équipements et travaux \N 609500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 453 Rabais, remises et ristournes obtenus sur achats d'approvisionnements non stockés \N 609600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 454 Rabais, remises et ristournes obtenus sur achats de marchandises \N 609700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 455 Rabais, remises et ristournes non affectés \N 609800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 457 Redevances de crédit-bail mobilier \N 612200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 458 Redevances de crédit-bail immobilier \N 612500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 459 Locations immobilières \N 613200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 460 Locations mobilières \N 613500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 461 Locations malis sur emballages \N 613600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 462 Charges locatives et de copropriété \N 614000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 456 Sous-traitance générale \N 611000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 443 Fournitures d'entretien et de petit équipement \N 606300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 463 Entretien et réparations sur biens immobiliers \N 615200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 464 Entretien et réparations sur biens mobiliers \N 615500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 465 Maintenance \N 615600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 466 Assurance multirisques \N 616100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 467 Assurance obligatoire dommage construction \N 616200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 468 Assurance transport sur achats \N 616360 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 469 Assurance transport sur ventes \N 616370 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 470 Assurance transport sur autres biens \N 616380 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 471 Assurance risques d'exploitation \N 616400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 472 Assurance insolvabilité clients \N 616500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 473 Études et recherches \N 617000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 474 Documentation générale \N 618100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 476 Frais de colloques, séminaires, conférences \N 618500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 477 Rabais, remises et ristournes obtenus sur services extérieurs \N 619000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 478 Personnel intérimaire \N 621100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 479 Personnel détaché ou prêté à l'entreprise \N 621400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 480 Commissions et courtages sur achats \N 622100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 481 Commissions et courtages sur ventes \N 622200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 482 Rémunérations des transitaires \N 622400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 483 Rémunérations d'affacturage \N 622500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 484 Honoraires \N 622600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 485 Frais d'actes et de contentieux \N 622700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 486 Rémunérations d'intermédiaires et honoraires - Divers \N 622800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 487 Annonces et insertions \N 623100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 488 Échantillons \N 623200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 490 Cadeaux à la clientèle \N 623400 f 16 other \N f Attention déclaration DAS fin d'année 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 491 Primes \N 623500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 492 Catalogues et imprimés \N 623600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 493 Publications \N 623700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 494 Publicité, publications, relations publiques - Divers (pourboires, dons courants...) \N 623800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 475 Documentation technique \N 618300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 489 Foires et expositions \N 623300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 495 Transports sur achats \N 624100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 496 Transports sur ventes \N 624200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 498 Transports administratifs \N 624400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 499 Transports collectifs du personnel \N 624700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 500 Transports divers \N 624800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 501 Voyages et déplacements \N 625100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 502 Frais de déménagement \N 625500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 503 Missions \N 625600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 504 Réceptions \N 625700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 505 Frais postaux et frais de télécommunications \N 626000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 506 Frais sur titres (achat, vente, garde) \N 627100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 507 Commissions et frais sur émission d'emprunts \N 627200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 508 Frais sur effets \N 627500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 510 Autres frais et commissions sur prestations de services \N 627800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 511 Concours divers (cotisations...) \N 628100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 512 Frais de recrutement de personnel \N 628400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 513 Rabais, remises et ristournes obtenus sur autres services extérieurs \N 629000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 514 Taxe sur les salaires \N 631100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 515 Taxe d'apprentissage \N 631200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 517 Cotisation pour défaut d'investissement obligatoire dans la construction \N 631400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 518 Autres impôts, taxes et versements assimilés sur rémunérations (administrations des impôts) \N 631800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 519 Versement de transport \N 633100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 520 Allocation logement \N 633200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 522 Participation des employeurs à l'effort de construction \N 633400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 523 Versements libératoires ouvrant droit à l'exonération de la taxe d'apprentissage \N 633500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 524 Autres impôts, taxes et versements assimilés sur rémunérations (autres organismes) \N 633800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 497 Transports entre établissements ou chantiers \N 624300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 516 Participation des employeurs à la formation professionnelle continue \N 631300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 521 Participation des employeurs à la formation professionnelle continue \N 633300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 509 Location de coffres \N 627600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 525 Cotisation foncière des entreprises \N 635111 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 526 Cotisation sur la valeur ajoutée des entreprises \N 635112 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 527 Taxes foncières \N 635120 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 528 Autres impôts locaux \N 635130 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 529 Taxe sur les véhicules des sociétés \N 635140 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 530 Taxes sur le chiffre d'affaires non récupérables \N 635200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 532 Droits de mutation \N 635410 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 533 Autres droits \N 635800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 534 Contribution sociale de solidarité à la charge des sociétés \N 637100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 535 Taxes perçues par les organismes publics internationaux \N 637200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 536 Impôts et taxes exigibles à l'étranger \N 637400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 537 Taxes diverses (autres organismes) \N 637800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 538 Salaires et appointements \N 641100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 539 Congés payés \N 641200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 541 Indemnités et avantages divers \N 641400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 542 Supplément familial \N 641500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 543 Rémunération du travail de l'exploitant \N 644000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 544 Cotisations à l'URSSAF \N 645100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 545 Cotisations aux mutuelles \N 645200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 547 Cotisations aux ASSEDIC \N 645400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 548 Cotisations aux autres organismes sociaux \N 645800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 549 Cotisations sociales personnelles de l'exploitant \N 646000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 550 Prestations directes \N 647100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 551 Versements aux comités d'entreprise et d'établissement \N 647200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 553 Versements aux autres oeuvres sociales \N 647400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 554 Médecine du travail, pharmacie \N 647500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 555 Autres charges de personnel \N 648000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 556 Crédit d’Impôt Compétitivité Emploi (CICE) \N 649000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 531 Impôts indirects \N 635300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 540 Primes et gratifications \N 641300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 546 Cotisations aux caisses de retraites \N 645300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 552 Versements aux comités d'hygiène et de sécurité \N 647300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 557 Redevances pour concessions brevets, licences, marques, procédés, logiciels \N 651100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 558 Droits d'auteur et de reproduction \N 651600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 559 Autres droits et valeurs similaires \N 651800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 561 Créances de l'exercice \N 654100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 562 Créances des exercices antérieurs \N 654400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 563 Quote-part de bénéfice transférée (comptabilité du gérant) \N 655100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 564 Quote-part de perte supportée (comptabilité des associés non gérants) \N 655500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 565 Charges diverses de gestion courante \N 658000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 566 Intérêts des emprunts et dettes assimilées \N 661160 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 567 Intérêts des dettes rattachées à des participations \N 661170 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 568 Intérêts des comptes courants et des dépôts créditeurs \N 661500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 569 Intérêts bancaires et sur opérations de financement (escompte, ...) \N 661600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 570 Intérêts des obligations cautionnées \N 661700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 571 Intérêts des dettes commerciales \N 661810 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 572 Intérêts des dettes diverses \N 661880 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 573 Pertes sur créances liées à des participations \N 664000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 574 Escomptes accordés \N 665000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 575 Pertes de change \N 666000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 576 Charges nettes sur cessions de valeurs mobilières de placement \N 667000 f 16 other \N f (contrepartie 767) 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 577 Autres charges financières \N 668000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 578 Charges exceptionnelles - Pénalités sur marchés (et dédits payés sur achats et ventes) \N 671100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 579 Charges exceptionnelles - Pénalités, amendes fiscales et pénales \N 671200 f 16 other \N f PV code de la route non déductibles 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 581 Charges exceptionnelles - Créances devenues irrécouvrables dans l'exercice \N 671400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 582 Charges exceptionnelles - Subventions accordées \N 671500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 583 Charges exceptionnelles - Rappels d'impôts (autres qu'impôts sur les bénéfices) \N 671700 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 584 Autres charges exceptionnelles sur opération de gestion \N 671800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 560 Jetons de présence \N 653000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 580 Charges exceptionnelles - Dons, libéralités \N 671300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 585 Charges exceptionnelles sur exercices antérieurs (en cours d'exercice seulement) \N 672000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 586 Valeurs comptables des éléments d'actif cédés - Immobilisations incorporelles \N 675100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 587 Valeurs comptables des éléments d'actif cédés - Immobilisations corporelles \N 675200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 588 Valeurs comptables des éléments d'actif cédés - Immobilisations financières \N 675600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 589 Valeurs comptables des éléments d'actif cédés - Autres éléments d'actif \N 675800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 590 Charges exceptionnelles - Malis provenant de clauses d'indexation \N 678100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 591 Charges exceptionnelles - Lots \N 678200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 593 Charges exceptionnelles diverses \N 678800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 594 Dotations aux amortissements sur immobilisations incorporelles \N 681110 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 595 Dotations aux amortissements sur immobilisations corporelles \N 681120 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 596 Dotations aux amortissements des charges d'exploitation à répartir \N 681200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 597 Dotations aux provisions pour risques et charges d'exploitation \N 681500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 598 Dotations aux dépréciations des immobilisations incorporelles \N 681610 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 599 Dotations aux dépréciations des immobilisations corporelles \N 681620 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 600 Dotations aux dépréciations des stocks et en-cours \N 681730 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 601 Dotations aux dépréciations des créances \N 681740 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 602 Dotations aux amortissements des primes de remboursement des obligations \N 686100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 603 Dotations aux provisions pour risques et charges financiers \N 686500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 604 Dotations aux dépréciations des immobilisations financières \N 686620 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 605 Dotations aux dépréciations des valeurs mobilières de placement \N 686650 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 606 Autres dotations aux amortissements, dépréciations et provisions - Charges financières \N 686800 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 607 Dotations aux amortissements exceptionnels des immobilisations \N 687100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 608 Dotations aux provisions réglementées exceptionnelles (immobilisations) - Amortissements dérogatoires \N 687250 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 592 Charges exceptionnelles - Malis provenant du rachat par l'entreprise d'actions et obligations émises par elle-même \N 678300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 609 Dotations aux provisions réglementées exceptionnelles (stocks) \N 687300 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 610 Dotations aux autres provisions réglementées exceptionnelles \N 687400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 611 Dotations aux provisions exceptionnelles \N 687500 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 614 Impôts sur les bénéfices dus en France \N 695100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 615 Contribution additionnelle à l'impôt sur les bénéfices \N 695200 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 616 Impôts sur les bénéfices dus à l'étranger \N 695400 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 617 Supplément d'impôt sur les sociétés lié aux distributions \N 696000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 618 Imposition forfaitaire annuelle des sociétés \N 697000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 619 Intégration fiscale - Charges \N 698100 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 620 Intégration fiscale - Produits \N 698900 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 621 Produits, Reports en arrière des déficits \N 699000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 622 Ventes de produits finis (ou groupe) A \N 701100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 623 Ventes de produits finis (ou groupe) B \N 701200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 624 Ventes de produits intermédiaires \N 702000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 626 Ventes de travaux de catégorie (ou activité) A \N 704100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 627 Ventes de travaux de catégorie (ou activité) B \N 704200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 628 Ventes d'études \N 705000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 629 Ventes de prestations de services \N 706000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 630 Ventes de marchandises (ou groupe) A \N 707100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 631 Ventes de marchandises (ou groupe) B \N 707200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 633 Produits des services exploités dans l'intérêt du personnel \N 708100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 634 Commissions et courtages \N 708200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 636 Mise à disposition de personnel facturée \N 708400 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 637 Ports et frais accessoires facturés \N 708500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 638 Bonis sur reprises d'emballages consignés \N 708600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 639 Bonifications obtenues des clients et primes sur ventes \N 708700 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 613 Participation des salariés aux résultats \N 691000 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 625 Ventes de produits résiduels \N 703000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 632 Ventes de marchandises à l'exportation \N 707300 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 635 Locations diverses \N 708300 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 612 Dotations aux dépréciations exceptionnelles \N 687600 f 16 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 640 Autres produits d'activités annexes (cessions d'approvisionnements...) \N 708800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 641 Rabais, remises et ristournes sur ventes de produits finis \N 709100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 642 Rabais, remises et ristournes sur ventes de produits intermédiaires \N 709200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 643 Rabais, remises et ristournes sur travaux \N 709400 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 644 Rabais, remises et ristournes sur études \N 709500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 645 Rabais, remises et ristournes sur prestations de services \N 709600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 646 Rabais, remises et ristournes sur ventes de marchandises \N 709700 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 647 Rabais, remises et ristournes sur produits des activités annexes \N 709800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 648 Variation des en-cours de production de biens - Produits en cours \N 713310 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 649 Variation des en-cours de production de biens - Travaux en cours \N 713350 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 650 Variation des en-cours de production de services - Études en cours \N 713410 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 651 Variation des en-cours de production de services - Prestations de services en cours \N 713450 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 652 Variation des stocks de produits intermédiaires \N 713510 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 653 Variation des stocks de produits finis \N 713550 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 654 Variation des stocks de produits résiduels \N 713580 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 656 Production immobilisée - Immobilisations corporelles \N 722000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 657 Subventions d'exploitation \N 740000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 658 Redevances pour concessions, brevets, licences, marques, procédés, logiciels \N 751100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 659 Droits d'auteur et de reproduction \N 751600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 660 Redevances pour autres droits et valeurs similaires \N 751800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 661 Revenus des immeubles non affectés aux activités professionnelles \N 752000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 663 Ristournes perçues des coopératives (provenant des excédents) \N 754000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 664 Quote-part de perte transférée (comptabilité du gérant) \N 755100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 665 Quote-part de bénéfice attribuée (comptabilité des associés non-gérants) \N 755500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 666 Produits divers de gestion courante \N 758000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 655 Production immobilisée - Immobilisations incorporelles \N 721000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 662 Jetons de présence et rémunérations d'administrateurs, gérants.. \N 753000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 667 Revenus des titres de participation \N 761100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 668 Revenus sur autres formes de participation \N 761600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 669 Revenus des titres immobilisés \N 762100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 670 Revenus des prêts \N 762600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 671 Revenus des créances immobilisées \N 762700 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 672 Revenus des créances commerciales \N 763100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 673 Revenus des créances diverses \N 763800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 674 Revenus des valeurs mobilières de placement \N 764000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 675 Escomptes obtenus \N 765000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 676 Gains de change \N 766000 f 13 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 677 Produits nets sur cessions de valeurs mobilières de placement \N 767000 f 14 other \N f (contrepartie 667) 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 678 Autres produits financiers \N 768000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 679 Produits exceptionnels - Dédits et pénalités perçus sur achats et sur ventes \N 771100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 681 Produits exceptionnels - Rentrées sur créances amorties \N 771400 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 682 Produits exceptionnels - Subventions d'équilibre \N 771500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 683 Produits exceptionnels - Dégrèvements d'impôts autres qu'impôts sur les bénéfices \N 771700 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 684 Autres produits exceptionnels sur opérations de gestion \N 771800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 685 Produits exceptionnels sur exercices antérieurs (en cours d'exercice seulement) \N 772000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 686 Produits exceptionnels des cessions d'éléments d'actif - Immobilisations incorporelles \N 775100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 687 Produits exceptionnels des cessions d'éléments d'actif - Immobilisations corporelles \N 775200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 688 Produits exceptionnels des cessions d'éléments d'actif - Immobilisations financières \N 775600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 689 Produits exceptionnels des cessions d'éléments d'actif - Autres éléments d'actif \N 775800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 690 Produits exceptionnels - Quote-part des subventions d'investissement virée au résultat de l'exercice \N 777000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 691 Produits exceptionnels - Bonis provenant de clauses d'indexation \N 778100 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 692 Produits exceptionnels - Lots \N 778200 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 680 Produits exceptionnels - Libéralités reçues \N 771300 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 693 Produits exceptionnels - Bonis provenant du rachat par l'entreprise d'actions et d'obligations émises par elle-même \N 778300 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 694 Produits exceptionnels divers \N 778800 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 695 Reprises sur amortissements des immobilisations incorporelles \N 781110 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 696 Reprises sur amortissements des immobilisations corporelles \N 781120 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 697 Reprises sur provisions d'exploitation \N 781500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 698 Reprises sur dépréciations des immobilisations incorporelles \N 781610 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 699 Reprises sur dépréciations des immobilisations corporelles \N 781620 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 700 Reprises sur dépréciations des actifs circulants - Stocks et en-cours \N 781730 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 701 Reprises sur dépréciations des actifs circulants - Créances \N 781740 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 702 Reprises sur provisions financières \N 786500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 703 Reprises sur dépréciations des immobilisations financières \N 786620 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 704 Reprises sur dépréciations des valeurs mobilières de placement \N 786650 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 705 Reprises sur provisions réglementées (immobilisations) - Amortissements dérogatoires \N 787250 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 706 Reprises sur provisions réglementées (immobilisations) - Provision spéciale de réévaluation \N 787260 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 707 Reprises sur provisions réglementées (immobilisations) - Plus-values réinvesties \N 787270 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 709 Reprises sur autres provisions réglementées \N 787400 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 710 Reprises sur provisions exceptionnelles \N 787500 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 713 Transferts de charges financières \N 796000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 714 Transferts de charges exceptionnelles \N 797000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 716 Banque \N 512001 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 717 Profits/pertes non distribués \N 999999 f 12 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:06:53.166234 712 Transferts de charges d'exploitation \N 791000 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 708 Reprises sur provisions réglementées (stocks) \N 787300 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 715 Espèces \N 530001 f 3 liquidity \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 711 Reprises sur dépréciations exceptionnelles \N 787600 f 14 other \N f \N 1 \N 1 2019-02-14 15:06:53.166234 1 2019-02-14 15:09:48.936423 \. |
Added doc/manuel/Comptabilité avancée (partie double).md version [4caaa3768c].
> > > > > > > | 1 2 3 4 5 6 7 | # Comptabilité avancée (partie double) ## Fonctionnement général Par défaut les opérations sont enregistrées en tant que brouillon (dans le *brouillard*) et peuvent être modifiées ou supprimées. Il faut valider les opérations pour les rendre définitivées. Une opération validée ne peut plus être modifiée ou supprimée. En cas d'erreur il faudra créer une nouvelle écriture corrective. |
Added doc/manuel/Sauvegarde et restauration.md version [a2332341db].
> > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # Sauvegarde et restauration ## Messages d'erreur ### Le fichier fourni est corrompu. Certaines clés étrangères référencent des lignes qui n'existent pas. Ce message indiquent que certaines lignes dans une table font référence à des lignes d'une autre table qui n'existent pas. Cette erreur se produit lorsque des modifications manuelles ont été apportées à une base de données. Pour trouver les lignes qui sont invalides, utiliser un outil de gestion de base de données SQLite et lancer la commande suivante : PRAGMA schema.integrity_check; |
Modified src/.htaccess.www from [0f46a6ebba] to [34b16e1e96].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # Désactiver le multiviews (conflit avec /admin/plugin.php) et les index (sécurité) Options -MultiViews -Indexes DirectoryIndex disabled DirectoryIndex index.php index.html # Au cas où <IfModule mod_alias.c> RedirectMatch 403 /include/ RedirectMatch 403 /cache/ RedirectMatch 403 /plugins/ RedirectMatch 403 /templates/ RedirectMatch 403 /.*\.sqlite RedirectMatch 403 /.*\.log RedirectMatch 403 /(README|VERSION|COPYING|Makefile|cron\.php) RedirectMatch 403 /config\.(.*)\.php RedirectMatch 403 /sous-domaine\.html RedirectMatch 403 _inc\.php </IfModule> # Redirection dynamique, pour les installations sans vhost dédié # Objectif: supprimer le /www/ de l'URL | > < | | | | | | | < < | 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 | # Désactiver le multiviews (conflit avec /admin/plugin.php) et les index (sécurité) Options -MultiViews -Indexes DirectoryIndex disabled DirectoryIndex index.php index.html # Au cas où <IfModule mod_alias.c> RedirectMatch 403 /include/ RedirectMatch 403 /cache/ RedirectMatch 403 /plugins/ RedirectMatch 403 /templates/ RedirectMatch 403 ^/scripts/ RedirectMatch 403 /.*\.sqlite RedirectMatch 403 /.*\.log RedirectMatch 403 /(README|VERSION|COPYING|Makefile|cron\.php) RedirectMatch 403 /config\.(.*)\.php RedirectMatch 403 /sous-domaine\.html RedirectMatch 403 _inc\.php </IfModule> # Redirection dynamique, pour les installations sans vhost dédié # Objectif: supprimer le /www/ de l'URL # Note: il est probable qu'il soit nécessaire d'adapter la configuration # à votre hébergeur ! <IfModule mod_rewrite.c> RewriteEngine on ## Remplacer dans les lignes suivantes ## /garradin/ par le nom du sous-répertoire où est installé Garradin RewriteBase /garradin/ FallbackResource /garradin/www/_route.php ## Ne pas modifier les lignes suivantes, les décommenter simplement ! RewriteCond %{REQUEST_URI} !www/ RewriteRule ^(.*)$ www/$1 [QSA,L] </IfModule> |
Modified src/Makefile from [cf4731ac96] to [c8d389d4f3].
|
| | | | > | > > > > > > > > | > > > > | 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 | .PHONY: dev-server release deps publish check-dependencies test minify KD2_FILE := https://fossil.kd2.org/kd2fw/uv/KD2-7.2.zip deps: $(eval TMP_KD2=$(shell mktemp -d)) #cd ${TMP_KD2} wget ${KD2_FILE} -O ${TMP_KD2}/kd2.zip rm -rf "include/lib/KD2" unzip "${TMP_KD2}/kd2.zip" -d include/lib rm -rf ${TMP_KD2} dev-server: php -S localhost:8082 -t www www/_route.php test: find . -name '*.php' -print0 | xargs -0 -n1 php -l > /dev/null release: test minify $(eval VERSION=$(shell cat VERSION)) rm -rf /tmp/garradin-build mkdir -p /tmp/garradin-build fossil zip ${VERSION} /tmp/garradin-build/src.zip --name garradin unzip -d /tmp/garradin-build /tmp/garradin-build/src.zip cd include/lib; \ rsync --files-from=dependencies.list -r ./ /tmp/garradin-build/garradin/src/include/lib/ mv www/admin/static/mini.css /tmp/garradin-build/garradin/src/www/admin/static/admin.css cd /tmp/garradin-build/garradin/src/www/admin/static; \ rm -f styles/[0-9]*.css; \ rm -f font/*.css font/*.json cd /tmp/garradin-build/garradin/src; \ rm -f Makefile include/lib/KD2/data/countries.en.json cd /tmp/garradin-build/garradin/src/plugins; \ wget https://fossil.kd2.org/garradin-plugins/uv/welcome.tar.gz mv /tmp/garradin-build/garradin/src /tmp/garradin-build/garradin-${VERSION} @#cd /tmp/garradin-build/; zip -r -9 garradin-${VERSION}.zip garradin-${VERSION}; @#mv -f /tmp/garradin-build/garradin-${VERSION}.zip ./ tar cjvfh garradin-${VERSION}.tar.bz2 -C /tmp/garradin-build garradin-${VERSION} deb: cd ../debian; ./makedeb.sh publish: release deb $(eval VERSION=$(shell cat VERSION)) fossil uv sync #fossil uv ls | fgrep -v 'garradin-0.8.5' | grep '^garradin-.*\.(tar\.bz2|deb)' | xargs fossil uv rm fossil uv add garradin-${VERSION}.tar.bz2 cd ../debian && fossil uv add garradin-${VERSION}-*.deb fossil uv sync check-dependencies: grep -hEo '^use \\?KD2\\[^; ]+|\\KD2\\[^\(:; ]+' -R include/lib/Garradin www | sed -r 's/^use \\?KD2\\|^\\KD2\\//' | sort | uniq minify: cat `ls www/admin/static/styles/[0-9]*.css` | sed 's/\.\.\///' > www/admin/static/mini.css yui-compressor --nomunge www/admin/static/mini.css -o www/admin/static/mini.css |
Modified src/VERSION from [bef1ccc9e8] to [d0cb76d66a].
|
| | | 1 | 1.0.0-rc7 |
Modified src/config.dist.php from [7d9b8d58eb] to [9561d21e0d].
︙ | ︙ | |||
15 16 17 18 19 20 21 | /** * Clé secrète, doit être unique à chaque instance de Garradin * * Ceci est utilisé afin de sécuriser l'envoi de formulaires * (protection anti-CSRF). * | > > > | | > | > | | | > | | > | > | | > | > > > > > > > > | > | > | > | | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | /** * Clé secrète, doit être unique à chaque instance de Garradin * * Ceci est utilisé afin de sécuriser l'envoi de formulaires * (protection anti-CSRF). * * Cette valeur peut être modifiée sans autre impact que la déconnexion des utilisateurs * actuellement connectés. * * Si cette constante n'est définie, Garradin ajoutera automatiquement * une valeur aléatoire dans le fichier config.local.php. */ //const SECRET_KEY = '3xUhIgGwuovRKOjVsVPQ5yUMfXUSIOX2GKzcebsz5OINrYC50r'; /** * Se connecter automatiquement avec l'ID de membre indiqué * Exemple: LOCAL_LOGIN = 42 connectera automatiquement le membre n°42 * Attention à ne pas utiliser en production ! * * Il est aussi possible de mettre "LOCAL_LOGIN = -1" pour se connecter * avec le premier membre trouvé qui peut gérer la configuration (et donc * modifier les droits des membres). * * Défault : false (connexion automatique désactivée) */ //const LOCAL_LOGIN = false; /** * Autoriser (ou non) l'import de sauvegarde qui a été modifiée ? * * Si mis à true, un avertissement et une confirmation seront demandés * Si mis à false, tout fichier SQLite importé qui ne comporte pas une signature * valide (hash SHA1) sera refusé. * * Ceci ne s'applique qu'à la page "Sauvegarde et restauration" de l'admin, * il est toujours possible de restaurer une base de données non signée en * la recopiant à la place du fichier association.sqlite * * Défaut : true */ //const ALLOW_MODIFIED_IMPORT = true; /** * Doit-on suggérer à l'utilisateur d'utiliser la version chiffrée du site ? * * 1 ou true = affiche un message de suggestion sur l'écran de connexion invitant à utiliser le site chiffré * (conseillé si vous avez un certificat auto-signé ou peu connu type CACert) * 2 = rediriger automatiquement sur la version chiffrée pour l'administration (mais pas le site public) * 3 = rediriger automatiquement sur la version chiffrée pour administration et site public * false ou 0 = aucune version chiffrée disponible, donc ne rien proposer ni rediriger * * Défaut : false */ //const PREFER_HTTPS = false; /** * Répertoire où se situe le code source de Garradin * * Défaut : répertoire racine de Garradin (__DIR__) */ //const ROOT = __DIR__; /** * Répertoire où sont situées les données de Garradin * (incluant la base de données SQLite, les sauvegardes, le cache et les fichiers locaux) * * Défaut : identique à ROOT */ //const DATA_ROOT = ROOT; /** * Répertoire où est situé le cache (fichiers temporaires utilisés pour accélérer le chargement des pages) * * Défaut : sous-répertoire 'cache' de DATA_ROOT */ //const CACHE_ROOT = ROOT . '/cache'; /** * Emplacement du fichier de base de données de Garradin * * Défaut : DATA_ROOT . '/association.sqlite' */ //const DB_FILE = DATA_ROOT . '/association.sqlite'; /** * Emplacement de stockage des plugins * * Défaut : DATA_ROOT . '/plugins' */ //const PLUGINS_ROOT = DATA_ROOT . '/plugins'; /** * Plugins fixes qui ne peuvent être désinstallés par l'utilisateur * (séparés par une virgule) * * Ils seront aussi réinstallés en cas de restauration de sauvegarde, * s'ils ne sont pas dans la sauvegarde. * * Exemple : PLUGINS_SYSTEM = 'gestion_emails,factures' * * Défaut : aucun (chaîne vide) */ //const PLUGINS_SYSTEM = ''; /** * Adresse URI de la racine du site Garradin * (doit se terminer par un slash) * * Défaut : découverte automatique à partir de SCRIPT_NAME */ |
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | //const WWW_URL = 'http://garradin.chezmoi.tld' . WWW_URI; /** * Adresse URL HTTP(S) de l'admin Garradin * * Défaut : WWW_URL + 'admin/' */ //const ADMIN_URL = 'https://admin.garradin.chezmoi.tld/'; /** * Affichage des erreurs * Si "true" alors un message expliquant l'erreur et comment rapporter le bug s'affiche * en cas d'erreur. Sinon rien ne sera affiché. * * Défaut : false * * Il est fortement conseillé de mettre cette valeur à false en production ! */ | > > | > | > | > > | < > < < > | > | | | > | | > | > | > | > | | 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 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 | //const WWW_URL = 'http://garradin.chezmoi.tld' . WWW_URI; /** * Adresse URL HTTP(S) de l'admin Garradin * * Défaut : WWW_URL + 'admin/' */ //const ADMIN_URL = 'https://admin.garradin.chezmoi.tld/'; /** * Affichage des erreurs * Si "true" alors un message expliquant l'erreur et comment rapporter le bug s'affiche * en cas d'erreur. Sinon rien ne sera affiché. * * Défaut : false * * Il est fortement conseillé de mettre cette valeur à false en production ! */ //const SHOW_ERRORS = false; /** * Envoi des erreurs par e-mail * * Si renseigné, un email sera envoyé à l'adresse indiquée à chaque fois qu'une erreur * d'exécution sera rencontrée. * Si "false" alors aucun email ne sera envoyé. * Note : les erreurs sont déjà toutes loguées dans error.log à la racine de DATA_ROOT * * Défaut : false */ //const MAIL_ERRORS = false; /** * Envoi des erreurs à une API compatible AirBrake/Errbit * * Si renseigné avec une URL HTTP(S) valide, chaque erreur système sera envoyée * automatiquement à cette URL. * * Si laissé à null, aucun rapport ne sera envoyé. * * Défaut : null */ //const ERRORS_REPORT_URL = null; /** * Activation des détails techniques (utile en auto-hébergement) : * - version de PHP * - page permettant de visualiser les erreurs présentes dans le error.log * - vérification de nouvelle version * * Ces infos ne sont visibles que par les membres ayant accès à la configuration. * * Défaut : true * (Afin d'aider au rapport de bugs des instances auto-hébergées) */ //const ENABLE_TECH_DETAILS = true; /** * Utilisation de cron pour les tâches automatiques * * Si "true" on s'attend à ce qu'une tâche automatisée appelle * le script cron.php dans le répertoire "scripts" toutes les 24 heures. * Sinon Garradin effectuera les actions automatiques quand quelqu'un * se connecte à l'administration ou visite le site. * * Défaut : false */ //const USE_CRON = false; /** * Activation de l'envoi de fichier directement par le serveur web. * (X-SendFile) * * Permet d'améliorer la rapidité d'envoi des fichiers. * Supporte les serveurs web suivants : * - Apache avec mod_xsendfile (paquet libapache2-mod-xsendfile) * - Lighttpd * * N'activer que si vous êtes sûr que le module est installé et activé (sinon * les fichiers ne pourront être vus ou téléchargés). * Nginx n'est PAS supporté, car X-Accel-Redirect ne peut gérer que des fichiers * qui sont *dans* le document root du vhost, ce qui n'est pas le cas ici. * * Pour activer X-SendFile mettre dans la config du virtualhost de Garradin: * XSendFile On * XSendFilePath /var/www/garradin * * (remplacer le chemin par le répertoire racine de Garradin) * * Détails : https://tn123.org/mod_xsendfile/ * * Défaut : false */ //const ENABLE_XSENDFILE = false; /** * Serveur NTP utilisé pour les connexions avec TOTP * (utilisé seulement si le code OTP fourni est faux) * * Désactiver (false) si vous êtes sûr que votre serveur est toujours à l'heure. * * Défaut : fr.pool.ntp.org */ //const NTP_SERVER = 'fr.pool.ntp.org'; /** * Hôte du serveur SMTP, mettre à false (défaut) pour utiliser la fonction * mail() de PHP * * Défaut : false */ //const SMTP_HOST = false; /** * Port du serveur SMTP * * 25 = port standard pour connexion non chiffrée (465 pour Gmail) * 587 = port standard pour connexion SSL * * Défaut : 587 */ //const SMTP_PORT = 587; /** * Login utilisateur pour le server SMTP * * mettre à null pour utiliser un serveur local ou anonyme * * Défaut : null |
︙ | ︙ | |||
270 271 272 273 274 275 276 | * NONE = pas de chiffrement * SSL = connexion SSL native * TLS = connexion TLS native (le plus sécurisé) * STARTTLS = utilisation de STARTTLS (moyennement sécurisé) * * Défaut : STARTTLS */ | > | > | > > > | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | * NONE = pas de chiffrement * SSL = connexion SSL native * TLS = connexion TLS native (le plus sécurisé) * STARTTLS = utilisation de STARTTLS (moyennement sécurisé) * * Défaut : STARTTLS */ //const SMTP_SECURITY = 'STARTTLS'; /** * Activer les sauvegardes automatiques * * Utile à désactiver si vous avez déjà des sauvegardes effectuées * automatiquement au niveau du système. * * Sinon les sauvegardes seront effectuées soit par la tâche cron * soit à l'affichage de la page d'accueil (si nécessaire). * * Voir paramètre USE_CRON aussi * * Défaut : true */ //const ENABLE_AUTOMATIC_BACKUPS = true; /** * Couleur primaire de l'interface admin par défaut * (peut être personnalisée dans la configuration) * * Défaut : #9c4f15 */ //const ADMIN_COLOR1 = '#20787a'; /** * Couleur secondaire de l'interface admin * Défaut : #d98628 */ //const ADMIN_COLOR2 = '#85b9ba'; /** * Image de fond par défaut de l'interface admin * * Cette URL doit être absolue (http://...) ou relative à l'admin (/admin/static...) * * Attention si l'image est sur un domaine différent vous devrez activer l'entête CORS: * Access-Control-Allow-Origin "*" * * sinon la personnalisation des couleurs ne fonctionnera pas * * Défaut : [ADMIN_URL]static/gdin_bg.png */ //const ADMIN_BACKGROUND_IMAGE = 'http://mon-asso.fr/fond_garradin.png'; |
Added src/include/data/1.0.0-beta6_migration.sql version [13c95a32fe].
> > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | ALTER TABLE fichiers_membres RENAME TO fichiers_membres_old; ALTER TABLE fichiers_wiki_pages RENAME TO fichiers_wiki_pages_old; ALTER TABLE fichiers_acc_transactions RENAME TO fichiers_acc_transactions_old; .read 1.0.0_schema.sql INSERT INTO fichiers_membres SELECT * FROM fichiers_membres_old; INSERT INTO fichiers_wiki_pages SELECT * FROM fichiers_wiki_pages_old; INSERT INTO fichiers_acc_transactions SELECT * FROM fichiers_acc_transactions_old; DROP TABLE fichiers_membres_old; DROP TABLE fichiers_wiki_pages_old; DROP TABLE fichiers_acc_transactions_old; |
Added src/include/data/1.0.0-beta8_migration.sql version [ff1b70a076].
> > | 1 2 | UPDATE acc_accounts SET type = 11 WHERE code = '120'; UPDATE acc_accounts SET type = 12 WHERE code = '129'; |
Added src/include/data/1.0.0-rc3_migration.sql version [46b4d521e5].
> | 1 | UPDATE acc_transactions SET type = 0 WHERE type = 6; |
Added src/include/data/1.0.0_migration.sql version [ba81ccc806].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 | 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 -- Fix: comptes de clôture et fermeture UPDATE compta_comptes SET libelle = 'Bilan d''ouverture' WHERE id = '890' AND libelle = 'Bilan de clôture'; INSERT OR REPLACE INTO compta_comptes (id, parent, libelle, position) VALUES ('891', '89', 'Bilan de clôture', 0); -- N'est pas utilisé DELETE FROM config WHERE cle = 'categorie_dons' OR cle = 'categorie_cotisations'; .read 1.0.0_schema.sql -------- MIGRATION COMPTA --------- INSERT INTO acc_charts (id, country, code, label) VALUES (1, 'FR', 'PCGA1999', 'Plan comptable associatif 1999'); -- Migration comptes de code comme identifiant à ID unique -- Inversement valeurs actif/passif et produit/charge INSERT INTO acc_accounts (id, id_chart, code, label, position, user) SELECT NULL, 1, id, libelle, CASE position WHEN 1 THEN 2 WHEN 2 THEN 1 WHEN 3 THEN 3 WHEN 4 THEN 5 WHEN 8 THEN 4 -- Suppression de la position "charge ou produit" qui n'a aucun sens WHEN 12 THEN 0 ELSE 0 END, CASE WHEN plan_comptable = 1 THEN 0 ELSE 1 END FROM compta_comptes; -- Migrations projets vers comptes analytiques INSERT INTO acc_accounts (id_chart, code, label, position, user, type) VALUES (1, '99', 'Projets', 0, 1, 0); INSERT INTO acc_accounts (id_chart, code, label, position, user, type) SELECT 1, '99' || substr('0000' || id, -4), libelle, 0, 1, 7 FROM compta_projets; -- Mise à jour de la position pour les comptes de tiers qui peuvent varier actif ou passif UPDATE acc_accounts SET position = 3 WHERE code IN (4010, 4110, 4210, 428, 438); -- Mise à jour position comptes bancaires, qui peuvent être à découvert et donc changer de côté au bilan UPDATE acc_accounts SET position = 3 WHERE code LIKE '512%'; -- Migration comptes bancaires UPDATE acc_accounts SET type = 1 WHERE code IN (SELECT id FROM compta_comptes_bancaires); -- Caisse UPDATE acc_accounts SET type = 2 WHERE code = '530'; -- Chèques et carte à encaisser UPDATE acc_accounts SET type = 3 WHERE code = '5112' OR code = '5113'; -- Comptes d'ouverture et de clôture UPDATE acc_accounts SET type = 9, position = 0 WHERE code = '890'; UPDATE acc_accounts SET type = 10, position = 0 WHERE code = '891'; -- Comptes de tiers UPDATE acc_accounts SET type = 4 WHERE code IN (SELECT id FROM compta_comptes WHERE id LIKE '4%' AND plan_comptable = 0 AND desactive = 0); -- Recopie des mouvements INSERT INTO acc_transactions (id, label, notes, reference, date, id_year, id_creator) SELECT id, libelle, remarques, numero_piece, date, id_exercice, id_auteur FROM compta_journal; -- Recettes UPDATE acc_transactions SET type = 1 WHERE id IN (SELECT id FROM compta_journal WHERE id_categorie IN (SELECT id FROM compta_categories WHERE type = 1)); -- Dépenses UPDATE acc_transactions SET type = 2 WHERE id IN (SELECT id FROM compta_journal WHERE id_categorie IN (SELECT id FROM compta_categories WHERE type = -1)); -- Virements UPDATE acc_transactions SET type = 3 WHERE id IN (SELECT id FROM compta_journal WHERE (compte_credit IN ('530', '5112', '5115') OR compte_credit LIKE '512%') AND (compte_debit IN ('530', '5112', '5115') OR compte_debit LIKE '512%')); -- Dettes UPDATE acc_transactions SET type = 4 WHERE id IN (SELECT id FROM compta_journal WHERE compte_debit LIKE '6%' AND compte_credit LIKE '4%'); -- Créances UPDATE acc_transactions SET type = 5 WHERE id IN (SELECT id FROM compta_journal WHERE compte_credit LIKE '7%' AND compte_debit LIKE '4%'); -- Création des lignes associées aux mouvements INSERT INTO acc_transactions_lines (id_transaction, id_account, debit, credit, reference, id_analytical) SELECT id, (SELECT id FROM acc_accounts WHERE code = compte_credit), 0, CAST(REPLACE(montant * 100, '.0', '') AS INT), numero_cheque, CASE WHEN id_projet IS NOT NULL THEN (SELECT id FROM acc_accounts WHERE code = '99' || substr('0000' || id_projet, -4)) ELSE NULL END FROM compta_journal; INSERT INTO acc_transactions_lines (id_transaction, id_account, debit, credit, reference, id_analytical) SELECT id, (SELECT id FROM acc_accounts WHERE code = compte_debit), CAST(REPLACE(montant * 100, '.0', '') AS INT), 0, numero_cheque, CASE WHEN id_projet IS NOT NULL THEN (SELECT id FROM acc_accounts WHERE code = '99' || substr('0000' || id_projet, -4)) ELSE NULL END FROM compta_journal; -- Recopie des descriptions de catégories dans la table des comptes, et mise des comptes en signets -- +Fix éventuels types qui ne correspondent pas à leur type… (@Fred C.) (... a.position = X) -- Revenus UPDATE acc_accounts SET type = 6, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code) WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = 1 AND a.position = 5); -- Dépenses UPDATE acc_accounts SET type = 5, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code) WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = -1 AND c.compte NOT LIKE '4%' AND a.position = 4); -- Tiers UPDATE acc_accounts SET type = 4, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code) WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = -1 AND c.compte LIKE '4%'); -- Recopie des opérations, mais le nom a changé pour acc_transactions_users INSERT INTO acc_transactions_users SELECT * FROM membres_operations_old; -- Recopie des exercices, mais la date de fin ne peut être nulle INSERT INTO acc_years (id, label, start_date, end_date, closed, id_chart) SELECT id, libelle, debut, CASE WHEN fin IS NULL THEN date(debut, '+1 year') ELSE fin END, cloture, 1 FROM compta_exercices; -- Recopie des catégories, on supprime la colonne id_cotisation_obligatoire INSERT INTO membres_categories SELECT id, nom, droit_wiki, droit_membres, droit_compta, droit_inscription, droit_connexion, droit_config, cacher FROM membres_categories_old; DROP TABLE membres_categories_old; -- Transfert des rapprochements UPDATE acc_transactions_lines SET reconciled = 1 WHERE id_transaction IN (SELECT id_operation FROM compta_rapprochement); --------- MIGRATION COTISATIONS ---------- -- A edge-case where the end date is after the start date, let's fix it… UPDATE cotisations SET fin = debut WHERE fin < debut; INSERT INTO services SELECT id, intitule, description, duree, debut, fin FROM cotisations; INSERT INTO services_fees (id, label, amount, id_service, id_account, id_year) SELECT id, intitule, CASE WHEN montant IS NOT NULL THEN CAST(montant*100 AS integer) ELSE NULL END, id, (SELECT id FROM acc_accounts WHERE code = (SELECT compte FROM compta_categories WHERE id = id_categorie_compta)), (SELECT MAX(id) FROM acc_years WHERE closed = 0) FROM cotisations; INSERT INTO services_users SELECT cm.id, cm.id_membre, cm.id_cotisation, cm.id_cotisation, 1, NULL, cm.date, CASE WHEN c.duree IS NOT NULL THEN date(cm.date, '+'||c.duree||' days') WHEN c.fin IS NOT NULL THEN c.fin ELSE NULL END FROM cotisations_membres cm INNER JOIN cotisations c ON c.id = cm.id_cotisation; INSERT INTO services_reminders SELECT * FROM rappels; INSERT INTO services_reminders_sent SELECT id, id_membre, id_cotisation, CASE WHEN id_rappel IS NULL THEN (SELECT MAX(id) FROM rappels) ELSE id_rappel END, date FROM rappels_envoyes WHERE id_rappel IS NOT NULL GROUP BY id_membre, id_cotisation, id_rappel; DROP TABLE cotisations; DROP TABLE cotisations_membres; DROP TABLE rappels; DROP TABLE rappels_envoyes; -- Suppression inutilisées DROP TABLE compta_rapprochement; DROP TABLE compta_journal; DROP TABLE compta_categories; DROP TABLE compta_comptes; DROP TABLE compta_exercices; DROP TABLE membres_operations_old; DROP TABLE compta_projets; DROP TABLE compta_comptes_bancaires; DROP TABLE compta_moyens_paiement; |
Modified src/include/data/1.0.0_schema.sql from [c8df01c2dd] to [2cb870482b].
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 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 120 121 | 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, droit_membres INTEGER NOT NULL DEFAULT 1, droit_compta INTEGER NOT NULL DEFAULT 1, droit_inscription INTEGER NOT NULL DEFAULT 0, droit_connexion INTEGER NOT NULL DEFAULT 1, droit_config INTEGER NOT NULL DEFAULT 0, cacher INTEGER NOT NULL DEFAULT 0 ); -- Membres de l'asso -- Table dynamique générée par l'application -- voir Garradin\Membres\Champs.php CREATE TABLE IF NOT EXISTS membres_sessions -- Sessions ( selecteur TEXT NOT NULL, hash TEXT NOT NULL, id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, expire INT NOT NULL, PRIMARY KEY (selecteur, id_membre) ); CREATE TABLE IF NOT EXISTS services -- Types de services (cotisations) ( id INTEGER PRIMARY KEY NOT NULL, label TEXT NOT NULL, description TEXT NULL, duration INTEGER NULL CHECK (duration IS NULL OR duration > 0), -- En jours start_date TEXT NULL CHECK (start_date IS NULL OR date(start_date) = start_date), end_date TEXT NULL CHECK (end_date IS NULL OR (date(end_date) = end_date AND date(end_date) >= date(start_date))) ); CREATE TABLE IF NOT EXISTS services_fees ( id INTEGER PRIMARY KEY NOT NULL, label TEXT NOT NULL, 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 si le type n'est pas associé automatiquement à la compta id_year INTEGER NULL REFERENCES acc_years (id) ON DELETE SET NULL -- NULL si le type n'est pas associé automatiquement à la compta ); 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, id_service INTEGER NOT NULL REFERENCES services (id) ON DELETE CASCADE, id_fee INTEGER NULL REFERENCES services_fees (id) ON DELETE CASCADE, paid INTEGER NOT NULL DEFAULT 0, expected_amount INTEGER NULL, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date), expiry_date TEXT NULL CHECK (date(expiry_date) IS NULL OR date(expiry_date) = expiry_date) ); CREATE UNIQUE INDEX IF NOT EXISTS su_unique ON services_users (id_user, id_service, date); CREATE INDEX IF NOT EXISTS su_service ON services_users (id_service); CREATE INDEX IF NOT EXISTS su_fee ON services_users (id_fee); CREATE INDEX IF NOT EXISTS su_paid ON services_users (paid); CREATE INDEX IF NOT EXISTS su_expiry ON services_users (expiry_date); CREATE TABLE IF NOT EXISTS services_reminders -- Rappels de devoir renouveller une cotisation ( id INTEGER NOT NULL PRIMARY KEY, id_service INTEGER NOT NULL REFERENCES services (id) ON DELETE CASCADE, delay INTEGER NOT NULL, -- Délai en jours pour envoyer le rappel subject TEXT NOT NULL, body TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS services_reminders_sent -- Enregistrement des rappels envoyés à qui et quand ( id INTEGER NOT NULL PRIMARY KEY, id_user INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_service INTEGER NOT NULL REFERENCES services (id) ON DELETE CASCADE, id_reminder INTEGER NOT NULL REFERENCES services_reminders (id) ON DELETE CASCADE, date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date) ); CREATE UNIQUE INDEX IF NOT EXISTS srs_index ON services_reminders_sent (id_user, id_service, id_reminder, date); CREATE INDEX IF NOT EXISTS srs_reminder ON services_reminders_sent (id_reminder); CREATE INDEX IF NOT EXISTS srs_user ON services_reminders_sent (id_user); -- -- WIKI -- CREATE TABLE IF NOT EXISTS wiki_pages -- Pages du wiki |
︙ | ︙ | |||
170 171 172 173 174 175 176 | -- Si le contenu est chiffré, la recherche n'affiche pas de contenu CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_chiffre AFTER INSERT ON wiki_revisions WHEN new.chiffrement = 1 BEGIN UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; | > > > | | < > | > > | > > > > > | > > | > > | > > > < < < < > > > | | | | | > > > | | < < | < < | | < < < < < < < < | < | | < < > < < > | | > | > > > | < < < | < < < | < > | | < | > | > | < | < | | > | | | | | | > | | < | | | | < < | < < < < < < < | < < | | < | < < < | < < | 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | -- Si le contenu est chiffré, la recherche n'affiche pas de contenu CREATE TRIGGER IF NOT EXISTS wiki_recherche_contenu_chiffre AFTER INSERT ON wiki_revisions WHEN new.chiffrement = 1 BEGIN UPDATE wiki_recherche SET contenu = '' WHERE id = new.id_page; END; -- -- COMPTA -- CREATE TABLE IF NOT EXISTS acc_charts -- 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, archived INTEGER NOT NULL DEFAULT 0 -- 1 = archivé, non-modifiable ); CREATE TABLE IF NOT EXISTS acc_accounts -- Comptes des plans comptables ( id INTEGER NOT NULL PRIMARY KEY, id_chart INTEGER NOT NULL REFERENCES acc_charts ON DELETE CASCADE, code TEXT NOT NULL, -- peut contenir des lettres, eg. 53A, 53B, etc. label TEXT NOT NULL, description TEXT NULL, position INTEGER NOT NULL, -- position actif/passif/charge/produit type INTEGER NOT NULL DEFAULT 0, -- Type de compte spécial : banque, caisse, en attente d'encaissement, etc. 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_chart); CREATE INDEX IF NOT EXISTS acc_accounts_type ON acc_accounts (type); CREATE INDEX IF NOT EXISTS acc_accounts_position ON acc_accounts (position); 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(start_date) IS NOT NULL AND date(start_date) = start_date), end_date TEXT NOT NULL CHECK (date(end_date) IS NOT NULL AND date(end_date) = end_date), closed INTEGER NOT NULL DEFAULT 0, id_chart INTEGER NOT NULL REFERENCES acc_charts (id) ); CREATE INDEX IF NOT EXISTS acc_years_closed ON acc_years (closed); CREATE TABLE IF NOT EXISTS acc_transactions -- Opérations comptables ( id INTEGER PRIMARY KEY NOT NULL, type INTEGER NOT NULL DEFAULT 0, -- Type d'écriture, 0 = avancée (normale) status INTEGER NOT NULL DEFAULT 0, -- Statut (bitmask) 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_creator INTEGER NULL REFERENCES membres(id) ON DELETE SET NULL, id_related INTEGER NULL REFERENCES acc_transactions(id) ON DELETE SET NULL -- écriture liée (par ex. remboursement d'une dette) ); 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 INDEX IF NOT EXISTS acc_transactions_related ON acc_transactions (id_related); CREATE INDEX IF NOT EXISTS acc_transactions_type ON acc_transactions (type); CREATE INDEX IF NOT EXISTS acc_transactions_status ON acc_transactions (status); 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, reference TEXT NULL, -- Référence de paiement, eg. numéro de chèque label TEXT NULL, reconciled INTEGER NOT NULL DEFAULT 0, id_analytical INTEGER NULL REFERENCES acc_accounts(id) ON DELETE SET NULL, 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 INDEX IF NOT EXISTS acc_transactions_lines_analytical ON acc_transactions_lines (id_analytical); CREATE INDEX IF NOT EXISTS acc_transactions_lines_reconciled ON acc_transactions_lines (reconciled); CREATE TABLE IF NOT EXISTS acc_transactions_users -- Liaison des écritures et des membres ( id_user INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, id_transaction INTEGER NOT NULL REFERENCES acc_transactions (id) ON DELETE CASCADE, id_service_user INTEGER NULL REFERENCES services_users (id) ON DELETE SET NULL, PRIMARY KEY (id_user, id_transaction) ); CREATE INDEX IF NOT EXISTS acc_transactions_users_service ON acc_transactions_users (id_service_user); CREATE TABLE IF NOT EXISTS plugins ( id TEXT NOT NULL PRIMARY KEY, officiel INTEGER NOT NULL DEFAULT 0, nom TEXT NOT NULL, description TEXT NULL, |
︙ | ︙ | |||
327 328 329 330 331 332 333 | ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); | < < < < < < < < | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE IF NOT EXISTS fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue |
︙ | ︙ | |||
362 363 364 365 366 367 368 | ); CREATE UNIQUE INDEX IF NOT EXISTS fichiers_hash ON fichiers_contenu (hash); CREATE TABLE IF NOT EXISTS fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( | | | | | | | | | | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | ); CREATE UNIQUE INDEX IF NOT EXISTS fichiers_hash ON fichiers_contenu (hash); CREATE TABLE IF NOT EXISTS fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id) ON DELETE CASCADE, id INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE, PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS fichiers_wiki_pages -- Associations entre fichiers et pages du wiki ( fichier INTEGER NOT NULL REFERENCES fichiers (id) ON DELETE CASCADE, id INTEGER NOT NULL REFERENCES wiki_pages (id) ON DELETE CASCADE, 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) ON DELETE CASCADE, id INTEGER NOT NULL REFERENCES acc_transactions (id) ON DELETE CASCADE, PRIMARY KEY(fichier, id) ); CREATE TABLE IF NOT EXISTS recherches -- Recherches enregistrées ( id INTEGER NOT NULL PRIMARY KEY, id_membre INTEGER NULL REFERENCES membres (id) ON DELETE CASCADE, -- Si non NULL, alors la recherche ne sera visible que par le membre associé intitule TEXT NOT NULL, creation TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK (datetime(creation) IS NOT NULL AND datetime(creation) = creation), cible TEXT NOT NULL, -- "membres" ou "compta" type TEXT NOT NULL, -- "json" ou "sql" contenu TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS compromised_passwords_cache -- Cache des hash de mots de passe compromis |
︙ | ︙ |
Deleted src/include/data/categories_comptables.sql version [7430a75c4a].
|
| < < < < < < < < < < < < < < < < < < < < < < < |
Added src/include/data/charts/fr_1999.csv version [38d9f67e8d].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 | code,label,description,position,type 1,"Classe 1 — Comptes de capitaux (Fonds propres, emprunts et dettes assimilés)",,Passif, 10,FONDS ASSOCIATIFS ET RÉSERVES,,Passif, 102,Fonds associatif sans droit de reprise,,Passif, 1021,Valeur du patrimoine intégré,,Passif, 1022,Fonds statutaire,,Passif, 1024,Apports sans droit de reprise,,Passif, 103,Fonds associatif avec droit de reprise,,Passif, 1034,Apports avec droit de reprise,,Passif, 105,Écarts de réévaluation,,Passif, 106,Réserves,,Passif, 1063,Réserves statutaires ou contractuelles,,Passif, 1064,Réserves réglementées,,Passif, 1068,Autres réserves (dont réserves pour projet associatif),,Passif, 11,REPORT À NOUVEAU,,Passif, 110,Report à nouveau (Solde créditeur),,Passif, 119,Report à nouveau (Solde débiteur),,Passif, 12,RÉSULTAT NET DE L'EXERCICE,,Passif, 120,Résultat de l'exercice (excédent),,Passif,Résultat excédentaire 129,Résultat de l'exercice (déficit),,Passif,Résultat déficitaire 13,SUBVENTIONS D'INVESTISSEMENT AFFECTÉES A DES BIENS NON RENOUVELABLES,,Passif, 131,Subventions d'investissement (renouvelables),,Passif, 139,Subventions d'investissement inscrites au compte de résultat,,Passif, 14,PROVISIONS REGLEMENTÉES,,Passif, 15,PROVISIONS,,Passif, 151,Provisions pour risques,,Passif, 157,Provisions pour charges à répartir sur plusieurs exercices,,Passif, 158,Autres provisions pour charges,,Passif, 16,EMPRUNTS ET DETTES ASSIMILÉES,,Passif, 164,Emprunts auprès des établissements de crédits,,Passif, 165,Dépôts et cautionnements reçus,,Passif, 167,Emprunts et dettes assorties de conditions particulières,,Passif, 168,Autres emprunts et dettes assimilés,,Passif, 17,DETTES RATTACHÉES À DES PARTICIPATIONS,,Passif, 18,COMPTES DE LIAISON DES ÉTABLISSEMENTS,,Passif, 181,Apports permanents entre siège social et établissements,,Passif, 185,Biens et prestations de services échangés entre établissements et siège social,,Passif, 186,Biens et prestations de services échangés entre établissements (charges),,Passif, 187,Biens et prestations de services échangés entre établissements (produits),,Passif, 19,FONDS DÉDIÉS,,Passif, 194,Fonds dédiés sur subventions de fonctionnement,,Passif, 195,Fonds dédiés sur dons manuels affectés,,Passif, 197,Fonds dédiés sur legs et donations affectés,,Passif, 198,Excédent disponible après affectation au projet associatif,,Passif, 199,Reprise des fonds affectés au projet associatif,,Passif, 2,Classe 2 — Comptes d'immobilisations,,Actif, 20,IMMOBILISATIONS INCORPORELLES,,Actif, 200,Immobilisations incorporelles,,Actif, 21,IMMOBILISATIONS CORPORELLES,,Actif, 210,Investissements,,Actif, 22,IMMOBILISATIONS GREVÉES DE DROITS,,Actif, 228,Immobilisations grevées de droits,,Actif, 229,Droits des propriétaires,,Actif, 23,IMMOBILISATIONS EN COURS,,Actif, 231,Immobilisations corporelles en cours,,Actif, 238,Avances et acomptes versés sur commande d'immobilisations corporelles,,Actif, 26,PARTICIPATIONS ET CRÉANCES RATTACHÉES A DES PARTICIPATIONS,,Actif, 261,Titres de participation,,Actif, 27,AUTRES IMMOBILISATIONS FINANCIÈRES,,Actif, 270,Participations financières,,Actif, 275,Dépôts et cautionnements versés,,Actif, 28,AMORTISSEMENTS DES IMMOBILISATIONS,,Actif, 280,Amortissements des immobilisations incorporelles,,Actif, 281,Amortissements des immobilisations corporelles,,Actif, 29,DÉPRÉCIATION DES IMMOBILISATIONS,,Actif, 290,Dépréciation des immobilisations incorporelles,,Actif, 291,Dépréciation des immobilisations corporelles,,Actif, 3,Classe 3 — Comptes de stocks,,Actif, 31,MATIERES PREMIERES ET FOURNITURES,,Actif, 311,Matières,,Actif, 317,Fournitures,,Actif, 32,AUTRES APPROVISIONNEMENTS,,Actif, 321,Matières consommables,,Actif, 322,Fournitures consommables,,Actif, 33,EN-COURS DE PRODUCTION DE BIENS,,Actif, 331,Produits en cours,,Actif, 335,Travaux en cours,,Actif, 34,EN-COURS DE PRODUCTION DE SERVICES,,Actif, 35,STOCKS DE PRODUITS,,Actif, 351,Produits intermédiaires,,Actif, 355,Produits finis,,Actif, 358,Produits résiduels,,Actif, 3581,Déchets,,Actif, 3585,Rebuts,,Actif, 3586,Matière de récupération,,Actif, 37,STOCKS DE MARCHANDISES,,Actif, 370,Autres stocks de marchandises,,Actif, 39,PROVISIONS POUR DEPRECIATION DES STOCKS ET EN-COURS,,Actif, 391,Provisions pour dépréciation des matières premières et fournitures,,Actif, 4,Classe 4 — Comptes de tiers,,Actif ou passif, 40,FOURNISSEURS ET COMPTES RATTACHÉS,,Passif, 401,Fournisseurs,,Passif, 4010,Autres fournisseurs,,Actif ou passif,Tiers 408,Fournisseurs - Factures non parvenues,,Passif, 409,Avances aux fournisseurs,,Actif, 41,USAGERS ET COMPTES RATTACHÉS,,Actif, 411,Usagers,,Actif, 4110,Autres usagers,,Actif ou passif,Tiers 419,Avances aux usagers,,Passif, 42,PERSONNEL ET COMPTES RATTACHÉS,,Passif, 421,Personnel - Rémunérations dues,,Passif, 4210,Autres membres du personnel,,Actif ou passif, 425,Personnel - Avances et acomptes,,Actif, 428,Personnel - Charges à payer et produits à recevoir,,Actif ou passif, 43,SÉCURITÉ SOCIALE ET AUTRES ORGANISMES SOCIAUX,,Passif, 430,Dettes et crédits envers les organismes sociaux,,Passif, 431,Sécurité sociale,,Passif, 437,Autres organismes sociaux,,Passif, 4372,Mutuelles,,Passif, 4373,Caisse de retraite et de prévoyance,,Passif, 4374,Caisse d'allocations de chômage - Pôle emploi,,Passif, 4375,AGESSA,,Passif, 4378,Autres organismes sociaux - Divers,,Passif, 438,Organismes sociaux - Charges à payer et produits à recevoir,,Actif ou passif, 4382,Charges sociales sur congés à payer,,Passif, 4386,Autres charges à payer,,Passif, 4387,Produits à recevoir,,Actif, 439,Avances auprès des organismes sociaux,,Passif, 44,ÉTAT ET AUTRES COLLECTIVITÉS PUBLIQUES,,Actif, 441,État - Subventions à recevoir,,Actif, 4411,Subventions d'investissement,,Actif, 4417,Subventions d'exploitation,,Actif, 4418,Subventions d'équilibre,,Actif, 4419,Avances sur subventions,,Actif, 442,État - Impôts et taxes recouvrables sur des tiers,,Passif, 444,État - Impôts sur les bénéfices,,Actif, 445,État - Taxes sur le chiffre d'affaires,,Actif, 4455,Taxes sur le chiffre d'affaires à décaisser,,Actif, 44551,TVA à décaisser,,Actif, 44558,Taxes assimilées à la TVA,,Actif, 4456,Taxes sur le chiffre d'affaires déductibles,,Actif, 44562,TVA sur immobilisations,,Actif, 44566,TVA sur autres biens et services,,Actif, 4457,Taxes sur le chiffre d'affaires collectées par l'association,,Actif, 4458,Taxes sur le chiffre d'affaires à régulariser ou en attente,,Actif, 44581,Acomptes - Régime simplifié d'imposition,,Actif, 44582,Acomptes - Régime du forfait,,Actif, 44583,Remboursement de taxes sur le chiffre d'affaires demandé,,Actif, 44584,TVA récupérée d'avance,,Actif, 44586,Taxes sur le chiffre d'affaires sur factures non parvenues,,Actif, 44587,Taxes sur le chiffre d'affaires sur factures à établir,,Actif, 447,"Autres impôts, taxes et versements assimilés",,Passif, 4471,"Autres impôts, taxes et versements assimilés sur rémunérations (Administration des impôts)",,Passif, 44711,Taxe sur les salaires,,Passif, 44713,Participation des employeurs à la formation professionnelle continue,,Passif, 44714,Cotisation par défaut d'investissement obligatoire dans la construction,,Passif, 44718,"Autres impôts, taxes et versements assimilés",,Passif, 4473,"Autres impôts, taxes et versements assimilés sur rémunérations (Autres organismes)",,Passif, 44733,Participation des employeurs à la formation professionnelle continue,,Passif, 44734,Participation des employeurs à l'effort de construction (versements à fonds perdus),,Passif, 4475,"Autres impôts, taxes et versements assimilés (Administration des impôts)",,Passif, 4477,"Autres impôts, taxes et versements assimilés (Autres organismes)",,Passif, 448,État - Charges à payer et produits à recevoir,,Passif, 4482,Charges fiscales sur congés à payer,,Passif, 4486,Autres charges à payer,,Passif, 4487,Produits à recevoir,,Actif, 449,Avances auprès de l'état et des collectivités publiques,,Passif, 45,"CONFÉDÉRATION, FÉDÉRATION, UNIONS ET ASSOCIATIONS AFFILIÉES",,Actif ou passif, 451,"Confédération, fédération et associations affiliées - Compte courant",,Actif ou passif, 455,Sociétaires - Comptes courants,,Actif ou passif, 46,DÉBITEURS DIVERS ET CRÉDITEURS DIVERS,,Actif ou passif, 467,Autres comptes débiteurs et créditeurs,,Actif ou passif, 468,Divers - Charges à payer et produits à recevoir,,Actif ou passif, 4686,Charges à payer,,Passif, 4687,Produits à recevoir,,Actif, 47,COMPTES TRANSITOIRES OU D'ATTENTE,,Actif ou passif, 471,Recettes à classer,,Passif, 472,Dépenses à classer et à régulariser,,Actif, 48,COMPTES DE RÉGULARISATION,,Actif ou passif, 481,Charges à répartir sur plusieurs exercices,,Actif, 486,Charges constatées d'avance,,Actif, 487,Produits constatés d'avance,,Passif, 49,DEPRECIATION DES COMPTES DE TIERS,,Actif, 491,Dépréciation des comptes clients,,Actif, 496,Dépréciation des comptes débiteurs divers,,Actif, 5,Classe 5 — Comptes financiers,,Actif, 50,VALEURS MOBILIÈRES DE PLACEMENT,,Actif, 51,"BANQUES, ÉTABLISSEMENTS FINANCIERS ET ASSIMILÉS",,Actif, 511,Valeurs à l'encaissement,,Actif, 5112,Chèques à encaisser,,Actif,Attente d'encaissement 5115,Paiements par carte à encaisser,,Actif, 512,Banques,,Actif ou passif, 53,CAISSE,,Actif, 530,Caisse,,Actif,Caisse 54,RÉGIES D'AVANCES ET ACCRÉDITIFS,,Actif, 58,VIREMENTS INTERNES,,Actif, 59,PROVISIONS POUR DÉPRÉCIATION DES COMPTES FINANCIERS,,Actif, 6,Classe 6 — Comptes de charges,,Charge, 60,ACHATS,,Charge, 601,Achats stockés - Matières premières et fournitures,,Charge, 602,Achats stockés - Autres approvisionnements,,Charge, 604,Achat d'études et prestations de services,,Charge,Dépenses 606,Achats non stockés de matières et fournitures,,Charge, 6061,"Fournitures non stockables (eau, énergie...)","Facture d'eau, d'opérateur électrique, etc.",Charge,Dépenses 6063,Fournitures d'entretien et de petit équipement,,Charge,Dépenses 6064,Fournitures administratives,"Cartouches d'encre, papier, matériel bureautique, etc.",Charge,Dépenses 6068,Autres matières et fournitures,,Charge,Dépenses 607,Achats de marchandises,Marchandises destinées à être revendues en l'état.,Charge,Dépenses 61,SERVICES EXTÉRIEURS,,Charge, 611,Sous-traitance générale,,Charge, 612,Redevances de crédit-bail,,Charge, 613,Locations,Locations versées pour un local ou du matériel.,Charge,Dépenses 614,Charges locatives et de co-propriété,,Charge, 615,Entretiens et réparations,,Charge, 616,Primes d'assurance,,Charge,Dépenses 618,Divers,,Charge, 62,AUTRES SERVICES EXTÉRIEURS,,Charge, 621,Personnel extérieur à l'association,,Charge, 62141,Mises à disposition de personnel salarié,,Charge,Dépenses 622,Rémunérations d'intermédiaires et honoraires,,Charge, 6226,Honoraires,,Charge, 6227,Frais d'actes et de contentieux,"Insertion au Journal Officiel, frais de justice, etc.",Charge,Dépenses 6228,Divers,,Charge, 623,"Publicité, publications, relations publiques","Bulletins, affiches, communication, etc.",Charge,Dépenses 624,Transports de biens et transports collectifs du personnel,,Charge, 625,"Déplacements, missions et réceptions","Billet SNCF, remboursement de frais kilométrique, etc.",Charge,Dépenses 626,Frais postaux et de télécommunications,"Facture d'accès à Internet, timbres, etc.",Charge,Dépenses 627,Services bancaires et assimilés,Frais bancaires,Charge,Dépenses 628,Divers,,Charge,Dépenses 63,"IMPÔTS, TAXES ET VERSEMENTS ASSIMILÉS",,Charge, 631,"Impôts, taxes et versements assimilés sur rémunérations (Administration des impôts)",,Charge, 6311,Taxes sur les salaires,,Charge, 6313,Participations des employeurs à la formation professionnelle continue,,Charge, 635,"Autres impôts, taxes et versements assimilés (Administration des impôts)",,Charge, 6351,Impôts directs (sauf impôts sur les bénéfices),,Charge, 6353,Impôts indirects,,Charge, 637,"Autres impôts, taxes et versements assimilés (Autres organismes)",,Charge, 64,CHARGES DE PERSONNEL,,Charge, 641,Rémunérations du personnel,,Charge, 643,Rémunérations du personnel artistique et assimilés,,Charge, 645,Charges de sécurité sociale et de prévoyance,,Charge, 647,Autres charges sociales,,Charge, 648,Autres charges de personnel,,Charge, 65,AUTRES CHARGES DE GESTION COURANTE,,Charge, 652,Licences fédérales,Licences payées pour les adhérents (par exemple fédération sportive etc.),Charge,Dépenses 658,Charges diverses de gestion courante,,Charge,Dépenses 66,CHARGES FINANCIÈRES,,Charge, 661,Charges d'intérêts,,Charge, 67,CHARGES EXCEPTIONNELLES,,Charge, 670,Charges exceptionnelles,Autres dépenses exceptionnelles,Charge,Dépenses 671,Charges exceptionnelles sur opérations de gestion,,Charge, 6713,"Dons, libéralités",,Charge, 678,Autres charges exceptionnelles,,Charge, 6788,Charges exceptionnelles diverses,,Charge, 68,"DOTATIONS AUX AMORTISSEMENTS, DÉPRÉCIATIONS, PROVISIONS ET ENGAGEMENTS",,Charge, 681,"Dotations aux amortissements, dépréciations et provisions - Charges d'exploitation",,Charge, 6811,Dotations aux amortissements des immobilisations incorporelles et corporelles,,Charge, 68111,Immobilisations incorporelles,,Charge, 68112,Immobilisations corporelles,,Charge, 686,"Dotations aux amortissements, dépréciations et provisions - Charges financières",,Charge, 69,PARTICIPATION DES SALARIÉS - IMPÔTS SUR LES BÉNÉFICES ET ASSIMILÉS,,Charge, 695,Impôts sur les sociétés (y compris impôts sur les sociétés des personnes morales non lucratives),,Charge, 7,Classe 7 — Comptes de produits,,Produit, 70,"VENTES DE PRODUITS FINIS, PRESTATIONS DE SERVICES, MARCHANDISES",,Produit, 701,Ventes de produits finis,Vente de produits fabriqués par l'association.,Produit,Recettes 706,Prestations de services,,Produit,Recettes 707,Ventes de marchandises,,Produit,Recettes 708,Produits des activités annexes,,Produit, 71,PRODUCTION STOCKÉE (OU DÉSTOCKAGE),,Produit, 72,PRODUCTION IMMOBILISÉE,,Produit, 74,SUBVENTIONS D'EXPLOITATION,,Produit, 740,Subventions reçues,,Produit,Recettes 75,AUTRES PRODUITS DE GESTION COURANTE,,Produit, 754,Collectes,,Produit,Recettes 756,Cotisations,,Produit,Recettes 758,Produits divers de gestion courante,,Produit, 7587,Ventes de dons en nature,,Produit, 7588,Autres produits de la générosité du public,,Produit, 76,PRODUITS FINANCIERS,,Produit, 760,Produits financiers,,Produit, 77,PRODUITS EXCEPTIONNELS,,Produit, 771,Produits exceptionnels sur opérations de gestion,,Produit, 7713,Libéralités reçues,,Produit, 7715,Subventions d'équilibre,,Produit, 775,Produits des cessions d'éléments d'actifs,,Produit, 778,Autres produits exceptionnels,,Produit, 7780,Manifestations diverses,"Revenus provenant de manifestations au profit de l'association : droit d'entrée, location d'emplacement en vide grenier, ventes, etc.",Produit,Recettes 7788,Produits exceptionnels divers,,Produit, 78,REPRISES SUR AMORTISSEMENTS ET PROVISIONS,,Produit, 79,TRANSFERT DE CHARGES,,Produit, 791,Transferts de charges d'exploitation,,Produit, 796,Transferts de charges financières,,Produit, 797,Transferts de charges exceptionnels,,Produit, 8,Classe 8 — Comptes spéciaux,,, 86,RÉPARTITION PAR NATURE DE CHARGES,,Charge, 861,Mise à dispositions gratuites de biens,,Charge, 862,Prestations,,Charge, 864,Personnel bénévole,,Charge, 87,RÉPARTITION PAR NATURE DE RESSOURCES,,Produit, 870,Bénévolat,,Produit, 871,Prestations en nature,,Produit, 875,Dons en nature,,Produit, 89,BILAN,,, 890,Bilan d'ouverture,,,Ouverture 891,Bilan de clôture,,,Clôture 9,Classe 9 — Comptes analytiques,,, 99,Projets,,,Analytique |
Added src/include/data/charts/fr_2018.csv version [7724166e91].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | code,label,description,position,type 1,"Classe 1 — Comptes de capitaux (Fonds propres, emprunts et dettes assimilés)",,Passif, 10,FONDS ASSOCIATIFS ET RÉSERVES,,Passif, 102,Fonds associatifs sans droit de reprise,,Passif, 1021,Première situation nette établie,,Passif, 1022,Fonds statutaires,,Passif, 1023,Dotations non consomptibles,,Passif, 10231,Dotations non consomptibles initiales,,Passif, 10232,Dotations non consomptibles complémentaires,,Passif, 1024,Autres fonds propres sans droit de reprise,,Passif, 103,Fonds associatif avec droit de reprise,,Passif, 1032,Fonds statutaires,,Passif, 1034,Autres fonds propres avec droit de reprise,,Passif, 105,Ecarts de réévaluation,,Passif, 1051,Ecarts réévaluation sur biens sans dt reprise,,Passif, 1052,Ecarts réévaluation sur biens avec dt reprise,,Passif, 106,Réserves,,Passif, 1062,Réserves indisponibles,,Passif, 1063,Réserves statutaires,,Passif, 1064,Réserves réglementées,,Passif, 1068,Réserves pour projet de l’entité,,Passif, 108,Dotations consomptibles,,Passif, 1081,Dotations consomptibles,,Passif, 1089,Dot. consomptibles inscrites au cpte de résul,,Passif, 11,REPORT à NOUVEAU,,Passif, 110,Report à nouveau (Solde créditeur),,Passif, 119,Report à nouveau (Solde débiteur),,Passif, 12,RÉSULTAT NET DE L'EXERCICE,,Passif, 120,Résultat de l'exercice (excédent),,Passif,Résultat excédentaire 129,Résultat de l'exercice (déficit),,Passif,Résultat déficitaire 13,SUBVENTIONS D'INVESTISSEMENTS,,Passif, 131,Subventions d'équipement,,Passif, 139,Subventions inscrites au compte de résultat,,Passif, 14,PROVISIONS RÉGLEMENTÉES,,Passif, 148,Autres provisions réglementées,,Passif, 15,PROVISIONS POUR RISQUES ET CHARGES,,Passif, 151,Provisions pour risques,,Passif, 152,Provisions pour charges sur legs ou donations,,Passif, 153,Provisions pour pensions et obligations simil,,Passif, 155,Provisions pour impôts,,Passif, 157,Provisions pour charges à répartir,,Passif, 158,Autres provisions pour charges,,Passif, 16,EMPRUNTS ET DETTES ASSIMILÉES,,Passif, 163,Autres emprunts obligataires,,Passif, 1631,Titres associatifs et assimilés,,Passif, 164,Emprunts auprès des établissements de crédit,,Passif, 165,Dépôts et cautionnements reçus,,Passif, 1651,Dépôts,,Passif, 1655,Cautionnements,,Passif, 167,Emprunts et dettes sous conditions particulières,,Passif, 168,Autres emprunts et dettes assimilées,,Passif, 18,COMPTES DE LIAISONS,,Passif, 181,Apports permanents siège-établissements,,Passif, 185,Biens & PS échangés siège-établissements,,Passif, 186,Biens & PS entre établissements - Charges,,Passif, 187,Biens & PS entre établissements - Produits,,Passif, 19,FONDS DÉDIÉS OU REPORTÉS,,Passif, 191,Fonds reportés liés aux legs ou donations,,Passif, 1911,Legs ou donations,,Passif, 1912,Donations temporaires d’usufruit,,Passif, 194,Fonds dédiés sur subventions fonctionnement,,Passif, 195,F.d. / contributions financières autres org.,,Passif, 196,F.d. / ressources liées à la générosité,,Passif, 2,Classe 2 — Comptes d'immobilisations,,Actif, 20,IMMOBILISATIONS INCORPORELLES,,Actif, 201,Frais d'établissement,,Actif, 203,Frais de recherche et de développement,,Actif, 204,Donations temporaires d’usufruit,,Actif, 205,"Brevets, licences, marques...",,Actif, 206,Droit au bail,,Actif, 208,Autres immobilisations incorporelles,,Actif, 21,IMMOBILISATIONS CORPORELLES,,Actif, 211,Terrains,,Actif, 212,Agencements / aménagements de terrains,,Actif, 2131,Bâtiments,,Actif, 2135,"Installations, agencements...de constructions",,Actif, 214,Constructions sur sol d'autrui,,Actif, 215,"Installations techniques, matériel, outillage",,Actif, 2154,Matériel industriel,,Actif, 2155,Outillage industriel,,Actif, 218,Autres immobilisations corporelles,,Actif, 2181,"Installations, agencements, aménagem. divers",,Actif, 2182,Matériel de transport,,Actif, 2183,Matériel bureau et informatique,,Actif, 2184,Mobilier,,Actif, 23,IMMOBILISATIONS EN COURS,,Actif, 231,Immobilisations corporelles en cours,,Actif, 238,"Avances, acomptes sur immobilis. corporelles",,Actif, 24,BIEN DESTINÉS À ÊTRE CÉDÉS,,Actif, 240,Biens reçus par legs ou donations à céder,,Actif, 26,PARTICIPATIONS ET CRÉANCES RATTACHÉES,,Actif, 261,Titres de participation,,Actif, 266,Autres formes de participation,,Actif, 267,Créances rattachées à des participations,,Actif, 269,Versements restants sur participations,,Actif, 27,IMMOBILISATIONS FINANCIERES,,Actif, 271,Titres immobilisés (droit de propriété),,Actif, 272,Titres immobilisés (droit de créance),,Actif, 274,Prêts,,Actif, 2742,Prêts aux partenaires,,Actif, 275,Dépôts et cautionnements versés,,Actif, 276,Autres créances immobilisées,,Actif, 28,AMORTISSEMENTS DES IMMOBILISAT,,Actif, 2801,Amt. frais d'établissement,,Actif, 2804,Amt. donations temporaires d’usufruit,,Actif, 2805,"Amt brevets, licences, marques...",,Actif, 2806,Amt. droit au bail,,Actif, 2808,Amt. autres immo.incorporelles,,Actif, 2812,"Amt.agencements, aménagements de terrains",,Actif, 28131,Amortissements bâtiments,,Actif, 28135,"Amt. installations, agencements...",,Actif, 2814,Amt.constructions sur sol d'autrui,,Actif, 2815,"Amt instal. techniques, matériel, outillage",,Actif, 28181,"Amt. intallations, agencements, aménagements",,Actif, 28182,Amt. matériel de transport,,Actif, 28183,"Amortiss.matériel de bureau, informatique",,Actif, 28184,Amortissements du mobilier,,Actif, 29,DÉPRÉCIATIONS DES IMMOBILISATIONS,,Actif, 2904,Donations temporaires d'usufruit,,Actif, 2905,"Brevets, licences, marques...",,Actif, 2906,Droit au bail,,Actif, 2908,Autres immobilisations incorporelles,,Actif, 2911,Terrains,,Actif, 2931,Immobilisations corporelles en cours,,Actif, 294,Biens reçus par legs ou donations à céder,,Actif, 2961,Titres de participations,,Actif, 2966,Autres formes de participations,,Actif, 2967,Créances rattachées à des participations,,Actif, 2971,Titres immobilisés (droit de propriété),,Actif, 2972,Titres immobilisés (droit de créance),,Actif, 2974,Prêts,,Actif, 2975,Dépôts et cautionnements versés,,Actif, 2976,Autres créances immobilisées,,Actif, 3,Classe 3 — Comptes de stocks,,Actif, 31,MATIÈRES PREMIÈRES ET FOURNITURES,,Actif, 318,Matières premières et fournitures,,Actif, 32,AUTRES APPROVISIONNEMENTS,,Actif, 321,Matières consommables,,Actif, 322,Fournitures consommables,,Actif, 326,Emballages,,Actif, 33,EN-COURS DE PRODUCTION DE BIENS,,Actif, 331,Produits en cours,,Actif, 335,Travaux en cours,,Actif, 34,EN-COURS DE PROUCTION DE SERVICES,,Actif, 341,Etudes en cours,,Actif, 345,Prestations de services en cours,,Actif, 35,STOCKS DE PRODUITS,,Actif, 351,Produits intermédiaires,,Actif, 355,Produits finis,,Actif, 358,Produits résiduels,,Actif, 37,STOCKS DE MARCHANDISES,,Actif, 370,Stocks de marchandises,,Actif, 39,PROVISIONS PR DÉPRECIATIONS STOCKS & EN-COURS,,Actif, 391,Matières premières et fournitures,,Actif, 392,Autres approvisionnements,,Actif, 393,En-cours de production de biens,,Actif, 394,En-cours de production de services,,Actif, 395,Stocks de produits,,Actif, 397,Stocks de marchandises,,Actif, 4,Classe 4 — Comptes de tiers,,Actif ou passif, 40,FOURNISSEURS ET COMPTES RATTACHÉS,,Actif ou passif, 401,Fournisseurs,,Actif ou passif, 4010,Autres fournisseurs,,Actif ou passif,Tiers 403,Fournisseurs - Effets à payer,,Passif, 404,Fournisseurs d'immobilisations,,Actif ou passif, 405,Fournisseurs d'immos - Effets à payer,,Passif, 408,Fournisseurs - Factures non parvenues,,Passif, 4091,Fournisseurs - Avances & acomptes,,Actif, 41,USAGERS ET COMPTES RATTACHÉS,,Actif ou passif, 411,Usagers,,Actif ou passif, 4110,Autres usagers,Pour les dettes ou créances des membres,Actif ou passif,Tiers 413,Usagers - Effets à recevoir,,Actif, 416,Usagers douteux ou litigieux,,Actif, 418,Usagers non encore facturés,,Actif, 4191,Usagers créditeurs : Avances et acomptes,,Passif, 42,PERSONNEL ET COMPTES RATTACHÉS,,Actif ou passif, 421,Personnel : Rémunérations dues,,Passif, 4210,Autres membres du personnel,Dettes dûes aux salarié⋅e⋅s,Actif ou passif,Tiers 422,"Comités d'entreprise, d'établissement",,Actif ou passif, 425,Personnel : Avances & acomptes,,Actif, 427,Personnel - Oppositions,,Passif, 4286,Personnel- Charges à payer,,Passif, 4287,Personnel- Produits à recevoir,,Actif, 43,SÉCURITÉ SOCIALE & AUTRES ORGANISMES SOCIAUX,,Passif, 431,Sécurité sociale,,Passif, 4372,Mutuelles,,Passif, 4373,Caisses de retraites et de prévoyance,,Passif, 4378,Autres organismes sociaux,,Passif, 44,ETAT ET AUTRES COLLECTIVITÉS PUBLIQUES,,Actif, 441,Etat - Subventions à recevoir,,Actif, 4421,Prélèvements à la source- Impôt sur le revenu,,Actif ou passif, 444,Etat - Impôts sur les bénéfices,,Actif ou passif, 4452,TVA due intracommunautaire,,Actif ou passif, 4455,Taxes sur CA à décaisser,,Actif, 44562,TVA déductible sur immobilisations,,Actif, 44566,TVA déductible sur autres biens et services,,Actif, 44571,TVA normale collectée,,Actif, 445711,TVA réduite collectée,,Actif, 445712,TVA super-réduite collectée,,Actif, 445713,TVA intermédiaire collectée,,Actif, 4458,Taxe sur CA à régulariser ou en attente,,Actif, 447,"Autres impôts, taxes et versements assimilés",,Actif, 4486,Etat - Charges à payer,,Passif, 4487,Etat - Produits à recevoir,,Actif, 45,"CONFÉDÉRATION, FEDERATION, UNIONS...AFFILIÉES",,Actif ou passif, 451,"Confédération, fédération at assoc. affiliées",,Actif ou passif, 455,Partenaires - comptes courants,,Actif ou passif, 46,DEBITEURS DIVERS ET CREDIT.DVS,,Actif ou passif, 461,Créances reçues par legs ou donations,,Actif, 466,Dettes des legs ou donations,,Passif, 4671,Débiteurs divers,,Actif ou passif, 4672,Créditeurs divers,,Actif ou passif, 4681,Frais des bénévoles,,Actif ou passif, 4686,Divers - Charges à payer,,Passif, 4687,Divers - Produits à recevoir,,Actif, 47,COMPTES D'ATTENTE,,Actif ou passif, 4715,Compte de transit,,Actif ou passif, 4718,Compte d'attente,,Actif ou passif, 48,COMPTES DE REGULARISATION,,Actif ou passif, 481,Charges à répartir,,Passif, 486,Charges constatées d'avance,,Passif, 487,Produits constatés d'avance,,Actif, 49,DÉPRECIATIONS DES COMPTES DE TIERS,,Actif ou passif, 491,Prov. pour dépreciation des comptes d'usagers,,Passif, 496,Prov. pour dépreci. cptes débiteurs divers,,Passif, 5,Classe 5 — Comptes financiers,,Actif, 50,VALEURS MOBILIERES DE PLACEMENT,,Actif, 503,Actions,,Actif, 506,Obligations,,Actif, 508,Autres VMP et créances assimilées,,Actif, 51,"BANQUES, ETABLISSEMENTS FINANCIERS",,Actif, 5112,Chèques à encaisser,,Actif,Attente d'encaissement 5115,Paiements par carte à encaisser,,Actif, 512,Banques,,Actif ou passif, 5186,Intérêts courus à payer,,Passif, 5187,Intérêts courus à recevoir,,Actif, 53,Caisses,,Actif ou passif, 530,Caisse,,Actif,Caisse 58,VIREMENTS INTERNES,,Actif ou passif, 580,Virements internes,,Actif ou passif, 59,DEPRECIATIONS DES COMPTES FINANCIERS,,Actif ou passif, 5903,Actions,,Actif ou passif, 5906,Obligations,,Actif ou passif, 5908,Autres VMP et créances assimilées,,Actif ou passif, 6,Classe 6 — Comptes de charges,,Charge, 60,ACHATS (SAUF 603),,Charge, 601,Achats stockés - Matières premières et fournitures,,Charge, 6010,Achats stockés de matières et fournitures,,Charge, 6011,Achats stockés - Matières premières,,Charge, 6017,Achats stockés - Fournitures,,Charge, 602,Achats stockés - Autres approvisionnements,,Charge, 6021,Achats stockés - Matières consommables,,Charge, 60221,Achats stockés - Combustibles,,Charge, 60222,Achats stockés - Produits d'entretien,,Charge, 60223,Achats stockés - Fournitures d'atelier,,Charge, 60224,Achats stockés - Fournitures de magasin,,Charge, 60225,Fournitures de bureau,,Charge, 6026,Achats stockés - Emballages,,Charge, 603,Variations de stocks,,Charge, 6031,Variations de stocks matières & fournitures,,Charge, 6032,Variations stocks autres approvisionnements,,Charge, 6037,Variations de stocks de marchandises,,Charge, 604,Achats d'études et prestations de services,,Charge, 605,"Achats matériel, équipements & travaux",,Charge, 606,Achats non stockés de matières et fournitures,,Charge, 6061,"Fournitures non stockables (eau, énergie...)","Facture d'eau, d’électricité, etc.",Charge,Dépenses 60611,Eau,,Charge, 60612,Electricité,,Charge, 60613,Chauffage,,Charge, 6063,Fournitures d'entretien et petit équipement,"Vis, et matériel de bricolage (sauf outils) par exemple",Charge,Dépenses 6064,Fournitures administratives,"Cartouches d'encre, papier, matériel bureautique, etc.",Charge,Dépenses 6065,Petits logiciels,Par exemple contribution à un logiciel de gestion associative génial :-),Charge,Dépenses 6068,Autres fournitures & matières,,Charge,Dépenses 607,Achats de marchandises,Marchandises destinées à être revendues en l'état.,Charge,Dépenses 608,Frais accessoires d'achats,,Charge, 60811,Frais accessoires d'achats sur matières,,Charge, 60817,Frais accessoires d'achats sur fournitures,,Charge, 609,"Rabais, remises et ristournes sur achats",,Charge, 6091,RRR sur achats matières et fournitures,,Charge, 6092,RRR sur achats et autres approvisionnements,,Charge, 6097,RRR sur achats de marchandises,,Charge, 61,SERVICES EXTERIEURS,,Charge, 611,Sous-traitance générale,,Charge, 6122,Redevance crédit-bail mobilier,,Charge, 6125,Redevances crédit-bail immobilier,,Charge, 6132,Locations immobilières,Locations versées pour un local ou du matériel.,Charge,Dépenses 6135,Locations mobilières,,Charge, 6136,Malis sur emballages,,Charge, 614,Charges locatives et de copropriété,,Charge, 6152,Entretien sur biens immobiliers,,Charge, 6155,Entretien sur biens mobiliers,,Charge, 6156,Maintenance,,Charge, 616,Primes d'assurance,"Frais d’assurance local, activité, etc.",Charge,Dépenses 6161,Primes d'assurances mutirisques,,Charge, 6164,Primes d'assurances / risques d'exploitation,,Charge, 6165,Primes d'assurances / insolvabilité usagers,,Charge, 6168,Autres assurances,,Charge, 617,Etudes et recherches,,Charge, 6181,Documentation générale,,Charge, 6183,Documentation technique,,Charge, 6185,"Frais de colloques, séminaires, conférences",,Charge, 6187,Prestations administratives,,Charge, 62,AUTRES SERVICES EXTERIEURS,,Charge, 621,Personnel extérieur à l'association,,Charge, 6211,Personnel intérimaire,,Charge, 6214,Personnel détaché ou prêté à l'association,,Charge, 62141,Mises à disposition de personnel salarié,Frais de mise à disposition via un groupement d’employeurs,Charge,Dépenses 622,Rémunérations d'intermédiaires et honoraires,,Charge, 6221,Commissions ... sur achats,,Charge, 6222,Commissions... sur ventes,,Charge, 6226,Honoraires,,Charge, 62264,Honoraires sur legs ou donations à céder,,Charge, 6227,Frais d'actes et de contentieux,,Charge, 6228,Rémunérations div .intermédiaires & honor.,,Charge, 623,"Publicité, publications, relations publiques","Bulletins, affiches, communication, etc.",Charge,Dépenses 6231,Annonces et insertions,,Charge, 6232,Fêtes et cérémonies,,Charge, 6233,Foires et expositions,,Charge, 6234,Cadeaux,,Charge, 6236,Catalogues et imprimés,,Charge, 6237,Publications,,Charge, 6238,"Divers : pourboires, dons courants",,Charge, 624,Transports de biens...,,Charge, 6241,Transports sur achats,,Charge, 6242,Transports sur ventes,,Charge, 6243,Transports entre établissements,,Charge, 6244,Transports administratifs,,Charge, 6247,Transports collectifs du personnel,,Charge, 6248,Transports divers,,Charge, 625,"Déplacements, missions et réceptions","Billet de train, remboursement de frais kilométrique, etc.",Charge,Dépenses 6251,Voyages et déplacements,,Charge, 6255,Frais de déménagement,,Charge, 6256,Frais de missions,,Charge, 6257,"Frais de réceptions, représentations",,Charge, 626,Frais postaux et de télécommunications,"Facture d'accès à Internet, timbres, etc.",Charge,Dépenses 6261,Liaisons spécialisées,,Charge, 6263,"Affranchissements, frais postaux",,Charge, 6265,Téléphone,,Charge, 627,Services bancaires et assimilés,Frais bancaires,Charge,Dépenses 628,Divers,,Charge,Dépenses 6281,Cotisations (liées à l'activité économique),,Charge, 6284,Frais de recrutement du personnel,,Charge, 63,"IMPÔTS, TAXES ET VERSEMENTS ASSIMILÉS",,Charge, 631,Sur rémunérations - administration des impôts,,Charge, 6311,Taxe sur les salaires,,Charge, 633,Sur rémunérations - autres organismes,,Charge, 6331,Versement de transport,,Charge, 6332,Allocation logement,,Charge, 6333,Formation professionnelle continue,,Charge, 6334,Participations employeurs à l'effort de const,,Charge, 635,Autres - Administration des impôts,,Charge, 63512,Taxes foncières,,Charge, 63513,Autres impôts locaux,,Charge, 6354,Droits d'enregistrement et de timbre,,Charge, 637,Autres - Autres organismes,,Charge, 64,CHARGES DE PERSONNEL,,Charge, 641,Rémunérations du personnel,,Charge, 6411,"Salaires, appointements",,Charge, 6412,Congés payés,,Charge, 6413,Primes et gratifications,,Charge, 6414,Indemnités et avantages divers,,Charge, 6415,Supplément familial,,Charge, 645,Charges de sécurité sociale et de prévoyance,,Charge, 6451,Cotisations à l'URSSAF,,Charge, 6452,Cotisations aux mutuelles,,Charge, 6453,Cotisations caisses de retraites et de prévoy,,Charge, 6458,Cotisations aux autres organismes sociaux,,Charge, 647,Autres charges sociales,,Charge, 6472,Versements aux comités d'entreprise et d'étab,,Charge, 6473,Versement aux comités d'hygiène et de sécurit,,Charge, 6474,Versements aux autres oeuvres sociales,,Charge, 6475,"Médecine du travail, pharmacie",,Charge, 648,Autres charges de personnel,,Charge, 6481,Indemnités du personnel de culte,,Charge, 6485,Charges sociales sur indemnités de culte,,Charge, 6488,Autres charges de personnel,,Charge, 65,AUTRES CHARGES DE GESTION COURANTE,,Charge, 6511,"Redevances pour concessions, brevets, licenc.",,Charge, 6516,Droits d'auteur et de reproduction,,Charge, 6518,Autres droits et valeurs similaires,,Charge, 652,Licences fédérales,Licences payées pour les adhérents (par exemple fédération sportive etc.),Charge,Dépenses 653,Charges de la générosité du public,,Charge, 6531,Autres charges sur legs ou donations,,Charge, 654,Pertes sur créances irrécouvrables,,Charge, 655,Quotes-parts sur opérations faites en commun,,Charge, 657,Aides financières,,Charge, 6571,Aides financières octroyées,,Charge, 6572,Quotes-parts de générosité reversée,,Charge, 658,Charges diverses de gestion courante,,Charge,Dépenses 6586,Cotisations (vie statutaire),,Charge, 6588,Charges diverses de gestion courante,,Charge, 66,CHARGES FINANCIERES,,Charge, 661,Charges d'intérêts,,Charge, 665,Escomptes accordés,,Charge, 666,Pertes de changes,,Charge, 667,Charges nettes sur cessions de VMP,,Charge, 668,Autres charges financières,,Charge, 67,CHARGES EXEPTIONNELLES,,Charge, 670,Charges exceptionnelles,Autres dépenses exceptionnelles,Charge,Dépenses 6712,"Pénalités, amendes fiscales at pénales",,Charge, 6713,"Dons, libéralités",,Charge, 6714,Créances devenues irrécouvrables,,Charge, 6718,Autres charges exceptionnelles de gestion,,Charge, 673,Apports ou affectations en numéraire,,Charge, 675,Valeurs comptables des éléments d'actifs cédés,,Charge, 6750,Valeurs comptables des actifs cédés,,Charge, 6754,Immobilisations reçues par legs ou donations,,Charge, 678,Autres charges exceptionnelles sur opération en capital,,Charge, 68,"DOT. AUX AMORTISS., DÉPRÉC. ET ENGAGEMENTS",,Charge, 6811,Dot. aux amortissements des immobilisations,,Charge, 6812,Dot. aux amortissements charges à répartir,,Charge, 6815,Dot. aux provisions d'exploitation,,Charge, 6816,Dot. provisions pour dépréciations des immos,,Charge, 68164,Dot. pr dépréc. d’actifs reçus par legs ou donations,,Charge, 6817,Dot. aux dépréciations des actifs circulants,,Charge, 68173,Dotations dépréciations stocks et en-cours,,Charge, 68174,Dotations dépréciations créances,,Charge, 686,Dot. aux amort. & prov. - Charges financières,,Charge, 68662,Dot. aux amort. & prov immos financières,,Charge, 68665,Dot. aux amort. & prov VMP,,Charge, 687,Dot. aux amort. & prov. - Charges exceptionn.,,Charge, 689,Reports en fonds dédiés,,Charge, 6891,Reports en fonds reportés,,Charge, 6894,Reports en fonds dédiés / subventions d’exploitation,,Charge, 6895,Reports en fds dédiés / contributions financières d'autres organismes,,Charge, 6896,Reports en fds dédiés / ressources générosité,,Charge, 69,IMPÔTS SUR LES BENEFICES,,Charge, 695,IS sur personnes non lucratives,,Charge, 7,Classe 7 — Comptes de produits,,Produit, 70,"VENTES PROD.FINIS, MARCHANDISES, PRESTATIONS",,Produit, 701,Ventes de produits finis,Vente de produits fabriqués par l'association.,Produit,Recettes 702,Ventes de produits intermédiaires,,Produit, 703,Ventes de produits résiduels,,Produit, 704,Travaux,,Produit, 705,Etudes,,Produit, 706,Prestations de services,,Produit,Recettes 7063,Parrainages,,Produit, 707,Ventes de marchandises,Ventes de produits achetés et revendus en l’état,Produit,Recettes 7073,Ventes de dons en nature,,Produit, 708,Produits des activités annexes,,Produit, 7081,Produits des prestations fournies au personne,,Produit, 7083,Locations diverses,,Produit, 7085,Ports et frais accessoires facturés,,Produit, 7088,Autres produits d'activités annexes,,Produit, 709,RRR accordés,,Produit, 7091,RRR sur ventes de produits finis,,Produit, 7092,RRR sur ventes de produits intermédiaires,,Produit, 7094,RRR sur travaux,,Produit, 7095,RRR sur études,,Produit, 7096,RRR sur prest.de services,,Produit, 7097,RRR sur ventes marchandises,,Produit, 71,PRODUCTION STOCKEE,,Produit, 713,"Variation de stocks (en-cours, productions)",,Produit, 7133,Variation des en-cours de production de biens,,Produit, 7134,Variation des en-cours de production services,,Produit, 7135,Variations de stocks de produits,,Produit, 72,PRODUCTION IMMOBILISEE,,Produit, 721,Production immobilisée incorporelle,,Produit, 722,Production immobilisée corporelle,,Produit, 73,CONCOURS PUBLICS,,Produit, 730,Concours publics,,Produit, 74,SUBVENTION D'EXPLOITATION,,Produit, 740,Subventions reçues,,Produit,Recettes 748,Subventions d'exploitation diverses,,Produit, 75,AUTRES PRODUITS DE GESTION COURANTE,,Produit, 751,"Redevances pour concessions, licences...",,Produit, 753,Versements des fondateurs ou consommation dot,,Produit, 7531,Versements des fondateurs,,Produit, 7532,Quotes-parts de dotation consomptible virée a,,Produit, 754,Ressources liées à la générosité du public,Dons reçus,Produit,Recettes 7541,Dons manuels,,Produit, 75411,Dons manuels,,Produit, 75412,Abandons de frais par les bénévoles,,Produit, 7542,Mécénats,,Produit, 7543,"Legs, donations et assurances-vie",,Produit, 75431,Assurances-vie,,Produit, 75432,Legs ou donations,,Produit, 75433,Autres produits sur legs ou donations,,Produit, 755,Contributions financières,,Produit, 7551,Contributions financières d’autres organismes,,Produit, 7552,Quotes-parts de générosité reçues,,Produit, 756,Cotisations,Cotisations des adherent⋅e⋅s,Produit,Recettes 7561,Cotisations sans contrepartie,,Produit, 7562,Cotisations avec contrepartie,,Produit, 757,Gains de change / créances et dettes d’exploitation,,Produit, 758,Produits divers de gestion courante,,Produit, 7588,Autres produits divers de gestion courante,,Produit, 76,PRODUITS FINANCIERS,,Produit, 761,Produits des participations,,Produit, 762,Produits des autres immobilisat. financières,,Produit, 763,Revenus des autres créances,,Produit, 764,Revenus des VMP,,Produit, 765,Escomptes obtenus,,Produit, 766,Gains de change,,Produit, 767,Produits nets sur cession VMP,,Produit, 768,Autres produits financiers,,Produit, 77,PRODUITS EXCEPTIONNELS,,Produit, 771,Produits exception. sur opération de gestion,,Produit, 7713,Libéralités perçues,,Produit, 7718,Autres produits exception. sur op. de gestion,,Produit, 775,Produits des cessions d'actif,,Produit, 7754,Immos reçues en legs ou donations à céder,,Produit, 777,QP subvention d'investissement virée au résul,,Produit, 778,Autres produits exceptionnels,,Produit, 7780,Manifestations diverses,"Revenus provenant de manifestations au profit de l'association : droit d'entrée, location d'emplacement en vide grenier, ventes, etc.",Produit,Recettes 78,"REPRISES SUR AMORT., DÉPRÉC., ENGAGEMENTS",,Produit, 781,Reprises / amt & prov. d'exploitation,,Produit, 7811,Amt immos corporelles & incorporelles,,Produit, 7815,Reprises sur provisions d'exploitation,,Produit, 7816,Déprec. immos corporelles & incorporelles,,Produit, 78164,Reprises dépréc. d’actifs reçus par legs ou donations destinés à être cédés,,Produit, 7817,Dépréciations actifs circulant,,Produit, 786,Reprises / amt & prov. financiers,,Produit, 7865,Risques & charges financiers,,Produit, 7866,Déprec.des éléments financiers,,Produit, 787,Reprises sur amt & prov. exceptionnelles,,Produit, 7872,Provisions réglementées - Immobilisations,,Produit, 7873,Provisions réglementées - stocks,,Produit, 7874,Autres provisions réglementées,,Produit, 7875,Risques et charges,,Produit, 7876,Dépréciations exceptionnelles,,Produit, 789,Utilisations fds reportés et de fds dédiés,,Produit, 7891,Utilisations de fonds reportés,,Produit, 7894,Utilisations des fonds dédiés / subventions,,Produit, 7895,Utilisations des fds dédiés / contributions,,Produit, 7896,Utilisations des fds dédiés / générosité,,Produit, 79,TRANSFERT DE CHARGES,,Produit, 791,Transferts de charges d'exploitation,,Produit, 796,Transferts de charges financières,,Produit, 797,Transferts de charges exceptionnelles,,Produit, 8,Classe 8 — Comptes spéciaux,,, 86,EMPLOIS CONTRIBUTIONS VOLONTAIRES EN NATURE,,, 860,Secours en nature,,, 8601,Alimentaires,,, 8602,Vestimentaires,,, 861,Mise à dispositions gratuites de biens,,, 8611,Locaux,,, 8612,Matériels,,, 862,Prestations,,, 864,Personnel bénévole,,, 87,CONTRIBUTIONS VOLONTAIRES EN NATURE,,, 870,Dons en nature,,, 871,Prestations en nature,,, 875,Bénévolat,,,Bénévolat 89,COMPTES DE BILAN,,, 890,Bilan d'ouverture,,,Ouverture 891,Bilan de clôture,,,Clôture 9,Classe 9 — Comptes analytiques,,, 90,COMPTES RÉFLÉCHIS,,, 906,Charges réfléchies,,, 907,Produits réfléchis,,, 99,Projets,,,Analytique |
Modified src/include/data/schema.sql from [c8df01c2dd] to [bdddcd8200].
|
| < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1 | 1.0.0_schema.sql |
Modified src/include/init.php from [d8b3de9018] to [53a38bd077].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php namespace Garradin; use KD2\ErrorManager; use KD2\Security; use KD2\Form; error_reporting(-1); /* * Version de Garradin */ function garradin_version() { | > | | | | | | | | | | | | | | | | | | | | | > > > > > | | | < < < < < < < < < < < < < < < < < < | < < < < < | | | | | | | | | | | | | | | < < < < < < | | < | < | | | | | < < | | | | | | | | | | | | > > | > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | > > > > | | | | | < | < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < < | < < < < | | | | | | | | | | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | <?php namespace Garradin; use KD2\ErrorManager; use KD2\Security; use KD2\Form; use KD2\DB\EntityManager; error_reporting(-1); /* * Version de Garradin */ function garradin_version() { if (defined('Garradin\VERSION')) { return VERSION; } $file = __DIR__ . '/../VERSION'; if (file_exists($file)) { $version = trim(file_get_contents($file)); } else { $version = 'unknown'; } define('Garradin\VERSION', $version); return $version; } function garradin_manifest() { $file = __DIR__ . '/../../manifest.uuid'; if (@file_exists($file)) { return substr(trim(file_get_contents($file)), 0, 10); } return false; } if (!defined('\SQLITE3_OPEN_READWRITE')) { echo 'Le module de base de données SQLite3 n\'est pas disponible.' . PHP_EOL; exit(1); } /* * Configuration globale */ // Configuration externalisée if (file_exists(__DIR__ . '/../config.local.php')) { require __DIR__ . '/../config.local.php'; } // Configuration par défaut, si les constantes ne sont pas définies dans config.local.php // (fallback) if (!defined('Garradin\ROOT')) { define('Garradin\ROOT', dirname(__DIR__)); } \spl_autoload_register(function (string $classname) { $classname = ltrim($classname, '\\'); // Plugins if (substr($classname, 0, 16) == 'Garradin\\Plugin\\') { $classname = substr($classname, 16); $plugin_name = substr($classname, 0, strpos($classname, '\\')); $filename = str_replace('\\', '/', substr($classname, strpos($classname, '\\')+1)); $path = Plugin::getPath(strtolower($plugin_name)) . '/lib/' . $filename . '.php'; } else { // PSR-0 autoload $filename = str_replace('\\', '/', $classname); $path = ROOT . '/include/lib/' . $filename . '.php'; } if (file_exists($path)) { require_once $path; } }, true); if (!defined('Garradin\DATA_ROOT')) { define('Garradin\DATA_ROOT', ROOT); } if (!defined('Garradin\WWW_URI')) { try { $uri = \KD2\HTTP::getRootURI(ROOT); } catch (\UnexpectedValueException $e) { $uri = null; } if ($uri == '/www/') { $uri = '/'; } elseif ($uri !== null) { readfile(ROOT . '/sous-domaine.html'); exit; } define('Garradin\WWW_URI', $uri); unset($uri); } if (!defined('Garradin\WWW_URL')) { $host = \KD2\HTTP::getHost(); } if (WWW_URI === null || (!empty($host) && $host == 'host.unknown')) { $title = 'Impossible de détecter automatiquement l\'URL du site web.'; $info = 'Consulter l\'aide pour configurer manuellement l\'URL avec la directive WWW_URL et WWW_URI.'; $url ='https://fossil.kd2.org/garradin/wiki?name=Installation'; if (PHP_SAPI == 'cli') { printf("\n/!\\ %s\n%s\n-> %s\n\n", $title, $info, $url); } else { printf('<h2 style="color: red">%s</h2><p><a href="%s">%s</a></p>', $title, $url, $info); } exit(1); } if (!defined('Garradin\WWW_URL')) { define('Garradin\WWW_URL', \KD2\HTTP::getScheme() . '://' . $host . WWW_URI); } static $default_config = [ 'CACHE_ROOT' => DATA_ROOT . '/cache', 'DB_FILE' => DATA_ROOT . '/association.sqlite', 'DB_SCHEMA' => ROOT . '/include/data/schema.sql', 'PLUGINS_ROOT' => DATA_ROOT . '/plugins', 'PREFER_HTTPS' => false, 'ALLOW_MODIFIED_IMPORT' => true, 'PLUGINS_SYSTEM' => '', 'SHOW_ERRORS' => true, 'MAIL_ERRORS' => false, 'ERRORS_REPORT_URL' => null, 'ENABLE_TECH_DETAILS' => true, 'USE_CRON' => false, 'ENABLE_XSENDFILE' => false, 'SMTP_HOST' => false, 'SMTP_USER' => null, 'SMTP_PASSWORD' => null, 'SMTP_PORT' => 587, 'SMTP_SECURITY' => 'STARTTLS', 'ADMIN_URL' => WWW_URL . 'admin/', 'NTP_SERVER' => 'fr.pool.ntp.org', 'ENABLE_AUTOMATIC_BACKUPS' => true, 'ADMIN_COLOR1' => '#9c4f15', 'ADMIN_COLOR2' => '#d98628', ]; foreach ($default_config as $const => $value) { $const = sprintf('Garradin\\%s', $const); if (!defined($const)) { define($const, $value); } } if (!defined('Garradin\ADMIN_BACKGROUND_IMAGE')) { define('Garradin\ADMIN_BACKGROUND_IMAGE', ADMIN_URL . 'static/gdin_bg.png'); } const WEBSITE = 'https://fossil.kd2.org/garradin/'; const PLUGINS_URL = 'https://garradin.eu/plugins/list.json'; // PHP devrait être assez intelligent pour chopper la TZ système mais nan // il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour // éviter le message d'erreur à la con on définit une timezone par défaut // Pour utiliser une autre timezone, il suffit de définir date.timezone dans // un .htaccess ou dans config.local.php if (!ini_get('date.timezone')) { if (($tz = @date_default_timezone_get()) && $tz != 'UTC') { ini_set('date.timezone', $tz); } else { ini_set('date.timezone', 'Europe/Paris'); } } /* * Gestion des erreurs et exceptions */ class UserException extends \LogicException { } class ValidationException extends UserException { } // activer le gestionnaire d'erreurs/exceptions ErrorManager::enable(SHOW_ERRORS ? ErrorManager::DEVELOPMENT : ErrorManager::PRODUCTION); ErrorManager::setLogFile(DATA_ROOT . '/error.log'); // activer l'envoi de mails si besoin est if (MAIL_ERRORS) { ErrorManager::setEmail(MAIL_ERRORS); } ErrorManager::setContext([ 'rootDirectory' => ROOT, 'garradin_data_root' => DATA_ROOT, 'garradin_version' => garradin_version(), ]); if (ERRORS_REPORT_URL) { ErrorManager::setRemoteReporting(ERRORS_REPORT_URL, true); } ErrorManager::setProductionErrorTemplate('<!DOCTYPE html><html><head><title>Erreur interne</title> <style type="text/css"> body {font-family: sans-serif; } code, p, h1 { max-width: 400px; margin: 1em auto; display: block; } code { text-align: right; color: #666; } a { color: blue; } form { text-align: center; } </style></head><body><h1>Erreur interne</h1><p>Désolé mais le serveur a rencontré une erreur interne et ne peut répondre à votre requête. Merci de ré-essayer plus tard.</p> <p>Si vous suspectez un bug dans Garradin, vous pouvez suivre <a href="http://dev.kd2.org/garradin/Rapporter+un+bug">ces instructions</a> pour le rapporter.</p> <if(sent)><p>Un-e responsable a été notifié-e et cette erreur sera corrigée dès que possible.</p></if> <if(logged)><code>L\'erreur a été enregistrée dans les journaux système (error.log) sous la référence : <b>{$ref}</b></code></if> <p><a href="' . WWW_URL . '">← Retour à la page d\'accueil</a></p> </body></html>'); ErrorManager::setHtmlHeader('<!DOCTYPE html><meta charset="utf-8" /><style type="text/css"> body { font-family: sans-serif; } * { margin: 0; padding: 0; } u, code b, i, h3 { font-style: normal; font-weight: normal; text-decoration: none; } #icn { color: #fff; font-size: 2em; float: right; margin: 1em; padding: 1em; background: #900; border-radius: 50%; } section header { background: #fdd; padding: 1em; } section article { margin: 1em; } section article h3, section article h4 { font-size: 1em; font-family: mono; } code { border: 1px dotted #ccc; display: block; } code b { margin-right: 1em; color: #999; } code u { background: #fcc; display: inline-block; width: 100%; } table { border-collapse: collapse; margin: 1em; } td, th { border: 1px solid #ccc; padding: .2em .5em; text-align: left; vertical-align: top; } input { padding: .3em; margin: .5em; font-size: 1.2em; cursor: pointer; } </style> <pre id="icn"> \__/<br /> (xx)<br />//||\\\\</pre> <section> <article> <h1>Une erreur s\'est produite</h1> <if(report)><form method="post" action="{$report_url}"><p><input type="hidden" name="report" value="{$report_json}" /><input type="submit" value="Rapporter l\'erreur aux développeur⋅euses de Garradin →" /></p></form></if> </article> </section> '); function user_error(\Exception $e) { if (PHP_SAPI == 'cli') { echo $e->getMessage(); } else { $tpl = Template::getInstance(); $tpl->assign('error', $e->getMessage()); $tpl->assign('admin_url', ADMIN_URL); $tpl->display('error.tpl'); } exit; } // Message d'erreur simple pour les erreurs de l'utilisateur ErrorManager::setCustomExceptionHandler('\Garradin\UserException', '\Garradin\user_error'); ErrorManager::setCustomExceptionHandler('\KD2\MiniSkelMarkupException', '\Garradin\user_error'); // Clé secrète utilisée pour chiffrer les tokens CSRF etc. if (!defined('Garradin\SECRET_KEY')) { $key = base64_encode(random_bytes(64)); Install::setLocalConfig('SECRET_KEY', $key); define('Garradin\SECRET_KEY', $key); } // Intégration du secret pour les tokens Form::tokenSetSecret(SECRET_KEY); EntityManager::setGlobalDB(DB::getInstance()); /* * Vérifications pour enclencher le processus d'installation ou de mise à jour */ if (!defined('Garradin\INSTALL_PROCESS') && !defined('Garradin\UPGRADE_PROCESS')) { if (!file_exists(DB_FILE)) { Utils::redirect(ADMIN_URL . 'install.php'); } $config = Config::getInstance(); if (version_compare($config->getVersion(), garradin_version(), '<')) { Utils::redirect(ADMIN_URL . 'upgrade.php'); } } |
Added src/include/lib/Garradin/Accounting/Accounts.php version [104aa964ca].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Account; use Garradin\Entities\Accounting\Line; use Garradin\Entities\Accounting\Transaction; use Garradin\Entities\Accounting\Year; use Garradin\CSV; use Garradin\DB; use Garradin\Utils; use KD2\DB\EntityManager; class Accounts { protected $chart_id; protected $em; const EXPECTED_CSV_COLUMNS = ['code', 'label', 'description', 'position', 'type']; public function __construct(int $chart_id) { $this->chart_id = $chart_id; $this->em = EntityManager::getInstance(Account::class); } static public function get(int $id) { return EntityManager::findOneById(Account::class, $id); } static public function getSelectorLabel(int $id) { return EntityManager::getInstance(Account::class)->col('SELECT code || \' — \' || label FROM @TABLE WHERE id = ?;', $id); } public function getIdFromCode(string $code): int { return $this->em->col('SELECT id FROM @TABLE WHERE code = ? AND id_chart = ?;', $code, $this->chart_id); } /** * Return common accounting accounts from current chart * (will not return analytical and volunteering accounts) */ public function listCommonTypes(): array { return $this->em->all('SELECT * FROM @TABLE WHERE id_chart = ? AND type != 0 AND type NOT IN (?, ?) ORDER BY code COLLATE NOCASE;', $this->chart_id, Account::TYPE_ANALYTICAL, Account::TYPE_VOLUNTEERING); } /** * Return all accounts from current chart */ public function listAll(): array { return $this->em->all('SELECT * FROM @TABLE WHERE id_chart = ? ORDER BY code COLLATE NOCASE;', $this->chart_id); } public function listForCodes(array $codes): array { return DB::getInstance()->getGrouped('SELECT code, id, label FROM acc_accounts WHERE id_chart = ?;', $this->chart_id); } /** * Return all accounts from current chart */ public function export(): \Generator { $res = $this->em->DB()->iterate($this->em->formatQuery('SELECT code, label, description, position, type FROM @TABLE WHERE id_chart = ? ORDER BY code COLLATE NOCASE;'), $this->chart_id); foreach ($res as $row) { $row->type = Account::TYPES_NAMES[$row->type]; $row->position = Account::POSITIONS_NAMES[$row->position]; yield $row; } } /** * Return only analytical accounts */ public function listAnalytical(): array { return $this->em->DB()->getAssoc($this->em->formatQuery('SELECT id, label FROM @TABLE WHERE id_chart = ? AND type = ? ORDER BY code COLLATE NOCASE;'), $this->chart_id, Account::TYPE_ANALYTICAL); } /** * Return only analytical accounts */ public function listVolunteering(): array { return $this->em->all('SELECT * FROM @TABLE WHERE id_chart = ? AND type = ? ORDER BY code COLLATE NOCASE;', $this->chart_id, Account::TYPE_VOLUNTEERING); } /** * List common accounts, grouped by type * @return array */ public function listCommonGrouped(array $types = null): array { if (null === $types) { $types = ''; } else { $types = array_map('intval', $types); $types = ' AND ' . $this->em->DB()->where('type', $types); } $out = []; $query = $this->em->iterate('SELECT * FROM @TABLE WHERE id_chart = ? AND type != 0 ' . $types . ' ORDER BY type, code COLLATE NOCASE;', $this->chart_id); foreach ($query as $row) { if (!isset($out[$row->type])) { $out[$row->type] = (object) [ 'label' => Account::TYPES_NAMES[$row->type], 'type' => $row->type, 'accounts' => [], ]; } $out[$row->type]->accounts[] = $row; } return $out; } public function getNextCodesForTypes(): array { $db = DB::getInstance(); $codes = $db->getAssoc(sprintf('SELECT type, MAX(code) FROM %s WHERE id_chart = ? AND type > 0 GROUP BY type;', Account::TABLE), $this->chart_id); foreach ($codes as &$code) { if (($letter = substr($code, -1)) && !is_numeric($letter)) { $code = substr($code, 0, -1); $letter = strtoupper($letter); $letter = ($letter == 'Z') ? 'AA' : chr(ord($letter)+1); } else { $letter = 'A'; } $code = $code . $letter; } unset($code); return $codes; } public function copyFrom(int $id) { $db = DB::getInstance(); return $db->exec(sprintf('INSERT INTO %s (id_chart, code, label, description, position, type, user) SELECT %d, code, label, description, position, type, user FROM %1$s WHERE id_chart = %d;', Account::TABLE, $this->chart_id, $id)); } public function importUpload(array $file) { if (empty($file['size']) || empty($file['tmp_name'])) { throw new UserException('Fichier invalide'); } self::importCSV($file['tmp_name']); } public function importCSV(string $file): void { $db = DB::getInstance(); $positions = array_flip(Account::POSITIONS_NAMES); $types = array_flip(Account::TYPES_NAMES); $db->begin(); try { foreach (CSV::import($file, self::EXPECTED_CSV_COLUMNS) as $line => $row) { $account = new Account; $account->id_chart = $this->chart_id; try { $row['position'] = $positions[$row['position']]; $row['type'] = $types[$row['type']]; $account->importForm($row); $account->save(); } catch (ValidationException $e) { throw new UserException(sprintf('Ligne %d : %s', $line, $e->getMessage())); } } $db->commit(); } catch (\Exception $e) { $db->rollback(); throw $e; } } public function countByType(int $type) { return DB::getInstance()->count(Account::TABLE, 'id_chart = ? AND type = ?', $this->chart_id, $type); } public function getSingleAccountForType(int $type) { return DB::getInstance()->first('SELECT * FROM acc_accounts WHERE type = ? AND id_chart = ? LIMIT 1;', $type, $this->chart_id); } /* FIXME: implement closing of accounts public function getClosingAccountId() { return DB::getInstance()->firstColumn('SELECT id FROM acc_accounts WHERE type = ? AND id_chart = ?;', Account::TYPE_CLOSING, $this->chart_id); } public function closeRevenueExpenseAccounts(Year $year, int $user_id) { $closing_id = $this->getClosingAccountId(); if (!$closing_id) { throw new UserException('Aucun compte n\'est indiqué comme compte de clôture dans le plan comptable'); } $transaction = new Transaction; $transaction->id_creator = $user_id; $transaction->id_year = $year->id(); $transaction->type = Transaction::TYPE_ADVANCED; $transaction->label = 'Clôture de l\'exercice'; $transaction->date = new \DateTime; $debit = 0; $credit = 0; $sql = 'SELECT a.id, SUM(l.credit - l.debit) AS sum, a.position, a.code FROM acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction INNER JOIN acc_accounts a ON a.id = l.id_account WHERE t.id_year = ? AND a.position IN (?, ?) GROUP BY a.id ORDER BY a.code;'; $res = DB::getInstance()->iterate($sql, $year->id(), Account::REVENUE, Account::EXPENSE); foreach ($res as $row) { $reversed = $row->position == Account::ASSET; $line = new Line; $line->id_account = $row->id; $line->credit = $reversed ? abs($row->sum) : 0; $line->debit = !$reversed ? abs($row->sum) : 0; $transaction->addLine($line); if ($reversed) { $debit += abs($row->sum); } else { $credit += abs($row->sum); } } if ($debit) { $line = new Line; $line->id_account = $closing_id; $line->credit = 0; $line->debit = $debit; $transaction->addLine($line); } if ($credit) { $line = new Line; $line->id_account = $closing_id; $line->credit = $credit; $line->debit = 0; $transaction->addLine($line); } $transaction->save(); } */ } |
Added src/include/lib/Garradin/Accounting/Charts.php version [23502d0c8f].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Chart; use Garradin\Utils; use Garradin\DB; use KD2\DB\EntityManager; class Charts { static public function get(int $id) { return EntityManager::findOneById(Chart::class, $id); } static public function list() { $em = EntityManager::getInstance(Chart::class); return $em->all('SELECT * FROM @TABLE ORDER BY country, label;'); } static public function listAssoc() { return DB::getInstance()->getAssoc(sprintf('SELECT id, country || \' - \' || label FROM %s ORDER BY country, label;', Chart::TABLE)); } static public function listByCountry() { $sql = sprintf('SELECT id, country, label FROM %s ORDER BY country, label;', Chart::TABLE); $list = DB::getInstance()->getGrouped($sql); $out = []; foreach ($list as $row) { $country = Utils::getCountryName($row->country); if (!array_key_exists($country, $out)) { $out[$country] = []; } $out[$country][$row->id] = $row->label; } return $out; } } |
Added src/include/lib/Garradin/Accounting/Graph.php version [a1b33675d1].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Account; use Garradin\Entities\Accounting\Line; use Garradin\Entities\Accounting\Transaction; use Garradin\Utils; use Garradin\Config; use Garradin\DB; use const Garradin\ADMIN_COLOR1; use const Garradin\ADMIN_COLOR2; use const Garradin\ADMIN_URL; use KD2\DB\EntityManager; use KD2\Graphics\SVG\Plot; use KD2\Graphics\SVG\Plot_Data; use KD2\Graphics\SVG\Pie; use KD2\Graphics\SVG\Pie_Data; class Graph { const URL_LIST = [ ADMIN_URL . 'acc/reports/graph_plot.php?type=assets&%s' => 'Évolution banques et caisses', ADMIN_URL . 'acc/reports/graph_plot.php?type=result&%s' => 'Évolution dépenses et recettes', ADMIN_URL . 'acc/reports/graph_plot.php?type=debts&%s' => 'Évolution créances (positif) et dettes (négatif)', ADMIN_URL . 'acc/reports/graph_pie.php?type=revenue&%s' => 'Répartition recettes', ADMIN_URL . 'acc/reports/graph_pie.php?type=expense&%s' => 'Répartition dépenses', ADMIN_URL . 'acc/reports/graph_pie.php?type=assets&%s' => 'Répartition actif', ]; const PLOT_TYPES = [ 'assets' => [ 'Total' => ['type' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING]], 'Banques' => ['type' => Account::TYPE_BANK], 'Caisses' => ['type' => Account::TYPE_CASH], 'En attente' => ['type' => Account::TYPE_OUTSTANDING], ], 'result' => [ 'Recettes' => ['position' => Account::REVENUE], 'Dépenses' => ['position' => Account::EXPENSE], ], 'debts' => [ 'Comptes de tiers' => ['type' => Account::TYPE_THIRD_PARTY], ], ]; const PIE_TYPES = [ 'revenue' => ['position' => Account::REVENUE], 'expense' => ['position' => Account::EXPENSE], 'assets' => ['type' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING]], ]; const WEEKLY_INTERVAL = 604800; // 7 days const MONTHLY_INTERVAL = 2635200; // 1 month static public function plot(string $type, array $criterias, int $interval = self::WEEKLY_INTERVAL, int $width = 700) { if (!array_key_exists($type, self::PLOT_TYPES)) { throw new \InvalidArgumentException('Unknown type'); } $plot = new Plot($width, 300); $lines = self::PLOT_TYPES[$type]; $data = []; foreach ($lines as $label => $line_criterias) { $line_criterias = array_merge($criterias, $line_criterias); $sums = Reports::getSumsByInterval($line_criterias, $interval); if (count($sums) <= 1) { continue; } // Invert sums for banks, cash, etc. if ('assets' === $type || 'debts' === $type || ('result' === $type && $line_criterias['position'] == Account::EXPENSE)) { $sums = array_map(function ($v) { return $v * -1; }, $sums); } $sums = array_map(function ($v) { return (int)$v/100; }, $sums); $graph = new Plot_Data($sums); $graph->title = $label; $data[] = $graph; } if (count($data)) { $labels = []; foreach ($data[0]->get() as $k=>$v) { $date = new \DateTime('@' . ($k * $interval)); $labels[] = Utils::date_fr($date, 'M y'); } $plot->setLabels($labels); $i = 0; $colors = self::getColors(); foreach ($data as $line) { $line->color = $colors[$i++]; $line->width = 3; $plot->add($line); if ($i >= count($colors)) $i = 0; } } return $plot->output(); } static public function pie(string $type, array $criterias) { if (!array_key_exists($type, self::PIE_TYPES)) { throw new \InvalidArgumentException('Unknown type'); } $pie = new Pie(700, 300); $pie_criterias = self::PIE_TYPES[$type]; $data = Reports::getClosingSumsWithAccounts(array_merge($criterias, $pie_criterias), 'ABS(sum) DESC'); $others = 0; $colors = self::getColors(); $max = count($colors); $total = 0; $count = 0; $i = 0; foreach ($data as $row) { $row->sum = abs($row->sum); $total += $row->sum; } foreach ($data as $row) { if ($i++ >= $max || $count > $total*0.95) { $others += $row->sum; } else { $label = strlen($row->label) > 40 ? substr($row->label, 0, 38) . '…' : $row->label; $pie->add(new Pie_Data(abs($row->sum) / 100, $label, $colors[$i-1])); } $count += $row->sum; } if ($others != 0) { $pie->add(new Pie_Data(abs($others) / 100, 'Autres', '#ccc')); } $pie->togglePercentage(true); return $pie->output(); } static protected function getColors() { $config = Config::getInstance(); $c1 = $config->get('couleur1') ?: ADMIN_COLOR1; $c2 = $config->get('couleur2') ?: ADMIN_COLOR2; list($h, $s, $v) = Utils::rgbToHsv($c1); list($h1, $s, $v) = Utils::rgbToHsv($c2); $colors = []; for ($i = 0; $i < 6; $i++) { if ($i % 2 == 0) { $s = $v = 50; $h =& $h1; } else { $s = $v = 70; $h =& $h2; } $colors[] = sprintf('hsl(%d, %d%%, %d%%)', $h, $s, $v); $h += 30; if ($h > 360) { $h -= 360; } } return $colors; } } |
Added src/include/lib/Garradin/Accounting/Reports.php version [bd1f8f1a69].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Account; use Garradin\Entities\Accounting\Line; use Garradin\Entities\Accounting\Transaction; use Garradin\Utils; use Garradin\DB; use KD2\DB\EntityManager; class Reports { static public function getWhereClause(array $criterias): string { $where = []; if (!empty($criterias['year'])) { $where[] = sprintf('t.id_year = %d', $criterias['year']); } if (!empty($criterias['position'])) { $db = DB::getInstance(); $where[] = $db->where('position', $criterias['position']); } if (!empty($criterias['exclude_position'])) { $db = DB::getInstance(); $where[] = $db->where('position', 'NOT IN', $criterias['exclude_position']); } if (!empty($criterias['type'])) { $db = DB::getInstance(); $criterias['type'] = array_map('intval', (array)$criterias['type']); $where[] = sprintf('a.type IN (%s)', implode(',', $criterias['type'])); } if (!empty($criterias['user'])) { $where[] = sprintf('t.id IN (SELECT id_transaction FROM acc_transactions_users WHERE id_user = %d)', $criterias['user']); } if (!empty($criterias['creator'])) { $where[] = sprintf('t.id_creator = %d', $criterias['creator']); } if (!empty($criterias['service_user'])) { $where[] = sprintf('t.id IN (SELECT tu.id_transaction FROM acc_transactions_users tu WHERE id_service_user = %d)', $criterias['service_user']); } if (!empty($criterias['analytical'])) { $where[] = sprintf('l.id_analytical = %d', $criterias['analytical']); } if (!count($where)) { throw new \LogicException('Unknown criteria'); } return implode(' AND ', $where); } /** * Return account sums per year or per account * @param bool $order_year If true will return accounts grouped by year, if false it will return years grouped by account */ static public function getAnalyticalSums(bool $by_year = false): \Generator { $sql = 'SELECT a.label AS account_label, a.id AS id_account, y.id AS id_year, y.label AS year_label, y.start_date, y.end_date, SUM(l.credit - l.debit) AS sum, SUM(l.credit) AS credit, SUM(l.debit) AS debit FROM acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction INNER JOIN acc_accounts a ON a.id = l.id_analytical INNER JOIN acc_years y ON y.id = t.id_year GROUP BY %s ORDER BY %s;'; if ($by_year) { $group = 'y.id, a.id'; $order = 'y.start_date DESC, a.label COLLATE NOCASE'; } else { $group = 'a.id, y.id'; $order = 'a.label COLLATE NOCASE, y.id'; } $sql = sprintf($sql, $group, $order); $current = null; foreach (DB::getInstance()->iterate($sql) as $row) { $id = $by_year ? $row->id_year : $row->id_account; if (null !== $current && $current->id !== $id) { $current->items[] = (object) [ 'label' => 'Total', 'credit' => $current->credit, 'debit' => $current->debit, 'sum' => $current->sum, 'id_account' => $by_year ? null : $current->id, 'id_year' => $by_year ? $current->id : null, ]; yield $current; $current = null; } if (null === $current) { $current = (object) [ 'id' => $by_year ? $row->id_year : $row->id_account, 'label' => $by_year ? $row->year_label : $row->account_label, 'credit' => 0, 'debit' => 0, 'sum' => 0, 'items' => [] ]; } $row->label = !$by_year ? $row->year_label : $row->account_label; $current->items[] = $row; $current->credit += $row->credit; $current->debit += $row->debit; $current->sum += $row->sum; } if ($current === null) { return; } $current->items[] = (object) [ 'label' => 'Total', 'credit' => $current->credit, 'debit' => $current->debit, 'sum' => $current->sum, 'id_account' => $by_year ? null : $row->id_account, 'id_year' => $by_year ? $row->id_year : null, ]; yield $current; } static public function getSumsByInterval(array $criterias, int $interval) { $where = self::getWhereClause($criterias); $where_interval = !empty($criterias['year']) ? sprintf(' WHERE id_year = %d', $criterias['year']) : ''; $db = DB::getInstance(); $sql = sprintf('SELECT strftime(\'%%s\', MIN(date)) / %d AS start_interval, strftime(\'%%s\', MAX(date)) / %1$d AS end_interval FROM acc_transactions %s;', $interval, $where_interval); extract((array)$db->first($sql)); $out = array_fill_keys(range($start_interval, $end_interval), 0); $sql = sprintf('SELECT strftime(\'%%s\', t.date) / %d AS interval, SUM(l.credit) - SUM(l.debit) AS sum, t.id_year FROM acc_transactions t INNER JOIN acc_transactions_lines l ON l.id_transaction = t.id INNER JOIN acc_accounts a ON a.id = l.id_account WHERE %s GROUP BY %s ORDER BY %3$s;', $interval, $where, isset($criterias['year']) ? 'interval' : 't.id_year, interval'); $data = $db->getGrouped($sql); $sum = 0; $year = null; foreach ($out as $k => &$v) { if (array_key_exists($k, $data)) { $row = $data[$k]; if ($row->id_year != $year) { $sum = 0; $year = $row->id_year; } $sum += $data[$k]->sum; } $v = $sum; } unset($v); return $out; } static public function getResult(array $criterias): int { $where = self::getWhereClause($criterias); $sql = sprintf('SELECT SUM(l.credit) - SUM(l.debit) FROM %s l INNER JOIN %s t ON t.id = l.id_transaction INNER JOIN %s a ON a.id = l.id_account WHERE %s AND a.position = ?;', Line::TABLE, Transaction::TABLE, Account::TABLE, $where); $db = DB::getInstance(); $a = $db->firstColumn($sql, Account::REVENUE); $b = $db->firstColumn($sql, Account::EXPENSE); return (int)$a - abs((int)$b); } static public function getClosingSumsWithAccounts(array $criterias, ?string $order = null, bool $reverse = false): array { $where = self::getWhereClause($criterias); $order = $order ?: 'a.code COLLATE NOCASE'; $reverse = $reverse ? '* - 1' : ''; // Find sums, link them to accounts $sql = sprintf('SELECT a.id, a.code, a.label, a.position, SUM(l.credit) AS credit, SUM(l.debit) AS debit, SUM(l.credit - l.debit) %s AS sum FROM %s l INNER JOIN %s t ON t.id = l.id_transaction INNER JOIN %s a ON a.id = l.id_account WHERE %s GROUP BY l.id_account HAVING sum != 0 ORDER BY %s;', $reverse, Line::TABLE, Transaction::TABLE, Account::TABLE, $where, $order); return DB::getInstance()->getGrouped($sql); } static public function getBalanceSheet(array $criterias): array { $out = [ Account::ASSET => [], Account::LIABILITY => [], 'sums' => [ Account::ASSET => 0, Account::LIABILITY => 0, ], ]; $position_criteria = ['position' => [Account::ASSET, Account::LIABILITY, Account::ASSET_OR_LIABILITY]]; $list = self::getClosingSumsWithAccounts($criterias + $position_criteria); foreach ($list as $row) { if ($row->sum == 0) { // Ignore empty accounts continue; } $position = $row->position; if ($position == Account::ASSET_OR_LIABILITY) { $position = $row->sum < 0 ? Account::ASSET : Account::LIABILITY; $row->sum = abs($row->sum); } elseif ($position == Account::ASSET) { // reverse number for assets $row->sum *= -1; } $out[$position][] = $row; } $result = self::getResult($criterias); $out[Account::LIABILITY][] = (object) [ 'id' => null, 'label' => $result > 0 ? 'Résultat de l\'exercice courant (excédent)' : 'Résultat de l\'exercice courant (perte)', 'sum' => $result, ]; // Calculate the total sum for assets and liabilities foreach ($out as $position => $rows) { if ($position == 'sums') { continue; } $sum = 0; foreach ($rows as $row) { $sum += $row->sum; } $out['sums'][$position] = $sum; } return $out; } /** * Return list of favorite accounts (accounts with a type), grouped by type, with their current sum * @return \Generator list of accounts grouped by type */ static public function getClosingSumsFavoriteAccounts(array $criterias): \Generator { $where = self::getWhereClause($criterias); $sql = sprintf('SELECT a.id, a.code, a.label, a.description, a.type, SUM(l.credit) - SUM(l.debit) AS sum FROM %s a INNER JOIN %s t ON t.id = l.id_transaction INNER JOIN %s l ON a.id = l.id_account WHERE a.type != 0 AND %s GROUP BY l.id_account ORDER BY a.type, a.code COLLATE NOCASE;', Account::TABLE, Transaction::TABLE, Line::TABLE, $where); $group = null; foreach (DB::getInstance()->iterate($sql) as $row) { if (null !== $group && $row->type !== $group->type) { yield $group; $group = null; } if (null === $group) { $group = (object) [ 'label' => Account::TYPES_NAMES[$row->type], 'type' => $row->type, 'accounts' => [] ]; } $reverse = Account::isReversed($row->type) ? -1 : 1; $row->sum *= $reverse; $group->accounts[] = $row; } if (null !== $group) { yield $group; } } /** * Grand livre */ static public function getGeneralLedger(array $criterias): \Generator { $where = self::getWhereClause($criterias); $db = DB::getInstance(); $sql = sprintf('SELECT t.id_year, l.id_account, l.debit, l.credit, t.id, t.date, t.reference, l.reference AS line_reference, t.label, l.label AS line_label FROM acc_transactions t INNER JOIN acc_transactions_lines l ON l.id_transaction = t.id INNER JOIN acc_accounts a ON a.id = l.id_account WHERE %s ORDER BY a.code COLLATE NOCASE, t.date, t.id;', $where); $account = null; $debit = $credit = 0; $accounts = null; foreach ($db->iterate($sql) as $row) { if (null === $accounts) { $accounts = $db->getGrouped('SELECT id, code, label FROM acc_accounts WHERE id_chart = (SELECT id_chart FROM acc_years WHERE id = ?);', $row->id_year); } if (null !== $account && $account->id != $row->id_account) { yield $account; $account = null; } if (null === $account) { $account = (object) [ 'code' => $accounts[$row->id_account]->code, 'label' => $accounts[$row->id_account]->label, 'id' => $row->id_account, 'id_year' => $row->id_year, 'sum' => 0, 'debit' => 0, 'credit'=> 0, 'lines' => [], ]; } $row->date = \DateTime::createFromFormat('Y-m-d', $row->date); $account->sum += ($row->credit - $row->debit); $account->debit += $row->debit; $account->credit += $row->credit; $debit += $row->debit; $credit += $row->credit; $row->running_sum = $account->sum; $account->lines[] = $row; } if (null === $account) { return; } $account->all_debit = $debit; $account->all_credit = $credit; yield $account; } static public function getJournal(array $criterias): \Generator { $where = self::getWhereClause($criterias); $sql = sprintf('SELECT t.id_year, l.id_account, l.debit, l.credit, t.id, t.date, t.reference, l.reference AS line_reference, t.label, l.label AS line_label FROM acc_transactions t INNER JOIN acc_transactions_lines l ON l.id_transaction = t.id WHERE %s ORDER BY t.date, t.id;', $where); $transaction = null; $accounts = null; $db = DB::getInstance(); foreach ($db->iterate($sql) as $row) { if (null === $accounts) { $accounts = $db->getGrouped('SELECT id, code, label FROM acc_accounts WHERE id_chart = (SELECT id_chart FROM acc_years WHERE id = ?);', $row->id_year); } if (null !== $transaction && $transaction->id != $row->id) { yield $transaction; $transaction = null; } if (null === $transaction) { $transaction = (object) [ 'id' => $row->id, 'label' => $row->label, 'date' => \DateTime::createFromFormat('Y-m-d', $row->date), 'reference' => $row->reference, 'lines' => [], ]; } if (!isset($accounts[$row->id_account])) { throw new \LogicException(sprintf('Account #%s not found', $row->id_account)); } $transaction->lines[] = (object) [ 'account_label' => $accounts[$row->id_account]->label, 'account_code' => $accounts[$row->id_account]->code, 'label' => $row->line_label, 'reference' => $row->line_reference, 'id_account' => $row->id_account, 'credit' => $row->credit, 'debit' => $row->debit, 'id_year' => $row->id_year, ]; } if (null === $transaction) { return; } yield $transaction; } } |
Added src/include/lib/Garradin/Accounting/Transactions.php version [6561462819].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Account; use Garradin\Entities\Accounting\Line; use Garradin\Entities\Accounting\Transaction; use Garradin\Entities\Accounting\Year; use KD2\DB\EntityManager; use Garradin\CSV; use Garradin\CSV_Custom; use Garradin\DB; use Garradin\DynamicList; use Garradin\Utils; use Garradin\UserException; class Transactions { const EXPECTED_CSV_COLUMNS_SELF = ['id', 'type', 'status', 'label', 'date', 'notes', 'reference', 'line_id', 'account', 'credit', 'debit', 'line_reference', 'line_label', 'reconciled']; const POSSIBLE_CSV_COLUMNS = [ 'id' => 'Numéro d\'écriture', 'label' => 'Libellé', 'date' => 'Date', 'notes' => 'Notes', 'reference' => 'Numéro pièce comptable', 'p_reference' => 'Référence paiement', 'debit_account' => 'Compte de débit', 'credit_account' => 'Compte de crédit', 'amount' => 'Montant', ]; const MANDATORY_CSV_COLUMNS = ['id', 'label', 'date', 'credit_account', 'debit_account', 'amount']; static public function get(int $id) { return EntityManager::findOneById(Transaction::class, $id); } static public function saveReconciled(\Generator $journal, ?array $checked) { if (null === $checked) { $checked = []; } $db = DB::getInstance(); $db->begin(); // Synchro des trucs cochés $st = $db->prepare('UPDATE acc_transactions_lines SET reconciled = :r WHERE id = :id;'); foreach ($journal as $row) { if (!isset($row->id_line)) { continue; } $st->bindValue(':id', (int)$row->id_line, \SQLITE3_INTEGER); $st->bindValue(':r', !empty($checked[$row->id_line]) ? 1 : 0, \SQLITE3_INTEGER); $st->execute(); } $db->commit(); } static public function saveDeposit(Transaction $transaction, \Generator $journal, array $checked) { $db = DB::getInstance(); $db->begin(); try { $ids = []; foreach ($journal as $row) { if (!array_key_exists($row->id, $checked)) { continue; } $ids[] = (int)$row->id; $line = new Line; $line->importForm([ 'reference' => $row->line_reference, 'id_account' => $row->id_account, ]); $line->credit = $row->debit; $transaction->addLine($line); } $transaction->save(); $ids = implode(',', $ids); $db->exec(sprintf('UPDATE acc_transactions SET status = (status | %d) WHERE id IN (%s);', Transaction::STATUS_DEPOSIT, $ids)); $db->commit(); } catch (\Exception $e) { $db->rollback(); throw $e; } } static public function countForUser(int $user_id): int { return DB::getInstance()->count('acc_transactions_users', 'id_user = ?', $user_id); } static public function countForCreator(int $user_id): int { return DB::getInstance()->count('acc_transactions', 'id_creator = ?', $user_id); } /** * Return all transactions from year */ static public function export(int $year_id): \Generator { $sql = 'SELECT t.id, t.type, t.status, t.label, t.date, t.notes, t.reference, l.id AS line_id, a.code AS account, l.debit AS debit, l.credit AS credit, l.reference AS line_reference, l.label AS line_label, l.reconciled, a2.code AS analytical FROM acc_transactions t INNER JOIN acc_transactions_lines l ON l.id_transaction = t.id INNER JOIN acc_accounts a ON a.id = l.id_account LEFT JOIN acc_accounts a2 ON a2.id = l.id_analytical WHERE t.id_year = ? ORDER BY t.date, t.id, l.id;'; $res = DB::getInstance()->iterate($sql, $year_id); $previous_id = null; foreach ($res as $row) { if ($previous_id === $row->id) { $row->id = $row->type = $row->status = $row->label = $row->date = $row->notes = $row->reference = null; } else { $row->type = Transaction::TYPES_NAMES[$row->type]; $status = []; foreach (Transaction::STATUS_NAMES as $k => $v) { if ($row->status & $k) { $status[] = $v; } } $row->status = implode(', ', $status); $row->date = \DateTime::createFromFormat('Y-m-d', $row->date); $row->date = $row->date->format('d/m/Y'); } $row->credit = Utils::money_format($row->credit, ',', ''); $row->debit = Utils::money_format($row->debit, ',', ''); $previous_id = $row->id; yield $row; } } static public function importCSV(Year $year, array $file, int $user_id) { if ($year->closed) { throw new \InvalidArgumentException('Closed year'); } $db = DB::getInstance(); $db->begin(); $accounts = $year->accounts(); $transaction = null; $types = array_flip(Transaction::TYPES_NAMES); $l = 0; try { foreach (CSV::importUpload($file, self::EXPECTED_CSV_COLUMNS_SELF) as $l => $row) { $row = (object) $row; $has_transaction = !empty($row->id) || !empty($row->type) || !empty($row->status) || !empty($row->label) || !empty($row->date) || !empty($row->notes) || !empty($row->reference); if (null !== $transaction && $has_transaction) { $transaction->save(); $transaction = null; } if (null === $transaction) { if (!$has_transaction) { throw new UserException('cette ligne n\'est reliée à aucune écriture'); } if ($row->id) { $transaction = self::get((int)$row->id); if (!$transaction) { throw new UserException(sprintf('l\'écriture n°%d est introuvable', $row->id)); } if ($transaction->validated) { throw new UserException(sprintf('l\'écriture n°%d est validée et ne peut être modifiée', $row->id)); } } else { $transaction = new Transaction; $transaction->id_creator = $user_id; $transaction->id_year = $year->id(); } if (!isset($types[$row->type])) { throw new UserException(sprintf('le type "%s" est inconnu', $row->type)); } $transaction->type = $types[$row->type]; $fields = array_intersect_key((array)$row, array_flip(['label', 'date', 'notes', 'reference'])); $transaction->importForm($fields); } $id_account = $accounts->getIdFromCode($row->account); if (!$id_account) { throw new UserException(sprintf('le compte "%s" n\'existe pas dans le plan comptable', $row->account)); } $row->line_id = trim($row->line_id); $id_analytical = null; $data = [ 'credit' => $row->credit ?: 0, 'debit' => $row->debit ?: 0, 'id_account' => $id_account, 'reference' => $row->line_reference, 'label' => $row->line_label, 'reconciled' => $row->reconciled, ]; if (!empty($row->analytical)) { $id_analytical = $accounts->getIdFromCode($row->analytical); if (!$id_analytical) { throw new UserException(sprintf('le compte analytique "%s" n\'existe pas dans le plan comptable', $row->analytical)); } $data['id_analytical'] = $id_analytical; } elseif (property_exists($row, 'analytical')) { $data['id_analytical'] = null; } if ($row->line_id) { $line = $transaction->getLine((int)$row->line_id); if (!$line) { throw new UserException(sprintf('le numéro de ligne "%s" n\'existe pas dans l\'écriture "%s"', $row->line_id, $transaction->id ?: 'à créer')); } } else { $line = new Line; } $line->importForm($data); if (!$row->line_id) { $transaction->addLine($line); } } if (null !== $transaction) { $transaction->save(); } } catch (UserException $e) { $db->rollback(); throw new UserException(sprintf('Erreur sur la ligne %d : %s', $l, $e->getMessage())); } $db->commit(); } static public function importCustom(Year $year, CSV_Custom $csv, int $user_id) { if ($year->closed) { throw new \InvalidArgumentException('Closed year'); } $db = DB::getInstance(); $db->begin(); $accounts = $year->accounts(); $l = 0; try { foreach ($csv->iterate() as $l => $row) { if (!isset($row->credit_account, $row->debit_account, $row->amount)) { throw new UserException('Une des colonnes compte de crédit, compte de débit ou montant est manquante.'); } if (!empty($row->id)) { $transaction = self::get((int)$row->id); if (!$transaction) { throw new UserException(sprintf('Ligne %d : l\'écriture n°%d est introuvable', $l, $row->id)); } if ($transaction->validated) { throw new UserException(sprintf('Ligne %d : l\'écriture n°%d est validée et ne peut être modifiée', $l, $row->id)); } $transaction->resetLines(); } else { $transaction = new Transaction; $transaction->type = Transaction::TYPE_ADVANCED; $transaction->id_creator = $user_id; $transaction->id_year = $year->id(); } $fields = array_intersect_key((array)$row, array_flip(['label', 'date', 'notes', 'reference'])); $transaction->importForm($fields); $credit_account = $accounts->getIdFromCode($row->credit_account); $debit_account = $accounts->getIdFromCode($row->debit_account); if (!$credit_account) { throw new UserException(sprintf('Compte de crédit "%s" inconnu dans le plan comptable', $row->credit_account)); } if (!$debit_account) { throw new UserException(sprintf('Compte de débit "%s" inconnu dans le plan comptable', $row->debit_account)); } $line = new Line; $line->importForm([ 'credit' => $row->amount, 'debit' => 0, 'id_account' => $credit_account, 'reference' => isset($row->p_reference) ? $row->p_reference : null, ]); $transaction->addLine($line); $line = new Line; $line->importForm([ 'credit' => 0, 'debit' => $row->amount, 'id_account' => $debit_account, 'reference' => isset($row->p_reference) ? $row->p_reference : null, ]); $transaction->addLine($line); $transaction->save(); } } catch (UserException $e) { $db->rollback(); throw new UserException(sprintf('Erreur sur la ligne %d : %s', $l, $e->getMessage())); } $db->commit(); } static public function setAnalytical(?int $id_analytical, array $lines) { $db = DB::getInstance(); if (null !== $id_analytical && !$db->test(Account::TABLE, 'type = 7 AND id = ?', $id_analytical)) { throw new \InvalidArgumentException('Chosen account ID is not analytical'); } $lines = array_map('intval', $lines); return $db->exec(sprintf('UPDATE acc_transactions_lines SET id_analytical = %s WHERE id IN (%s);', (int)$id_analytical ?: 'NULL', implode(', ', $lines))); } static public function listByType(int $year_id, int $type) { $reverse = 1; $columns = Account::LIST_COLUMNS; unset($columns['line_label'], $columns['sum'], $columns['debit'], $columns['credit']); $columns['line_reference']['label'] = 'Réf. paiement'; $columns['change']['select'] = sprintf('SUM(l.credit) * %d', $reverse); $columns['change']['label'] = 'Montant'; $tables = 'acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction INNER JOIN acc_accounts a ON a.id = l.id_account LEFT JOIN acc_accounts b ON b.id = l.id_analytical'; $conditions = sprintf('t.type = %s AND t.id_year = %d', $type, $year_id); $sum = 0; $list = new DynamicList($columns, $tables, $conditions); $list->orderBy('date', true); $list->setCount('COUNT(*)'); $list->groupBy('t.id'); $list->setModifier(function (&$row) use (&$sum, $reverse) { $row->date = \DateTime::createFromFormat('!Y-m-d', $row->date); }); $list->setExportCallback(function (&$row) { $row->change = Utils::money_format($row->change, '.', '', false); }); return $list; } } |
Added src/include/lib/Garradin/Accounting/Years.php version [31fc8b31a2].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Year; use Garradin\Utils; use Garradin\DB; use KD2\DB\EntityManager; class Years { static public function get(int $year_id) { return EntityManager::findOneById(Year::class, $year_id); } static public function getCurrentOpenYear() { return EntityManager::findOne(Year::class, 'SELECT * FROM @TABLE WHERE closed = 0 ORDER BY start_date LIMIT 1;'); } static public function listOpen() { $db = EntityManager::getInstance(Year::class)->DB(); return $db->get('SELECT *, (SELECT COUNT(*) FROM acc_transactions WHERE id_year = acc_years.id) AS nb_transactions FROM acc_years WHERE closed = 0 ORDER BY end_date;'); } static public function listAssoc() { return DB::getInstance()->getAssoc('SELECT id, label FROM acc_years ORDER BY end_date;'); } static public function listClosed() { $em = EntityManager::getInstance(Year::class); return $em->all('SELECT * FROM @TABLE WHERE closed = 1 ORDER BY end_date;'); } static public function countClosed() { return DB::getInstance()->count(Year::TABLE, 'closed = 1'); } static public function list(bool $reverse = false) { $desc = $reverse ? 'DESC' : ''; $em = EntityManager::getInstance(Year::class); return $em->all(sprintf('SELECT * FROM @TABLE ORDER BY end_date %s;', $desc)); } static public function getNewYearDates(): array { $last_year = EntityManager::findOne(Year::class, 'SELECT * FROM @TABLE ORDER BY end_date DESC LIMIT 1;'); if ($last_year) { $start_date = clone $last_year->start_date; $start_date->modify('+1 year'); $end_date = clone $last_year->end_date; $end_date->modify('+1 year'); } else { $start_date = new \DateTime; $end_date = clone $start_date; $end_date->modify('+1 year'); } return [$start_date, $end_date]; } } |
Added src/include/lib/Garradin/CSV.php version [b79b34dab0].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 | <?php namespace Garradin; use KD2\Office\Calc\Writer as ODSWriter; class CSV { static public function readAsArray(string $path) { if (!file_exists($path) || !is_readable($path)) { throw new \RuntimeException('Fichier inconnu : '.$path); } $fp = self::open($path); if (!$fp) { return false; } $delim = self::findDelimiter($fp); self::skipBOM($fp); $line = 0; $out = []; $nb_columns = null; while (!feof($fp)) { $row = fgetcsv($fp, 4096, $delim); $line++; if (empty($row)) { continue; } if (null === $nb_columns) { $nb_columns = count($row); } if (count($row) != $nb_columns) { throw new UserException('Erreur sur la ligne ' . $line . ' : incohérence dans le nombre de colonnes avec la première ligne.'); } $out[$line] = $row; } fclose($fp); return $out; } static public function open(string $file) { ini_set('auto_detect_line_endings', true); return fopen($file, 'r'); } static public function findDelimiter(&$fp) { $line = ''; while ($line === '' && !feof($fp)) { $line = fgets($fp, 4096); } if (strlen($line) >= 4095) { throw new UserException('Fichier CSV illisible : la première ligne est trop longue.'); } // Delete the columns content $line = preg_replace('/".*?"/', '', $line); $delims = [ ';' => substr_count($line, ';'), ',' => substr_count($line, ','), "\t"=> substr_count($line, "\t") ]; arsort($delims); reset($delims); rewind($fp); return key($delims); } static public function skipBOM(&$fp) { // Skip BOM if (fgets($fp, 4) !== chr(0xEF) . chr(0xBB) . chr(0xBF)) { fseek($fp, 0); } } static public function row($row): string { $row = (array) $row; array_walk($row, function (&$field) { $field = strtr($field, ['"' => '""', "\r\n" => "\n"]); }); return sprintf("\"%s\"\r\n", implode('","', $row)); } static public function export(string $format, string $name, iterable $iterator, ?array $header = null, ?callable $row_map_callback = null): void { if ('csv' == $format) { self::toCSV(... array_slice(func_get_args(), 1)); } else { self::toODS(... array_slice(func_get_args(), 1)); } } static protected function rowToArray($row, ?callable $row_map_callback) { if (null !== $row_map_callback) { call_user_func_array($row_map_callback, [&$row]); } if (is_object($row) && $row instanceof Entity) { $row = $row->asArray(); } elseif (is_object($row)) { $row = (array) $row; } foreach ($row as $key => &$v) { if ((is_object($v) && !($v instanceof \DateTimeInterface)) || is_array($v)) { throw new \UnexpectedValueException(sprintf('Unexpected value for "%s": %s', $key, gettype($v))); } } return $row; } static public function toCSV(string $name, iterable $iterator, ?array $header = null, ?callable $row_map_callback = null): void { header('Content-type: application/csv'); header(sprintf('Content-Disposition: attachment; filename="%s.csv"', $name)); $fp = fopen('php://output', 'w'); if ($header) { fputs($fp, self::row($header)); } if ($iterator->valid()) { foreach ($iterator as $row) { foreach ($row as $key => &$v) { if (is_object($v)&& $v instanceof \DateTimeInterface) { $v = $v->format('d/m/Y'); } } $row = self::rowToArray($row, $row_map_callback); if (!$header) { fputs($fp, self::row(array_keys($row))); $header = true; } fputs($fp, self::row($row)); } } fclose($fp); } static public function toODS(string $name, iterable $iterator, ?array $header = null, ?callable $row_map_callback = null): void { header('Content-type: application/vnd.oasis.opendocument.spreadsheet'); header(sprintf('Content-Disposition: attachment; filename="%s.ods"', $name)); $ods = new ODSWriter; $ods->table_name = $name; if ($header) { $ods->add((array) $header); } if ($iterator->valid()) { foreach ($iterator as $row) { $row = self::rowToArray($row, $row_map_callback); if (!$header) { $ods->add(array_keys($row)); $header = true; } $ods->add((array) $row); } } $ods->output(); } static public function importUpload(array $file, array $expected_columns): \Generator { if (empty($file['size']) || empty($file['tmp_name'])) { throw new UserException('Fichier invalide'); } return self::import($file['tmp_name'], $expected_columns); } static public function import(string $file, array $expected_columns): \Generator { $fp = fopen($file, 'r'); if (!$fp) { throw new UserException('Le fichier ne peut être ouvert'); } // Find the delimiter $delim = self::findDelimiter($fp); self::skipBOM($fp); $line = 1; $columns = fgetcsv($fp, 4096, $delim); $columns = array_map('trim', $columns); // Check for required columns foreach ($expected_columns as $column) { if (!in_array($column, $columns, true)) { throw new UserException(sprintf('La colonne "%s" est absente du fichier importé', $column)); } } while (!feof($fp)) { $row = fgetcsv($fp, 4096, $delim); $line++; // Empty line, skip if (empty($row)) { continue; } if (count($row) != count($columns)) { throw new UserException('Erreur sur la ligne ' . $line . ' : le nombre de colonnes est incorrect.'); } $row = array_combine($columns, $row); yield $line => $row; } fclose($fp); } } |
Added src/include/lib/Garradin/CSV_Custom.php version [12dd8c64a5].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 201 202 | <?php namespace Garradin; use KD2\UserSession; class CSV_Custom { protected $session; protected $key; protected $csv; protected $translation; protected $columns; protected $mandatory_columns = []; protected $skip = 1; public function __construct(UserSession $session, string $key) { $this->session = $session; $this->key = $key; $this->csv = $this->session->get($this->key); $this->translation = $this->session->get($this->key . '_translation') ?: []; $this->skip = $this->session->get($this->key . '_skip') ?: 1; } public function load(array $file) { if (empty($file['size']) || empty($file['tmp_name'])) { throw new UserException('Fichier invalide'); } $csv = CSV::readAsArray($file['tmp_name']); if (!count($csv)) { throw new UserException('Ce fichier est vide (aucune ligne trouvée).'); } $this->session->set($this->key, $csv); } public function iterate(): \Generator { if (empty($this->csv)) { throw new \LogicException('No file has been loaded'); } if (!$this->columns || !$this->translation) { throw new \LogicException('Missing columns or translation table'); } $default = array_map(function ($a) { return null; }, $this->columns); $i = 0; foreach ($this->csv as $k => $line) { if ($i++ < $this->skip) { continue; } $row = $default; foreach ($line as $col => $value) { if (!isset($this->translation[$col])) { continue; } $row[$this->translation[$col]] = $value; } $row = (object) $row; yield $k => $row; } } public function getFirstLine(): array { if (empty($this->csv)) { throw new \LogicException('No file has been loaded'); } return reset($this->csv); } public function getSelectedTable(?array $source = null): array { if (null === $source && isset($_POST['translation_table'])) { $source = $_POST['translation_table']; } elseif (null === $source) { $source = []; } $selected = $this->getFirstLine(); foreach ($selected as $k => &$v) { if (isset($source[$k])) { $v = $source[$k]; } elseif (isset($this->translation[$k])) { $v = $this->translation[$k]; } elseif (false !== ($pos = array_search($v, $this->columns, true))) { $v = $pos; } else { $v = null; } } return $selected; } public function getTranslationTable(): array { return $this->translation; } public function setTranslationTable(array $table): void { $translation = []; foreach ($table as $csv => $target) { if (empty($target)) { continue; } if (!array_key_exists($target, $this->columns)) { throw new UserException('Colonne inconnue'); } $translation[(int)$csv] = $target; } foreach ($this->mandatory_columns as $key) { if (!in_array($key, $translation, true)) { throw new UserException(sprintf('La colonne "%s" est obligatoire mais n\'a pas été sélectionnée ou n\'existe pas.', $this->columns[$key])); } } $this->translation = $translation; $this->session->set($this->key . '_translation', $this->translation); } public function clear(): void { $this->session->set($this->key, null); $this->session->set($this->key . '_translation', null); $this->session->set($this->key . '_skip', null); } public function loaded(): bool { return null !== $this->csv; } public function ready(): bool { return $this->loaded() && !empty($this->translation); } public function count(): ?int { return null !== $this->csv ? count($this->csv) : null; } public function skip(int $count): void { $this->skip = $count; $this->session->set($this->key . '_skip', $count); } public function setColumns(array $columns): void { $this->columns = $columns; } public function setMandatoryColumns(array $columns): void { $this->mandatory_columns = $columns; } public function getColumnsString(): string { return implode(', ', $this->getColumns()); } public function getMandatoryColumnsString(): string { return implode(', ', $this->getMandatoryColumns()); } public function getColumns(): array { return $this->columns; } public function getMandatoryColumns(): array { return array_intersect_key($this->columns, $this->mandatory_columns); } } |
Deleted src/include/lib/Garradin/Compta/Categories.php version [aacf281b4b].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Comptes.php version [9bf36bdeef].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Comptes_Bancaires.php version [c2ddfadd03].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Exercices.php version [3bc6667d2a].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Import.php version [f437eb905d].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Journal.php version [88e9a2c624].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Projets.php version [e557763ba3].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Rapports.php version [9726d24a12].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Rapprochement.php version [21098b9dae].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/include/lib/Garradin/Compta/Stats.php version [5104b17973].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Modified src/include/lib/Garradin/Config.php from [c889a0eda3] to [85c9d942d5].
︙ | ︙ | |||
45 46 47 48 49 50 51 | $object = new \stdClass; $this->fields_types = [ 'nom_asso' => $string, 'adresse_asso' => $string, 'email_asso' => $string, 'site_asso' => $string, | | | | | < < < | | | > > | | | 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 | $object = new \stdClass; $this->fields_types = [ 'nom_asso' => $string, 'adresse_asso' => $string, 'email_asso' => $string, 'site_asso' => $string, 'monnaie' => $string, 'pays' => $string, 'champs_membres' => $object, 'categorie_membres' => $int, 'accueil_wiki' => $string, 'accueil_connexion' => $string, 'frequence_sauvegardes' => $int, 'nombre_sauvegardes' => $int, 'champ_identifiant' => $string, 'champ_identite' => $string, 'version' => $string, 'last_chart_change' => $int, 'last_version_check' => $string, 'couleur1' => $string, 'couleur2' => $string, 'image_fond' => $string, 'desactiver_site' => $bool, ]; $db = DB::getInstance(); $this->config = $db->getAssoc('SELECT cle, valeur FROM config ORDER BY cle;'); foreach ($this->config as $key=>&$value) |
︙ | ︙ | |||
118 119 120 121 122 123 124 | { if (empty($this->modified)) return true; $values = []; $db = DB::getInstance(); | > | > > | | | > > | | > > | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | { if (empty($this->modified)) return true; $values = []; $db = DB::getInstance(); // Image files if (isset($this->modified['image_fond'])) { $key = 'image_fond'; $value =& $this->config[$key]; if ($current = $db->firstColumn('SELECT valeur FROM config WHERE cle = ?;', $key)) { try { $f = new Fichiers($current); $f->remove(); } catch (\InvalidArgumentException $e) { // Ignore: the file has already been deleted } } if (strlen($value) > 0) { $content = $value; $value = null; $f = Fichiers::storeFromBase64($key . '.png', $content); $value = $f->id; unset($f); } } unset($value, $key); $db->begin(); foreach ($this->modified as $key=>$modified) { $value = $this->config[$key]; |
︙ | ︙ | |||
161 162 163 164 165 166 167 | $db->preparedQuery('INSERT OR REPLACE INTO config (cle, valeur) VALUES (?, ?);', [$key, $value]); } if (!empty($this->modified['champ_identifiant'])) { // Mettre les champs identifiant vides à NULL pour pouvoir créer un index unique | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | $db->preparedQuery('INSERT OR REPLACE INTO config (cle, valeur) VALUES (?, ?);', [$key, $value]); } if (!empty($this->modified['champ_identifiant'])) { // Mettre les champs identifiant vides à NULL pour pouvoir créer un index unique $db->exec('UPDATE membres SET '.$this->get('champ_identifiant').' = NULL WHERE '.$this->get('champ_identifiant').' = "";'); // Création de l'index unique $db->exec('DROP INDEX IF EXISTS membres_identifiant;'); $db->exec('CREATE UNIQUE INDEX membres_identifiant ON membres ('.$this->get('champ_identifiant').');'); } |
︙ | ︙ | |||
187 188 189 190 191 192 193 | throw new \OutOfBoundsException('Ce champ est inconnu.'); } if (!array_key_exists($key, $this->config)) { return null; } | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | throw new \OutOfBoundsException('Ce champ est inconnu.'); } if (!array_key_exists($key, $this->config)) { return null; } return $this->config[$key]; } public function getVersion() { if (!array_key_exists('version', $this->config)) { |
︙ | ︙ | |||
297 298 299 300 301 302 303 | // Vérification que le champ existe bien if (!$champs->get($value)) { throw new UserException('Le champ '.$value.' n\'existe pas pour la configuration de '.$key); } // Vérification que le champ est unique pour l'identifiant | | | < < < < < < < < < < < | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | // Vérification que le champ existe bien if (!$champs->get($value)) { throw new UserException('Le champ '.$value.' n\'existe pas pour la configuration de '.$key); } // Vérification que le champ est unique pour l'identifiant if ($key == 'champ_identifiant' && !$db->firstColumn('SELECT (COUNT(DISTINCT lower('.$value.')) = COUNT(*)) FROM membres WHERE '.$value.' IS NOT NULL AND '.$value.' != \'\';')) { throw new UserException('Le champ '.$value.' comporte des doublons et ne peut donc pas servir comme identifiant pour la connexion.'); } break; } case 'categorie_membres': { $db = DB::getInstance(); if (!$db->firstColumn('SELECT 1 FROM membres_categories WHERE id = ?;', $value)) { |
︙ | ︙ |
Deleted src/include/lib/Garradin/Cotisations.php version [895e912baf].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Modified src/include/lib/Garradin/DB.php from [b5f765f6ec] to [dad60ad267].
1 2 3 4 | <?php namespace Garradin; | | | | > > > > | | < < < < | < | < < < < < < < < < < | | | | | | | > > > > | | | < | < < < < < < | < > > | < | < < | | > | 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 | <?php namespace Garradin; use KD2\DB\SQLite3; class DB extends SQLite3 { /** * Application ID pour SQLite * @link https://www.sqlite.org/pragma.html#pragma_application_id */ const APPID = 0x5da2d811; static protected $_instance = null; static public function getInstance($create = false, $readonly = false) { if (null === self::$_instance) { self::$_instance = new DB('sqlite', ['file' => DB_FILE]); } return self::$_instance; } private function __clone() { // Désactiver le clonage, car on ne veut qu'une seule instance } public function connect(): void { if (null !== $this->db) { return; } parent::connect(); // Activer les contraintes des foreign keys $this->db->exec('PRAGMA foreign_keys = ON;'); // 10 secondes $this->db->busyTimeout(10 * 1000); // Performance enhancement // see https://www.cs.utexas.edu/~jaya/slides/apsys17-sqlite-slides.pdf // https://ericdraken.com/sqlite-performance-testing/ $this->exec(sprintf('PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA journal_size_limit = %d;', 32 * 1024 * 1024)); $this->db->createFunction('transliterate_to_ascii', ['Garradin\Utils', 'transliterateToAscii']); } public function close(): void { parent::close(); self::$_instance = null; } public function beginSchemaUpdate() { $this->toggleForeignKeys(false); $this->begin(); } public function commitSchemaUpdate() { $this->commit(); $this->toggleForeignKeys(true); } /** * @see https://www.sqlite.org/lang_altertable.html */ public function toggleForeignKeys($enable) { |
︙ | ︙ |
Added src/include/lib/Garradin/DynamicList.php version [f85cc3737c].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | <?php namespace Garradin; class DynamicList { protected $columns; protected $tables; protected $conditions; protected $group; protected $order; protected $modifier; protected $export_callback; protected $title = 'Liste'; protected $count = 'COUNT(*)'; protected $desc = true; protected $per_page = 100; protected $page = 1; private $count_result; public function __construct(array $columns, string $tables, string $conditions) { $this->columns = $columns; $this->tables = $tables; $this->conditions = $conditions; $this->order = key($columns); } public function __get($key) { return $this->$key; } public function setTitle(string $title) { $this->title = $title; } public function setModifier(callable $fn) { $this->modifier = $fn; } public function setExportCallback(callable $fn) { $this->export_callback = $fn; } public function setPageSize(?int $size) { $this->per_page = $size; } public function setConditions(string $conditions) { $this->conditions = $conditions; } public function orderBy(string $key, bool $desc) { if (!array_key_exists($key, $this->columns)) { throw new UserException('Invalid order: ' . $key); } $this->order = $key; $this->desc = $desc; } public function groupBy(string $value) { $this->group = $value; } public function count() { if (null === $this->count_result) { $sql = sprintf('SELECT %s FROM %s WHERE %s;', $this->count, $this->tables, $this->conditions); $this->count_result = DB::getInstance()->firstColumn($sql); } return $this->count_result; } public function export(string $name, string $format = 'csv') { $this->setPageSize(null); $columns = []; foreach ($this->columns as $key => $column) { if (empty($column['label'])) { $columns[] = $key; continue; } $columns[] = $column['label']; } if ('csv' == $format) { CSV::toCSV($name, $this->iterate(false), $this->getHeaderColumns(true), $this->export_callback); } else if ('ods' == $format) { CSV::toODS($name, $this->iterate(false), $this->getHeaderColumns(true), $this->export_callback); } else { throw new UserException('Invalid export format'); } } public function paginationURL() { return Utils::getModifiedURL('?p=[ID]'); } public function orderURL(string $order, bool $desc) { $query = array_merge($_GET, ['o' => $order, 'd' => (int) $desc]); $url = Utils::getSelfURL($query); return $url; } public function setCount(string $count) { $this->count = $count; } public function getHeaderColumns(bool $label_only = false) { $columns = []; foreach ($this->columns as $alias => $properties) { if (isset($properties['only_with_order']) && !($properties['only_with_order'] == $this->order && !$this->desc)) { continue; } // Skip columns that require a certain order AND paginated result if (isset($properties['only_with_order']) && $this->page > 1) { continue; } if (!isset($properties['label'])) { continue; } $columns[$alias] = $label_only ? $properties['label'] : $properties; } return $columns; } public function iterate(bool $include_hidden = true) { $start = ($this->page - 1) * $this->per_page; $columns = []; foreach ($this->columns as $alias => $properties) { // Skip columns that require a certain order (eg. calculating a running sum) if (isset($properties['only_with_order']) && !($properties['only_with_order'] == $this->order && !$this->desc)) { continue; } // Skip columns that require a certain order AND paginated result if (isset($properties['only_with_order']) && $this->page > 1) { continue; } if (!isset($properties['label']) && !$include_hidden) { continue; } $select = array_key_exists('select', $properties) ? $properties['select'] : $alias; if (null === $select) { $select = 'NULL'; } $columns[] = sprintf('%s AS %s', $select, $alias); } $columns = implode(', ', $columns); if (isset($this->columns[$this->order]['order'])) { $order = sprintf($this->columns[$this->order]['order'], $this->desc ? 'DESC' : 'ASC'); } else { $order = $this->order; if (true === $this->desc) { $order .= ' DESC'; } } $group = $this->group ? 'GROUP BY ' . $this->group : ''; $sql = sprintf('SELECT %s FROM %s WHERE %s %s ORDER BY %s', $columns, $this->tables, $this->conditions, $group, $order); if (null !== $this->per_page) { $sql .= sprintf(' LIMIT %d,%d', $start, $this->per_page); } foreach (DB::getInstance()->iterate($sql) as $row) { if ($this->modifier) { call_user_func_array($this->modifier, [&$row]); } yield $row; } } public function loadFromQueryString() { if (!empty($_GET['export'])) { $this->export($this->title, $_GET['export']); exit; } if (!empty($_GET['o'])) { $this->orderBy($_GET['o'], !empty($_GET['d'])); } if (!empty($_GET['p'])) { $this->page = (int)$_GET['p']; } } } |
Added src/include/lib/Garradin/Entities/Accounting/Account.php version [bfec22341c].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | <?php namespace Garradin\Entities\Accounting; use DateTimeInterface; use Garradin\Config; use Garradin\CSV_Custom; use Garradin\DB; use Garradin\DynamicList; use Garradin\Entity; use Garradin\Utils; use Garradin\UserException; use Garradin\ValidationException; use Garradin\Accounting\Charts; class Account extends Entity { const TABLE = 'acc_accounts'; // Actif const ASSET = 1; // Passif const LIABILITY = 2; // Passif ou actif const ASSET_OR_LIABILITY = 3; // Charge const EXPENSE = 4; // Produit const REVENUE = 5; const POSITIONS_NAMES = [ '', 'Actif', 'Passif', 'Actif ou passif', 'Charge', 'Produit', ]; const TYPE_NONE = 0; const TYPE_BANK = 1; const TYPE_CASH = 2; /** * Outstanding transaction accounts (like cheque or card payments) */ const TYPE_OUTSTANDING = 3; const TYPE_THIRD_PARTY = 4; const TYPE_EXPENSE = 5; const TYPE_REVENUE = 6; const TYPE_ANALYTICAL = 7; const TYPE_VOLUNTEERING = 8; const TYPE_OPENING = 9; const TYPE_CLOSING = 10; const TYPE_POSITIVE_RESULT = 11; const TYPE_NEGATIVE_RESULT = 12; const TYPES_NAMES = [ '', 'Banque', 'Caisse', 'Attente d\'encaissement', 'Tiers', 'Dépenses', 'Recettes', 'Analytique', 'Bénévolat', 'Ouverture', 'Clôture', 'Résultat excédentaire', 'Résultat déficitaire', ]; const LIST_COLUMNS = [ 'id' => [ 'select' => 't.id', 'label' => 'N°', ], 'id_line' => [ 'select' => 'l.id', ], 'date' => [ 'label' => 'Date', 'select' => 't.date', 'order' => 'date %s, id %1$s', ], 'debit' => [ 'select' => 'l.debit', 'label' => 'Débit', ], 'credit' => [ 'select' => 'l.credit', 'label' => 'Crédit', ], 'change' => [ 'select' => '(l.credit - l.debit) * %d', 'label' => 'Mouvement', ], 'sum' => [ 'select' => NULL, 'label' => 'Solde cumulé', 'only_with_order' => 'date', ], 'reference' => [ 'label' => 'Pièce comptable', 'select' => 't.reference', ], 'type' => [ 'select' => 't.type', ], 'label' => [ 'select' => 't.label', 'label' => 'Libellé', ], 'line_label' => [ 'select' => 'l.label', 'label' => 'Libellé ligne' ], 'line_reference' => [ 'label' => 'Réf. ligne', 'select' => 'l.reference', ], 'id_analytical' => [ 'select' => 'l.id_analytical', ], 'code_analytical' => [ 'label' => 'Projet', 'select' => 'b.code', ], 'status' => [ 'select' => 't.status', ], ]; protected $id; protected $id_chart; protected $code; protected $label; protected $description; protected $position; protected $type; protected $user = 0; protected $_types = [ 'id' => 'int', 'id_chart' => 'int', 'code' => 'string', 'label' => 'string', 'description' => '?string', 'position' => 'int', 'type' => 'int', 'user' => 'int', ]; protected $_form_rules = [ 'code' => 'required|string|alpha_num|max:10', 'label' => 'required|string|max:200', 'description' => 'string|max:2000', 'position' => 'required|numeric|min:0', 'type' => 'required|numeric|min:0', ]; public function selfCheck(): void { $db = DB::getInstance(); $this->assert(!empty($this->id_chart), 'Aucun plan comptable lié'); $where = 'code = ? AND id_chart = ?'; $where .= $this->exists() ? sprintf(' AND id != %d', $this->id()) : ''; if ($db->test(self::TABLE, $where, $this->code, $this->id_chart)) { throw new ValidationException(sprintf('Le code "%s" est déjà utilisé par un autre compte.', $this->code)); } $this->assert(array_key_exists($this->type, self::TYPES_NAMES), 'Type invalide'); $this->assert(array_key_exists($this->position, self::POSITIONS_NAMES), 'Position invalide'); $this->assert($this->user === 0 || $this->user === 1); parent::selfCheck(); } public function listJournal(int $year_id, bool $simple = false) { $columns = self::LIST_COLUMNS; $tables = 'acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction LEFT JOIN acc_accounts b ON b.id = l.id_analytical'; $conditions = sprintf('l.id_account = %d AND t.id_year = %d', $this->id(), $year_id); $sum = 0; $reverse = $simple && self::isReversed($this->type) ? -1 : 1; if ($simple) { unset($columns['debit']['label'], $columns['credit']['label'], $columns['line_label']); $columns['line_reference']['label'] = 'Réf. paiement'; $columns['change']['select'] = sprintf($columns['change']['select'], $reverse); } else { unset($columns['change']); } $list = new DynamicList($columns, $tables, $conditions); $list->orderBy('date', false); $list->setCount('COUNT(*)'); $list->setPageSize(null); $list->setModifier(function (&$row) use (&$sum, $reverse) { if (property_exists($row, 'sum')) { $sum += isset($row->change) ? $row->change : ($row->credit - $row->debit); $row->sum = $sum; } $row->date = \DateTime::createFromFormat('!Y-m-d', $row->date); }); $list->setExportCallback(function (&$row) { static $columns = ['change', 'sum', 'credit', 'debit']; foreach ($columns as $key) { if (isset($row->$key)) { $row->$key = Utils::money_format($row->$key, '.', '', false); } } }); return $list; } static public function isReversed(int $type): bool { return in_array($type, [self::TYPE_BANK, self::TYPE_CASH, self::TYPE_OUTSTANDING, self::TYPE_EXPENSE, self::TYPE_THIRD_PARTY]); } public function getReconcileJournal(int $year_id, DateTimeInterface $start_date, DateTimeInterface $end_date, bool $only_non_reconciled = false) { if ($end_date < $start_date) { throw new ValidationException('La date de début ne peut être avant la date de fin.'); } $condition = $only_non_reconciled ? ' AND l.reconciled = 0' : ''; $db = DB::getInstance(); $sql = 'SELECT l.debit, l.credit, t.id, t.date, t.reference, l.reference AS line_reference, t.label, l.label AS line_label, l.reconciled, l.id AS id_line FROM acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction WHERE l.id_account = ? AND t.id_year = ? AND t.date >= ? AND t.date <= ? %s ORDER BY t.date, t.id;'; $rows = $db->iterate(sprintf($sql, $condition), $this->id(), $year_id, $start_date->format('Y-m-d'), $end_date->format('Y-m-d')); $sum = $this->getSumAtDate($year_id, $start_date); $reconciled_sum = $this->getSumAtDate($year_id, $start_date, true); $start_sum = false; foreach ($rows as $row) { if (!$start_sum) { yield (object) ['sum' => $sum, 'date' => $start_date]; $start_sum = true; } $row->date = \DateTime::createFromFormat('Y-m-d', $row->date); $sum += ($row->credit - $row->debit); $row->running_sum = $sum; if ($row->reconciled) { $reconciled_sum += ($row->credit - $row->debit); } $row->reconciled_sum = $reconciled_sum; yield $row; } if (!$only_non_reconciled) { yield (object) ['sum' => $sum, 'reconciled_sum' => $reconciled_sum, 'date' => $end_date]; } } public function mergeReconcileJournalAndCSV(\Generator $journal, CSV_Custom $csv) { $lines = []; $csv = iterator_to_array($csv->iterate()); $journal = iterator_to_array($journal); $i = 0; $sum = 0; foreach ($csv as $k => &$line) { try { $date = \DateTime::createFromFormat('!d/m/Y', $line->date); $line->amount = ($line->amount < 0 ? -1 : 1) * Utils::moneyToInteger($line->amount); if (!$date) { throw new UserException('Date invalide : ' . $line->date); } $line->date = $date; } catch (UserException $e) { throw new UserException(sprintf('Ligne %d : %s', $k, $e->getMessage())); } } unset($line); foreach ($journal as $j) { $id = $j->date->format('Ymd') . '.' . $i++; $row = (object) ['csv' => null, 'journal' => $j]; if (isset($j->debit)) { foreach ($csv as &$line) { if (!isset($line->date)) { continue; } if ($j->date->format('Ymd') == $line->date->format('Ymd') && ($j->credit == abs($line->amount) || $j->debit == abs($line->amount))) { $row->csv = $line; $line = null; break; } } } $lines[$id] = $row; } unset($j); foreach ($csv as $line) { if (null == $line) { continue; } $id = $line->date->format('Ymd') . '.' . ($i++); $lines[$id] = (object) ['csv' => $line, 'journal' => null]; } ksort($lines); $prev = null; foreach ($lines as &$line) { $line->add = false; if (isset($line->csv)) { $sum += $line->csv->amount; $line->csv->running_sum = $sum; if ($prev && ($prev->date->format('Ymd') != $line->csv->date->format('Ymd') || $prev->label != $line->csv->label)) { $prev = null; } } if (isset($line->csv) && isset($line->journal)) { $prev = null; } if (isset($line->csv) && !isset($line->journal) && !$prev) { $line->add = true; $prev = $line->csv; } } return $lines; } public function getDepositJournal(int $year_id, array $checked = []): \Generator { $res = DB::getInstance()->iterate('SELECT l.debit, l.credit, t.id, t.date, t.reference, l.reference AS line_reference, t.label, l.label AS line_label, l.reconciled, l.id AS id_line, l.id_account FROM acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction WHERE t.id_year = ? AND l.id_account = ? AND l.credit = 0 AND NOT (t.status & ?) ORDER BY t.date, t.id;', $year_id, $this->id(), Transaction::STATUS_DEPOSIT); $sum = 0; foreach ($res as $row) { $row->date = \DateTime::createFromFormat('Y-m-d', $row->date); $sum += ($row->credit - $row->debit); $row->running_sum = $sum; $row->checked = array_key_exists($row->id, $checked); yield $row; } } public function getSum(int $year_id, bool $simple = false): int { $sum = (int) DB::getInstance()->firstColumn('SELECT SUM(l.credit) - SUM(l.debit) FROM acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction wHERE l.id_account = ? AND t.id_year = ?;', $this->id(), $year_id); if ($simple && self::isReversed($this->type)) { $sum *= -1; } return $sum; } public function getSumAtDate(int $year_id, DateTimeInterface $date, bool $reconciled_only = false): int { $sql = sprintf('SELECT SUM(l.credit) - SUM(l.debit) FROM acc_transactions_lines l INNER JOIN acc_transactions t ON t.id = l.id_transaction wHERE l.id_account = ? AND t.id_year = ? AND t.date < ? %s;', $reconciled_only ? 'AND l.reconciled = 1' : ''); return (int) DB::getInstance()->firstColumn($sql, $this->id(), $year_id, $date->format('Y-m-d')); } public function importSimpleForm(array $translate_type_position, array $translate_type_codes, ?array $source = null) { if (null === $source) { $source = $_POST; } if (empty($source['type'])) { throw new UserException('Le type est obligatoire dans ce formulaire'); } $type = (int) $source['type']; if (array_key_exists($type, $translate_type_position)) { $source['position'] = $translate_type_position[$type]; } else { $source['position'] = self::ASSET_OR_LIABILITY; } if (array_key_exists($type, $translate_type_codes)) { $source['code'] = $translate_type_codes[$type]; } $this->importForm($source); } public function importLimitedForm(?array $source = null) { if (null === $source) { $source = $_POST; } $data = array_intersect_key($source, array_flip(['type', 'description'])); parent::import($data); } public function canDelete(): bool { return !DB::getInstance()->firstColumn(sprintf('SELECT 1 FROM %s WHERE id_account = ? LIMIT 1;', Line::TABLE), $this->id()); } /** * An account properties (position, label and code) can only be changed if: * * it's either a user-created account or an account part of a user-created chart * * has no transactions in a closed year * @return bool */ public function canEdit(): bool { $db = DB::getInstance(); $sql = sprintf('SELECT 1 FROM %s l INNER JOIN %s t ON t.id = l.id_transaction INNER JOIN %s y ON y.id = t.id_year WHERE l.id_account = ? AND y.closed = 1 LIMIT 1;', Line::TABLE, Transaction::TABLE, Year::TABLE); $has_transactions_in_closed_year = $db->firstColumn($sql, $this->id()); if ($has_transactions_in_closed_year) { return false; } if ($this->user) { return true; } return $db->test(Chart::TABLE, 'id = ? AND code IS NULL', $this->id_chart); } public function chart(): Chart { return Charts::get($this->id_chart); } public function save(): bool { Config::getInstance()->set('last_chart_change', time()); return parent::save(); } } |
Added src/include/lib/Garradin/Entities/Accounting/Chart.php version [297b8e2f31].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin\Entities\Accounting; use Garradin\DB; use Garradin\Entity; use Garradin\Utils; use Garradin\ValidationException; use Garradin\UserException; use Garradin\Accounting\Accounts; class Chart extends Entity { const TABLE = 'acc_charts'; protected $id; protected $label; protected $country; protected $code; protected $archived = 0; protected $_types = [ 'id' => 'int', 'label' => 'string', 'country' => 'string', 'code' => '?string', 'archived' => 'int', ]; protected $_form_rules = [ 'label' => 'required|string|max:200', 'country' => 'required|string|size:2', 'archived' => 'numeric|min:0|max:1' ]; public function selfCheck(): void { parent::selfCheck(); $this->assert(Utils::getCountryName($this->country), 'Le code pays doit être un code ISO valide'); $this->assert($this->archived === 0 || $this->archived === 1); } public function accounts() { return new Accounts($this->id()); } public function canDelete() { return !DB::getInstance()->firstColumn(sprintf('SELECT 1 FROM %s WHERE id_chart = ? LIMIT 1;', Year::TABLE), $this->id()); } } |
Added src/include/lib/Garradin/Entities/Accounting/Line.php version [0fde672e4f].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin\Entities\Accounting; use Garradin\Entity; use Garradin\ValidationException; use Garradin\Utils; class Line extends Entity { const TABLE = 'acc_transactions_lines'; protected $id; protected $id_transaction; protected $id_account; protected $credit = 0; protected $debit = 0; protected $reference; protected $label; protected $reconciled = 0; protected $id_analytical; protected $_types = [ 'id' => 'int', 'id_transaction' => 'int', 'id_account' => 'int', 'credit' => 'int', 'debit' => 'int', 'reference' => '?string', 'label' => '?string', 'reconciled' => 'int', 'id_analytical' => '?int', ]; protected $_form_rules = [ 'id_account' => 'required|numeric|in_table:acc_accounts,id', 'id_analytical' => 'numeric|in_table:acc_accounts,id', 'credit' => 'money|min:0', 'debit' => 'money|min:0', 'reference' => 'string|max:200', 'label' => 'string|max:200', ]; public function filterUserValue(string $type, $value, string $key) { if ($key == 'credit' || $key == 'debit') { $value = Utils::moneyToInteger($value); } elseif ($key == 'id_analytical' && $value == 0) { $value = null; } $value = parent::filterUserValue($type, $value, $key); return $value; } public function selfCheck(): void { 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.'); $this->assert($this->reconciled === 0 || $this->reconciled === 1); } } |
Added src/include/lib/Garradin/Entities/Accounting/Transaction.php version [d64763b884].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | <?php namespace Garradin\Entities\Accounting; use KD2\DB\EntityManager; use Garradin\Entity; use Garradin\Fichiers; use Garradin\Accounting\Accounts; use Garradin\ValidationException; use Garradin\DB; use Garradin\Config; use Garradin\Utils; use Garradin\UserException; class Transaction extends Entity { const TABLE = 'acc_transactions'; const TYPE_ADVANCED = 0; const TYPE_REVENUE = 1; const TYPE_EXPENSE = 2; const TYPE_TRANSFER = 3; const TYPE_DEBT = 4; const TYPE_CREDIT = 5; const STATUS_WAITING = 1; const STATUS_PAID = 2; const STATUS_DEPOSIT = 4; const STATUS_NAMES = [ 1 => 'En attente de règlement', 2 => 'Réglé', 4 => 'Déposé en banque', ]; const TYPES_NAMES = [ 'Avancé', 'Recette', 'Dépense', 'Virement', 'Dette', 'Créance', ]; protected $id; protected $type; protected $status = 0; protected $label; protected $notes; protected $reference; protected $date; protected $validated = 0; protected $hash; protected $prev_hash; protected $id_year; protected $id_creator; protected $id_related; protected $_types = [ 'id' => 'int', 'type' => 'int', 'status' => 'int', 'label' => 'string', 'notes' => '?string', 'reference' => '?string', 'date' => 'date', 'validated' => 'bool', 'hash' => '?string', 'prev_hash' => '?string', 'id_year' => 'int', 'id_creator' => '?int', 'id_related' => '?int', ]; protected $_form_rules = [ 'label' => 'required|string|max:200', 'notes' => 'string|max:20000', 'reference' => 'string|max:200', 'date' => 'required|date_format:d/m/Y', ]; protected $_lines; protected $_old_lines = []; protected $_related; static public function getTypeFromAccountType(int $account_type) { switch ($account_type) { case Account::TYPE_REVENUE: return self::TYPE_REVENUE; case Account::TYPE_EXPENSE: return self::TYPE_EXPENSE; case Account::TYPE_THIRD_PARTY: return self::TYPE_DEBT; default: return self::TYPE_TRANSFER; } } public function getLinesWithAccounts() { $em = EntityManager::getInstance(Line::class); return $em->DB()->get('SELECT l.*, a.label AS account_name, a.code AS account_code, b.label AS analytical_name FROM acc_transactions_lines l INNER JOIN acc_accounts a ON a.id = l.id_account LEFT JOIN acc_accounts b ON b.id = l.id_analytical WHERE l.id_transaction = ? ORDER BY l.id;', $this->id); } public function getLines($with_accounts = false) { if (null === $this->_lines && $this->exists()) { $em = EntityManager::getInstance(Line::class); $this->_lines = $em->all('SELECT * FROM @TABLE WHERE id_transaction = ? ORDER BY id;', $this->id); } elseif (null === $this->_lines) { $this->_lines = []; } return $this->_lines; } public function removeLine(Line $remove) { $new = []; foreach ($this->getLines() as $line) { if ($line->id === $remove->id) { $this->_old_lines[] = $remove; } else { $new[] = $line; } } $this->_lines = $new; } public function resetLines() { $this->_old_lines = $this->getLines(); $this->_lines = []; } public function getLine(int $id) { foreach ($this->getLines() as $line) { if ($line->id === $id) { return $line; } } return null; } public function getLinesCreditSum() { $sum = 0; foreach ($this->getLines() as $line) { $sum += $line->credit; } return $sum; } public function getTypesAccounts() { if ($this->type == self::TYPE_ADVANCED) { return []; } $debit = null; $credit = null; $lines = $this->getLinesWithAccounts(); foreach ($lines as $line) { $account = [$line->id_account => sprintf('%s — %s', $line->account_code, $line->account_name)]; if ($line->debit) { $debit = $account; } else { $credit = $account; } } $type = $this->getTypesDetails()[$this->type]; return [ $type->accounts[0]->position == 'credit' ? $credit : $debit, $type->accounts[1]->position == 'credit' ? $credit : $debit, ]; } /* 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 $line) { hash_update($hash, implode(',', [$line->compte, $line->debit, $line->credit])); } return hash_final($hash, false); } public function checkHash() { return hash_equals($this->getHash(), $this->hash); } */ public function addLine(Line $line) { $this->_lines[] = $line; } public function sum(): int { $sum = 0; foreach ($this->getLines() as $line) { $sum += $line->credit; // Because credit == debit, we only use credit } return $sum; } public function save(): bool { if ($this->validated && !isset($this->_modified['validated'])) { throw new ValidationException('Il n\'est pas possible de modifier une écriture qui a été validé'); } $db = DB::getInstance(); if ($db->test(Year::TABLE, 'id = ? AND closed = 1', $this->id_year)) { throw new ValidationException('Il n\'est pas possible de modifier une écriture qui fait partie d\'un exercice clôturé'); } if (!parent::save()) { return false; } foreach ($this->getLines() as $line) { $line->id_transaction = $this->id(); $line->save(); } foreach ($this->_old_lines as $line) { $line->delete(); } // Remove flag if ((self::TYPE_DEBT == $this->type || self::TYPE_CREDIT == $this->type) && $this->_related) { $this->_related->removeStatus(self::STATUS_WAITING); $this->_related->addStatus(self::STATUS_PAID); $this->_related->save(); } return true; } public function removeStatus(int $property) { $this->set('status', $this->status & ~$property); } public function addStatus(int $property) { $this->set('status', $this->status | $property); } public function delete(): bool { if ($this->validated) { throw new ValidationException('Il n\'est pas possible de supprimer une écriture qui a été validée'); } $db = DB::getInstance(); if ($db->test(Year::TABLE, 'id = ? AND closed = 1', $this->id_year)) { throw new ValidationException('Il n\'est pas possible de supprimer une écriture qui fait partie d\'un exercice clôturé'); } Fichiers::deleteLinkedFiles(Fichiers::LIEN_COMPTA, $this->id()); return parent::delete(); } public function selfCheck(): void { parent::selfCheck(); $db = DB::getInstance(); $config = Config::getInstance(); // ID d'exercice obligatoire if (null === $this->id_year) { throw new \LogicException('Aucun exercice spécifié.'); } if (!$db->test(Year::TABLE, 'id = ? AND start_date <= ? AND end_date >= ?;', $this->id_year, $this->date->format('Y-m-d'), $this->date->format('Y-m-d'))) { throw new ValidationException('La date ne correspond pas à l\'exercice sélectionné : ' . $this->date->format('d/m/Y')); } $total = 0; $lines = $this->getLines(); foreach ($lines as $line) { $total += $line->credit; $total -= $line->debit; } if (0 !== $total) { throw new ValidationException(sprintf('Écriture non équilibrée : déséquilibre (%s) entre débits et crédits', Utils::money_format($total))); } if (!array_key_exists($this->type, self::TYPES_NAMES)) { throw new ValidationException('Type d\'écriture inconnu : ' . $this->type); } } public function importFromDepositForm(?array $source = null): void { if (null === $source) { $source = $_POST; } if (empty($source['amount'])) { throw new UserException('Montant non précisé'); } $this->type = self::TYPE_TRANSFER; $amount = $source['amount']; $key = 'account_transfer'; $account = isset($source[$key]) && @count($source[$key]) ? key($source[$key]) : null; $line = new Line; $line->importForm([ 'debit' => $amount, 'credit' => 0, 'id_account' => $account, ]); $this->addLine($line); $this->importForm($source); } public function importFromNewForm(?array $source = null): void { if (null === $source) { $source = $_POST; } if (!isset($source['type'])) { throw new ValidationException('Type d\'écriture inconnu'); } $type = $source['type']; $this->importForm($source); if (self::TYPE_ADVANCED == $type) { $lines = Utils::array_transpose($source['lines']); foreach ($lines as $i => $line) { $line['id_account'] = @count($line['account']) ? key($line['account']) : null; if (!$line['id_account']) { throw new ValidationException('Numéro de compte invalide sur la ligne ' . ($i+1)); } $line = (new Line)->import($line); $this->addLine($line); } } else { $details = self::getTypesDetails(); if (!array_key_exists($type, $details)) { throw new ValidationException('Type d\'écriture inconnu'); } if (empty($this->_related) && ($type == self::TYPE_DEBT || $type == self::TYPE_CREDIT)) { $this->status = self::STATUS_WAITING; } if (empty($source['amount'])) { throw new UserException('Montant non précisé'); } $amount = $source['amount']; // Fill lines using a pre-defined setup obtained from getTypesDetails foreach ($details[$type]->accounts as $k => $account) { $credit = $account->position == 'credit' ? $amount : 0; $debit = $account->position == 'debit' ? $amount : 0; $key = sprintf('account_%d_%d', $type, $k); $account = isset($source[$key]) && @count($source[$key]) ? key($source[$key]) : null; $line = new Line; $line->importForm([ 'reference' => $source['payment_reference'], 'credit' => $credit, 'debit' => $debit, 'id_account' => $account, 'id_analytical' => !empty($source['id_analytical']) ? $source['id_analytical'] : null, ]); $this->addLine($line); } } } public function importFromEditForm(?array $source = null): void { if (null === $source) { $source = $_POST; } $this->resetLines(); $this->importFromNewForm($source); } public function importFromBalanceForm(Year $year, ?array $source = null): void { if (null === $source) { $source = $_POST; } if (!isset($source['lines']) || !is_array($source['lines'])) { throw new ValidationException('Aucun contenu trouvé dans le formulaire.'); } $this->label = 'Balance d\'ouverture'; $this->date = $year->start_date; $this->id_year = $year->id(); $this->type = self::TYPE_ADVANCED; try { $lines = Utils::array_transpose($source['lines']); } catch (\LogicException $e) { throw new ValidationException('Aucun compte sélectionné pour certaines lignes.'); } $debit = $credit = 0; foreach ($lines as $line) { $line['id_account'] = @count($line['account']) ? key($line['account']) : null; $line = (new Line)->importForm($line); $this->addLine($line); $debit += $line->debit; $credit += $line->credit; } if ($debit != $credit) { // Add final balance line $line = new Line; if ($debit > $credit) { $line->debit = $debit - $credit; } else { $line->credit = $credit - $debit; } $open_account = EntityManager::findOne(Account::class, 'SELECT * FROM @TABLE WHERE id_chart = ? AND type = ? LIMIT 1;', $year->id_chart, Account::TYPE_OPENING); if (!$open_account) { throw new ValidationException('Aucun compte favori de bilan d\'ouverture n\'existe dans le plan comptable'); } $line->id_account = $open_account->id(); $this->addLine($line); } } public function year() { return EntityManager::findOneById(Year::class, $this->id_year); } public function listFiles() { return Fichiers::listLinkedFiles(Fichiers::LIEN_COMPTA, $this->id()); } public function linkToUser(int $user_id, ?int $service_id = null) { $db = EntityManager::getInstance(self::class)->DB(); return $db->preparedQuery('INSERT OR IGNORE INTO acc_transactions_users (id_transaction, id_user, id_service_user) VALUES (?, ?, ?);', $this->id(), $user_id, $service_id); } public function updateLinkedUsers(array $users) { $db = EntityManager::getInstance(self::class)->DB(); $db->begin(); $sql = sprintf('DELETE FROM acc_transactions_users WHERE id_transaction = ? AND id_service_user IS NULL AND %s;', $db->where('id_user', 'NOT IN', $users)); $db->preparedQuery($sql, $this->id()); foreach ($users as $id) { $db->preparedQuery('INSERT OR IGNORE INTO acc_transactions_users (id_transaction, id_user) VALUES (?, ?);', $this->id(), $id); } $db->commit(); } public function listLinkedUsers() { $db = EntityManager::getInstance(self::class)->DB(); $identity_column = Config::getInstance()->get('champ_identite'); $sql = sprintf('SELECT m.id, m.%s AS identity, l.id_service_user FROM membres m INNER JOIN acc_transactions_users l ON l.id_user = m.id WHERE l.id_transaction = ?;', $identity_column); return $db->get($sql, $this->id()); } public function listLinkedUsersAssoc() { $db = EntityManager::getInstance(self::class)->DB(); $identity_column = Config::getInstance()->get('champ_identite'); $sql = sprintf('SELECT m.id, m.%s AS identity FROM membres m INNER JOIN acc_transactions_users l ON l.id_user = m.id WHERE l.id_transaction = ?;', $identity_column); return $db->getAssoc($sql, $this->id()); } static public function getTypesDetails() { $details = [ self::TYPE_REVENUE => [ 'accounts' => [ [ 'label' => 'Type de recette', 'targets' => [Account::TYPE_REVENUE], 'position' => 'credit', ], [ 'label' => 'Compte d\'encaissement', 'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING], 'position' => 'debit', ], ], 'label' => self::TYPES_NAMES[self::TYPE_REVENUE], ], self::TYPE_EXPENSE => [ 'accounts' => [ [ 'label' => 'Type de dépense', 'targets' => [Account::TYPE_EXPENSE], 'position' => 'debit', ], [ 'label' => 'Compte de décaissement', 'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING], 'position' => 'credit', ], ], 'label' => self::TYPES_NAMES[self::TYPE_EXPENSE], 'help' => null, ], self::TYPE_TRANSFER => [ 'accounts' => [ [ 'label' => 'De', 'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING], 'position' => 'credit', ], [ 'label' => 'Vers', 'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING], 'position' => 'debit', ], ], 'label' => self::TYPES_NAMES[self::TYPE_TRANSFER], 'help' => 'Dépôt en banque, virement interne, etc.', ], self::TYPE_DEBT => [ 'accounts' => [ [ 'label' => 'Compte de tiers', 'targets' => [Account::TYPE_THIRD_PARTY], 'position' => 'credit', ], [ 'label' => 'Type de dette (dépense)', 'targets' => [Account::TYPE_EXPENSE], 'position' => 'debit', ], ], 'label' => self::TYPES_NAMES[self::TYPE_DEBT], 'help' => 'Quand l\'association doit de l\'argent à un membre ou un fournisseur', ], self::TYPE_CREDIT => [ 'accounts' => [ [ 'label' => 'Compte de tiers', 'targets' => [Account::TYPE_THIRD_PARTY], 'position' => 'debit', ], [ 'label' => 'Type de créance (recette)', 'targets' => [Account::TYPE_REVENUE], 'position' => 'credit', ], ], 'label' => self::TYPES_NAMES[self::TYPE_CREDIT], 'help' => 'Quand un membre ou un fournisseur doit de l\'argent à l\'association', ], self::TYPE_ADVANCED => [ 'accounts' => [], 'label' => self::TYPES_NAMES[self::TYPE_ADVANCED], 'help' => 'Choisir les comptes du plan comptable, ventiler une écriture sur plusieurs comptes, etc.', ], ]; foreach ($details as $key => &$type) { $type = (object) $type; $type->id = $key; foreach ($type->accounts as &$account) { $account = (object) $account; $account->targets_string = implode(':', $account->targets); } } return $details; } public function payOffFrom(int $id): \stdClass { $this->_related = EntityManager::findOneById(self::class, $id); if (!$this->_related) { throw new \LogicException('Écriture d\'origine invalide'); } $this->id_related = $this->_related->id(); $this->label = ($this->_related->type == Transaction::TYPE_DEBT ? 'Règlement de dette : ' : 'Règlement de créance : ') . $this->_related->label; $this->type = $this->_related->type; $out = (object) [ 'id' => $this->_related->id, 'sum' => $this->_related->sum(), 'id_account' => null, 'form_account_name' => sprintf('account_%d_%d', $this->type, 1), 'form_target_name' => sprintf('account_%d_%d', $this->type, 0), ]; foreach ($this->_related->getLines() as $line) { if (($this->_related->type == self::TYPE_DEBT && $line->debit) || ($this->_related->type == self::TYPE_CREDIT && $line->credit)) { // Skip the type of debt/credit, just keep the thirdparty account continue; } $out->id_account = $line->id_account; break; } return $out; } } |
Added src/include/lib/Garradin/Entities/Accounting/Year.php version [efb670bde0].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin\Entities\Accounting; use KD2\DB\EntityManager; use Garradin\DB; use Garradin\Entity; use Garradin\Fichiers; use Garradin\UserException; use Garradin\Accounting\Accounts; class Year extends Entity { const TABLE = 'acc_years'; protected $id; protected $label; protected $start_date; protected $end_date; protected $closed = 0; protected $id_chart; protected $_types = [ 'id' => 'int', 'label' => 'string', 'start_date' => 'date', 'end_date' => 'date', 'closed' => 'int', 'id_chart' => 'int', ]; protected $_form_rules = [ 'label' => 'required|string|max:200', 'start_date' => 'required|date_format:d/m/Y', 'end_date' => 'required|date_format:d/m/Y', ]; 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 === 0 || $this->closed === 1); $this->assert($this->closed == 1 || !isset($this->_modified['closed']), 'Il est interdit de réouvrir un exercice clôturé'); $db = DB::getInstance(); $this->assert($this->id_chart !== null); if ($this->exists()) { $this->assert( !$db->test(Transaction::TABLE, 'id_year = ? AND date < ?', $this->id(), $this->start_date->format('Y-m-d')), '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->format('Y-m-d')), 'Des mouvements de cet exercice ont une date postérieure à la date de fin de l\'exercice.' ); } } public function close(int $user_id): void { if ($this->closed) { throw new \LogicException('Cet exercice est déjà clôturé'); } $this->set('closed', 1); $this->save(); } public function delete(): bool { // Manual delete of transactions, as there is a voluntary safeguard in SQL: no cascade DB::getInstance()->preparedQuery('DELETE FROM acc_transactions WHERE id_year = ?;', $this->id()); // Clean up files Fichiers::deleteUnlinkedFiles(); return parent::delete(); } public function countTransactions(): int { $db = DB::getInstance(); return $db->count(Transaction::TABLE, $db->where('id_year', $this->id())); } public function chart() { return EntityManager::findOneById(Chart::class, $this->id_chart); } public function accounts() { return new Accounts($this->id_chart); } } |
Added src/include/lib/Garradin/Entities/Services/Fee.php version [6f825919cc].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 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 | <?php namespace Garradin\Entities\Services; use Garradin\Config; use Garradin\DB; use Garradin\DynamicList; use Garradin\Entity; use Garradin\ValidationException; use Garradin\Utils; use Garradin\Entities\Accounting\Account; use Garradin\Entities\Accounting\Year; use KD2\DB\EntityManager; class Fee extends Entity { const TABLE = 'services_fees'; protected $id; protected $label; protected $description; protected $amount; protected $formula; protected $id_service; protected $id_account; protected $id_year; protected $_types = [ 'id' => 'int', 'label' => 'string', 'description' => '?string', 'amount' => '?int', 'formula' => '?string', 'id_service' => 'int', 'id_account' => '?int', 'id_year' => '?int', ]; 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['amount_type'])) { if ($source['amount_type'] == 2) { $source['amount'] = null; } elseif ($source['amount_type'] == 1) { $source['formula'] = null; } else { $source['amount'] = $source['formula'] = null; } } if (empty($source['accounting'])) { $source['id_account'] = $source['id_year'] = null; } return parent::importForm($source); } public function selfCheck(): void { $db = DB::getInstance(); parent::selfCheck(); $this->assert(trim($this->label) !== '', 'Le libellé doit être renseigné'); $this->assert(strlen($this->label) <= 200, 'Le libellé doit faire moins de 200 caractères'); $this->assert(strlen($this->description) <= 2000, 'La description doit faire moins de 2000 caractères'); $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->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) { return $this->amount; } elseif ($this->formula) { $db = DB::getInstance(); return (int) $db->firstColumn($this->getFormulaSQL(), $user_id); } return null; } protected function getFormulaSQL() { return sprintf('SELECT %s FROM membres WHERE id = ?;', $this->formula); } protected function checkFormula() { try { $db = DB::getInstance(); $sql = $this->getFormulaSQL(); $db->protectSelect(['membres' => null], $sql); return true; } catch (\Exception $e) { throw $e; return false; } } public function service() { return EntityManager::findOneById(Service::class, $this->id_service); } public function paidUsersList(): DynamicList { $identity = Config::getInstance()->get('champ_identite'); $columns = [ 'id_user' => [ 'select' => 'su.id_user', ], 'identity' => [ 'label' => 'Membre', 'select' => 'm.' . $identity, 'order' => sprintf('transliterate_to_ascii(m.%s) COLLATE NOCASE', $identity), ], 'paid' => [ 'label' => 'Payé ?', 'select' => 'su.paid', ], 'paid_amount' => [ 'label' => 'Montant payé', 'select' => 'SUM(l.credit)', ], 'date' => [ 'label' => 'Date', 'select' => 'su.date', ], ]; $tables = 'services_users su INNER JOIN membres m ON m.id = su.id_user INNER JOIN services_fees sf ON sf.id = su.id_fee LEFT JOIN acc_transactions_users tu ON tu.id_service_user = su.id LEFT JOIN acc_transactions_lines l ON l.id_transaction = tu.id_transaction'; $conditions = sprintf('su.id_fee = %d AND su.paid = 1 AND su.expiry_date >= date()', $this->id()); $list = new DynamicList($columns, $tables, $conditions); $list->groupBy('su.id_user'); $list->orderBy('date', true); $list->setCount('COUNT(DISTINCT su.id_user)'); return $list; } public function unpaidUsersList(): DynamicList { $list = $this->paidUsersList(); $conditions = sprintf('su.id_fee = %d AND su.paid = 0', $this->id()); $list->setConditions($conditions); return $list; } public function expiredUsersList(): DynamicList { $list = $this->paidUsersList(); $conditions = sprintf('su.id_fee = %d AND su.expiry_date < date()', $this->id()); $list->setConditions($conditions); return $list; } } |
Added src/include/lib/Garradin/Entities/Services/Reminder.php version [308065935f].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin\Entities\Services; use Garradin\DynamicList; use Garradin\Entity; use Garradin\ValidationException; use Garradin\Config; use KD2\DB\EntityManager; class Reminder extends Entity { const TABLE = 'services_reminders'; protected $id; protected $id_service; protected $delay; protected $subject; protected $body; protected $_types = [ 'id' => 'int', 'id_service' => 'int', 'delay' => 'int', 'subject' => 'string', 'body' => 'string', ]; public function selfCheck(): void { parent::selfCheck(); $this->assert($this->id_service, 'Aucun service n\'a été indiqué pour ce tarif.'); $this->assert(trim($this->subject) !== '', 'Le sujet doit être renseigné'); $this->assert(strlen($this->subject) <= 200, 'Le sujet doit faire moins de 200 caractères'); $this->assert(trim($this->body) !== '', 'Le corps du message doit être renseigné'); $this->assert(strlen($this->body) <= 64000, 'Le corps du message doit faire moins de 64.000 caractères'); $this->assert($this->delay !== null, 'Le délai de rappel doit être renseigné'); } public function service() { return EntityManager::findOneById(Service::class, $this->id_service); } public function importForm(array $source = null) { if (null === $source) { $source = $_POST; } if (isset($source['delay_type'])) { if (1 == $source['delay_type'] && !empty($source['delay_before'])) { $source['delay'] = (int)$source['delay_before'] * -1; } elseif (2 == $source['delay_type'] && !empty($source['delay_after'])) { $source['delay'] = (int)$source['delay_after']; } else { $source['delay'] = 0; } } parent::importForm($source); } public function sentList(): DynamicList { $identity = Config::getInstance()->get('champ_identite'); $columns = [ 'id_user' => [ 'select' => 'srs.id_user', ], 'identity' => [ 'label' => 'Membre', 'select' => 'm.' . $identity, 'order' => sprintf('transliterate_to_ascii(m.%s) COLLATE NOCASE', $identity), ], 'email' => [ 'label' => 'Adresse e-mail', 'select' => 'm.email', ], 'date' => [ 'label' => 'Date', 'select' => 'srs.date', ], ]; $tables = 'services_reminders_sent srs INNER JOIN membres m ON m.id = srs.id_user'; $conditions = sprintf('srs.id_reminder = %d', $this->id()); $list = new DynamicList($columns, $tables, $conditions); $list->orderBy('date', true); return $list; } } |
Added src/include/lib/Garradin/Entities/Services/Service.php version [5fa29d7db5].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | <?php namespace Garradin\Entities\Services; use Garradin\Config; use Garradin\DynamicList; use Garradin\Entity; use Garradin\ValidationException; use Garradin\Utils; use Garradin\Services\Fees; class Service extends Entity { const TABLE = 'services'; protected $id; protected $label; protected $description; protected $duration; protected $start_date; protected $end_date; protected $_types = [ 'id' => 'int', 'label' => 'string', 'description' => '?string', 'duration' => '?int', 'start_date' => '?date', 'end_date' => '?date', ]; public function selfCheck(): void { parent::selfCheck(); $this->assert(trim($this->label) !== '', 'Le libellé doit être renseigné'); $this->assert(strlen($this->label) <= 200, 'Le libellé doit faire moins de 200 caractères'); $this->assert(strlen($this->description) <= 2000, 'La description doit faire moins de 2000 caractères'); $this->assert(!isset($this->duration, $this->start_date, $this->end_date) || $this->duration || ($this->start_date && $this->end_date), 'Seulement une option doit être choisie : durée ou dates de début et de fin de validité'); $this->assert(null === $this->start_date || $this->start_date instanceof \DateTimeInterface); $this->assert(null === $this->end_date || $this->end_date instanceof \DateTimeInterface); $this->assert(null === $this->duration || (is_int($this->duration) && $this->duration > 0), 'La durée n\'est pas valide'); $this->assert(null === $this->start_date || $this->end_date > $this->start_date, 'La date de fin de validité doit être après la date de début'); } public function importForm(?array $source = null) { if (null === $source) { $source = $_POST; } if (isset($source['period'])) { if (1 == $source['period']) { $source['start_date'] = $source['end_date'] = null; } elseif (2 == $source['period']) { $source['duration'] = null; } else { $source['duration'] = $source['start_date'] = $source['end_date'] = null; } } parent::importForm($source); } public function fees() { return new Fees($this->id()); } public function paidUsersList(): DynamicList { $identity = Config::getInstance()->get('champ_identite'); $columns = [ 'id_user' => [ ], 'end_date' => [ ], 'identity' => [ 'label' => 'Membre', 'select' => 'm.' . $identity, 'order' => sprintf('transliterate_to_ascii(m.%s) COLLATE NOCASE', $identity), ], 'status' => [ 'label' => 'Statut', 'select' => 'CASE WHEN su.expiry_date < date() THEN -1 WHEN su.expiry_date >= date() THEN 1 ELSE 0 END', ], 'paid' => [ 'label' => 'Payé ?', 'select' => 'su.paid', ], 'expiry' => [ 'label' => 'Date d\'expiration', 'select' => 'MAX(su.expiry_date)', ], 'fee' => [ 'label' => 'Tarif', 'select' => 'sf.label', ], 'date' => [ 'label' => 'Date d\'inscription', 'select' => 'su.date', ], ]; $tables = 'services_users su INNER JOIN membres m ON m.id = su.id_user INNER JOIN services s ON s.id = su.id_service INNER JOIN services_fees sf ON sf.id = su.id_fee'; $conditions = sprintf('su.id_service = %d AND su.paid = 1 AND su.expiry_date >= date()', $this->id()); $list = new DynamicList($columns, $tables, $conditions); $list->groupBy('su.id_user'); $list->orderBy('date', true); $list->setCount('COUNT(DISTINCT su.id_user)'); return $list; } public function unpaidUsersList(): DynamicList { $list = $this->paidUsersList(); $conditions = sprintf('su.id_service = %d AND su.paid = 0', $this->id()); $list->setConditions($conditions); return $list; } public function expiredUsersList(): DynamicList { $list = $this->paidUsersList(); $conditions = sprintf('su.id_service = %d AND su.expiry_date < date()', $this->id()); $list->setConditions($conditions); return $list; } } |
Added src/include/lib/Garradin/Entities/Services/Service_User.php version [d694479106].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | <?php namespace Garradin\Entities\Services; use Garradin\DB; use Garradin\Entity; use Garradin\ValidationException; use Garradin\Services\Fees; use Garradin\Services\Services; use Garradin\Entities\Accounting\Transaction; class Service_User extends Entity { const TABLE = 'services_users'; protected $id; protected $id_user; protected $id_service; protected $id_fee; protected $paid; protected $expected_amount; protected $date; protected $expiry_date; protected $_types = [ 'id' => 'int', 'id_user' => 'int', 'id_service' => 'int', 'id_fee' => '?int', 'paid' => 'bool', 'expected_amount' => '?int', 'date' => 'date', 'expiry_date' => '?date', ]; protected $_service, $_fee; public function selfCheck(): void { $this->paid = (bool) $this->paid; $this->assert(!$this->exists() && !DB::getInstance()->test(self::TABLE, 'id_user = ? AND id_service = ? AND date = ?', $this->id_user, $this->id_service, $this->date->format('Y-m-d')), 'Cette activité a déjà été enregistrée pour ce membre et cette date'); } public function importForm(?array $source = null) { if (null === $source) { $source = $_POST; } if (!empty($source['id_service']) && empty($source['expiry_date'])) { $service = $this->_service = Services::get((int) $source['id_service']); if (!$service) { throw new \LogicException('The requested service is not found'); } if ($service->duration) { $dt = new \DateTime; $dt->modify(sprintf('+%d days', $service->duration)); $this->expiry_date = $dt; } elseif ($service->end_date) { $this->expiry_date = $service->end_date; } else { $this->expiry_date = null; } } return parent::importForm($source); } public function service() { if (null === $this->_service) { $this->_service = Services::get($this->id_service); } return $this->_service; } public function fee() { if (null === $this->_fee) { $this->_fee = Fees::get($this->id_fee); } return $this->_fee; } public function addPayment(int $user_id, ?array $source = null) { if (null === $source) { $source = $_POST; } $transaction = new Transaction; $transaction->id_creator = $user_id; $transaction->id_year = $this->fee()->id_year; $source['type'] = Transaction::TYPE_REVENUE; $key = sprintf('account_%d_', $source['type']); $source[$key . '0'] = [$this->fee()->id_account => '']; $source[$key . '1'] = isset($source['account']) ? $source['account'] : null; $source['label'] = 'Règlement activité - ' . $this->service()->label . ' - ' . $this->fee()->label; $source['date'] = $this->date->format('d/m/Y'); $transaction->importFromNewForm($source); $transaction->save(); $transaction->linkToUser($this->id_user, $this->id()); return $transaction; } static public function saveFromForm(int $user_id, ?array $source = null) { if (null === $source) { $source = $_POST; } $db = DB::getInstance(); $db->begin(); $su = new self; $su->date = new \DateTime; $su->importForm($source); if ($su->id_fee && $su->fee()->id_account && $su->id_user) { $su->expected_amount = $su->fee()->getAmountForUser($su->id_user); } $su->save(); if ($su->id_fee && $su->fee()->id_account && !empty($source['amount'])) { $su->addPayment($user_id, $source); } $db->commit(); return $su; } } |
Added src/include/lib/Garradin/Entity.php version [de03b9076a].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin; use Garradin\Form; use KD2\DB\AbstractEntity; class Entity extends AbstractEntity { protected $_form_rules = []; /** * Valider les champs avant enregistrement * @throws ValidationException Si une erreur de validation survient */ public function importForm(array $source = null) { if (null === $source) { $source = $_POST; } $form = new Form; if (!$form->validate($this->_form_rules, $source)) { $messages = $form->getErrorMessages(); throw new ValidationException(implode("\n", $messages)); } return $this->import($source); } protected function filterUserValue(string $type, $value, string $key) { if ($type == 'date') { if (!trim($value)) { return null; } if (preg_match('!^\d{2}/\d{2}/\d{2}$!', $value)) { return \DateTime::createFromFormat('d/m/y', $value); } elseif (preg_match('!^\d{2}/\d{2}/\d{4}$!', $value)) { return \DateTime::createFromFormat('d/m/Y', $value); } elseif (null !== $value) { throw new ValidationException('Format de date invalide (merci d\'utiliser le format JJ/MM/AAAA) : ' . $value); } } else { return parent::filterUserValue($type, $value, $key); } } protected function assert(bool $test, string $message = null): void { if ($test) { return; } if (null === $message) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); $caller_class = array_pop($backtrace); $caller = array_pop($backtrace); $message = sprintf('Entity assertion fail from class %s on line %d', $caller_class['class'], $caller['line']); throw new \UnexpectedValueException($message); } else { throw new ValidationException($message); } } } |
Modified src/include/lib/Garradin/Fichiers.php from [b62209a8ff] to [76103311d2].
1 2 3 4 | <?php namespace Garradin; | | | | | | > > | 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 | <?php namespace Garradin; use KD2\Graphics\Image; use Garradin\Membres\Session; class Fichiers { public $id; public $nom; public $type; public $image; public $datetime; public $hash; public $taille; public $id_contenu; /** * Tailles de miniatures autorisées, pour ne pas avoir 500 fichiers générés avec 500 tailles différentes * @var array */ protected static $allowed_thumb_sizes = [200, 500]; const LIEN_COMPTA = 'acc_transactions'; const LIEN_WIKI = 'wiki_pages'; const LIEN_MEMBRES = 'membres'; /** * Renvoie l'URL vers un fichier * @param integer $id Numéro du fichier * @param string $nom Nom de fichier avec extension * @param integer $size Taille de la miniature désirée (pour les images) * @return string URL du fichier */ static public function _getURL(int $id, string $nom, string $hash, $size = false): string { $url = sprintf('%sf/%s/%s?', WWW_URL, base_convert((int)$id, 10, 36), $nom); if ($size) { $url .= self::_findThumbSize($size) . 'px&'; } $url .= substr($hash, 0, 10); return $url; } /** * Renvoie la taille de miniature la plus proche de la taille demandée * @param integer $size Taille demandée |
︙ | ︙ | |||
69 70 71 72 73 74 75 76 | return max(self::$allowed_thumb_sizes); } /** * Constructeur de l'objet pour un fichier * @param integer $id Numéro unique du fichier */ | > | | | | 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 | return max(self::$allowed_thumb_sizes); } /** * Constructeur de l'objet pour un fichier * @param integer $id Numéro unique du fichier * @param $data array|object File data to populate object */ public function __construct(int $id, $data = null) { if (is_null($data)) { $data = DB::getInstance()->first('SELECT fichiers.*, fc.hash, fc.taille, strftime(\'%s\', datetime) AS datetime FROM fichiers INNER JOIN fichiers_contenu AS fc ON fc.id = fichiers.id_contenu WHERE fichiers.id = ?;', (int)$id); } if (!$data) { throw new \InvalidArgumentException('Ce fichier n\'existe pas.'); } foreach ((array)$data as $key => $value) { $this->$key = $value; } } /** * Renvoie l'adresse d'accès au fichier * @param boolean $size Taille éventuelle de la miniature demandée * @return string URL d'accès au fichier */ public function getURL($size = false) { return self::_getURL($this->id, $this->nom, $this->hash, $size); } /** * Lier un fichier à un contenu * @param string $type Type de contenu (constantes LIEN_*) * @param integer $foreign_id ID du contenu lié * @return boolean TRUE en cas de succès |
︙ | ︙ | |||
142 143 144 145 146 147 148 | throw new \LogicException('Ce fichier est déjà lié à un autre contenu : ' . $check_type); } return $db->preparedQuery('INSERT OR IGNORE INTO fichiers_' . $type . ' (fichier, id) VALUES (?, ?);', [(int)$this->id, (int)$foreign_id]); } | > > > | > > | > | | > > | | < < | | > > > > > > > > > > > > > > > > > > | > | > | | > > > > | | | | | 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 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 | throw new \LogicException('Ce fichier est déjà lié à un autre contenu : ' . $check_type); } return $db->preparedQuery('INSERT OR IGNORE INTO fichiers_' . $type . ' (fichier, id) VALUES (?, ?);', [(int)$this->id, (int)$foreign_id]); } public function getLinkedId(string $type) { $check = [self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA]; if (!in_array($type, $check)) { throw new \LogicException('Type de lien de fichier inconnu.'); } return DB::getInstance()->firstColumn(sprintf('SELECT id FROM fichiers_%s WHERE fichier = %d;', $type, $this->id)); } public function isPublic(&$wiki = null): bool { $config = Config::getInstance(); if ($config->get('image_fond') == $this->id) { return true; } // On regarde déjà si le fichier n'est pas lié au wiki $query = sprintf('SELECT wp.droit_lecture FROM fichiers_%s AS link INNER JOIN wiki_pages AS wp ON wp.id = link.id WHERE link.fichier = ? LIMIT 1;', self::LIEN_WIKI); $wiki = DB::getInstance()->firstColumn($query, (int)$this->id); // Page wiki publique, aucune vérification à faire, seul cas d'accès à un fichier en dehors de l'espace admin if ($wiki !== false && $wiki == Wiki::LECTURE_PUBLIC) { return true; } return false; } /** * Vérifie que l'utilisateur a bien le droit d'accéder à ce fichier * @param mixed $user Tableau contenant les infos sur l'utilisateur connecté, provenant de Session::getUser, ou false * @return boolean TRUE si l'utilisateur a le droit d'accéder au fichier, sinon FALSE */ public function checkAccess(Session $session, bool $require_admin = false) { $wiki = null; if ($this->isPublic($wiki) && !$require_admin) { return true; } // Pas d'utilisateur connecté, pas d'accès aux fichiers de l'espace admin if (!$session->isLogged()) { return false; } $user = $session->getUser(); if ($wiki !== false) { // S'il n'a même pas droit à accéder au wiki c'est mort if (!$session->canAccess('wiki', Membres::DROIT_ACCES)) { return false; } // On renvoie à l'objet Wiki pour savoir si l'utilisateur a le droit de lire ce fichier $_w = new Wiki; $_w->setRestrictionCategorie($user->id_categorie, $user->droit_wiki); return $require_admin ? $_w->canWritePage($wiki) : $_w->canReadPage($wiki); } $level = $require_admin ? Membres::DROIT_ADMIN : Membres::DROIT_ACCES; $db = DB::getInstance(); // On regarde maintenant si le fichier est lié à la compta $query = sprintf('SELECT 1 FROM fichiers_%s WHERE fichier = ? LIMIT 1;', self::LIEN_COMPTA); $compta = $db->firstColumn($query, (int)$this->id); if ($compta) { // OK si accès à la compta return $session->canAccess('compta', $level); } // Enfin, si le fichier est lié à un membre $query = sprintf('SELECT id FROM fichiers_%s WHERE fichier = ? LIMIT 1;', self::LIEN_MEMBRES); $membre = $db->firstColumn($query, (int)$this->id); if ($membre !== false) { // De manière évidente, l'utilisateur a le droit d'accéder aux fichiers liés à son profil if ((int)$membre == $user->id) { return true; } // Pour voir les fichiers des membres il faut pouvoir les gérer if ($level == Membres::DROIT_ACCES) { $level = Membres::DROIT_ECRITURE; } if ($session->canAccess('membres', $level)) { return true; } } return false; } /** * Supprime le fichier * @return boolean TRUE en cas de succès */ public function remove() { $db = DB::getInstance(); $db->begin(); $db->delete('fichiers_' . self::LIEN_COMPTA, 'fichier = ?', (int)$this->id); $db->delete('fichiers_' . self::LIEN_WIKI, 'fichier = ?', (int)$this->id); $db->delete('fichiers_' . self::LIEN_MEMBRES, 'fichier = ?', (int)$this->id); $db->delete('fichiers', 'id = ?', (int)$this->id); // Suppression du contenu s'il n'est pas utilisé par un autre fichier if (!$db->firstColumn('SELECT 1 FROM fichiers WHERE id_contenu = ? AND id != ? LIMIT 1;', (int)$this->id_contenu, (int)$this->id)) { |
︙ | ︙ | |||
283 284 285 286 287 288 289 | /** * Envoie le fichier au client HTTP * @return void */ public function serve() { | | | > > > > > | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | /** * Envoie le fichier au client HTTP * @return void */ public function serve() { return $this->_serve($this->getFilePathFromCache(), $this->type, ($this->image ? false : $this->nom), $this->taille, $this->isPublic()); } /** * Envoie une miniature à la taille indiquée au client HTTP * @return void */ public function serveThumbnail($width = null) { if (!$this->image) { throw new UserException('Il n\'est pas possible de fournir une miniature pour un fichier qui n\'est pas une image.'); } if (!$width) { $width = reset(self::$allowed_thumb_sizes); } if (!in_array($width, self::$allowed_thumb_sizes)) { throw new UserException('Cette taille de miniature n\'est pas autorisée.'); } $cache_id = 'fichiers.' . $this->id_contenu . '.thumb.' . (int)$width; |
︙ | ︙ | |||
329 330 331 332 333 334 335 | * Servir un fichier local en HTTP * @param string $path Chemin vers le fichier local * @param string $type Type MIME du fichier * @param string $name Nom du fichier avec extension * @param integer $size Taille du fichier en octets (facultatif) * @return boolean TRUE en cas de succès */ | | > > > > | | | | > | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | * Servir un fichier local en HTTP * @param string $path Chemin vers le fichier local * @param string $type Type MIME du fichier * @param string $name Nom du fichier avec extension * @param integer $size Taille du fichier en octets (facultatif) * @return boolean TRUE en cas de succès */ protected function _serve($path, $type, $name = false, $size = null, bool $public = false) { if ($public) { Utils::HTTPCache($this->hash, $this->datetime); } else { // Désactiver le cache header('Pragma: public'); header('Expires: -1'); header('Cache-Control: public, must-revalidate, post-check=0, pre-check=0'); } header('Content-Type: '.$type); if ($name) { header('Content-Disposition: attachment; filename="' . $name . '"'); } // Utilisation de XSendFile si disponible if (ENABLE_XSENDFILE && isset($_SERVER['SERVER_SOFTWARE'])) { if (stristr($_SERVER['SERVER_SOFTWARE'], 'apache') && function_exists('apache_get_modules') && in_array('mod_xsendfile', apache_get_modules())) { |
︙ | ︙ | |||
373 374 375 376 377 378 379 | @ini_set('zlib.output_compression', 'Off'); if ($size) { header('Content-Length: '. (int)$size); } | > | > > | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | @ini_set('zlib.output_compression', 'Off'); if ($size) { header('Content-Length: '. (int)$size); } if (@ob_get_length()) { @ob_clean(); } flush(); // Sinon on envoie le fichier à la mano return readfile($path); } /** |
︙ | ︙ | |||
462 463 464 465 466 467 468 | } if (!is_uploaded_file($file['tmp_name'])) { throw new \RuntimeException('Le fichier n\'a pas été envoyé de manière conventionnelle.'); } | < < < < < < < < < < < < < < < < < < < < < < < | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | } if (!is_uploaded_file($file['tmp_name'])) { throw new \RuntimeException('Le fichier n\'a pas été envoyé de manière conventionnelle.'); } $name = preg_replace('/\s+/', '_', $file['name']); $name = preg_replace('/[^\d\w._-]/ui', '', $name); return self::storeFile($name, $file['tmp_name']); } /** * Upload de fichier à partir d'une chaîne en base64 * @param string $name * @param string $content * @return Fichiers */ static public function storeFromBase64($name, $content) |
︙ | ︙ | |||
547 548 549 550 551 552 553 | // Check that it's a real image if ($is_image) { try { if ($path && !$content) { $i = new Image($path); } else { | | > > > > > > > > > > > > | > > > | > | | < | | | < < > > | | > | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 | // Check that it's a real image if ($is_image) { try { if ($path && !$content) { $i = new Image($path); } else { $i = Image::createFromBlob($content); } // Recompress PNG files from base64, assuming they are coming // from JS canvas which doesn't know how to gzip (d'oh!) if ($i->format() == 'png' && null !== $content) { $content = $i->output('png', true); $hash = sha1($content); $size = strlen($content); } unset($i); } catch (\RuntimeException $e) { if (strstr($e->getMessage(), 'No suitable image library found')) { throw new UserException('Le serveur n\'a aucune bibliothèque de gestion d\'image installée, et ne peut donc pas accepter les images. Installez Imagick ou GD.'); } throw new UserException('Fichier image invalide'); } } $db = DB::getInstance(); $db->begin(); // Il peut arriver que l'on renvoie ici un fichier déjà stocké, auquel cas, ne pas le re-stocker if (!($id_contenu = $db->firstColumn('SELECT id FROM fichiers_contenu WHERE hash = ?;', $hash))) { $db->preparedQuery('INSERT INTO fichiers_contenu (hash, taille, contenu) VALUES (?, ?, zeroblob(?));', [$hash, (int)$size, (int)$size]); $id_contenu = $db->lastInsertRowID(); // Écrire le contenu $blob = $db->openBlob('fichiers_contenu', 'contenu', $id_contenu, 'main', SQLITE3_OPEN_READWRITE); if (null !== $content) { fwrite($blob, $content); } else{ fwrite($blob, file_get_contents($path)); } fclose($blob); } $db->insert('fichiers', [ 'id_contenu' => (int)$id_contenu, 'nom' => $name, 'type' => $type, 'image' => (int)$is_image, |
︙ | ︙ | |||
623 624 625 626 627 628 629 | } /** * Récupère la liste des fichiers liés à une ressource * * @param string $type Type de ressource * @param integer $id Numéro de ressource | | | | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | } /** * Récupère la liste des fichiers liés à une ressource * * @param string $type Type de ressource * @param integer $id Numéro de ressource * @param boolean|null $images TRUE pour retourner seulement les images, * FALSE pour retourner les fichiers sans images, NULL pour tout retourner * @return array Liste des fichiers */ static public function listLinkedFiles($type, $id, $images = null) { $check = [self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA]; if (!in_array($type, $check)) { throw new \LogicException('Type de lien de fichier inconnu.'); } |
︙ | ︙ | |||
649 650 651 652 653 654 655 | WHERE fwp.id = ? %s ORDER BY fichiers.nom COLLATE NOCASE;', $type, $images); $files = DB::getInstance()->get($query, (int)$id); foreach ($files as &$file) { | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | WHERE fwp.id = ? %s ORDER BY fichiers.nom COLLATE NOCASE;', $type, $images); $files = DB::getInstance()->get($query, (int)$id); foreach ($files as &$file) { $file->url = self::_getURL($file->id, $file->nom, $file->hash); $file->thumb = $file->image ? self::_getURL($file->id, $file->nom, $file->hash, 200) : false; } return $files; } static public function deleteLinkedFiles($type, int $id) { static $check = [self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA]; if (!in_array($type, $check)) { throw new \LogicException('Type de lien de fichier inconnu.'); } $files = DB::getInstance()->delete('fichiers_' . $type, 'id = ?', $id); return self::deleteUnlinkedFiles(); } static public function deleteUnlinkedFiles() { static $all = [self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA]; $id_background = Config::getInstance()->get('image_fond'); $list = DB::getInstance()->iterate(sprintf('SELECT f.id, f.id_contenu FROM fichiers f LEFT JOIN fichiers_%s a ON a.fichier = f.id LEFT JOIN fichiers_%s b ON b.fichier = f.id LEFT JOIN fichiers_%s c ON c.fichier = f.id WHERE a.id IS NULL AND b.id IS NULL AND c.id IS NULL;', self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA)); foreach ($list as $file) { if ($file->id == $id_background) { // FIXME: want to use something cleaner here! continue; } $f = new Fichiers($file->id, (array) $file); $f->remove(); } } /** * Enlève d'une liste de fichiers ceux qui sont mentionnés dans un texte wiki * @param array $files Liste de fichiers * @param string $text texte wiki * @return array Un tableau qui ne contient pas les fichiers mentionnés dans $text */ |
︙ | ︙ | |||
680 681 682 683 684 685 686 | * @param string $text Texte wiki * @return array Liste des IDs de fichiers mentionnés */ static public function listFilesUsedInText($text) { preg_match_all('/<<?(?:fichier|image)\s*(?:\|\s*)?(\d+)/', $text, $match, PREG_PATTERN_ORDER); preg_match_all('/(?:fichier|image):\/\/(\d+)/', $text, $match2, PREG_PATTERN_ORDER); | | | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 | * @param string $text Texte wiki * @return array Liste des IDs de fichiers mentionnés */ static public function listFilesUsedInText($text) { preg_match_all('/<<?(?:fichier|image)\s*(?:\|\s*)?(\d+)/', $text, $match, PREG_PATTERN_ORDER); preg_match_all('/(?:fichier|image):\/\/(\d+)/', $text, $match2, PREG_PATTERN_ORDER); return array_merge($match[1], $match2[1]); } /** * Callback utilisé pour l'extension <<fichier>> dans le wiki-texte * @param array $args Arguments passés à l'extension * @param string $content Contenu éventuel (en mode bloc) |
︙ | ︙ |
Modified src/include/lib/Garradin/Form.php from [4384bc9995] to [024879329f].
1 2 3 4 5 6 7 8 9 10 11 12 | <?php namespace Garradin; class Form { protected $errors = []; public function __construct() { // Valide un montant de monnaie valide (deux décimales, ne peut être négatif) \KD2\Form::registerValidationRule('money', function ($name, $params, $value) { | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 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 | <?php namespace Garradin; class Form { protected $errors = []; public function __construct() { // Valide un montant de monnaie valide (deux décimales, ne peut être négatif) \KD2\Form::registerValidationRule('money', function ($name, $params, $value) { return preg_match('/^\d+(?:[.,]\d{1,2})?$/', $value) && $value >= 0; }); // Test si la valeur existe dans cette table // in_table:compta_categories,id \KD2\Form::registerValidationRule('in_table', function ($name, $params, $value) { $db = DB::getInstance(); return $db->test($params[0], $db->where($params[1], $value)); }); } public function run(callable $fn, ?string $csrf_key = null, ?string $redirect = null): bool { if (null !== $csrf_key && !$this->check($csrf_key)) { return false; } try { call_user_func($fn); if (null !== $redirect) { Utils::redirect($redirect); } return true; } catch (UserException $e) { $this->addError($e->getMessage()); return false; } } public function runIf($condition, callable $fn, ?string $csrf_key = null, ?string $redirect = null): ?bool { if (is_string($condition) && empty($_POST[$condition])) { return null; } elseif (is_bool($condition) && !$condition) { return null; } return $this->run($fn, $csrf_key, $redirect); } public function check($token_action = '', Array $rules = null) { if (!\KD2\Form::tokenCheck($token_action)) { $this->errors[] = 'Une erreur est survenue, merci de bien vouloir renvoyer le formulaire.'; return false; } if (!is_null($rules) && !$this->validate($rules)) { return false; } return true; } public function validate(Array $rules, array $source = null) { return \KD2\Form::validate($rules, $this->errors, $source); } public function hasErrors() { return (count($this->errors) > 0); } |
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | { case '_id': return 'identifiant'; case 'passe': return 'mot de passe'; case 'debut': return 'date de début'; case 'fin': return 'date de fin'; case 'duree': return 'durée'; case 'passe_check': return 'vérification de mot de passe'; default: return $name; } } protected function getErrorMessage($rule, $element, Array $params) { $element = $this->getFieldName($element); | > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | { case '_id': return 'identifiant'; case 'passe': return 'mot de passe'; case 'debut': return 'date de début'; case 'fin': return 'date de fin'; case 'duree': return 'durée'; case 'passe_check': return 'vérification de mot de passe'; case 'id_account': return 'compte'; case 'label': return 'libellé'; default: return $name; } } protected function getErrorMessage($rule, $element, Array $params) { $element = $this->getFieldName($element); |
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | case 'date_format': return sprintf('Format de date invalide dans le champ %s.', $element); case 'numeric': return sprintf('Le champ %s doit être un nombre.', $element); case 'money': return sprintf('Le champ %s n\'est pas un nombre valide.', $element); case 'in': return sprintf('Valeur invalide dans le champ \'%s\'.', $element); default: return sprintf('Erreur "%s" dans le champ "%s"', $rule, $element); } } public function __invoke($key) { return \KD2\Form::get($key); } } | > | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | case 'date_format': return sprintf('Format de date invalide dans le champ %s.', $element); case 'numeric': return sprintf('Le champ %s doit être un nombre.', $element); case 'money': return sprintf('Le champ %s n\'est pas un nombre valide.', $element); case 'in': case 'in_table': return sprintf('Valeur invalide dans le champ \'%s\'.', $element); default: return sprintf('Erreur "%s" dans le champ "%s"', $rule, $element); } } public function __invoke($key) { return \KD2\Form::get($key); } } |
Modified src/include/lib/Garradin/Install.php from [3140a79786] to [a5c31079aa].
1 2 3 4 5 6 7 8 9 10 11 | <?php namespace Garradin; /** * Pour procéder à l'installation de l'instance Garradin * Utile pour automatiser l'installation sans passer par la page d'installation */ class Install { static public function reset(Membres\Session $session, $password, array $options = []) | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php namespace Garradin; use Garradin\Entities\Accounting\Account; use Garradin\Entities\Accounting\Chart; use Garradin\Entities\Accounting\Year; /** * Pour procéder à l'installation de l'instance Garradin * Utile pour automatiser l'installation sans passer par la page d'installation */ class Install { static public function reset(Membres\Session $session, $password, array $options = []) |
︙ | ︙ | |||
21 22 23 24 25 26 27 | (new Sauvegarde)->create(date('Y-m-d-His-') . 'avant-remise-a-zero'); DB::getInstance()->close(); Config::deleteInstance(); unlink(DB_FILE); | > > | > > | < | | | 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 | (new Sauvegarde)->create(date('Y-m-d-His-') . 'avant-remise-a-zero'); DB::getInstance()->close(); Config::deleteInstance(); unlink(DB_FILE); // We can't use the real password, as it might not be valid (too short or compromised) $ok = self::install($config->nom_asso, $user->identite, $user->email, md5($password . SECRET_KEY)); // Restore password DB::getInstance()->preparedQuery('UPDATE membres SET passe = ? WHERE id = 1;', [$session::hashPassword($password)]); if ($ok) { // Force l'installation de plugin système Plugin::checkAndInstallSystemPlugins(); } return $ok; } static public function install($nom_asso, $nom_membre, $email_membre, $passe_membre) { $db = DB::getInstance(true); // Taille de la page de DB, on force à 4096 (défaut dans les dernières // versions de SQLite mais pas les vieilles) $db->exec('PRAGMA page_size = 4096;'); $db->exec('VACUUM;'); // Création de la base de données $db->begin(); $db->exec('PRAGMA application_id = ' . DB::APPID . ';'); $db->exec(file_get_contents(DB_SCHEMA)); $db->commit(); // Configuration de base // c'est dans Config::set que sont vérifiées les données utilisateur (renvoie UserException) $config = Config::getInstance(); $config->set('nom_asso', $nom_asso); $config->set('email_asso', $email_membre); $config->set('site_asso', WWW_URL); $config->set('monnaie', '€'); $config->set('pays', 'FR'); $config->setVersion(garradin_version()); $champs = Membres\Champs::importInstall(); $champs->save(false); // Pas de copie car pas de table membres existante |
︙ | ︙ | |||
83 84 85 86 87 88 89 | 'droit_compta' => Membres::DROIT_AUCUN, 'droit_config' => Membres::DROIT_AUCUN, 'droit_connexion' => Membres::DROIT_AUCUN, 'cacher' => 1, ]); $id = $cats->add([ | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 'droit_compta' => Membres::DROIT_AUCUN, 'droit_config' => Membres::DROIT_AUCUN, 'droit_connexion' => Membres::DROIT_AUCUN, 'cacher' => 1, ]); $id = $cats->add([ 'nom' => 'Administrateurs', 'droit_inscription' => Membres::DROIT_AUCUN, 'droit_wiki' => Membres::DROIT_ADMIN, 'droit_membres' => Membres::DROIT_ADMIN, 'droit_compta' => Membres::DROIT_ADMIN, 'droit_config' => Membres::DROIT_ADMIN, ]); |
︙ | ︙ | |||
129 130 131 132 133 134 135 | $wiki->editRevision($id_page, 0, [ 'id_auteur' => $id_membre, 'contenu' => "Bienvenue dans l'administration de ".$nom_asso." !\n\n" . "Utilisez le menu à gauche pour accéder aux différentes rubriques.", ]); $config->set('accueil_connexion', $page); | | | > > > > | > | > > > | > > | | | | > > > | | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 136 137 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 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | $wiki->editRevision($id_page, 0, [ 'id_auteur' => $id_membre, 'contenu' => "Bienvenue dans l'administration de ".$nom_asso." !\n\n" . "Utilisez le menu à gauche pour accéder aux différentes rubriques.", ]); $config->set('accueil_connexion', $page); // Import plan comptable $chart = new Chart; $chart->label = 'Plan comptable associatif 2018'; $chart->country = 'FR'; $chart->code = 'PCA2018'; $chart->save(); $chart->accounts()->importCSV(ROOT . '/include/data/charts/fr_2018.csv'); // Premier exercice $year = new Year; $year->label = sprintf('Exercice %d', date('Y')); $year->start_date = new \DateTime('January 1st'); $year->end_date = new \DateTime('December 31'); $year->id_chart = $chart->id(); $year->save(); // Compte bancaire $account = new Account; $account->import([ 'label' => 'Compte courant', 'code' => '512A', 'type' => Account::TYPE_BANK, 'position' => Account::ASSET_OR_LIABILITY, 'id_chart' => $chart->id(), 'user' => 1, ]); $account->save(); // Ajout d'une recherche avancée en exemple (membres) $query = (object) [ 'query' => [[ 'operator' => 'AND', 'conditions' => [ [ 'column' => 'lettre_infos', 'operator' => '= 1', 'values' => [], ], ], ]], 'order' => 'numero', 'desc' => true, 'limit' => '10000', ]; $recherche = new Recherche; $recherche->add('Membres inscrits à la lettre d\'information', null, $recherche::TYPE_JSON, 'membres', $query); // Ajout d'une recherche avancée en exemple (compta) $query = (object) [ 'query' => [[ 'operator' => 'AND', 'conditions' => [ [ 'column' => 'a2.code', 'operator' => 'IS NULL', 'values' => [], ], ], ]], 'order' => 't.id', 'desc' => false, 'limit' => '100', ]; $recherche = new Recherche; $recherche->add('Écritures sans projet', null, $recherche::TYPE_JSON, 'compta', $query); // Install welcome plugin if available $has_welcome_plugin = Plugin::getPath('welcome', false); if ($has_welcome_plugin) { Plugin::install('welcome', true); } return $config->save(); } static public function checkAndCreateDirectories() { // Vérifier que les répertoires vides existent, sinon les créer |
︙ | ︙ |
Modified src/include/lib/Garradin/Membres.php from [1c694ab262] to [312c7859a9].
︙ | ︙ | |||
288 289 290 291 292 293 294 | } public function getIDWithNumero($numero) { return DB::getInstance()->firstColumn('SELECT id FROM membres WHERE numero = ?;', (int) $numero); } | | > > | > | > > | < | | < > | > | > > | | | | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | } public function getIDWithNumero($numero) { return DB::getInstance()->firstColumn('SELECT id FROM membres WHERE numero = ?;', (int) $numero); } public function quickSearch(string $query) { $identity = Config::getInstance()->get('champ_identite'); $operator = 'LIKE'; if (is_numeric(trim($query))) { $column = 'numero'; $operator = '= ?'; } elseif (strpos($query, '@') !== false) { $column = 'email'; } else { $column = $identity; } if ($operator == 'LIKE') { $query = '%' . str_replace(['%', '_'], '\\', $query) . '%'; $operator = 'LIKE ? ESCAPE \'\\\''; } $sql = sprintf('SELECT id, numero, %s AS identite FROM membres WHERE %s %s ORDER BY %1$s LIMIT 50;', $identity, $column, $operator); return DB::getInstance()->get($sql, $query); } public function sendMessage(array $recipients, $subject, $message, $send_copy) { $config = Config::getInstance(); foreach ($recipients as $key => $recipient) |
︙ | ︙ |
Modified src/include/lib/Garradin/Membres/Categories.php from [cfad189ba8] to [2ef27a72a7].
︙ | ︙ | |||
15 16 17 18 19 20 21 | 'connexion' => Membres::DROIT_ACCES, 'membres' => Membres::DROIT_AUCUN, 'compta' => Membres::DROIT_AUCUN, 'wiki' => Membres::DROIT_ACCES, 'config' => Membres::DROIT_AUCUN, ]; | < < < < < < < < < < < < < < < < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 'connexion' => Membres::DROIT_ACCES, 'membres' => Membres::DROIT_AUCUN, 'compta' => Membres::DROIT_AUCUN, 'wiki' => Membres::DROIT_ACCES, 'config' => Membres::DROIT_AUCUN, ]; protected function _checkData(&$data) { $db = DB::getInstance(); if (!isset($data['nom']) || !trim($data['nom'])) { throw new UserException('Le nom de catégorie ne peut rester vide.'); } } public function add($data) { $this->_checkData($data); foreach ($this->droits as $key=>$value) |
︙ | ︙ |
Deleted src/include/lib/Garradin/Membres/Cotisations.php version [f8b5327ae2].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Modified src/include/lib/Garradin/Membres/Import.php from [5800dd1bd4] to [99caaf5adf].
1 2 3 4 5 6 7 8 9 10 11 12 | <?php namespace Garradin\Membres; use Garradin\Membres; use Garradin\Config; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; class Import { | > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | 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 | <?php namespace Garradin\Membres; use Garradin\Membres; use Garradin\Config; use Garradin\DB; use Garradin\Utils; use Garradin\CSV; use Garradin\CSV_Custom; use Garradin\UserException; class Import { /** * Importer un CSV générique * @return boolean TRUE en cas de succès */ public function fromCustomCSV(CSV_Custom $csv, int $current_user_id) { $db = DB::getInstance(); $db->begin(); $membres = new Membres; foreach ($csv->iterate() as $line => $row) { if (!empty($row->numero) && $row->numero > 0) { $numero = (int)$row->numero; } else { unset($row->numero); $numero = false; } try { if ($numero && ($id = $membres->getIDWithNumero($numero))) { if ($id === $current_user_id) { // Ne pas modifier le membre courant, on risque de se tirer une balle dans le pied continue; } $membres->edit($id, (array)$row); } else { $membres->add((array)$row, false); } } catch (UserException $e) { $db->rollback(); throw new UserException('Erreur sur la ligne ' . $line . ' : ' . $e->getMessage()); } |
︙ | ︙ | |||
175 176 177 178 179 180 181 | public function fromGarradinCSV($path, $current_user_id) { if (!file_exists($path) || !is_readable($path)) { throw new \RuntimeException('Fichier inconnu : '.$path); } | | | | | 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 | public function fromGarradinCSV($path, $current_user_id) { if (!file_exists($path) || !is_readable($path)) { throw new \RuntimeException('Fichier inconnu : '.$path); } $fp = CSV::open($path); if (!$fp) { return false; } $db = DB::getInstance(); $db->begin(); $membres = new Membres; // On récupère les champs qu'on peut importer $champs_membres = Config::getInstance()->get('champs_membres'); $champs_multiples = $champs_membres->getMultiples(); $champs = $champs_membres->getKeys(); $champs[] = 'date_inscription'; //$champs[] = 'date_connexion'; //$champs[] = 'id'; //$champs[] = 'id_categorie'; $line = 0; $delim = CSV::findDelimiter($fp); CSV::skipBOM($fp); while (!feof($fp)) { $row = fgetcsv($fp, 4096, $delim); $line++; |
︙ | ︙ | |||
306 307 308 309 310 311 312 | protected function export(array $list = null) { $db = DB::getInstance(); $champs = Config::getInstance()->get('champs_membres')->getKeys(); $champs = array_map([$db, 'quoteIdentifier'], $champs); | | > > > > > > | | > | | | > | | | 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 | protected function export(array $list = null) { $db = DB::getInstance(); $champs = Config::getInstance()->get('champs_membres')->getKeys(); $champs = array_map([$db, 'quoteIdentifier'], $champs); $fields = 'm.' . implode(', m.', $champs); if ($list) { $list = array_map('intval', $list); $where = sprintf('WHERE m.%s', $db->where('id', $list)); } else { $where = ''; } $sql = sprintf('SELECT %s, c.nom AS "Catégorie membre" FROM membres AS m INNER JOIN membres_categories AS c ON m.id_categorie = c.id %s ORDER BY c.id;', $fields, $where); $res = $db->iterate($sql); return [ array_keys((array) $res->current()), $res, sprintf('Export membres - %s - %s', Config::getInstance()->get('nom_asso'), date('Y-m-d')), ]; } public function toCSV(array $list = null) { list($champs, $result, $name) = $this->export($list); return CSV::toCSV($name, $result, $champs, [$this, 'exportRow']); } public function toODS(array $list = null) { list($champs, $result, $name) = $this->export($list); return CSV::toODS($name, $result, $champs, [$this, 'exportRow']); } public function exportRow(\stdClass $row) { // Pas hyper efficace, il faudrait ne pas récupérer la liste pour chaque ligne... FIXME $champs_multiples = Config::getInstance()->get('champs_membres')->getMultiples(); // convertir les champs à choix multiple de binaire vers liste séparée par des points virgules |
︙ | ︙ |
Modified src/include/lib/Garradin/Membres/Session.php from [fa679095c9] to [db8cb5f1d1].
︙ | ︙ | |||
11 12 13 14 15 16 17 | use const Garradin\SECRET_KEY; use const Garradin\WWW_URL; use const Garradin\ADMIN_URL; use KD2\Security; use KD2\Security_OTP; | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | use const Garradin\SECRET_KEY; use const Garradin\WWW_URL; use const Garradin\ADMIN_URL; use KD2\Security; use KD2\Security_OTP; use KD2\Graphics\QRCode; use KD2\HTTP; class Session extends \KD2\UserSession { // Personalisation de la config de UserSession protected $cookie_name = 'gdin'; protected $remember_me_cookie_name = 'gdinp'; |
︙ | ︙ | |||
57 58 59 60 61 62 63 | } // Extension des méthodes de UserSession public function __construct() { $url = parse_url(ADMIN_URL); | < < < < < < < < < < < < < | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | } // Extension des méthodes de UserSession public function __construct() { $url = parse_url(ADMIN_URL); parent::__construct(DB::getInstance(), [ 'cookie_domain' => $url['host'], 'cookie_path' => preg_replace('!/admin/$!', '/', $url['path']), 'cookie_secure' => (\Garradin\PREFER_HTTPS >= 2) ? true : false, ]); } protected function getUserForLogin($login) { $champ_id = Config::getInstance()->get('champ_identifiant'); // Ne renvoie un membre que si celui-ci a le droit de se connecter $query = 'SELECT m.id, m.%1$s AS login, m.passe AS password, m.secret_otp AS otp_secret FROM membres AS m |
︙ | ︙ | |||
150 151 152 153 154 155 156 | { $logged = parent::isLogged(); if (!$disable_local_login && defined('\Garradin\LOCAL_LOGIN')) { $login_id = \Garradin\LOCAL_LOGIN; | | | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | { $logged = parent::isLogged(); if (!$disable_local_login && defined('\Garradin\LOCAL_LOGIN')) { $login_id = \Garradin\LOCAL_LOGIN; // On va chercher le premier membre avec le droit de gérer la config if (-1 === $login_id) { $login_id = $this->db->firstColumn('SELECT id FROM membres WHERE id_categorie IN (SELECT id FROM membres_categories WHERE droit_config = ?) LIMIT 1', Membres::DROIT_ADMIN); } if ($login_id > 0 && (!$logged || ($logged && $this->user->id != $login_id))) { $logged = $this->create($login_id); } |
︙ | ︙ |
Modified src/include/lib/Garradin/Plugin.php from [de7f4cd5b0] to [245a731876].
︙ | ︙ | |||
183 184 185 186 187 188 189 | /** * Inclure un fichier depuis le plugin (dynamique ou statique) * @param string $file Chemin du fichier à aller chercher : si c'est un .php il sera inclus, * sinon il sera juste affiché * @return void * @throws UserException Si le fichier n'existe pas ou fait partie des fichiers qui ne peuvent * être appelés que par des méthodes de Plugin. | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | /** * Inclure un fichier depuis le plugin (dynamique ou statique) * @param string $file Chemin du fichier à aller chercher : si c'est un .php il sera inclus, * sinon il sera juste affiché * @return void * @throws UserException Si le fichier n'existe pas ou fait partie des fichiers qui ne peuvent * être appelés que par des méthodes de Plugin. * @throws \RuntimeException Si le chemin indiqué tente de sortir du contexte du PHAR */ public function call($file) { $file = preg_replace('!^[./]*!', '', $file); if (preg_match('!(?:\.\.|[/\\\\]\.|\.[/\\\\])!', $file)) { |
︙ | ︙ | |||
439 440 441 442 443 444 445 | '{Membres::DROIT_ECRITURE}' => Membres::DROIT_ECRITURE, '{Membres::DROIT_ADMIN}' => Membres::DROIT_ADMIN, ]); $condition = preg_replace_callback('/\{\$user\.(\w+)\}/', function ($m) use ($user) { return $user->{$m[1]}; }, $condition); $query = 'SELECT 1 WHERE ' . $condition . ';'; | < | | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | '{Membres::DROIT_ECRITURE}' => Membres::DROIT_ECRITURE, '{Membres::DROIT_ADMIN}' => Membres::DROIT_ADMIN, ]); $condition = preg_replace_callback('/\{\$user\.(\w+)\}/', function ($m) use ($user) { return $user->{$m[1]}; }, $condition); $query = 'SELECT 1 WHERE ' . $condition . ';'; $res = $db->protectSelect(['membres' => []], $query); if (!$db->firstColumn($query)) { unset($list[$id]); continue; } $row = $row->nom; } |
︙ | ︙ | |||
528 529 530 531 532 533 534 | 'disable_compression' => true, ] ]; $context = stream_context_create($context_options); try { | | > > > > > | 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | 'disable_compression' => true, ] ]; $context = stream_context_create($context_options); try { $result = file_get_contents(PLUGINS_URL, false, $context); } catch (\Exception $e) { throw new UserException('Le téléchargement de la liste des plugins a échoué : ' . $e->getMessage()); } Static_Cache::store('plugins_list', $result); } else { $result = Static_Cache::get('plugins_list'); } $list = json_decode($result, true); return $list; } static public function fetchOfficialList() { return []; // FIXME } /** * Vérifier le hash du plugin $id pour voir s'il correspond au hash du fichier téléchargés * @param string $id Identifiant du plugin * @return boolean TRUE si le hash correspond (intégrité OK), sinon FALSE */ static public function checkHash($id) |
︙ | ︙ | |||
578 579 580 581 582 583 584 | return array_key_exists($id, $list); } /** * Télécharge un plugin depuis le repository officiel, et l'installe * @param string $id Identifiant du plugin * @return boolean TRUE si ça marche | | | | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | return array_key_exists($id, $list); } /** * Télécharge un plugin depuis le repository officiel, et l'installe * @param string $id Identifiant du plugin * @return boolean TRUE si ça marche * @throws \LogicException Si le plugin n'est pas dans la liste des plugins officiels * @throws UserException Si le plugin est déjà installé ou que le téléchargement a échoué * @throws \RuntimeException Si l'archive téléchargée est corrompue (intégrité du hash ne correspond pas) */ static public function download($id) { $list = self::fetchOfficialList(); if (!array_key_exists($id, $list)) { |
︙ | ︙ | |||
756 757 758 759 760 761 762 763 764 765 766 767 768 769 | static public function fireSignal($signal, $params = null, &$callback_return = null) { $list = DB::getInstance()->get('SELECT * FROM plugins_signaux WHERE signal = ?;', $signal); if (!count($list)) { return null; } $system = explode(',', PLUGINS_SYSTEM); foreach ($list as $row) { // Ne pas appeler les plugins dont le code n'existe pas/plus, // SAUF si c'est un plugin système (auquel cas ça fera une erreur) | > > > > > > | > > | 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 | static public function fireSignal($signal, $params = null, &$callback_return = null) { $list = DB::getInstance()->get('SELECT * FROM plugins_signaux WHERE signal = ?;', $signal); if (!count($list)) { return null; } if (null === $params) { $params = []; } $system = explode(',', PLUGINS_SYSTEM); foreach ($list as $row) { $path = self::getPath($row->plugin, in_array($row->plugin, $system)); // Ne pas appeler les plugins dont le code n'existe pas/plus, // SAUF si c'est un plugin système (auquel cas ça fera une erreur) if (!$path) { continue; } $params['plugin_root'] = $path; $return = call_user_func_array('Garradin\\Plugin\\' . $row->callback, [&$params, &$callback_return]); if (true === $return) { return true; } } return false; } } |
Deleted src/include/lib/Garradin/Rappels_Envoyes.php version [fcaa354186].
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Modified src/include/lib/Garradin/Recherche.php from [98002e1aea] to [5f2af851fc].
1 2 3 4 5 6 7 8 9 10 11 | <?php namespace Garradin; class Recherche { const TYPE_JSON = 'json'; const TYPE_SQL = 'sql'; const TARGETS = [ 'membres', | > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php namespace Garradin; use Garradin\Entities\Accounting\Transaction; class Recherche { const TYPE_JSON = 'json'; const TYPE_SQL = 'sql'; const TARGETS = [ 'membres', 'compta', ]; protected function _checkFields($data) { $db = DB::getInstance(); if (array_key_exists('intitule', $data) && trim($data['intitule']) === '') |
︙ | ︙ | |||
55 56 57 58 59 60 61 | throw new \InvalidArgumentException('Recherche invalide pour le type SQL'); } $query = $data['contenu']; if ($data['type'] == self::TYPE_JSON) { | | > > > > > > | 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 | throw new \InvalidArgumentException('Recherche invalide pour le type SQL'); } $query = $data['contenu']; if ($data['type'] == self::TYPE_JSON) { if (!is_object($query)) { throw new \InvalidArgumentException('Recherche invalide pour le type JSON'); } $query = json_encode($query); if (!json_decode($query)) { throw new \InvalidArgumentException('JSON invalide pour le type JSON'); } } } return $query; } public function duplicate(int $id) { DB::getInstance()->preparedQuery('INSERT INTO recherches (id_membre, intitule, cible, type, contenu) SELECT id_membre, \'Copie de : \' || intitule, cible, type, contenu FROM recherches WHERE id = ?;', [$id]); } public function edit($id, $data) { $allowed = ['intitule', 'id_membre', 'type', 'cible', 'contenu']; // Supprimer les champs qui ne sont pas ceux de la BDD $data = array_intersect_key($data, array_flip($allowed)); |
︙ | ︙ | |||
110 111 112 113 114 115 116 | return DB::getInstance()->delete('recherches', 'id = ?', (int) $id); } public function get($id) { $r = DB::getInstance()->first('SELECT * FROM recherches WHERE id = ?;', (int) $id); | | < | < < < < < < < | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | return DB::getInstance()->delete('recherches', 'id = ?', (int) $id); } public function get($id) { $r = DB::getInstance()->first('SELECT * FROM recherches WHERE id = ?;', (int) $id); if ($r && $r->type == self::TYPE_JSON) { $r->query = (object) json_decode($r->contenu, true); } return $r; } public function getList($id_membre, $cible) { |
︙ | ︙ | |||
146 147 148 149 150 151 152 | if (!$search) { return false; } if ($search->type == self::TYPE_JSON) { | > | > > > > > > > > > > > > > > > > > > > > > > > < < | 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 201 202 203 204 205 206 207 208 209 210 211 212 | if (!$search) { return false; } if ($search->type == self::TYPE_JSON) { $query = $search->query; $search->contenu = $this->buildQuery($search->cible, $query->query, $query->order, $query->desc, $no_limit ? 10000 : $query->limit); } return $this->searchSQL($search->cible, $search->contenu, $force_select, $no_limit); } public function getResultHeader(string $target, array $result) { if (!count($result)) { return []; } $out = []; $columns = $this->getColumns($target); foreach (reset($result) as $key => $v) { foreach ($columns as $ckey => $config) { if ($ckey == $key) { $out[$key] = $config->label; } elseif (isset($config->alias) && $config->alias == $key) { $out[$config->alias] = $config->label; } } } return $out; } /** * Renvoie la liste des colonnes d'une cible */ public function getColumns($target) { $columns = []; $db = DB::getInstance(); if ($target == 'membres') { $champs = Config::getInstance()->get('champs_membres'); $columns['id_categorie'] = (object) [ 'textMatch'=> false, 'label' => 'Catégorie', 'type' => 'enum', 'null' => false, 'values' => $db->getAssoc('SELECT id, nom FROM membres_categories ORDER BY nom;'), ]; foreach ($champs->getList() as $champ => $config) { $column = (object) [ 'textMatch'=> $champs->isText($champ), 'label' => $config->title, 'type' => 'text', 'null' => true, ]; if ($config->type == 'checkbox') |
︙ | ︙ | |||
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | { $column->type = $config->type; } elseif ($config->type == 'number' || $champ == 'numero') { $column->type = 'integer'; } $columns[$champ] = $column; } } return $columns; } /** * Construire une recherche SQL à partir d'un objet généré par QueryBuilder * @param string $target Cible de la requête : membres, compta_journal, etc. * @param array $groups Groupes de critères * @param string $order Ordre de tri * @param boolean $desc Inverser le tri * @param integer $limit Limite * @return string Chaîne SQL */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | 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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | { $column->type = $config->type; } elseif ($config->type == 'number' || $champ == 'numero') { $column->type = 'integer'; } if ($config->type == 'tel') { $column->originalType = 'tel'; } $columns[$champ] = $column; } } elseif ($target === 'compta') { $columns['t.id'] = (object) [ 'textMatch'=> false, 'label' => 'Numéro écriture', 'type' => 'integer', 'null' => false, 'alias' => 'id', ]; $columns['t.date'] = (object) [ 'textMatch'=> false, 'label' => 'Date', 'type' => 'date', 'null' => false, 'alias' => 'date', ]; $columns['t.label'] = (object) [ 'textMatch'=> true, 'label' => 'Libellé écriture', 'type' => 'text', 'null' => false, 'alias' => 'label', ]; $columns['t.reference'] = (object) [ 'textMatch'=> true, 'label' => 'Numéro pièce comptable', 'type' => 'text', 'null' => true, 'alias' => 'reference', ]; $columns['t.notes'] = (object) [ 'textMatch'=> true, 'label' => 'Notes', 'type' => 'text', 'null' => true, 'alias' => 'notes', ]; $columns['l.label'] = (object) [ 'textMatch'=> true, 'label' => 'Libellé ligne', 'type' => 'text', 'null' => true, 'alias' => 'line_label', ]; $columns['l.debit'] = (object) [ 'textMatch'=> false, 'label' => 'Débit', 'type' => 'integer', 'null' => false, 'alias' => 'debit', 'originalType' => 'money', ]; $columns['l.credit'] = (object) [ 'textMatch'=> false, 'label' => 'Crédit', 'type' => 'integer', 'null' => false, 'alias' => 'credit', 'originalType' => 'money', ]; $columns['l.reference'] = (object) [ 'textMatch'=> true, 'label' => 'Référence ligne écriture', 'type' => 'text', 'null' => true, 'alias' => 'line_reference', ]; $columns['t.type'] = (object) [ 'textMatch'=> false, 'label' => 'Type d\'écriture', 'type' => 'enum', 'null' => false, 'values' => Transaction::TYPES_NAMES, 'alias' => 'type', ]; $columns['a.code'] = (object) [ 'textMatch'=> true, 'label' => 'Numéro de compte', 'type' => 'text', 'null' => false, 'alias' => 'code', ]; $columns['t.id_year'] = (object) [ 'textMatch'=> false, 'label' => 'Exercice', 'type' => 'enum', 'null' => false, 'values' => $db->getAssoc('SELECT id, label FROM acc_years ORDER BY end_date;'), 'alias' => 'id_year', |