Changes In Branch dev Excluding Merge-Ins

This is equivalent to a diff from cba6b145a6 to eea005f855

2020-06-24
01:49
Essai de correction / simplification envoi rappels check-in: 16d295170c user: bohwaz tags: trunk, stable
00:43
Create new branch named "1.0" Closed-Leaf check-in: 3868d39e05 user: bohwaz tags: mistake
2020-06-23
00:32
Merge avec trunk Leaf check-in: eea005f855 user: bohwaz tags: dev
00:21
Afficher le lien vers l'historique des rappels dans tous les cas check-in: cba6b145a6 user: bohwaz tags: trunk, stable
00:08
Ajout d'un format de date exotique check-in: e4c2076e26 user: bohwaz tags: trunk, stable, 0.9.7
2020-06-22
21:27
Simplification des cibles check-in: a3184ce2f1 user: bohwaz tags: dev

Modified .travis.yml from [ab9c965cec] to [4da8c0eef1].

1
2
3
4
5
6
7
8
9
10
11
12
language: php
php:
  - '5.6'
  - '7.0'
  - '7.1'
  - '7.2'
  - '7.3'
  - '7.4'

install:
  - make -C src deps



<
<
<







1
2



3
4
5
6
7
8
9
language: php
php:



  - '7.2'
  - '7.3'
  - '7.4'

install:
  - make -C src deps

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/VERSION from [c142a1f0a9] to [c538b66c71].

1
0.9.7
|
1
1.0.0

Deleted src/include/data/0.7.0.sql version [acaa57e895].

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
CREATE TABLE 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 compta_rapprochement
-- Rapprochement entre compta et relevés de comptes
(
    operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id),
    date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    auteur INTEGER NOT NULL REFERENCES membres (id)
);

CREATE TABLE 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, -- Date d'ajout ou mise à jour du fichier
    id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id)
);

CREATE INDEX fichiers_date ON fichiers (datetime);

CREATE TABLE 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 fichiers_hash ON fichiers_contenu (hash);

CREATE TABLE 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 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 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)
);
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































Added src/include/data/0.7.0_migration.sql version [acaa57e895].

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
CREATE TABLE 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 compta_rapprochement
-- Rapprochement entre compta et relevés de comptes
(
    operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id),
    date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    auteur INTEGER NOT NULL REFERENCES membres (id)
);

CREATE TABLE 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, -- Date d'ajout ou mise à jour du fichier
    id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id)
);

CREATE INDEX fichiers_date ON fichiers (datetime);

CREATE TABLE 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 fichiers_hash ON fichiers_contenu (hash);

CREATE TABLE 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 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 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)
);

Deleted src/include/data/0.7.2.sql version [ba4b5fbcc7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- Colonne manquante
ALTER TABLE rappels_envoyes ADD COLUMN id_rappel INTEGER NULL REFERENCES rappels (id);

-- Un bug a permis d'insérer des comptes avec des lettres minuscules, créant des problèmes
-- corrigeons donc les comptes pour les mettre en majuscules.

UPDATE compta_comptes SET id = UPPER(id);

-- Le champ id_auteur était à NOT NULL, il faut corriger ça pour pouvoir avoir un rapprochement anonyme
-- une fois que le membre a été supprimé

CREATE TABLE compta_rapprochement2
-- Rapprochement entre compta et relevés de comptes
(
    id_operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id),
    date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    id_auteur INTEGER NULL REFERENCES membres (id)
);

INSERT INTO compta_rapprochement2 SELECT operation, date, auteur FROM compta_rapprochement;

DROP TABLE compta_rapprochement;

ALTER TABLE compta_rapprochement2 RENAME TO compta_rapprochement;
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































Added src/include/data/0.7.2_migration.sql version [ba4b5fbcc7].

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- Colonne manquante
ALTER TABLE rappels_envoyes ADD COLUMN id_rappel INTEGER NULL REFERENCES rappels (id);

-- Un bug a permis d'insérer des comptes avec des lettres minuscules, créant des problèmes
-- corrigeons donc les comptes pour les mettre en majuscules.

UPDATE compta_comptes SET id = UPPER(id);

-- Le champ id_auteur était à NOT NULL, il faut corriger ça pour pouvoir avoir un rapprochement anonyme
-- une fois que le membre a été supprimé

CREATE TABLE compta_rapprochement2
-- Rapprochement entre compta et relevés de comptes
(
    id_operation INTEGER NOT NULL PRIMARY KEY REFERENCES compta_journal (id),
    date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    id_auteur INTEGER NULL REFERENCES membres (id)
);

INSERT INTO compta_rapprochement2 SELECT operation, date, auteur FROM compta_rapprochement;

DROP TABLE compta_rapprochement;

ALTER TABLE compta_rapprochement2 RENAME TO compta_rapprochement;

Deleted src/include/data/0.8.0.sql version [34e1625504].

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
-- Ajouter champ pour OTP
ALTER TABLE membres ADD COLUMN secret_otp TEXT NULL;

-- Ajouter champ clé PGP
ALTER TABLE membres ADD COLUMN clef_pgp TEXT NULL;

--------------------------------------------------------------------------------
-- Mise à jour des tables contenant un champ date pour ajouter la contrainte  --
-- Ceci afin de forcer les champs à contenir un format de date correct        --
-- On en profite pour ajouter les ON DELETE nécessaires                       --
--------------------------------------------------------------------------------

-- Convertir les dates UNIX en date Y-m-d, apparemment il y en a encore parfois ?
UPDATE wiki_pages SET date_creation = datetime(date_creation, "unixepoch") WHERE CAST(date_creation AS INT) = date_creation;
UPDATE wiki_pages SET date_creation = datetime(date_creation) WHERE datetime(date_creation) != date_creation;

-- Renommage des tables qu'il faut mettre à jour
ALTER TABLE cotisations_membres RENAME TO cotisations_membres_old;
ALTER TABLE rappels RENAME TO rappels_old;
ALTER TABLE rappels_envoyes RENAME TO rappels_envoyes_old;
ALTER TABLE wiki_pages RENAME TO wiki_pages_old;
ALTER TABLE wiki_revisions RENAME TO wiki_revisions_old;
ALTER TABLE compta_categories RENAME TO compta_categories_old;
ALTER TABLE compta_comptes_bancaires RENAME TO compta_comptes_bancaires_old;
ALTER TABLE compta_exercices RENAME TO compta_exercices_old;
ALTER TABLE compta_journal RENAME TO compta_journal_old;
ALTER TABLE compta_rapprochement RENAME TO compta_rapprochement_old;
ALTER TABLE fichiers RENAME TO fichiers_old;
ALTER TABLE membres_operations RENAME TO membres_operations_old;
ALTER TABLE membres_categories RENAME TO membres_categories_old;

-- Suppression des index pour que les nouveaux soient liés aux nouvelles tables
DROP INDEX cm_unique;
DROP INDEX wiki_uri;
DROP INDEX wiki_revisions_id_page;
DROP INDEX wiki_revisions_id_auteur;
DROP INDEX compta_operations_exercice;
DROP INDEX compta_operations_date;
DROP INDEX compta_operations_comptes;
DROP INDEX compta_operations_auteur;
DROP INDEX fichiers_date;

-- Suppression ancienne table recherche
DROP TABLE wiki_recherche;

-- Suppression des triggers
-- 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 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;
INSERT INTO compta_categories SELECT * FROM compta_categories_old;
INSERT INTO compta_comptes_bancaires SELECT * FROM compta_comptes_bancaires_old;
INSERT INTO compta_exercices SELECT * FROM compta_exercices_old;
INSERT INTO compta_journal SELECT *, NULL FROM compta_journal_old;
INSERT INTO compta_rapprochement SELECT * FROM compta_rapprochement_old;
INSERT INTO fichiers SELECT * FROM fichiers_old;
INSERT INTO membres_operations SELECT * FROM membres_operations_old;
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 cotisations_membres_old;
DROP TABLE rappels_old;
DROP TABLE rappels_envoyes_old;
DROP TABLE wiki_pages_old;
DROP TABLE wiki_revisions_old;
DROP TABLE compta_categories_old;
DROP TABLE compta_comptes_bancaires_old;
DROP TABLE compta_exercices_old;
DROP TABLE compta_journal_old;
DROP TABLE compta_rapprochement_old;
DROP TABLE fichiers_old;
DROP TABLE membres_operations_old;
DROP TABLE membres_categories_old;
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































Added src/include/data/0.8.0_migration.sql version [b56b968950].











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
-- Ajouter champ pour OTP
ALTER TABLE membres ADD COLUMN secret_otp TEXT NULL;

-- Ajouter champ clé PGP
ALTER TABLE membres ADD COLUMN clef_pgp TEXT NULL;

--------------------------------------------------------------------------------
-- Mise à jour des tables contenant un champ date pour ajouter la contrainte  --
-- Ceci afin de forcer les champs à contenir un format de date correct        --
-- On en profite pour ajouter les ON DELETE nécessaires                       --
--------------------------------------------------------------------------------

-- Convertir les dates UNIX en date Y-m-d, apparemment il y en a encore parfois ?
UPDATE wiki_pages SET date_creation = datetime(date_creation, "unixepoch") WHERE CAST(date_creation AS INT) = date_creation;
UPDATE wiki_pages SET date_creation = datetime(date_creation) WHERE datetime(date_creation) != date_creation;

-- Renommage des tables qu'il faut mettre à jour
ALTER TABLE cotisations_membres RENAME TO cotisations_membres_old;
ALTER TABLE rappels RENAME TO rappels_old;
ALTER TABLE rappels_envoyes RENAME TO rappels_envoyes_old;
ALTER TABLE wiki_pages RENAME TO wiki_pages_old;
ALTER TABLE wiki_revisions RENAME TO wiki_revisions_old;
ALTER TABLE compta_categories RENAME TO compta_categories_old;
ALTER TABLE compta_comptes_bancaires RENAME TO compta_comptes_bancaires_old;
ALTER TABLE compta_exercices RENAME TO compta_exercices_old;
ALTER TABLE compta_journal RENAME TO compta_journal_old;
ALTER TABLE compta_rapprochement RENAME TO compta_rapprochement_old;
ALTER TABLE fichiers RENAME TO fichiers_old;
ALTER TABLE membres_operations RENAME TO membres_operations_old;
ALTER TABLE membres_categories RENAME TO membres_categories_old;

-- Suppression des index pour que les nouveaux soient liés aux nouvelles tables
DROP INDEX cm_unique;
DROP INDEX wiki_uri;
DROP INDEX wiki_revisions_id_page;
DROP INDEX wiki_revisions_id_auteur;
DROP INDEX compta_operations_exercice;
DROP INDEX compta_operations_date;
DROP INDEX compta_operations_comptes;
DROP INDEX compta_operations_auteur;
DROP INDEX fichiers_date;

-- Suppression ancienne table recherche
DROP TABLE wiki_recherche;

-- Suppression des triggers
-- 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;
INSERT INTO compta_categories SELECT * FROM compta_categories_old;
INSERT INTO compta_comptes_bancaires SELECT * FROM compta_comptes_bancaires_old;
INSERT INTO compta_exercices SELECT * FROM compta_exercices_old;
INSERT INTO compta_journal SELECT *, NULL FROM compta_journal_old;
INSERT INTO compta_rapprochement SELECT * FROM compta_rapprochement_old;
INSERT INTO fichiers SELECT * FROM fichiers_old;
INSERT INTO membres_operations SELECT * FROM membres_operations_old;
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 cotisations_membres_old;
DROP TABLE rappels_old;
DROP TABLE rappels_envoyes_old;
DROP TABLE wiki_pages_old;
DROP TABLE wiki_revisions_old;
DROP TABLE compta_categories_old;
DROP TABLE compta_comptes_bancaires_old;
DROP TABLE compta_exercices_old;
DROP TABLE compta_journal_old;
DROP TABLE compta_rapprochement_old;
DROP TABLE fichiers_old;
DROP TABLE membres_operations_old;
DROP TABLE membres_categories_old;

Added src/include/data/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)
);

Deleted src/include/data/0.8.3.sql version [68c67cd1a9].

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 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 src/include/data/0.8.3_migration.sql version [78f64dc820].























>
>
>
>
>
>
>
>
>
>
>
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 src/include/data/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)
);

Deleted src/include/data/0.8.4.sql version [107bec2b2d].

1
2
3
-- Mise à jour des URI du wiki pour ne pas inclure les tirets en début et fin de chaîne
-- (problème de concordance entre API PHP et données SQLite)
UPDATE wiki_pages SET uri = trim(uri, '-') WHERE uri != trim(uri, '-');
<
<
<






Added src/include/data/0.8.4_migration.sql version [107bec2b2d].







>
>
>
1
2
3
-- Mise à jour des URI du wiki pour ne pas inclure les tirets en début et fin de chaîne
-- (problème de concordance entre API PHP et données SQLite)
UPDATE wiki_pages SET uri = trim(uri, '-') WHERE uri != trim(uri, '-');

Deleted src/include/data/0.9.0.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\', '');
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































Added src/include/data/0.9.0_migration.sql version [90ab72f7f4].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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 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;

-- 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\', '');

Added src/include/data/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\', '');

Deleted src/include/data/0.9.1.sql version [8d911832a5].

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 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 src/include/data/0.9.1_migration.sql version [6227606b97].





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
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 src/include/data/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 src/include/data/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
);

Added src/include/data/1.0.0_migration.sql version [eac19def50].





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
ALTER TABLE membres_operations RENAME TO membres_operations_old;
ALTER TABLE membres_categories RENAME TO membres_categories_old;

DROP TABLE fichiers_compta_journal; -- Inutilisé à ce jour

-- N'est pas utilisé
DELETE FROM config WHERE cle = 'categorie_dons' OR cle = 'categorie_cotisations';

.read 1.0.0_schema.sql

-- FIXME: insertion en comptes analytiques des projets et associations dans transactions

INSERT INTO acc_charts (id, country, code, label) VALUES (1, 'FR', 'PCGA1999', 'Plan comptable associatif 1999');

--.read plan_comptable_1999.sql
--.read plan_comptable_2020.sql

-- Migration comptes de code comme identifiant à ID unique
INSERT INTO acc_accounts (id, id_chart, code, label, position, user)
	SELECT NULL, 1, id, libelle, position, 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, 4 FROM compta_projets;

-- Suppression des positions "actif ou passif" et "charge ou produit"
UPDATE acc_accounts SET position = 0 WHERE position = 3 OR position = 12;

-- Modification des valeurs de la position (qui n'est plus un champ binaire)
UPDATE acc_accounts SET position = 3 WHERE position = 4;
UPDATE acc_accounts SET position = 4 WHERE position = 8;

-- 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';

-- Bénévolat en nature
UPDATE acc_accounts SET type = 5 WHERE code = '870';

-- Recopie des mouvements
INSERT INTO acc_transactions (id, label, notes, reference, date, id_year, id_analytical)
	SELECT id, libelle, remarques, numero_piece, date, id_exercice,
	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;

-- Création des lignes associées aux mouvements
INSERT INTO acc_transactions_lines (id_transaction, id_account, debit, credit, payment_reference)
	SELECT id, (SELECT id FROM acc_accounts WHERE code = compte_credit), 0, CAST(montant * 100 AS INT), numero_cheque FROM compta_journal;

INSERT INTO acc_transactions_lines (id_transaction, id_account, debit, credit, payment_reference)
	SELECT id, (SELECT id FROM acc_accounts WHERE code = compte_debit), CAST(montant * 100 AS INT), 0, numero_cheque FROM compta_journal;

-- Recopie des descriptions de catégories dans la table des comptes, et mise des comptes en signets
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);

-- Recopie des opérations, mais le nom a changé pour "mouvements"
INSERT INTO membres_mouvements
	SELECT * FROM membres_operations_old;

-- FIXME: ajout d'entrées dans le le log utilisateur à partir de id_auteur

-- 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 compta_journal;
DROP TABLE compta_categories;
DROP TABLE compta_comptes;
DROP TABLE compta_exercices;
DROP TABLE membres_operations_old;

-- Transfert des rapprochements
UPDATE acc_transactions_lines SET reconcilied = 1 WHERE id_transaction IN (SELECT id_operation FROM compta_rapprochement);

-- Suppression de la table rapprochements
DROP TABLE compta_rapprochement;

-- Suppression inutilisées
DROP TABLE compta_projets;
DROP TABLE compta_comptes_bancaires;
DROP TABLE compta_moyens_paiement;

Added src/include/data/1.0.0_schema.sql version [2862cb96ce].

























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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 cotisations
-- Types de cotisations et activités
(
    id INTEGER PRIMARY KEY NOT NULL,

    intitule TEXT NOT NULL,
    description TEXT NULL,

    duree INTEGER NULL, -- En jours
    debut TEXT NULL, -- timestamp
    fin TEXT NULL
);

CREATE TABLE IF NOT EXISTS cotisations_tarifs
(
    id INTEGER PRIMARY KEY NOT NULL,
    label TEXT NOT NULL,
    description TEXT NULL,
    amount INTEGER NULL,
    formula TEXT NULL,
    id_account INTEGER NULL REFERENCES acc_accounts (id) ON DELETE SET NULL -- NULL si le type n'est pas associé automatiquement à la compta
);

CREATE TABLE IF NOT EXISTS cotisations_membres
-- Enregistrement des cotisations et activités
(
    id INTEGER NOT NULL PRIMARY KEY,
    id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE,
    id_cotisation INTEGER NOT NULL REFERENCES cotisations (id) ON DELETE CASCADE,

    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_mouvements
-- Liaison des enregistrement des paiements en compta
(
    id_membre INTEGER NOT NULL REFERENCES membres (id) ON DELETE CASCADE,
    id_transaction INTEGER NOT NULL REFERENCES acc_transactions (id) ON DELETE CASCADE,
    id_cotisation INTEGER NULL REFERENCES cotisations_membres (id) ON DELETE SET NULL,

    PRIMARY KEY (id_membre, id_transaction)
);

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;

--
-- 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,

    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, favori, 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 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 TABLE IF NOT EXISTS acc_transactions
-- Opérations comptables
(
    id INTEGER PRIMARY KEY NOT NULL,

    label TEXT NOT NULL,
    notes TEXT NULL,
    reference TEXT NULL, -- N° de pièce comptable

    date TEXT NOT NULL DEFAULT CURRENT_DATE CHECK (date(date) IS NOT NULL AND date(date) = date),

    validated INTEGER NOT NULL DEFAULT 0, -- 1 = écriture validée, non modifiable

    hash TEXT NULL,
    prev_hash TEXT NULL,

    id_year INTEGER NOT NULL REFERENCES acc_years(id),
    id_analytical INTEGER NULL REFERENCES acc_accounts(id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS acc_transactions_year ON acc_transactions (id_year);
CREATE INDEX IF NOT EXISTS acc_transactions_date ON acc_transactions (date);

CREATE TABLE IF NOT EXISTS acc_transactions_lines
-- Lignes d'écritures d'une opération
(
    id INTEGER PRIMARY KEY NOT NULL,

    id_transaction INTEGER NOT NULL REFERENCES acc_transactions (id) ON DELETE CASCADE,
    id_account INTEGER NOT NULL REFERENCES acc_accounts (id), -- N° du compte dans le plan comptable

    credit INTEGER NOT NULL,
    debit INTEGER NOT NULL,

    reconcilied INTEGER NOT NULL DEFAULT 0,
    payment_reference TEXT NULL, -- Référence de paiement, eg. numéro de chèque

    CONSTRAINT line_check1 CHECK ((credit * debit) = 0),
    CONSTRAINT line_check2 CHECK ((credit + debit) > 0)
);

CREATE INDEX IF NOT EXISTS acc_transactions_lines_account ON acc_transactions_lines (id_account);

CREATE TABLE IF NOT EXISTS 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 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_acc_transactions
-- Associations entre fichiers et journal de compta (pièce comptable par exemple)
(
    fichier INTEGER NOT NULL REFERENCES fichiers (id),
    id INTEGER NOT NULL REFERENCES acc_transactions (id),
    PRIMARY KEY(fichier, id)
);

CREATE TABLE IF NOT EXISTS recherches
-- Recherches enregistrées
(
    id INTEGER NOT NULL PRIMARY KEY,
    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
(
    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 src/include/data/plan_comptable.json from [4d7e33a414] to [c496246466].

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
    },
    "890": {
        "code": 891,
        "nom": "Bilan de clôture",
        "parent": 89,
        "position": 3
    },
    "9": {
        "code": 9,
        "nom": "Classe 9 \u2014 Comptes analytiques",
        "parent": 0,
        "position": 12
    }
}







|












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
    }
}

Deleted src/include/data/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 src/include/init.php from [d8b3de9018] to [1ff1ce35fc].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
<?php

namespace Garradin;

use KD2\ErrorManager;
use KD2\Security;
use KD2\Form;


error_reporting(-1);

/*
 * Version de Garradin
 */

................................................................................
    Install::setLocalConfig('SECRET_KEY', $key);
    define('Garradin\SECRET_KEY', $key);
}

// Intégration du secret pour les tokens
Form::tokenSetSecret(SECRET_KEY);

// Fonctions utilitaires bien utiles d'avoir dans le namespace global de Garradin
function obj_has($obj, $pattern)
{
    return \KD2\Helpers::obj_has($obj, $pattern);
}

function obj_get($src, $pattern, $default = null)
{
    return \KD2\Helpers::obj_get($src, $pattern, $default);
}

/*
 * Vérifications pour enclencher le processus d'installation ou de mise à jour
 */

if (!defined('Garradin\INSTALL_PROCESS') && !defined('Garradin\UPGRADE_PROCESS'))
{







>







 







|
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
315
316
317
318
319
320
321
322









323
324
325
326
327
328
329
<?php

namespace Garradin;

use KD2\ErrorManager;
use KD2\Security;
use KD2\Form;
use KD2\DB\EntityManager;

error_reporting(-1);

/*
 * Version de Garradin
 */

................................................................................
    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'))
{

Added src/include/lib/Garradin/Compta/Categorie.php version [18c8c13e3d].











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Compta;

use Garradin\DB;
use Garradin\Utils;
use Garradin\UserException;
use Garradin\Entity;

/**
 * Catégories comptables
 */
class Categorie extends Entity
{
	const DEPENSE = 1;
	const RECETTE = 2;
	const VIREMENT = 3;

	const DETTE_ADHERENT = 5;
	const DETTE_FOURNISSEUR = 6;
	const CREANCE_ADHERENT = 7;
	const CREANCE_FOURNISSEUR = 8;

	protected $id;
	protected $type;
	protected $intitule;
	protected $description;

	protected $compte;

	protected $_fields = [
		'type'        => 'required|in:1,2,3',
		'intitule'    => 'required|string',
		'description' => 'string',
		'compte'      => 'required|alpha_num|in_table:compta_comptes,id',
	];
}

Modified src/include/lib/Garradin/Compta/Comptes.php from [9bf36bdeef] to [7cc9fbed31].

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
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
...
432
433
434
435
436
437
438




















439
440
441
442
443
444
445
446
447
448
449
450
451
<?php

namespace Garradin\Compta;


use \Garradin\DB;
use \Garradin\Utils;
use \Garradin\UserException;

class Comptes
{
    const CAISSE = '530';

    const CHEQUE_A_ENCAISSER = '5112';
    const CARTE_A_ENCAISSER = '5115';

    const PASSIF = 0x01;
    const ACTIF = 0x02;
    const PRODUIT = 0x04;
    const CHARGE = 0x08;

    /**
     * Importe un plan comptable
................................................................................
        if(is_null($plan))
        {
            throw new UserException('Le fichier n\'est pas du JSON ou n\'a pas pu être décodé.');
        }

        $db = DB::getInstance();
        $db->begin();
        $ids = [];

        foreach ($plan as $id=>$compte)
        {
            $ids[] = $id;

            if ($db->test('compta_comptes', $db->where('id', $id)))




            {







                $db->update('compta_comptes', [
                    'parent'    =>  $compte->parent,
                    'libelle'   =>  $compte->nom,
                    'position'  =>  $compte->position,
                    'plan_comptable' => $reset || !empty($compte->plan_comptable) ? 1 : 0,
                    'desactive' => !empty($compte->desactive) ? 1 : 0,
                ], $db->where('id', $id));
            }
            else
            {
                $db->insert('compta_comptes', [
                    'id'        =>  $id,
                    'parent'    =>  $compte->parent,
                    'libelle'   =>  $compte->nom,
                    'position'  =>  $compte->position,
                    'plan_comptable' => $reset || !empty($compte->plan_comptable) ? 1 : 0,
                    'desactive' => !empty($compte->desactive) ? 1 : 0,
                ]);


            }
        }

        // Effacer les comptes du plan comptable s'ils ne sont pas utilisés ailleurs
        // et qu'ils ne sont pas dans le nouveau plan comptable qu'on vient d'importer
        $sql = 'DELETE FROM compta_comptes WHERE id NOT IN (
            SELECT id FROM compta_comptes_bancaires
            UNION SELECT compte_credit FROM compta_journal
            UNION SELECT compte_debit FROM compta_journal
            UNION SELECT id FROM compta_categories)
            AND '. $db->where('id', 'NOT IN', $ids);

        // Si on ne fait qu'importer une mise à jour du plan comptable,
        // ne supprimer que les comptes qui n'ont pas été créés par l'usager
        if (!$delete_all) {
            $sql .= ' AND ' . $db->where('plan_comptable', 1);
        }

................................................................................
            {
                throw new UserException('Le compte '.$data['id'].' n\'est pas un sous-compte de '.$data['parent'].'.');
            }
        }

        return true;
    }





















    public function getPositions()
    {
        return [
            self::ACTIF     =>  'Actif',
            self::PASSIF    =>  'Passif',
            self::ACTIF | self::PASSIF      =>  'Actif ou passif (déterminé automatiquement au bilan selon le solde du compte)',
            self::CHARGE    =>  'Charge',
            self::PRODUIT   =>  'Produit',
            self::CHARGE | self::PRODUIT    =>  'Charge et produit',
        ];
    }
}




>
|
|
|



<
<
<
<
<







 







|

|

|

|
>
>
>
>
|
>
>
>
>
>
>
>

|



|
<




|
|



|

>
>





|

|
<
|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













1
2
3
4
5
6
7
8
9
10
11





12
13
14
15
16
17
18
..
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
...
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
<?php

namespace Garradin\Compta;

use Garradin\Entity;
use Garradin\DB;
use Garradin\Utils;
use Garradin\UserException;

class Comptes
{





    const PASSIF = 0x01;
    const ACTIF = 0x02;
    const PRODUIT = 0x04;
    const CHARGE = 0x08;

    /**
     * Importe un plan comptable
................................................................................
        if(is_null($plan))
        {
            throw new UserException('Le fichier n\'est pas du JSON ou n\'a pas pu être décodé.');
        }

        $db = DB::getInstance();
        $db->begin();
        $codes = [];

        foreach ($plan as $code=>$compte)
        {
            $codes[$code] = $db->firstColumn('SELECT id FROM compta_comptes WHERE code = ?;', $code);

            if (0 === $compte->parent) {
                $parent = null;
            }
            else {
                $parent = $db->firstColumn('SELECT id FROM compta_comptes WHERE code = ?;', $compte->parent);

                if (!$parent) {
                    throw new UserException(sprintf('Le compte parent "%s" n\'existe pas', $compte->parent));
                }
            }

            if ($codes[$code])
            {
                $db->update('compta_comptes', [
                    'parent'    =>  $parent,
                    'libelle'   =>  $compte->nom,
                    'position'  =>  $compte->position,
                    'plan_comptable' => $reset || !empty($compte->plan_comptable) ? 1 : 0,
                ], 'code = :code AND id_exercice IS NULL', ['code' => $code]);

            }
            else
            {
                $db->insert('compta_comptes', [
                    'code'      =>  $code,
                    'parent'    =>  $parent,
                    'libelle'   =>  $compte->nom,
                    'position'  =>  $compte->position,
                    'plan_comptable' => $reset || !empty($compte->plan_comptable) ? 1 : 0,
                    'id_exercice' => null,
                ]);

                $codes[$code] = $db->lastInsertRowId();
            }
        }

        // Effacer les comptes du plan comptable s'ils ne sont pas utilisés ailleurs
        // et qu'ils ne sont pas dans le nouveau plan comptable qu'on vient d'importer
        $sql = 'DELETE FROM compta_comptes WHERE id_exercice IS NULL AND id NOT IN (
            SELECT id FROM compta_comptes_bancaires
            UNION SELECT compte FROM compta_mouvements_lignes

            UNION SELECT compte FROM compta_categories)
            AND '. $db->where('code', 'NOT IN', array_keys($codes));

        // Si on ne fait qu'importer une mise à jour du plan comptable,
        // ne supprimer que les comptes qui n'ont pas été créés par l'usager
        if (!$delete_all) {
            $sql .= ' AND ' . $db->where('plan_comptable', 1);
        }

................................................................................
            {
                throw new UserException('Le compte '.$data['id'].' n\'est pas un sous-compte de '.$data['parent'].'.');
            }
        }

        return true;
    }

    public function listSimpleTargetAccounts()
    {
        $accounts = DB::getInstance()->get('SELECT id, parent, label, b.label AS parent_label
            FROM acc_accounts a
            INNER JOIN acc_accounts b ON b.id = a.parent
            WHERE type != 0 ORDER BY type, parent, code;');

        $out = [];

        foreach ($accounts as $account) {
            if (!isset($out[$account->parent_label])) {
                $out[$account->parent_label] = [];
            }

            $out[$account->parent_label][$account->id] = $account->label;
        }

        return $out;
    }

    public function getPositions()
    {
        return [
            self::ACTIF     =>  'Actif',
            self::PASSIF    =>  'Passif',
            self::ACTIF | self::PASSIF      =>  'Actif ou passif (déterminé automatiquement au bilan selon le solde du compte)',
            self::CHARGE    =>  'Charge',
            self::PRODUIT   =>  'Produit',
            self::CHARGE | self::PRODUIT    =>  'Charge et produit',
        ];
    }
}

Deleted src/include/lib/Garradin/Compta/Comptes_Bancaires.php version [c2ddfadd03].

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
<?php

namespace Garradin\Compta;

use \Garradin\DB;
use \Garradin\Utils;
use \Garradin\UserException;


class Comptes_Bancaires extends Comptes
{
    const NUMERO_PARENT_COMPTES = 512;

    public function add($data)
    {
        $db = DB::getInstance();

        $data['parent'] = self::NUMERO_PARENT_COMPTES;
        $data['id'] = null;

        $this->_checkBankFields($data);

        $new_id = parent::add($data);

        $db->insert('compta_comptes_bancaires', [
            'id'     =>  $new_id,
            'banque' =>  $data['banque'],
            'iban'   =>  $data['iban'],
            'bic'    =>  $data['bic'],
        ]);

        return $new_id;
    }

    public function edit($id, $data)
    {
        $db = DB::getInstance();
        $id = trim($id);

        if (!$db->test('compta_comptes_bancaires', $db->where('id', $id)))
        {
            throw new UserException('Ce compte n\'est pas un compte bancaire.');
        }

        $this->_checkBankFields($data);
        $result = parent::edit($id, $data);

        if (!$result)
        {
            return $result;
        }

        $db->update('compta_comptes_bancaires', [
            'banque' =>  $data['banque'],
            'iban'   =>  $data['iban'],
            'bic'    =>  $data['bic'],
        ], $db->where('id', $id));

        return true;
    }

    /**
     * Supprime un compte bancaire
     * La suppression sera refusée si le compte est utilisé dans l'exercice en cours
     * ou dans une catégorie.
     * Le compte bancaire sera supprimé et le compte au plan comptable seulement désactivé
     * si le compte est utilisé dans un exercice précédent.
     *
     * La désactivation d'un compte fait qu'il n'est plus utilisable dans l'exercice courant
     * ou les exercices suivants, mais il est possible de le réactiver.
     * @param  string $id  Numéro du compte
     * @return boolean     TRUE si la suppression ou désactivation a été effectuée, une exception ou FALSE sinon
     */
    public function delete($id)
    {
        $db = DB::getInstance();
        $id = trim($id);

        if (!$db->test('compta_comptes_bancaires', $db->where('id', $id)))
        {
            throw new UserException('Ce compte n\'est pas un compte bancaire.');
        }

        // Ne pas supprimer/désactiver un compte qui est utilisé dans l'exercice courant
        if ($db->firstColumn('SELECT 1 FROM compta_journal
                WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1) 
                AND (compte_debit = ? OR compte_credit = ?) LIMIT 1;', $id, $id))
        {
            throw new UserException('Ce compte ne peut être supprimé car des écritures y sont liées sur l\'exercice courant. '
                . 'Il faut supprimer ou ré-attribuer ces écritures avant de pouvoir supprimer le compte.');
        }

        // Il n'est pas possible de supprimer ou désactiver un compte qui est lié à des catégories
        if ($db->test('compta_categories', $db->where('compte', $id)))
        {
            throw new UserException('Ce compte ne peut être supprimé car des catégories y sont liées. '
                . 'Merci de supprimer ou modifier les catégories liées avant de le supprimer.');
        }

        $db->delete('compta_comptes_bancaires', $db->where('id', $id));

        try {
            $return = parent::delete($id);
        }
        catch (UserException $e) {
            // Impossible de supprimer car des opérations y sont encore liées
            // sur les exercices précédents, alors on le désactive
            $return = parent::disable($id);
        }

        return $return;
    }

    public function get($id)
    {
        $db = DB::getInstance();
        return $db->first('SELECT * FROM compta_comptes AS c
            INNER JOIN compta_comptes_bancaires AS cc
            ON c.id = cc.id
            WHERE c.id = ?;', $id);
    }

    public function getList($parent = false)
    {
        $db = DB::getInstance();
        return $db->getGrouped('SELECT c.id AS id, * FROM compta_comptes AS c
            INNER JOIN compta_comptes_bancaires AS cc ON c.id = cc.id
            WHERE c.parent = ? ORDER BY c.id;', self::NUMERO_PARENT_COMPTES);
    }

    protected function _checkBankFields(&$data)
    {
        if (empty($data['banque']) || !trim($data['banque']))
        {
            throw new UserException('Le nom de la banque ne peut rester vide.');
        }

        if (empty($data['bic']))
        {
            $data['bic'] = '';
        }
        else
        {
            $data['bic'] = trim(strtoupper($data['bic']));
            $data['bic'] = preg_replace('![^\dA-Z]!', '', $data['bic']);

            if (!Utils::checkBIC($data['bic']))
            {
                throw new UserException('Code BIC/SWIFT invalide.');
            }
        }

        if (empty($data['iban']))
        {
            $data['iban'] = '';
        }
        else
        {
            $data['iban'] = trim(strtoupper($data['iban']));
            $data['iban'] = preg_replace('![^\dA-Z]!', '', $data['iban']);

            if (!Utils::checkIBAN($data['iban']))
            {
                throw new UserException('Code IBAN invalide.');
            }
        }

        return true;
    }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































































































































































































Modified src/include/lib/Garradin/Compta/Exercices.php from [3bc6667d2a] to [d2b3e3d39a].

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
...
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
<?php

namespace Garradin\Compta;



use \Garradin\DB;
use \Garradin\Utils;
use \Garradin\UserException;

class Exercices
{
    public function add($data)
    {
        $this->_checkFields($data);

        $db = DB::getInstance();

        if ($db->firstColumn('SELECT 1 FROM compta_exercices WHERE
            (debut <= :debut AND fin >= :debut) OR (debut <= :fin AND fin >= :fin);',
            ['debut' => $data['debut'], 'fin' => $data['fin']]))
        {
            throw new UserException('La date de début ou de fin se recoupe avec un autre exercice.');
        }

        if ($db->firstColumn('SELECT 1 FROM compta_exercices WHERE cloture = 0;'))
        {
            throw new UserException('Il n\'est pas possible de créer un nouvel exercice tant qu\'il existe un exercice non-clôturé.');
        }

        $db->insert('compta_exercices', [
            'libelle'   =>  trim($data['libelle']),
            'debut'     =>  $data['debut'],
            'fin'       =>  $data['fin'],
        ]);

        return $db->lastInsertRowId();
    }

    public function edit($id, $data)
    {
        $db = DB::getInstance();

        $this->_checkFields($data);

        // Evitons que les exercices se croisent
        if ($db->firstColumn('SELECT 1 FROM compta_exercices WHERE id != :id AND
            ((debut <= :debut AND fin >= :debut) OR (debut <= :fin AND fin >= :fin));',
            ['debut' => $data['debut'], 'fin' => $data['fin'], 'id' => (int) $id]))
        {
            throw new UserException('La date de début ou de fin se recoupe avec un autre exercice.');
        }

        // On vérifie qu'on ne va pas mettre des opérations en dehors de tout exercice
        if ($db->firstColumn('SELECT 1 FROM compta_journal WHERE id_exercice = ?
            AND date < ? LIMIT 1;', (int)$id, $data['debut']))
        {
            throw new UserException('Des opérations de cet exercice ont une date antérieure à la date de début de l\'exercice.');
        }

        if ($db->firstColumn('SELECT 1 FROM compta_journal WHERE id_exercice = ?
            AND date > ? LIMIT 1;', (int)$id, $data['fin']))
        {
            throw new UserException('Des opérations de cet exercice ont une date postérieure à la date de fin de l\'exercice.');
        }

        $db->update('compta_exercices', [
            'libelle'   =>  trim($data['libelle']),
            'debut'     =>  $data['debut'],
            'fin'       =>  $data['fin'],
        ], 'id = :id', ['id' => (int)$id]);

        return true;
    }

    /**
     * Clôturer un exercice et en ouvrir un nouveau
     * Le report à nouveau n'est pas effectué automatiquement par cette fonction, voir doReports pour ça.
     * @param  integer  $id     ID de l'exercice à clôturer
     * @param  string   $end    Date de clôture de l'exercice au format Y-m-d
     * @return integer          L'ID du nouvel exercice créé
     */
    public function close($id, $end)
    {
        $db = DB::getInstance();

        if (!Utils::checkDate($end))
        {
            throw new UserException('Date de fin vide ou invalide.');
        }

        $db->begin();

        // Clôture de l'exercice
        $db->update('compta_exercices', [
            'cloture'   =>  1,
            'fin'       =>  $end,
        ], 'id = :id', ['id' => (int)$id]);

        // Date de début du nouvel exercice : lendemain de la clôture du précédent exercice
        $new_begin = Utils::modifyDate($end, '+1 day');

        // Date de fin du nouvel exercice : un an moins un jour après l'ouverture
        $new_end = Utils::modifyDate($new_begin, '+1 year -1 day');

        // Enfin sauf s'il existe déjà des opérations après cette date, auquel cas la date de fin
        // est fixée à la date de la dernière opération, ceci pour ne pas avoir d'opération
        // orpheline d'exercice
        $last = $db->firstColumn('SELECT date FROM compta_journal WHERE id_exercice = ? AND date >= ? ORDER BY date DESC LIMIT 1;', $id, $new_end);
        $new_end = $last ?: $new_end;

        $year_begin = substr($new_begin, 0, 4);
        $year_end = substr($new_end, 0, 4);

        // Nom du nouvel exercice
        if ($year_begin == $year_end) {
            $label = sprintf('Exercice %d', $year_begin);
        }
        else {
            $label = sprintf('Exercice %d-%d', $year_begin, $year_end);
        }

        // Création du nouvel exercice
        $new_id = $this->add([
            'debut'     =>  $new_begin,
            'fin'       =>  $new_end,
            'libelle'   =>  $label,
        ]);

        // Ré-attribution des opérations de l'exercice à clôturer qui ne sont pas dans son
        // intervale au nouvel exercice
        $db->update('compta_journal', ['id_exercice' => $new_id], 'id_exercice = :id AND date >= :date', [
            'id'   => $id,
            'date' => $new_begin,
        ]);

        $db->commit();

        return $new_id;

    }

    /**
     * Créer les reports à nouveau issus de l'exercice $old_id dans le nouvel exercice courant
     * @param  integer $old_id  ID de l'ancien exercice
     * @param  integer $new_id  ID du nouvel exercice
     * @param  string  $date    Date Y-m-d donnée aux opérations créées
................................................................................
                'date'      =>  $date,
                'montant'   =>  abs($resultat),
                'compte_debit'  =>  $resultat < 0 ? $resultat_debiteur : 890,
                'compte_credit' =>  $resultat > 0 ? $resultat_excedent : 890,
            ]);
        }

        return true;
    }

    public function delete($id)
    {
        $db = DB::getInstance();

        // Ne pas supprimer un compte qui est utilisé !
        if ($db->test('compta_journal', $db->where('id_exercice', $id)))
        {
            throw new UserException('Cet exercice ne peut être supprimé car des opérations comptables y sont liées.');
        }

        $db->delete('compta_exercices', 'id = ?', (int)$id);

        return true;
    }

    public function get($id, $with_count = false)
    {
        $with_count = $with_count
            ? ', (SELECT COUNT(*) FROM compta_journal WHERE id_exercice = compta_exercices.id) AS nb_operations'
            : '';

        $db = DB::getInstance();
        return $db->first('SELECT *, strftime(\'%s\', debut) AS debut,
            strftime(\'%s\', fin) AS fin ' . $with_count . '
            FROM compta_exercices WHERE id = ?;', (int)$id);
    }

    public function getCurrent()
    {
        $db = DB::getInstance();
        return $db->first('SELECT *, strftime(\'%s\', debut) AS debut, strftime(\'%s\', fin) AS fin FROM compta_exercices
            WHERE cloture = 0 LIMIT 1;');
    }

    public function getCurrentId()
    {
        $db = DB::getInstance();
        return $db->firstColumn('SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1;');
    }

    public function getList()
    {
        $db = DB::getInstance();
        return $db->getGrouped('SELECT id, *, strftime(\'%s\', debut) AS debut,
            strftime(\'%s\', fin) AS fin,
            (SELECT COUNT(*) FROM compta_journal WHERE id_exercice = compta_exercices.id) AS nb_operations
            FROM compta_exercices ORDER BY fin DESC;');
    }

    protected function _checkFields(&$data)
    {
        if (empty($data['libelle']) || !trim($data['libelle']))
        {
            throw new UserException('Le libellé ne peut rester vide.');
        }

        $data['libelle'] = trim($data['libelle']);

        if (empty($data['debut']) || !checkdate(substr($data['debut'], 5, 2), substr($data['debut'], 8, 2), substr($data['debut'], 0, 4)))
        {
            throw new UserException('Date de début vide ou invalide.');
        }

        if (empty($data['fin']) || !checkdate(substr($data['fin'], 5, 2), substr($data['fin'], 8, 2), substr($data['fin'], 0, 4)))
        {
            throw new UserException('Date de fin vide ou invalide.');
        }

        return true;
    }
}




>
>
|
|
|



|

|
|
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>







 









|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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
...
138
139
140
141
142
143
144
145
146
147







































































<?php

namespace Garradin\Compta;

use Garradin\Entities\Compta\Exercice;
use KD2\DB\EntityManager;
use Garradin\DB;
use Garradin\Utils;
use Garradin\UserException;

class Exercices
{
    public function listOpen()
    {
        return EntityManager::getInstance(Exercice::class)->all('SELECT * FROM @TABLE WHERE cloture = 0;');
    }























    public function getCurrent()
    {


































































































        return EntityManager::findOne(Exercice::class, 'SELECT * FROM @TABLE ORDER BY fin DESC LIMIT 1');
    }

    /**
     * Créer les reports à nouveau issus de l'exercice $old_id dans le nouvel exercice courant
     * @param  integer $old_id  ID de l'ancien exercice
     * @param  integer $new_id  ID du nouvel exercice
     * @param  string  $date    Date Y-m-d donnée aux opérations créées
................................................................................
                'date'      =>  $date,
                'montant'   =>  abs($resultat),
                'compte_debit'  =>  $resultat < 0 ? $resultat_debiteur : 890,
                'compte_credit' =>  $resultat > 0 ? $resultat_excedent : 890,
            ]);
        }

        return true;
    }
}







































































Modified src/include/lib/Garradin/Compta/Journal.php from [88e9a2c624] to [6361a8ebe9].

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
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    {
        if (is_null($id))
            return true;

        return DB::getInstance()->test('compta_exercices', 'cloture = 0 AND id = ?', (int)$id);
    }

    public function getSolde($id_compte, $inclure_sous_comptes = false, $exercice = null)
    {
        $db = DB::getInstance();
        $exercice = (int) $exercice ?: $this->_getCurrentExercice();
        $compte = $inclure_sous_comptes
            ? 'LIKE \'' . $db->escapeString(trim($id_compte)) . '%\''
            : '= \'' . $db->escapeString(trim($id_compte)) . '\'';

        $debit = 'COALESCE((SELECT SUM(montant) FROM compta_journal WHERE compte_debit '.$compte.' AND id_exercice = '.(int)$exercice.'), 0)';
        $credit = 'COALESCE((SELECT SUM(montant) FROM compta_journal WHERE compte_credit '.$compte.' AND id_exercice = '.(int)$exercice.'), 0)';




        // L'actif augmente au débit, le passif au crédit
        $position = $db->firstColumn('SELECT position FROM compta_comptes WHERE id = ?;', $id_compte);


        if (($position & Comptes::ACTIF) || ($position & Comptes::CHARGE))
        {
            $query = $debit . ' - ' . $credit;

        }
        else
        {
            $query = $credit . ' - ' . $debit;
        }

        return $db->firstColumn('SELECT ' . $query . ';');

    }

    public function getJournalCompte($compte, $inclure_sous_comptes = false, $exercice = null)
    {
        $db = DB::getInstance();

        $position = $db->firstColumn('SELECT position FROM compta_comptes WHERE id = ?;', $compte);
................................................................................
    public function get($id)
    {
        $db = DB::getInstance();
        return $db->first('SELECT *, strftime(\'%s\', date) AS date FROM compta_journal WHERE id = ?;', $id);
    }

    /**
     * Compte le nombre d'écritures liées à un membre
     * @param  integer $id Numéro de membre
     * @return integer     Nombre d'écritures liées
     */
    public function countForMember($id)
    {
        $db = DB::getInstance();
        return $db->count('compta_journal', $db->where('id_auteur', $id));
    }

    /**
     * Lister les écritures liées à un membre
     * @param  integer $id       Identifiant de membre
     * @param  integer $exercice Identifiant d'exercice
     * @return array           Liste des écritures liées







|


<
<
<
<

<
<
>
>
>

<


>
|
<
<
>

<
|
<
<
<
<
>







 







|






|







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
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    {
        if (is_null($id))
            return true;

        return DB::getInstance()->test('compta_exercices', 'cloture = 0 AND id = ?', (int)$id);
    }

    public function getSolde(int $id_compte, ?int $id_exercice = null): int
    {
        $db = DB::getInstance();







        $solide = (int) $db->firstColumn('SELECT SUM(credit) - SUM(debit) FROM compta_mouvements_lignes AS l
            INNER JOIN compta_mouvements AS m ON m.id = l.id_mouvement
            WHERE compte = ? AND m.id_exercice = ?;', $id_compte, $id_exercice);


        $position = $db->firstColumn('SELECT position FROM compta_comptes WHERE id = ?;', $id_compte);

        // L'actif augmente au débit, le passif au crédit
        if (($position & Comptes::ACTIF) || ($position & Comptes::CHARGE)) {


            $solde = -$solde;
        }






        return $solde;
    }

    public function getJournalCompte($compte, $inclure_sous_comptes = false, $exercice = null)
    {
        $db = DB::getInstance();

        $position = $db->firstColumn('SELECT position FROM compta_comptes WHERE id = ?;', $compte);
................................................................................
    public function get($id)
    {
        $db = DB::getInstance();
        return $db->first('SELECT *, strftime(\'%s\', date) AS date FROM compta_journal WHERE id = ?;', $id);
    }

    /**
     * Compte le nombre d'écritures créées par un membre
     * @param  integer $id Numéro de membre
     * @return integer     Nombre d'écritures liées
     */
    public function countForMember($id)
    {
        $db = DB::getInstance();
        return $db->count('compta_mouvements', $db->where('id_auteur', $id));
    }

    /**
     * Lister les écritures liées à un membre
     * @param  integer $id       Identifiant de membre
     * @param  integer $exercice Identifiant d'exercice
     * @return array           Liste des écritures liées

Modified src/include/lib/Garradin/Compta/Stats.php from [5104b17973] to [2aec4ff612].

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
	}

	public function depenses()
	{
		return $this->_parType(Categories::DEPENSES);
	}

	public function soldeCompte($compte, $augmente = 'debit', $diminue = 'credit')
	{
		$db = DB::getInstance();

		if (strpos($compte, '%') !== false)
		{
			$compte = 'LIKE \''. $db->escapeString($compte) . '\'';
		}
		else
		{
			$compte = '= \''. $db->escapeString($compte) . '\'';
		}

		$stats = $this->getStats('SELECT strftime(\'%Y%m\', date) AS date,
			(COALESCE((SELECT SUM(montant) FROM compta_journal
				WHERE compte_'.$augmente.' '.$compte.' AND id_exercice = cj.id_exercice
				AND date >= strftime(\'%Y-%m-01\', cj.date)
				AND date <= strftime(\'%Y-%m-31\', cj.date)), 0)
			- COALESCE((SELECT SUM(montant) FROM compta_journal
				WHERE compte_'.$diminue.' '.$compte.' AND id_exercice = cj.id_exercice
				AND date >= strftime(\'%Y-%m-01\', cj.date)
				AND date <= strftime(\'%Y-%m-31\', cj.date)), 0)
			) AS solde
			FROM compta_journal AS cj
			WHERE (compte_debit '.$compte.' OR compte_credit '.$compte.')
			AND id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0)


			GROUP BY strftime(\'%Y-%m\', date) ORDER BY date;');

		$c = 0;
		foreach ($stats as $k=>$v)
		{
			$c += $v;
			$stats[$k] = $c;
		}







|



<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
>
>
|







43
44
45
46
47
48
49
50
51
52
53









54









55


56
57
58
59
60
61
62
63
64
65
	}

	public function depenses()
	{
		return $this->_parType(Categories::DEPENSES);
	}

	public function soldeCompte(int $compte, ?int $id_exercice = null)
	{
		$db = DB::getInstance();










		$stats = $this->getAssoc('SELECT strftime(\'%Y%m\', m.date), SUM(credit) - SUM(debit)









			FROM compta_mouvements_lignes AS l


            INNER JOIN compta_mouvements AS m ON m.id = l.id_mouvement
            WHERE compte = ? AND id_exercice = ?
            GROUP BY strftime(\'%Y%m\', m.date) ORDER BY m.date;');

		$c = 0;
		foreach ($stats as $k=>$v)
		{
			$c += $v;
			$stats[$k] = $c;
		}

Modified src/include/lib/Garradin/Config.php from [9e09070cbb] to [0818359e22].

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
...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
...
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
        $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,
            
            'categorie_dons'          =>  $int,
            'categorie_cotisations'   =>  $int,
            
            'accueil_wiki'            =>  $string,
            'accueil_connexion'       =>  $string,
            
            'frequence_sauvegardes'   =>  $int,
            'nombre_sauvegardes'      =>  $int,
            
            'champ_identifiant'       =>  $string,
            'champ_identite'          =>  $string,
            
            'version'                 =>  $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)
................................................................................
            $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').');');
        }

................................................................................
            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))
        {
................................................................................
                // 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_cotisations':
            case 'categorie_dons':
            {
                return false;
                $db = DB::getInstance();
                if (!$db->firstColumn('SELECT 1 FROM compta_categories WHERE id = ?;', $value))
                {
                    throw new UserException('Champ '.$key.' : La catégorie comptable numéro \''.$value.'\' ne semble pas exister.');
                }
                break;
            }
            case 'categorie_membres':
            {
                $db = DB::getInstance();
                if (!$db->firstColumn('SELECT 1 FROM membres_categories WHERE id = ?;', $value))
                {







|


|

|

|
<
<
<


|


|


|

|




|







 







|







 







|







 







|
|




<
<
<
<
<
<
<
<
<
<
<







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
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
289
290
291
292
293
294
295
296
297
298
299
300
301











302
303
304
305
306
307
308
        $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,

            '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)
................................................................................
            $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').');');
        }

................................................................................
            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))
        {
................................................................................
                // 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))
                {

Modified src/include/lib/Garradin/DB.php from [b5f765f6ec] to [9be1dc4464].

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
<?php

namespace Garradin;

use KD2\DB_SQLite3;

class DB extends DB_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)
    {













        return self::$_instance ?: self::$_instance = new DB($create);
    }

    private function __clone()
    {
        // Désactiver le clonage, car on ne veut qu'une seule instance
    }

    public function __construct($create = false)
    {
        if (!defined('\SQLITE3_OPEN_READWRITE'))
        {
            throw new \Exception('Module SQLite3 de PHP non présent. Merci de l\'installer.');

        }

        $flags = \SQLITE3_OPEN_READWRITE;

        if ($create)
        {
            $flags |= \SQLITE3_OPEN_CREATE;
        }

        parent::__construct(DB_FILE, $flags);

        // Ne pas se connecter ici, on ne se connectera que quand une requête sera faite
    }

    public function connect()
    {
        if (parent::connect())
        {
            // Activer les contraintes des foreign keys
            $this->exec('PRAGMA foreign_keys = ON;');

            // 10 secondes
            $this->db->busyTimeout(10 * 1000);
            $this->exec('PRAGMA journal_mode = TRUNCATE;');

            $this->db->createFunction('transliterate_to_ascii', ['Garradin\Utils', 'transliterateToAscii']);
        }
    }

    public function close()
    {
        parent::close();
        self::$_instance = null;
    }

    /**
     * Import a file containing SQL commands
     * Allows to use the statement ".read other_file.sql" to load other files
     * @param  string $file Path to file containing SQL commands
     * @return boolean
     */
    public function import($file)
    {
        $sql = file_get_contents($file);



        $dir = dirname($file);

        $sql = preg_replace_callback('/^\.read (.+\.sql)$/m', function ($match) use ($dir) {
            return file_get_contents($dir . DIRECTORY_SEPARATOR . $match[1]) . "\n";
        }, $sql);


        return $this->exec($sql);


    }

    /**
     * @see https://www.sqlite.org/lang_altertable.html
     */
    public function toggleForeignKeys($enable)
    {




|

|









|

>
>
>
>
>
>
>
>
>
>
>
>
>
|







|

|
<
<
>


<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|

|
|
|

|
|
|
<
|





<
<
<
<
<
<
|

<
>
>
|
<

<
<
<
>
|
<
>
>







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
<?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]);

            $flags = \SQLITE3_OPEN_READWRITE;

            if ($create)
            {
                $flags |= \SQLITE3_OPEN_CREATE;
            }

            self::$_instance->flags = $flags;
        }

        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);
        $this->exec('PRAGMA journal_mode = TRUNCATE;');

        $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/Entities/Accounting/Account.php version [098abf148d].















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Entities\Accounting;

use Garradin\Entity;
use Garradin\DB;
use Garradin\Utils;
use Garradin\UserException;

class Account extends Entity
{
	const TABLE = 'acc_accounts';

	// Passif
	const LIABILITY = 1;

	// Actif
	const ASSET = 2;

	// Produit
	const REVENUE = 3;

	// Charge
	const EXPENSE = 4;

	const POSITIONS_NAMES = [
		'',
		'Passif',
		'Actif',
		'Produit',
		'Charge',
	];

	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_ANALYTICAL = 4;
	const TYPE_VOLUNTEERING = 5;

	const TYPE_BOOKMARK = 6;

	const TYPES_NAMES = [
		'',
		'Banque',
		'Caisse',
		'Attente d\'encaissement',
		'Analytique',
		'Bénévolat',
		'Favori',
	];

	protected $id;
	protected $id_chart;
	protected $code;
	protected $label;
	protected $description;
	protected $position;
	protected $type;
	protected $user;

	protected $_types = [
		'id'          => 'int',
		'id_chart'    => 'int',
		'code'        => 'string',
		'label'       => 'string',
		'description' => '?string',
		'position'    => 'int',
		'type'        => 'int',
		'user'        => 'int',
	];

	protected $_validation_rules = [
		'id_chart'    => 'required|integer|in_table:acc_charts,id',
		'code'        => 'required|string|alpha_num|max:6',
		'label'       => 'required|string|max:200',
		'description' => 'string|max:2000',
		'position'    => 'required|integer',
		'type'        => 'required|integer',
		'user'        => 'integer|min:0|max:1',
	];
}

Added src/include/lib/Garradin/Entities/Accounting/Chart.php version [2ddf8263f9].











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Entities\Accounting;

use Garradin\Entity;

class Chart extends Entity
{
    const TABLE = 'acc_charts';

    protected $id;
    protected $label;
    protected $country;
    protected $code;
    protected $archived;

    protected $_types = [
        'id'       => 'integer',
        'label'    => 'string',
        'country'  => 'string',
        'code'     => '?string',
        'archived' => 'integer',
    ];

    protected $_validation_rules = [
        'label'    => 'required|string|max:200',
        'country'  => 'required|string|size:2',
        'code'     => 'string',
        'archived' => 'integer|required|max:1|min:0',
    ];

    public function selfCheck(): void
    {
        parent::selfCheck();
        $this->assert(Utils::getCountryName($this->country), 'Le code pays doit être un code ISO valide');
    }
}

Added src/include/lib/Garradin/Entities/Accounting/Line.php version [90430b6221].





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Entities\Accounting;

use Garradin\Entity;
use Garradin\ValidationException;

class Line extends Entity
{
	const TABLE = 'acc_transactions_lines';

	protected $id;
	protected $id_transaction;
	protected $id_account;
	protected $credit = 0;
	protected $debit = 0;
	protected $payment_reference;
	protected $reconciled;

	protected $_types = [
		'id_transaction'    => 'int',
		'id_account'        => 'int',
		'credit'            => 'int',
		'debit'             => 'int',
		'payment_reference' => '?string',
		'reconcilied'       => 'int',
	];

	protected $_validation_rules = [
		'id_transaction'    => 'required|integer|in_table:acc_transactions,id',
		'id_account'        => 'required|integer|in_table:acc_accounts,id',
		'credit'            => 'required|integer|min:0',
		'debit'             => 'required|integer|min:0',
		'payment_reference' => 'string|max:200',
		'reconcilied'       => 'int|min:0|max:1',
	];

	public function filterUserValue(string $key, $value, array $source)
	{
		$value = parent::filterUserValue($key, $value);

		if ($key == 'credit' || $key == 'debit')
		{
			if (!preg_match('/^(\d+)(?:[,.](\d{2}))?$/', $value, $match))
			{
				throw new ValidationException('Le format du montant est invalide. Format accepté, exemple : 142,02');
			}

			$value = $match[1] . sprintf('%02d', $match[2]);
		}

		return $value;
	}

	public function selfCheck()
	{
		parent::selfCheck();
		$this->assert($this->credit || $this->debit, 'Aucun montant au débit ou au crédit.');
		$this->assert(($this->credit * $this->debit) === 0 && ($this->credit + $this->debit) > 0, 'Ligne non équilibrée : crédit ou débit doit valoir zéro.');
		$this->assert($this->id_transaction, 'Aucun mouvement n\'a été indiqué pour cette ligne.');
	}
}

Added src/include/lib/Garradin/Entities/Accounting/Transaction.php version [76582d1811].







































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Entities\Accounting;

use Garradin\Entity;
use Garradin\validatedException;
use Garradin\DB;
use Garradin\Config;

class Transaction extends Entity
{
	const TABLE = 'acc_transactions';

	protected $id;
	protected $label;
	protected $notes;
	protected $reference;

	protected $date;

	protected $validated;

	protected $hash;
	protected $prev_hash;

	protected $id_year;
	protected $id_analytical;

	protected $_types = [
		'label'             => 'string',
		'notes'             => '?string',
		'reference'         => '?string',
		'date'              => 'date',
		'validated'         => 'bool',
		'hash'              => '?string',
		'prev_hash'         => '?string',
		'id_year'           => 'int',
		'id_analytical'     => '?int',
	];

	protected $_validated_rules = [
		'label'             => 'required|string|max:200',
		'notes'             => 'string|max:20000',
		'reference'         => 'string|max:200',
		'date'              => 'required|date',
		'validated'         => 'bool',
		'id_year'           => 'integer|in_table:acc_years,id',
		'id_analytical'     => 'integer|in_table:acc_accounts,id'
	];

	protected $lines;

	public function getLines()
	{
		if (null === $this->lines && $this->exists()) {
			$db = DB::getInstance();
			$this->lines = $db->toObject($db->get('SELECT * FROM acc_transactions_lines WHERE id_transaction = ? ORDER BY id;', $this->id), Ligne::class);
		}
		else {
			$this->lines = [];
		}

		return $this->lines;
	}

/*
	public function getHash()
	{
		if (!$this->id_year) {
			throw new \LogicException('Il n\'est pas possible de hasher un mouvement qui n\'est pas associé à un exercice');
		}

		static $keep_keys = [
			'label',
			'notes',
			'reference',
			'date',
			'validated',
			'prev_hash',
		];

		$hash = hash_init('sha256');
		$values = $this->asArray();
		$values = array_intersect_key($values, $keep_keys);

		hash_update($hash, implode(',', array_keys($values)));
		hash_update($hash, implode(',', $values));

		foreach ($this->getLines() as $ligne) {
			hash_update($hash, implode(',', [$ligne->compte, $ligne->debit, $ligne->credit]));
		}

		return hash_final($hash, false);
	}

	public function checkHash()
	{
		return hash_equals($this->getHash(), $this->hash);
	}
*/

	public function add(Ligne $line)
	{
		$this->lines[] = $line;
	}

	public function transfer(int $amount, int $from, int $to)
	{
		$ligne1 = new Ligne;
		$ligne1->compte = $from;
		$ligne1->debit = $amount;
		$ligne1->credit = 0;

		$ligne2 = new Ligne;
		$ligne1->compte = $to;
		$ligne1->debit = 0;
		$ligne1->credit = $amount;

		return $this->add($ligne1) && $this->add($ligne2);
	}

	public function save()
	{
		if ($this->validated && !isset($this->_modified['validated'])) {
			throw new validatedException('Il n\'est pas possible de modifier un mouvement qui a été validé');
		}

		if (!parent::save()) {
			return false;
		}

		foreach ($this->lines as $ligne)
		{
			$ligne->id_transaction = $this->id;
			$ligne->save();
		}
	}

	public function delete()
	{
		if ($this->validated) {
			throw new validatedException('Il n\'est pas possible de supprimer un mouvement qui a été validé');
		}

		parent::delete();
	}

	public function selfCheck()
	{
		parent::selfCheck();

		$db = DB::getInstance();
		$config = Config::getInstance();

		// ID d'exercice obligatoire s'il existe déjà des exercices
		if (null === $this->id_year && $db->firstColumn('SELECT 1 FROM acc_years LIMIT 1;')) {
			throw new validatedException('Aucun exercice spécifié.');
		}

		if (null !== $this->id_year
			&& !$db->test('acc_years', 'id = ? AND start_date <= ? AND end_date >= ?;', $this->id_year, $this->date, $this->date))
		{
			throw new validatedException('La date ne correspond pas à l\'exercice sélectionné.');
		}

		$total = 0;

		$lines = $this->getLines();

		foreach ($lines as $line) {
			$total += $line->credit;
			$total -= $line->debit;
		}

		if (0 !== $total) {
			throw new validatedException('Mouvement non équilibré : déséquilibre entre débits et crédits');
		}
	}
}

Added src/include/lib/Garradin/Entities/Accounting/Year.php version [2715ee53bc].





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Entities\Accounting;

use Garradin\Entity;
use Garradin\DB;
use Garradin\UserException;

class Year extends Entity
{
    const TABLE = 'acc_years';

    protected $id;
    protected $label;
    protected $start_date;
    protected $end_date;
    protected $closed = 0;

    protected $_types = [
        'id'         => 'integer',
        'label'      => 'string',
        'start_date' => 'date',
        'end_date'   => 'date',
        'closed'     => 'integer',
    ];

    protected $_validation_rules = [
        'label'      => 'required|string|max:200',
        'start_date' => 'required|date|before:end_date',
        'end_date'   => 'required|date|after:start_date',
        'closed'     => 'int|min:0|max:1',
    ];

    public function selfCheck(): void
    {
        parent::selfCheck();
        $this->assert($this->start_date < $this->end_date, 'La date de fin doit être postérieure à la date de début');
        $this->assert($this->closed == 1 || !isset($this->_modified['closed']), 'Il est interdit de réouvrir un exercice clôturé');

        $db = DB::getInstance();

        // Vérifier qu'on ne crée pas 2 exercices qui se recoupent
        if ($this->exists()) {
            $this->assert(
                !$db->test(self::TABLE, 'id != :id AND ((start_date <= :start_date AND end_date >= :start_date) OR (start_date <= :end_date AND end_date >= :start_date))',
                    ['id' => $this->id(), 'start_date' => $this->start_date, 'end_date' => $this->end_date]),
                'La date de début ou de fin se recoupe avec un exercice existant.'
            );

            $this->assert(
                !$db->test(Transaction::TABLE, 'id_year = ? AND date < ?', $this->id(), $this->start_date),
                'Des mouvements de cet exercice ont une date antérieure à la date de début de l\'exercice.'
            );

            $this->assert(
                !$db->test(Transaction::TABLE, 'id_year = ? AND date > ?', $this->id(), $this->end_date),
                'Des mouvements de cet exercice ont une date postérieure à la date de fin de l\'exercice.'
            );
        }
        else {
            $this->assert(
                !$db->test(self::TABLE, '(start_date <= :start_date AND end_date >= :start_date) OR (start_date <= :end_date AND end_date >= :start_date)',
                    ['start_date' => $this->start_date, 'end_date' => $this->end_date]),
                'La date de début ou de fin se recoupe avec un exercice existant.'
            );
        }
    }

    public function close()
    {
        if ($this->closed) {
            throw new \LogicException('Cet exercice est déjà clôturé');
        }

        $this->set('closed', 1);
    }

    public function delete(): bool
    {
        $db = DB::getInstance();

        // Ne pas supprimer un compte qui est utilisé !
        if ($db->test(Transaction::TABLE, $db->where('id_year', $this->id())))
        {
            throw new UserException('Cet exercice ne peut être supprimé car des mouvements y sont liés.');
        }

        return parent::delete();
    }
}

Added src/include/lib/Garradin/Entity.php version [c7993d892d].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin;

use KD2\Form;
use KD2\DB\AbstractEntity;

class Entity extends AbstractEntity
{
	/**
	 * Valider les champs avant enregistrement
	 * @throws ValidationException Si une erreur de validation survient
	 */
	public function selfValidate()
	{
		$errors = [];

		if (!Form::validate($this->_fields, $errors, $this->toArray()))
		{
			$messages = [];

			foreach ($errors as $error)
			{
				$messages[] = $this->getValidationMessage($error);
			}

			throw new ValidationException(implode("\n", $messages));
		}
	}
}

Modified src/include/lib/Garradin/Fichiers.php from [2575ef0c54] to [10416ad902].

290
291
292
293
294
295
296
297
298
299
300
301
302





303
304
305
306
307
308
309
...
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
...
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
...
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
		return $this->_serve($this->getFilePathFromCache(), $this->type, ($this->image ? false : $this->nom), $this->taille);
	}

	/**
	 * Envoie une miniature à la taille indiquée au client HTTP
	 * @return void
	 */
	public function serveThumbnail($width = self::TAILLE_MINIATURE)
	{
		if (!$this->image)
		{
			throw new \LogicException('Il n\'est pas possible de fournir une miniature pour un fichier qui n\'est pas une image.');
		}






		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;
................................................................................
		}

		if (!is_uploaded_file($file['tmp_name']))
		{
			throw new \RuntimeException('Le fichier n\'a pas été envoyé de manière conventionnelle.');
		}

		$max_blob_size = self::getMaxBlobSize();

		// Vérifier que le fichier peut rentrer en base de données (dans PHP < 7.2 on n'utilise pas openBlob)
		if (null !== $max_blob_size && $file['size'] > $max_blob_size) {
			unlink($file['tmp_name']);
			throw new UserException('Taille du fichier supérieure au maximum autorisé en base de données');
		}

		$name = preg_replace('/\s+/', '_', $file['name']);
		$name = preg_replace('/[^\d\w._-]/ui', '', $name);

		return self::storeFile($name, $file['tmp_name']);
	}

    /**
     * Returns the maximum value size that can be handled by a bindValue
     * @return null|integer
     */
	static public function getMaxBlobSize()
	{
        $memory_limit = Utils::return_bytes(ini_get('memory_limit'));

        if (!$memory_limit) {
            return null;
        }

        return round(($memory_limit - memory_get_usage()) * 0.9);
	}

	/**
	 * Upload de fichier à partir d'une chaîne en base64
	 * @param  string $name
	 * @param  string $content
	 * @return Fichiers
	 */
	static public function storeFromBase64($name, $content)
................................................................................
		$is_image = preg_match('/^image\/(?:png|jpe?g|gif)$/', $type);

		$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->insert('fichiers_contenu', [
				'hash'		=>	$hash,
				'taille'	=>	(int)$size,







				'contenu'	=>	[\SQLITE3_BLOB, $content ?: file_get_contents($path)],
			]);

			// FIXME: utiliser Sqlite3::openBlob pour écrire quand dispo dans PHP
			// cf. https://github.com/php/php-src/pull/2528

			$id_contenu = $db->lastInsertRowID();

		}

		$db->insert('fichiers', [
			'id_contenu'	=>	(int)$id_contenu,
			'nom'			=>	$name,
			'type'			=>	$type,
			'image'			=>	(int)$is_image,
................................................................................
	}

	/**
	 * 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 $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 = false)
	{
		$check = [self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA];

		if (!in_array($type, $check))
		{
			throw new \LogicException('Type de lien de fichier inconnu.');
		}







|





>
>
>
>
>







 







<
<
<
<
<
<
<
<






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
>
>
>
|
<
<
<
>
>
>
>
>
>
>
|
<
|
<
<

<
>







 







|



|







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
...
462
463
464
465
466
467
468








469
470
471
472
473
474















475
476
477
478
479
480
481
...
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
...
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
		return $this->_serve($this->getFilePathFromCache(), $this->type, ($this->image ? false : $this->nom), $this->taille);
	}

	/**
	 * Envoie une miniature à la taille indiquée au client HTTP
	 * @return void
	 */
	public function serveThumbnail($width = null)
	{
		if (!$this->image)
		{
			throw new \LogicException('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;
................................................................................
		}

		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)
................................................................................
		$is_image = preg_match('/^image\/(?:png|jpe?g|gif)$/', $type);

		$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,
................................................................................
	}

	/**
	 * 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.');
		}

Modified src/include/lib/Garradin/Membres/Categories.php from [cfad189ba8] to [2ef27a72a7].

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
        'connexion' =>  Membres::DROIT_ACCES,
        'membres'   =>  Membres::DROIT_AUCUN,
        'compta'    =>  Membres::DROIT_AUCUN,
        'wiki'      =>  Membres::DROIT_ACCES,
        'config'    =>  Membres::DROIT_AUCUN,
    ];

    static public function getDroitsDefaut()
    {
        return $this->droits;
    }

    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.');
        }

        if (!empty($data['id_cotisation_obligatoire']) 
            && !$db->test('cotisations', 'id = ?', (int)$data['id_cotisation_obligatoire']))
        {
            throw new UserException('Numéro de cotisation inconnu.');
        }

        if (isset($data['id_cotisation_obligatoire']) && empty($data['id_cotisation_obligatoire']))
        {
            $data['id_cotisation_obligatoire'] = null;
        }
    }

    public function add($data)
    {
        $this->_checkData($data);

        foreach ($this->droits as $key=>$value)







<
<
<
<
<








<
<
<
<
<
<
<
<
<
<
<







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)

Modified src/include/lib/Garradin/Membres/Cotisations.php from [0eef95049b] to [0f169947fd].

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
	}

	/**
	 * Liste des membres qui sont inscrits à une cotisation
	 * @param  integer $id Numéro de la cotisation
	 * @return array     Liste des membres
	 */
	public function listMembersForCotisation($id, $include_category, $page = 1, $order = null, $desc = true)
	{
		$begin = ($page - 1) * self::ITEMS_PER_PAGE;

		$db = DB::getInstance();
		$champ_id = Config::getInstance()->get('champ_identite');

		if (empty($order))







|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
	}

	/**
	 * Liste des membres qui sont inscrits à une cotisation
	 * @param  integer $id Numéro de la cotisation
	 * @return array     Liste des membres
	 */
	public function listMembersForCotisation($id, $page = 1, $order = null, $desc = true)
	{
		$begin = ($page - 1) * self::ITEMS_PER_PAGE;

		$db = DB::getInstance();
		$champ_id = Config::getInstance()->get('champ_identite');

		if (empty($order))

Modified src/include/lib/Garradin/Plugin.php from [de7f4cd5b0] to [267ceae2a7].

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
...
545
546
547
548
549
550
551





552
553
554
555
556
557
558
...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
	/**
	 * 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))
		{
................................................................................
					'disable_compression'	=>	true,
				]
			];

			$context = stream_context_create($context_options);

			try {
				$result = file_get_contents(PLUGINS_URL, NULL, $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);
................................................................................
		{
			$result = Static_Cache::get('plugins_list');
		}

		$list = json_decode($result, true);
		return $list;
	}






	/**
	 * 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)
................................................................................
		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))
		{







|







 







|







 







>
>
>
>
>







 







|

|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
	/**
	 * 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))
		{
................................................................................
					'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);
................................................................................
		{
			$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)
................................................................................
		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))
		{

Modified src/include/lib/Garradin/Sauvegarde.php from [adf221aa11] to [1afcef389e].

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
...
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
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
314
315
316
317
318
319
320










321
322
323
324
325
326
327
...
370
371
372
373
374
375
376




377
378
379
380
381
382
383
	}

	/**
	 * Restaure une sauvegarde locale
	 * @param  string $file Le nom de fichier à utiliser comme point de restauration
	 * @return boolean true si la restauration a fonctionné, false sinon
	 */
	public function restoreFromLocal($file)
	{
		if (preg_match('!\.\.+!', $file) || !preg_match('!^[\w\d._ -]+$!iu', $file))
		{
			throw new UserException('Nom de fichier non valide.');
		}

		if (!file_exists(DATA_ROOT . '/' . $file))
		{
			throw new UserException('Le fichier fourni n\'existe pas.');
		}

		return $this->restoreDB(DATA_ROOT . '/' . $file);
	}

	/**
	 * Restaure une copie distante (fichier envoyé)
	 * @param  array   $file    Tableau provenant de $_FILES
	 * @param  integer $user_id ID du membre actuellement connecté, utilisé pour 
	 * vérifier qu'il est toujours administrateur dans la sauvegarde
................................................................................
			}
			elseif ($integrity === false)
			{
				throw new UserException('Le fichier fourni a été modifié par un programme externe.', self::INTEGRITY_FAIL);
			}
		}

		$r = $this->restoreDB($file['tmp_name'], $user_id);

		if ($r)
		{
			Utils::safe_unlink($file['tmp_name']);
		}

		return $r;
	}

	/**
	 * Vérifie l'intégrité d'une sauvegarde Garradin
	 * @param  string $file Chemin absolu vers la base de donnée
	 * @return boolean
	 */
	protected function checkIntegrity($file_path, $remove_hash = true)
	{
		$size = filesize($file_path);
		$fp = fopen($file_path, 'r+');

		$header = fread($fp, 16);
................................................................................

	/**
	 * Restauration de base de données, la fonction qui le fait vraiment
	 * @param  string $file Chemin absolu vers la base de données à utiliser
	 * @return mixed 		true si rien ne va plus, ou self::NEED_UPGRADE si la version de la DB
	 * ne correspond pas à la version de Garradin (mise à jour nécessaire).
	 */
	protected function restoreDB($file, $user_id = false)
	{
		$return = 1;

		// Essayons déjà d'ouvrir la base de données à restaurer en lecture
		try {
			$db = new \SQLite3($file, SQLITE3_OPEN_READONLY);
		}
		catch (\Exception $e)
		{
			throw new UserException('Le fichier fourni n\'est pas une base de données valide. ' .
				'Message d\'erreur de SQLite : ' . $e->getMessage(), self::NOT_A_DB);
		}

................................................................................
				'Message d\'erreur de SQLite : ' . $e->getMessage(), self::NOT_A_DB);
		}

		if (strtolower(trim($check)) != 'ok')
		{
			throw new UserException('Le fichier fourni est corrompu. SQLite a trouvé ' . $check . ' erreurs.');
		}











		// On ne peut pas faire de vérifications très poussées sur la structure de la base de données,
		// celle-ci pouvant changer d'une version à l'autre et on peut vouloir importer une base
		// un peu vieille, mais on vérifie quand même que ça ressemble un minimum à une base garradin
		$table = $db->querySingle('SELECT 1 FROM sqlite_master WHERE type=\'table\' AND tbl_name=\'config\';');

		if (!$table)
................................................................................
		}

		if (!copy($file, DB_FILE))
		{
			rename($backup, DB_FILE);
			throw new \RuntimeException('Unable to copy backup DB to main location.');
		}





		if ($return & self::NOT_AN_ADMIN)
		{
			// Forcer toutes les catégories à pouvoir gérer les droits
			$db = DB::getInstance();
			$db->update('membres_categories', [
				'droit_membres' => Membres::DROIT_ADMIN,







|











|







 







|











|
|







 







|





|







 







>
>
>
>
>
>
>
>
>
>







 







>
>
>
>







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
...
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
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
	}

	/**
	 * Restaure une sauvegarde locale
	 * @param  string $file Le nom de fichier à utiliser comme point de restauration
	 * @return boolean true si la restauration a fonctionné, false sinon
	 */
	public function restoreFromLocal($file, bool $do_backup = true)
	{
		if (preg_match('!\.\.+!', $file) || !preg_match('!^[\w\d._ -]+$!iu', $file))
		{
			throw new UserException('Nom de fichier non valide.');
		}

		if (!file_exists(DATA_ROOT . '/' . $file))
		{
			throw new UserException('Le fichier fourni n\'existe pas.');
		}

		return $this->restoreDB(DATA_ROOT . '/' . $file, false, false, false);
	}

	/**
	 * Restaure une copie distante (fichier envoyé)
	 * @param  array   $file    Tableau provenant de $_FILES
	 * @param  integer $user_id ID du membre actuellement connecté, utilisé pour 
	 * vérifier qu'il est toujours administrateur dans la sauvegarde
................................................................................
			}
			elseif ($integrity === false)
			{
				throw new UserException('Le fichier fourni a été modifié par un programme externe.', self::INTEGRITY_FAIL);
			}
		}

		$r = $this->restoreDB($file['tmp_name'], $user_id, true);

		if ($r)
		{
			Utils::safe_unlink($file['tmp_name']);
		}

		return $r;
	}

	/**
	 * Vérifie l'intégrité d'une sauvegarde Garradin
	 * @param  string $file_path Chemin absolu vers la base de donnée
	 * @return boolean|null
	 */
	protected function checkIntegrity($file_path, $remove_hash = true)
	{
		$size = filesize($file_path);
		$fp = fopen($file_path, 'r+');

		$header = fread($fp, 16);
................................................................................

	/**
	 * Restauration de base de données, la fonction qui le fait vraiment
	 * @param  string $file Chemin absolu vers la base de données à utiliser
	 * @return mixed 		true si rien ne va plus, ou self::NEED_UPGRADE si la version de la DB
	 * ne correspond pas à la version de Garradin (mise à jour nécessaire).
	 */
	protected function restoreDB($file, $user_id = false, $check_foreign_keys = false, $do_backup = true)
	{
		$return = 1;

		// Essayons déjà d'ouvrir la base de données à restaurer en lecture
		try {
			$db = new \SQLite3($file, \SQLITE3_OPEN_READONLY);
		}
		catch (\Exception $e)
		{
			throw new UserException('Le fichier fourni n\'est pas une base de données valide. ' .
				'Message d\'erreur de SQLite : ' . $e->getMessage(), self::NOT_A_DB);
		}

................................................................................
				'Message d\'erreur de SQLite : ' . $e->getMessage(), self::NOT_A_DB);
		}

		if (strtolower(trim($check)) != 'ok')
		{
			throw new UserException('Le fichier fourni est corrompu. SQLite a trouvé ' . $check . ' erreurs.');
		}

		if ($check_foreign_keys)
		{
			$check = $db->querySingle('PRAGMA foreign_key_check;');

			if ($check)
			{
				throw new UserException('Le fichier fourni est corrompu. Certaines clés étrangères référencent des lignes qui n\'existent pas.');
			}
		}

		// On ne peut pas faire de vérifications très poussées sur la structure de la base de données,
		// celle-ci pouvant changer d'une version à l'autre et on peut vouloir importer une base
		// un peu vieille, mais on vérifie quand même que ça ressemble un minimum à une base garradin
		$table = $db->querySingle('SELECT 1 FROM sqlite_master WHERE type=\'table\' AND tbl_name=\'config\';');

		if (!$table)
................................................................................
		}

		if (!copy($file, DB_FILE))
		{
			rename($backup, DB_FILE);
			throw new \RuntimeException('Unable to copy backup DB to main location.');
		}

		if (!$do_backup) {
			unlink($backup);
		}

		if ($return & self::NOT_AN_ADMIN)
		{
			// Forcer toutes les catégories à pouvoir gérer les droits
			$db = DB::getInstance();
			$db->update('membres_categories', [
				'droit_membres' => Membres::DROIT_ADMIN,

Modified src/include/lib/Garradin/Template.php from [f7f37fea68] to [e69b34a2ee].

1
2
3
4
5
6

7
8
9
10
11
12
13
..
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
...
146
147
148
149
150
151
152























































































153
154
155
156
157
158
159
<?php

namespace Garradin;

use KD2\Form;
use Garradin\Membres\Session;


class Template extends \KD2\Smartyer
{
	static protected $_instance = null;

	static public function getInstance()
	{
................................................................................
		});

		$this->register_function('form_errors', [$this, 'formErrors']);
		$this->register_function('show_error', [$this, 'showError']);
		$this->register_function('form_field', [$this, 'formField']);
		$this->register_function('select_compte', [$this, 'formSelectCompte']);
		$this->register_function('html_champ_membre', [$this, 'formChampMembre']);


		$this->register_function('custom_colors', [$this, 'customColors']);
		$this->register_function('plugin_url', ['Garradin\Utils', 'plugin_url']);
		$this->register_function('diff', [$this, 'diff']);
		$this->register_function('pagination', [$this, 'pagination']);
		$this->register_function('format_droits', [$this, 'formatDroits']);

		$this->register_function('csrf_field', function ($params) {
			return Form::tokenHTML($params['key']);
		});



		$this->register_modifier('strlen', 'strlen');
		$this->register_modifier('dump', ['KD2\ErrorManager', 'dump']);
		$this->register_modifier('get_country_name', ['Garradin\Utils', 'getCountryName']);
		$this->register_modifier('format_sqlite_date_to_french', ['Garradin\Utils', 'sqliteDateToFrench']);
		$this->register_modifier('format_bytes', ['Garradin\Utils', 'format_bytes']);
		$this->register_modifier('format_tel', [$this, 'formatPhoneNumber']);
		$this->register_modifier('abs', 'abs');
		$this->register_modifier('display_champ_membre', [$this, 'displayChampMembre']);









		$this->register_modifier('get_nom_compte', function ($compte) {
			if (is_null($compte))
			{
				return '';
			}

................................................................................
		if (!$params['if'])
		{
			return '';
		}

		return '<p class="error">' . $this->escape($params['message']) . '</p>';
	}
























































































	protected function formField(array $params, $escape = true)
	{
		if (!isset($params['name']))
		{
			throw new \BadFunctionCallException('name argument is mandatory');
		}






>







 







>











>
>








>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
..
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
...
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
<?php

namespace Garradin;

use KD2\Form;
use Garradin\Membres\Session;
use Garradin\Entities\Accounting\Account;

class Template extends \KD2\Smartyer
{
	static protected $_instance = null;

	static public function getInstance()
	{
................................................................................
		});

		$this->register_function('form_errors', [$this, 'formErrors']);
		$this->register_function('show_error', [$this, 'showError']);
		$this->register_function('form_field', [$this, 'formField']);
		$this->register_function('select_compte', [$this, 'formSelectCompte']);
		$this->register_function('html_champ_membre', [$this, 'formChampMembre']);
		$this->register_function('input', [$this, 'formInput']);

		$this->register_function('custom_colors', [$this, 'customColors']);
		$this->register_function('plugin_url', ['Garradin\Utils', 'plugin_url']);
		$this->register_function('diff', [$this, 'diff']);
		$this->register_function('pagination', [$this, 'pagination']);
		$this->register_function('format_droits', [$this, 'formatDroits']);

		$this->register_function('csrf_field', function ($params) {
			return Form::tokenHTML($params['key']);
		});

		$this->register_function('icon', [$this, 'widgetIcon']);

		$this->register_modifier('strlen', 'strlen');
		$this->register_modifier('dump', ['KD2\ErrorManager', 'dump']);
		$this->register_modifier('get_country_name', ['Garradin\Utils', 'getCountryName']);
		$this->register_modifier('format_sqlite_date_to_french', ['Garradin\Utils', 'sqliteDateToFrench']);
		$this->register_modifier('format_bytes', ['Garradin\Utils', 'format_bytes']);
		$this->register_modifier('format_tel', [$this, 'formatPhoneNumber']);
		$this->register_modifier('abs', 'abs');
		$this->register_modifier('display_champ_membre', [$this, 'displayChampMembre']);

		$this->register_modifier('account_type', function ($value) {
			return Account::TYPES_NAMES[$value];
		});

		$this->register_modifier('account_position', function ($value) {
			return Account::POSITIONS_NAMES[$value];
		});

		$this->register_modifier('get_nom_compte', function ($compte) {
			if (is_null($compte))
			{
				return '';
			}

................................................................................
		if (!$params['if'])
		{
			return '';
		}

		return '<p class="error">' . $this->escape($params['message']) . '</p>';
	}

	protected function widgetIcon(array $params): string
	{
		if (empty($params['href'])) {
			return sprintf('<b class="icn">%s</b>', Utils::iconUnicode($params['shape']));
		}

		return sprintf('<a href="%s" class="icn" title="%s">%s</a>', $this->escape(ADMIN_URL . $params['href']), $this->escape($params['label']), Utils::iconUnicode($params['shape']));
	}

	protected function formInput(array $params)
	{
		static $keep_attributes = ['pattern', 'max', 'min', 'step', 'title', 'name', 'cols', 'rows', 'maxlength'];
		extract($params, \EXTR_SKIP);

		if (!isset($name, $type)) {
			throw new \InvalidArgumentException('Missing name or type');
		}

		$current_value = null;

		if (isset($_POST[$name])) {
			$current_value = $_POST[$name];
		}
		elseif (isset($default)) {
			$current_value = $default;
		}

		$required_label = array_key_exists('required', $params) ? ' <b title="Champ obligatoire">(obligatoire)</b>' : '';

		$out = sprintf('<dt><label for="f_%s">%s</label>%s</dt>', $name, $this->escape($label), $required_label);

		if (isset($help)) {
			$out .= sprintf('<dd class="help">%s</dd>', $this->escape($help));
		}

		$attributes = array_intersect_key($params, array_flip($keep_attributes));
		$attributes['id'] = 'f_' . $name;

		// Create attributes string
		if (array_key_exists('required', $params)) {
			$attributes['required'] = 'required';
		}

		array_walk($attributes, function (&$v, $k) {
			$v = sprintf('%s="%s"', $k, $v);
		});

		$attributes = implode(' ', $attributes);

		$out .= '<dd>';

		if ($type == 'select') {
			$out .= sprintf('<select %s>', $attributes);

			foreach ($options as $_key => $_value) {
				$out .= sprintf('<option value="%s"%s>%s</option>', $_key, $current_value == $_key ? ' selected="selected"' : '', $this->escape($_value));
			}

			$out .= '</select>';
		}
		elseif ($type == 'select_groups') {
			$out .= sprintf('<select %s>', $attributes);

			foreach ($options as $optgroup => $suboptions) {
				$out .= sprintf('<optgroup label="%s">', $this->escape($optgroup));

				foreach ($suboptions as $_key => $_value) {
					$out .= sprintf('<option value="%s"%s>%s</option>', $_key, $current_value == $_key ? ' selected="selected"' : '', $this->escape($_value));
				}

				$out .= '</optgroup>';
			}

			$out .= '</select>';
		}
		elseif ($type == 'textarea') {
			$out .= sprintf('<textarea %s>%s</textarea>', $attributes, $this->escape($current_value));
		}
		else {
			$out .= sprintf('<input type="%s" %s value="%s" />', $type, $attributes, $this->escape($current_value));
		}

		$out .= '</dd>';

		return $out;
	}

	protected function formField(array $params, $escape = true)
	{
		if (!isset($params['name']))
		{
			throw new \BadFunctionCallException('name argument is mandatory');
		}

Modified src/include/lib/Garradin/Utils.php from [eeb7ab32e4] to [6ab057f79b].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
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
...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
...
552
553
554
555
556
557
558
559

560
561

562
563
564
565
566
567
568
569
570
...
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
...
823
824
825
826
827
828
829
830






































    static protected $skriv = null;

    static private $french_date_names = [
        'January'=>'Janvier', 'February'=>'Février', 'March'=>'Mars', 'April'=>'Avril', 'May'=>'Mai',
        'June'=>'Juin', 'July'=>'Juillet', 'August'=>'Août', 'September'=>'Septembre', 'October'=>'Octobre',
        'November'=>'Novembre', 'December'=>'Décembre', 'Monday'=>'Lundi', 'Tuesday'=>'Mardi', 'Wednesday'=>'Mercredi',
        'Thursday'=>'Jeudi','Friday'=>'Vendredi','Saturday'=>'Samedi','Sunday'=>'Dimanche',
        'Feb'=>'Fév','Apr'=>'Avr','May'=>'Mai','Jun'=>'Juin', 'Jul'=>'Juil','Aug'=>'Aout','Dec'=>'Déc',
        'Mon'=>'Lun','Tue'=>'Mar','Wed'=>'Mer','Thu'=>'Jeu','Fri'=>'Ven','Sat'=>'Sam','Sun'=>'Dim'];

    static public function strftime_fr($format=null, $ts=null)
    {
        if (is_null($format))
        {
            $format = '%d/%m/%Y à %H:%M';
................................................................................
     * $listLength représente la longueur d'items de la pagination à génerer
     *
     * @param int $current
     * @param int $total
     * @param int $bypage
     * @param int $listLength
     * @param bool $showLast Toggle l'affichage du dernier élément de la pagination
     * @return array
     */
    public static function getGenericPagination($current, $total, $bypage, $listLength=11, $showLast = true)
    {
        if ($total <= $bypage)
            return false;

        $total = ceil($total / $bypage);

        if ($total < $current)
            return false;

        $length = ($listLength / 2);

        $begin = $current - ceil($length);
        if ($begin < 1)
        {
            $begin = 1;
................................................................................

    static public function safe_unlink($path)
    {
        if (!@unlink($path))
        {
            return true;
        }
        
        if (!file_exists($path))
        {
            return true;
        }

        throw new \RuntimeException(sprintf('Impossible de supprimer le fichier %s: %s', $path, error_get_last()));

................................................................................
        return Security::getRandomPassphrase(ROOT . '/include/data/dictionary.fr');
    }

    static public function checkIBAN($value)
    {
        // Enlever les caractères indésirables (espaces, tirets),
        $value = preg_replace('/[^A-Z0-9]/', '', strtoupper($value));
        
        // Supprimer les 4 premiers caractères et les replacer à la fin du compte
        $value = substr($value, 4) . substr($value, 0, 4);

        // Remplacer les lettres par des chiffres au moyen d'une table de conversion (A=10, B=11, C=12 etc.)
        $value = str_replace(range('A', 'Z'), range(10, 35), $value);

        // Diviser le nombre ainsi obtenu par 97
................................................................................
            case 'G': case 'g': return (int)$size_str * pow(1024, 3);
            case 'M': case 'm': return (int)$size_str * pow(1024, 2);
            case 'K': case 'k': return (int)$size_str * 1024;
            default: return $size_str;
        }
    }

    static public function format_bytes($size) {

        if ($size > (1024 * 1024))
            return str_replace('.', ',', round($size / 1024 / 1024, 2)) . ' Mo';

        elseif ($size > 1024)
            return str_replace('.', ',', round($size / 1024, 2)) . ' Ko';
        else
            return $size . ' o';
    }

    static public function deleteRecursive($path)
    {
        if (!file_exists($path))
................................................................................
            if (is_dir($path . '/' . $file))
            {
                if (!self::deleteRecursive($path . '/' . $file))
                    return false;
            }
            else
            {
                utils::safe_unlink($path . '/' . $file);
            }
        }

        $dir->close();
        rmdir($path);

        return true;
................................................................................
            {
                $raw_headers .= sprintf("%s: %s\r\n", $name, $value);
            }

            return \mail($to, $subject, $content, $raw_headers);
        }
    }
}













































|







 







|




|




|







 







|







 







|







 







|
>

<
>

|







 







|







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
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
...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
...
552
553
554
555
556
557
558
559
560
561

562
563
564
565
566
567
568
569
570
571
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
    static protected $skriv = null;

    static private $french_date_names = [
        'January'=>'Janvier', 'February'=>'Février', 'March'=>'Mars', 'April'=>'Avril', 'May'=>'Mai',
        'June'=>'Juin', 'July'=>'Juillet', 'August'=>'Août', 'September'=>'Septembre', 'October'=>'Octobre',
        'November'=>'Novembre', 'December'=>'Décembre', 'Monday'=>'Lundi', 'Tuesday'=>'Mardi', 'Wednesday'=>'Mercredi',
        'Thursday'=>'Jeudi','Friday'=>'Vendredi','Saturday'=>'Samedi','Sunday'=>'Dimanche',
        'Feb'=>'Fév','Apr'=>'Avr','Jun'=>'Juin', 'Jul'=>'Juil','Aug'=>'Aout','Dec'=>'Déc',
        'Mon'=>'Lun','Tue'=>'Mar','Wed'=>'Mer','Thu'=>'Jeu','Fri'=>'Ven','Sat'=>'Sam','Sun'=>'Dim'];

    static public function strftime_fr($format=null, $ts=null)
    {
        if (is_null($format))
        {
            $format = '%d/%m/%Y à %H:%M';
................................................................................
     * $listLength représente la longueur d'items de la pagination à génerer
     *
     * @param int $current
     * @param int $total
     * @param int $bypage
     * @param int $listLength
     * @param bool $showLast Toggle l'affichage du dernier élément de la pagination
     * @return array|null
     */
    public static function getGenericPagination($current, $total, $bypage, $listLength=11, $showLast = true)
    {
        if ($total <= $bypage)
            return null;

        $total = ceil($total / $bypage);

        if ($total < $current)
            return null;

        $length = ($listLength / 2);

        $begin = $current - ceil($length);
        if ($begin < 1)
        {
            $begin = 1;
................................................................................

    static public function safe_unlink($path)
    {
        if (!@unlink($path))
        {
            return true;
        }

        if (!file_exists($path))
        {
            return true;
        }

        throw new \RuntimeException(sprintf('Impossible de supprimer le fichier %s: %s', $path, error_get_last()));

................................................................................
        return Security::getRandomPassphrase(ROOT . '/include/data/dictionary.fr');
    }

    static public function checkIBAN($value)
    {
        // Enlever les caractères indésirables (espaces, tirets),
        $value = preg_replace('/[^A-Z0-9]/', '', strtoupper($value));

        // Supprimer les 4 premiers caractères et les replacer à la fin du compte
        $value = substr($value, 4) . substr($value, 0, 4);

        // Remplacer les lettres par des chiffres au moyen d'une table de conversion (A=10, B=11, C=12 etc.)
        $value = str_replace(range('A', 'Z'), range(10, 35), $value);

        // Diviser le nombre ainsi obtenu par 97
................................................................................
            case 'G': case 'g': return (int)$size_str * pow(1024, 3);
            case 'M': case 'm': return (int)$size_str * pow(1024, 2);
            case 'K': case 'k': return (int)$size_str * 1024;
            default: return $size_str;
        }
    }

    static public function format_bytes($size)
    {
        if ($size > (1024 * 1024))

            return number_format(round($size / 1024 / 1024, 2), 2, ',', '') . ' Mo';
        elseif ($size > 1024)
            return round($size / 1024) . ' Ko';
        else
            return $size . ' o';
    }

    static public function deleteRecursive($path)
    {
        if (!file_exists($path))
................................................................................
            if (is_dir($path . '/' . $file))
            {
                if (!self::deleteRecursive($path . '/' . $file))
                    return false;
            }
            else
            {
                self::safe_unlink($path . '/' . $file);
            }
        }

        $dir->close();
        rmdir($path);

        return true;
................................................................................
            {
                $raw_headers .= sprintf("%s: %s\r\n", $name, $value);
            }

            return \mail($to, $subject, $content, $raw_headers);
        }
    }

    static public function iconUnicode(string $shape): string
    {
        switch ($shape) {
            case 'up': return '↑';
            case 'down': return '↓';
            case 'export': return '↷';
            case 'reset': return '↺';
            case 'upload': return '⇑';
            case 'download': return '⇓';
            case 'home': return '⌂';
            case 'print': return '⎙';
            case 'star': return '★';
            case 'check': return '☑';
            case 'settings': return '☸';
            case 'alert': return '⚠';
            case 'mail': return '✉';
            case 'edit': return '✎';
            case 'delete': return '✘';
            case 'help': return '❓';
            case 'plus': return '➕';
            case 'minus': return '➖';
            case 'logout': return '⤝';
            case 'eye-off': return '⤫';
            case 'menu': return '𝍢';
            case 'eye': return '👁';
            case 'user': return '👤';
            case 'users': return '👪';
            case 'attach': return '📎';
            case 'search': return '🔍';
            case 'lock': return '🔒';
            case 'unlock': return '🔓';
            case 'folder': return '🗀';
            case 'document': return '🗅';
            default:
                throw new \InvalidArgumentException('Unknown icon shape: ' . $shape);
        }
    }
}

Modified src/include/lib/Garradin/Wiki.php from [a63e6d83d2] to [f692dbeb62].

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
                'id'        =>  $id,
                'titre'     =>  $res->titre,
                'uri'       =>  $res->uri,
            ];

            if ($id == $res->parent)
            {
                throw new Exception('Parent! ' . $id . '/' . $res->parent);
            }

            $id = (int)$res->parent;
        }

        return array_reverse($flat);
    }







|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
                'id'        =>  $id,
                'titre'     =>  $res->titre,
                'uri'       =>  $res->uri,
            ];

            if ($id == $res->parent)
            {
                throw new \Exception('Parent! ' . $id . '/' . $res->parent);
            }

            $id = (int)$res->parent;
        }

        return array_reverse($flat);
    }

Modified src/include/lib/dependencies.list from [7b518732e5] to [b0f8f3486c].

1
2
3


4
5
6
7
8
9
10
KD2/data/
KD2/DB.php
KD2/DB_SQLite3.php


KD2/ErrorManager.php
KD2/FileInfo.php
KD2/Form.php
KD2/Helpers.php
KD2/Image.php
KD2/MiniSkel.php
KD2/QRCode.php

|
|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
KD2/data/
KD2/DB/DB.php
KD2/DB/SQLite3.php
KD2/DB/Entity.php
KD2/DB/Entity_Manager.php
KD2/ErrorManager.php
KD2/FileInfo.php
KD2/Form.php
KD2/Helpers.php
KD2/Image.php
KD2/MiniSkel.php
KD2/QRCode.php

Modified src/include/test_required.php from [69fc54870f] to [a96dd46521].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
        echo "Pour plus d'informations consulter http://dev.kd2.org/garradin/Probl%C3%A8mes%20fr%C3%A9quents\n";
    }

    exit;
}

test_requis(
    version_compare(phpversion(), '5.6', '>='),
    'PHP 5.6 ou supérieur requis. PHP version ' . phpversion() . ' installée.'
);

test_requis(
    defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH,
    'L\'algorithme de hashage de mot de passe Blowfish n\'est pas présent (pas installé ou pas compilé).'
);

................................................................................
    class_exists('SQLite3'),
    'Le module de base de données SQLite3 n\'est pas disponible.'
);

$v = \SQLite3::version();

test_requis(
    version_compare($v['versionString'], '3.7.4', '>='),
    'SQLite3 version 3.7.4 ou supérieur requise. Version installée : ' . $v['versionString']
);

test_requis(
    file_exists(__DIR__ . '/lib/KD2'),
    'Librairie KD2 non disponible.'
);







|
|







 







|
|






30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
        echo "Pour plus d'informations consulter http://dev.kd2.org/garradin/Probl%C3%A8mes%20fr%C3%A9quents\n";
    }

    exit;
}

test_requis(
    version_compare(phpversion(), '7.2', '>='),
    'PHP 7.2 ou supérieur requis. PHP version ' . phpversion() . ' installée.'
);

test_requis(
    defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH,
    'L\'algorithme de hashage de mot de passe Blowfish n\'est pas présent (pas installé ou pas compilé).'
);

................................................................................
    class_exists('SQLite3'),
    'Le module de base de données SQLite3 n\'est pas disponible.'
);

$v = \SQLite3::version();

test_requis(
    version_compare($v['versionString'], '3.16', '>='),
    'SQLite3 version 3.16 ou supérieur requise. Version installée : ' . $v['versionString']
);

test_requis(
    file_exists(__DIR__ . '/lib/KD2'),
    'Librairie KD2 non disponible.'
);

Modified src/templates/admin/_head.tpl from [ab1e909a41] to [eaf03f63a4].

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
                <li class="member cotisations{if $current == 'membres/cotisations'} current{/if}"><a href="{$admin_url}membres/cotisations/">Cotisations</a></li>
                <li class="member message{if $current == 'membres/message'} current{/if}"><a href="{$admin_url}membres/message_collectif.php">Message collectif</a></li>
            </ul>
            {/if}
            </li>
        {/if}
        {if $session->canAccess('compta', Membres::DROIT_ACCES)}
            <li class="compta{if $current == 'compta'} current{elseif $current_parent == 'compta'} current_parent{/if}"><a href="{$admin_url}compta/"><b>€</b><i> Comptabilité</i></a>
            <ul>
            {if $session->canAccess('compta', Membres::DROIT_ECRITURE)}
                <li class="compta new{if $current == 'compta/saisie'} current{/if}"><a href="{$admin_url}compta/operations/saisir.php">Saisie</a></li>
            {/if}
                <li class="compta list{if $current == 'compta/gestion'} current{/if}"><a href="{$admin_url}compta/operations/">Suivi des opérations</a></li>
                <li class="compta banks{if $current == 'compta/banques'} current{/if}"><a href="{$admin_url}compta/banques/">Banques &amp; caisse</a></li>
            {if $session->canAccess('compta', Membres::DROIT_ADMIN)}
                <li class="compta admin config{if $current == 'compta/categories'} current{/if}"><a href="{$admin_url}compta/categories/">Catégories &amp; comptes</a></li>
            {/if}
                <li class="compta admin reports{if $current == 'compta/exercices'} current{/if}"><a href="{$admin_url}compta/exercices/">Exercices &amp; projets</a></li>
            </ul>
            </li>
        {/if}
        {if $session->canAccess('wiki', Membres::DROIT_ACCES)}
            <li class="wiki{if $current == 'wiki'} current{elseif $current_parent == 'wiki'} current_parent{/if}"><a href="{$admin_url}wiki/"><b class="icn">✎</b><i> Wiki</i></a>
            <ul>
                <li class="wiki list{if $current == 'wiki/recent'} current{/if}"><a href="{$admin_url}wiki/recent.php">Dernières modifications</a>







|


|

|
|

|

<







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
                <li class="member cotisations{if $current == 'membres/cotisations'} current{/if}"><a href="{$admin_url}membres/cotisations/">Cotisations</a></li>
                <li class="member message{if $current == 'membres/message'} current{/if}"><a href="{$admin_url}membres/message_collectif.php">Message collectif</a></li>
            </ul>
            {/if}
            </li>
        {/if}
        {if $session->canAccess('compta', Membres::DROIT_ACCES)}
            <li class="compta{if $current == 'acc'} current{elseif $current_parent == 'acc'} current_parent{/if}"><a href="{$admin_url}acc/"><b>€</b><i> Comptabilité</i></a>
            <ul>
            {if $session->canAccess('compta', Membres::DROIT_ECRITURE)}
                <li class="compta new{if $current == 'acc/new'} current{/if}"><a href="{$admin_url}acc/transactions/new.php">Saisie</a></li>
            {/if}
                <li class="compta journals{if $current == 'acc/journals'} current{/if}"><a href="{$admin_url}acc/transactions/">Journaux</a></li>
                <li class="compta admin reports{if $current == 'acc/years'} current{/if}"><a href="{$admin_url}acc/years/">Exercices &amp; rapports</a></li>
            {if $session->canAccess('compta', Membres::DROIT_ADMIN)}
                <li class="compta admin config{if $current == 'acc/charts'} current{/if}"><a href="{$admin_url}acc/charts/">Plans comptables</a></li>
            {/if}

            </ul>
            </li>
        {/if}
        {if $session->canAccess('wiki', Membres::DROIT_ACCES)}
            <li class="wiki{if $current == 'wiki'} current{elseif $current_parent == 'wiki'} current_parent{/if}"><a href="{$admin_url}wiki/"><b class="icn">✎</b><i> Wiki</i></a>
            <ul>
                <li class="wiki list{if $current == 'wiki/recent'} current{/if}"><a href="{$admin_url}wiki/recent.php">Dernières modifications</a>

Added src/templates/admin/acc/accounts/index.tpl version [93c3d88c2e].

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
{include file="admin/_head.tpl" title=$chart.label current="acc/charts"}

<ul class="actions">
	<li><a href="{$admin_url}acc/charts/">Gérer les plans</a></li>
	<li class="current"><a href="{$admin_url}acc/accounts/?id={$chart.id}">Modifier le plan</a></li>
	<li><a href="{$admin_url}acc/charts/export.php?id={$chart.id}">Exporter ce plan en CSV</a></li>
	<li><a href="{$admin_url}acc/charts/import.php?id={$chart.id}">Importer</a></li>
	<li><a href="{$admin_url}acc/charts/delete.php?id={$chart.id}">Supprimer</a></li>
	<li><a href="{$admin_url}acc/charts/reset.php?id={$chart.id}">Remettre à zéro</a></li>
</ul>

{if count($accounts)}
	<table class="list accounts">
		<thead>
			<td>Code</td>
			<th>Libellé</th>
			<td>Position</td>
			<td></td>
			<td></td>
		</thead>
		<tbody>
			{foreach from=$accounts item="item"}
				<tr class="account-level-<?=strlen($item->code)?>">
					<td>{$item.code}</td>
					<th>{$item.label}</th>
					<td>{$item.position|account_position}</td>
					<td>
						{if $item.type == $item::TYPE_BOOKMARK}{icon shape="star"}{/if}
						{$item.type|account_type}
					</td>
					<td class="actions">
						{if $item.user}
							{icon shape="delete" label="Supprimer" href="acc/charts/accounts/delete.php?id=%d"|args:$item.id}
						{/if}
						{icon shape="edit" label="Modifier" href="acc/charts/accounts/edit.php?id=%d"|args:$item.id}
					</td>
				</tr>
			{/foreach}
		</tbody>
	</table>
{/if}

<form method="post" action="{$self_url_no_qs}">
	<fieldset>
		<legend>Ajouter un compte au plan comptable</legend>
		<dl>
			{input type="text" name="code" label="Code" required=1 pattern="\d+" maxlength=6 help="Utilisé pour ordonner la liste des comptes. Seuls les chiffres sont acceptés."}
			{input type="text" name="label" label="Libellé" required=1}
		</dl>
		<p class="submit">
			<input type="submit" value="Créer &rarr;" />
		</p>
	</fieldset>
</form>

{include file="admin/_foot.tpl"}

Added src/templates/admin/acc/charts/index.tpl version [c2019af16c].







































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
{include file="admin/_head.tpl" title="Gestion des plans comptables" current="acc/charts"}

<ul class="actions">
	<li class="current"><a href="{$admin_url}acc/charts/">Gérer les plans</a></li>
	<li><a href="{$admin_url}acc/charts/import.php">Importer</a></li>
</ul>

{if count($list)}
    <table class="list">
        <thead>
        	<td>Pays</td>
            <th>Libellé</th>
            <td></td>
        </thead>
        <tbody>
            {foreach from=$list item="item"}
                <tr>
                	<td>{$item.country|get_country_name}</td>
                    <th><a href="{$admin_url}acc/accounts/?id={$item.id}">{$item.label}</a> <em>{if $item.code}(officiel){else}(copie){/if}</em></th>
                    <td class="actions">
                        {icon shape="menu" label="Gérer les comptes" href="acc/accounts/?id=%d"|args:$item.id}
                        {icon shape="edit" label="Renommer" href="acc/charts/edit.php?id=%d"|args:$item.id}
                        {icon shape="export" label="Exporter en CSV" href="acc/charts/export.php?id=%d"|args:$item.id}
                        {if empty($item.code)}
                            {icon shape="upload" label="Importer" href="acc/charts/import.php?id=%d"|args:$item.id}
                            {icon shape="delete" label="Supprimer" href="acc/charts/delete.php?id=%d"|args:$item.id}
                        {else}
                            {icon shape="reset" label="Remettre à zéro" href="acc/charts/reset.php?id=%d"|args:$item.id}
                        {/if}
                    </td>
                </tr>
            {/foreach}
        </tbody>
    </table>
{/if}

<form method="post" action="{$self_url_no_qs}">
	<fieldset>
		<legend>Créer un nouveau plan comptable</legend>
		<dl>
			{input type="select_groups" name="plan" options=$charts_groupped label="Recopier depuis" required=1}
			{input type="text" name="label" label="Libellé" required=1}
			{input type="select" name="country" label="Pays" required=1 options=$country_list default=$config.pays}
		</dl>
		<p class="submit">
			<input type="submit" value="Créer &rarr;" />
		</p>
	</fieldset>
</form>

{include file="admin/_foot.tpl"}

Modified src/templates/admin/compta/operations/saisir.tpl from [14b3e3ace9] to [b6541e1492].

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
...
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
{include file="admin/_head.tpl" title="Saisie d'une opération" current="compta/saisie" js=1}

<form method="post" action="{$self_url}">
    <ul class="actions">
        <li><input type="radio" name="type" value="recette" {form_field name=type checked=recette default=recette} id="f_type_recette" /><label for="f_type_recette">Recette</label></li>
        <li><input type="radio" name="type" value="depense" {form_field name=type checked=depense} id="f_type_depense" /><label for="f_type_depense">Dépense</label></li>
        <li><input type="radio" name="type" value="virement" {form_field name=type checked=virement} id="f_type_virement" /><label for="f_type_virement">Virement interne</label></li>
        <li><input type="radio" name="type" value="avance" {form_field name=type checked=avance} id="f_type_avance" /><label for="f_type_avance">Saisie avancée</label></li>
    </ul>

    {form_errors}

    {if $ok}
        <p class="confirm">
            L'opération numéro <a href="{$admin_url}compta/operations/voir.php?id={$ok}">{$ok}</a> a été ajoutée.
            (<a href="{$admin_url}compta/operations/voir.php?id={$ok}">Voir l'opération</a>)
        </p>
    {/if}

    <fieldset>
        <legend>Informations sur l'opération</legend>
        <dl>
            <dt><label for="f_date">Date</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd><input type="date" name="date" id="f_date" value="{form_field name=date default=$date}" size="10" required="required" /></dd>
            <dt><label for="f_libelle">Libellé</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd><input type="text" name="libelle" id="f_libelle" value="{form_field name=libelle}" required="required" /></dd>
            <dt><label for="f_montant">Montant</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd><input type="number" size="5" name="montant" id="f_montant" value="{form_field name=montant default=0.00}" min="0.00" step="0.01" required="required" /> {$config.monnaie}</dd>
            <dt><label for="f_numero_piece">Numéro de pièce comptable</label></dt>
            <dd><input type="text" name="numero_piece" id="f_numero_piece" value="{form_field name=numero_piece}" /></dd>
            <dt><label for="f_remarques">Remarques</label></dt>

            <dd><textarea name="remarques" id="f_remarques" rows="4" cols="30">{form_field name=remarques}</textarea></dd>
            {if count($projets) > 0}
            <dt><label for="f_projet">Projet</label></dt>
            <dd>

                <select name="projet" id="f_projet">
                    <option value="0">-- Aucun</option>
                    {foreach from=$projets key="id" item="libelle"}
                    <option value="{$id}"{form_field name="projet" selected=$id}>{$libelle}</option>
                    {/foreach}
                </select>
            </dd>
            {/if}
        </dl>
        <dl class="type_recette type_depense">
            <dt><label for="f_moyen_paiement">Moyen de paiement</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd>
                <select name="moyen_paiement" id="f_moyen_paiement" required="required">
                {foreach from=$moyens_paiement item="moyen"}
                    <option value="{$moyen.code}"{if $moyen.code == $moyen_paiement} selected="selected"{/if}>{$moyen.nom}</option>
                {/foreach}
                </select>


            </dd>
            <dd class="f_a_encaisser">
                <input type="checkbox" name="a_encaisser" value="1" id="f_a_encaisser" {form_field name=a_encaisser checked="1"} />
                <label for="f_a_encaisser">En attente d'encaissement</label>
            </dd>
            <dt class="f_cheque"><label for="f_numero_cheque">Numéro de chèque</label></dt>
            <dd class="f_cheque"><input type="text" name="numero_cheque" id="f_numero_cheque" value="{form_field name=numero_cheque}" /></dd>
            <dt class="f_banque"><label for="f_banque">Compte bancaire</label></dt>
            <dd class="f_banque">
                <select name="banque" id="f_banque">
                {foreach from=$comptes_bancaires item="compte"}
                    <option value="{$compte.id}"{if $compte.id == $banque} selected="selected"{/if}>{$compte.libelle} - {$compte.banque}</option>
                {/foreach}
                </select>
            </dd>

        </dl>
    </fieldset>

    <fieldset class="type_avance">
        <legend>Saisie avancée</legend>

        <dl>
            <dt><label for="f_compte_debit">Compte débité</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd>
                {select_compte comptes=$comptes name="compte_debit"}
            </dd>
            <dt><label for="f_compte_credit">Compte crédité</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd>
                {select_compte comptes=$comptes name="compte_credit"}
            </dd>


        </dl>
    </fieldset>

    <fieldset class="type_virement">
        <legend>Virement</legend>

        <dl>
            <dt><label for="f_compte2">De</label></dt>
            <dd>
                <select name="compte2" id="f_compte2">
                    <option value="{$id_caisse}">Caisse</option>
                {foreach from=$comptes_bancaires item="compte"}
                    <option value="{$compte.id}"{if $compte.id == $banque} selected="selected"{/if}>{$compte.libelle} - {$compte.banque}</option>
                {/foreach}
                    <option value="{$compte_cheque_e_encaisser}">Chèques à encaisser</option>
                    <option value="{$compte_carte_e_encaisser}">Paiement CB à encaisser</option>
                </select>
            </dd>
            <dt><label for="f_compte1">Vers</label></dt>
            <dd>
                <select name="compte1" id="f_compte1">
                    <option value="{$id_caisse}">Caisse</option>
                {foreach from=$comptes_bancaires item="compte"}
                    <option value="{$compte.id}"{if $compte.id == $banque} selected="selected"{/if}>{$compte.libelle} - {$compte.banque}</option>
                {/foreach}
                </select>
            </dd>







        </dl>
    </fieldset>

    <fieldset class="type_dette">
        <legend>Dette</legend>
        <dl>
            <dt><label for="f_compte_usager">Type de dette</label></dt>
................................................................................
        </dl>
    </fieldset>

    <fieldset class="type_recette">
        <legend>Catégorie</legend>
        <dl class="catList">
        {foreach from=$categories_recettes item="cat"}
            <dt>
                <input type="radio" name="categorie_recette" value="{$cat.id}" id="f_cat_{$cat.id}" {form_field name="categorie" checked=$cat.id} />
                <label for="f_cat_{$cat.id}">{$cat.intitule}</label>
            </dt>
            {if !empty($cat.description)}
                <dd class="desc">{$cat.description}</dd>
            {/if}
        {/foreach}
        </dl>
    </fieldset>

    <fieldset class="type_depense type_dette">
        <legend>Catégorie</legend>
        <dl class="catList">
        {foreach from=$categories_depenses item="cat"}
            <dt>
                <input type="radio" name="categorie_depense" value="{$cat.id}" id="f_cat_{$cat.id}" {form_field name="categorie" checked=$cat.id} />
                <label for="f_cat_{$cat.id}">{$cat.intitule}</label>
            </dt>
            {if !empty($cat.description)}
                <dd class="desc">{$cat.description}</dd>
            {/if}
        {/foreach}
        </dl>
    </fieldset>




<
<
<
<
<
<
<










|

|
|
|
|
|
|
|
|
<
>
|
|
<
|
>
|
|
<
<
<
<
<
<


<
<
<
<
<
<
<
>
>
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
>



|
<
>

<
<
<
<
<
<
<
<
>
>



|
<
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
>
>
>
>







 







<
|
<
<











<
|
<
<







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
..
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
{include file="admin/_head.tpl" title="Saisie d'une opération" current="compta/saisie" js=1}

<form method="post" action="{$self_url}">







    {form_errors}

    {if $ok}
        <p class="confirm">
            L'opération numéro <a href="{$admin_url}compta/operations/voir.php?id={$ok}">{$ok}</a> a été ajoutée.
            (<a href="{$admin_url}compta/operations/voir.php?id={$ok}">Voir l'opération</a>)
        </p>
    {/if}

    <fieldset>
        <legend>Type d'écriture</legend>
        <dl>
            {input type="radio" name="type" value="recette" label="Recette"}
            {input type="radio" name="type" value="depense" label="Dépense"}
            {input type="radio" name="type" value="virement" label="Virement" help="Faire un virement entre comptes, déposer des espèces en banque, etc."}
            {input type="radio" name="type" value="dette" label="Dette" help="Quand l'association doit de l'argent à un membre ou un fournisseur"}
            {input type="radio" name="type" value="creance" label="Créance" help="Quand un membre ou un fournisseur doit de l'argent à l'association"}
            {input type="radio" name="type" value="avance" label="Saisie avancée" help="Choisir les comptes du plan comptable, ventiler une écriture sur plusieurs comptes, etc."}
        </dl>
    </fieldset>


    <fieldset>
        <legend>Informations</legend>

        <dl>
            {input type="date" name="date" value=$date label="Date" required=1}
            {input type="text" name="label" label="Libellé" required=1}
            {input type="number" name="amount" label="Montant" min="0.00" step="0.01" value="0.00" required=1} {$config.monnaie}






        </dl>
        <dl class="type_recette type_depense">







            {input type="select_groups" name="account" label="Compte" required=1}
            {input type="text" name="reference_paiement" label="Référence de paiement" help="Numéro de chèque, numéro de transaction CB, etc."}
        </dl>







        <dl class="type_avance">






            {input type="compta_lignes" name="lignes" label="Lignes de l'écriture"}
        </dl>
    </fieldset>

    <fieldset class="type_virement">

        <legend>Virement</legend>
        <dl>








            {input type="select" name="from" options=$comptes label="De" required=1}
            {input type="select" name="to" options=$comptes label="Vers" required=1}
        </dl>
    </fieldset>

    <fieldset>

        <legend>Détails</legend>
        <dl>




















            {input type="datalist" name="membre" label="Membres associés"}
            {input type="text" name="numero_piece" label="Numéro de pièce comptable"}
            {input type="textarea" name="remarques" label="Remarques" rows=4 cols=30}

            {if count($projets) > 0}
                {input type="select" name="projet" options=$projets}
            {/if}
        </dl>
    </fieldset>

    <fieldset class="type_dette">
        <legend>Dette</legend>
        <dl>
            <dt><label for="f_compte_usager">Type de dette</label></dt>
................................................................................
        </dl>
    </fieldset>

    <fieldset class="type_recette">
        <legend>Catégorie</legend>
        <dl class="catList">
        {foreach from=$categories_recettes item="cat"}

            {input type="radio" name="categorie_recette" value=$cat.id label=$cat.intitule}


            {if !empty($cat.description)}
                <dd class="desc">{$cat.description}</dd>
            {/if}
        {/foreach}
        </dl>
    </fieldset>

    <fieldset class="type_depense type_dette">
        <legend>Catégorie</legend>
        <dl class="catList">
        {foreach from=$categories_depenses item="cat"}

            {input type="radio" name="categorie_depense" value=$cat.id label=$cat.intitule}


            {if !empty($cat.description)}
                <dd class="desc">{$cat.description}</dd>
            {/if}
        {/foreach}
        </dl>
    </fieldset>

Modified src/templates/admin/config/categories/modifier.tpl from [5f082eb8b5] to [5b06ee18b0].

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
                <label for="f_cacher">Catégorie cachée</label>
            </dt>
            <dd class="help">
                Si coché cette catégorie ne sera visible qu'aux administrateurs et ne recevra pas
                de messages collectifs ou de rappels.
            </dd>
        </dl>
    </fieldset>

    <fieldset>
        <legend>Cotisation obligatoire</legend>
        <dl>
            <dt><label for="f_id_cotisation_obligatoire">Cotisation obligatoire</label></dt>
            <dd>
                <select name="id_cotisation_obligatoire" id="f_id_cotisation_obligatoire">
                    <option value="">-- Non</option>
                    {foreach from=$cotisations item="cotisation"}
                    <option value="{$cotisation.id}" {form_field name="id_cotisation_obligatoire" selected=$cotisation.id data=$cat}>
                        {$cotisation.intitule} 
                        — {$cotisation.montant|escape|html_money} {$config.monnaie}
                        — {if $cotisation.duree}pour {$cotisation.duree} jours
                        {elseif $cotisation.debut}
                            du {$cotisation.debut|format_sqlite_date_to_french} au {$cotisation.fin|format_sqlite_date_to_french}
                        {else}
                            ponctuelle
                        {/if}
                    </option>
                    {/foreach}
                </select>
            </dd>
        </dl>
    </fieldset>

    <fieldset>
        <legend>Droits</legend>
        <dl class="droits">
            <dt><label for="f_droit_connexion_aucun">Les membres de cette catégorie peuvent-ils se connecter ?</label></dt>
            {if $readonly}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







16
17
18
19
20
21
22
























23
24
25
26
27
28
29
                <label for="f_cacher">Catégorie cachée</label>
            </dt>
            <dd class="help">
                Si coché cette catégorie ne sera visible qu'aux administrateurs et ne recevra pas
                de messages collectifs ou de rappels.
            </dd>
        </dl>
























    </fieldset>

    <fieldset>
        <legend>Droits</legend>
        <dl class="droits">
            <dt><label for="f_droit_connexion_aucun">Les membres de cette catégorie peuvent-ils se connecter ?</label></dt>
            {if $readonly}

Modified src/templates/admin/index.tpl from [68896b2b83] to [a728eba131].

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
{include file="admin/_head.tpl" title="Bonjour %s !"|args:$user.identite current="home"}

{$banniere|raw}

<ul class="actions">
    <li><a href="{$admin_url}mes_infos.php">Modifier mes informations personnelles</a></li>
    {if $cotisation}
    <li>
        {if !$cotisation.a_jour}
            <b class="error">Cotisation en retard&nbsp;!</b>
        {else}
            <b class="confirm">Cotisation à jour</b>
            {if $cotisation.expiration}
                (expire le {$cotisation.expiration|format_sqlite_date_to_french})
            {/if}
        {/if}
    </li>
    {/if}
    <li><a href="{$admin_url}mes_cotisations.php">Suivi de mes cotisations</a></li>
</ul>


<aside class="describe">
    <h3>{$config.nom_asso}</h3>
    {if !empty($config.adresse_asso)}






<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6












7
8
9
10
11
12
13
{include file="admin/_head.tpl" title="Bonjour %s !"|args:$user.identite current="home"}

{$banniere|raw}

<ul class="actions">
    <li><a href="{$admin_url}mes_infos.php">Modifier mes informations personnelles</a></li>












    <li><a href="{$admin_url}mes_cotisations.php">Suivi de mes cotisations</a></li>
</ul>


<aside class="describe">
    <h3>{$config.nom_asso}</h3>
    {if !empty($config.adresse_asso)}

Modified src/templates/admin/membres/cotisations.tpl from [329d9b5092] to [000e2dab08].

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
    {if $session->canAccess('membres', Membres::DROIT_ADMIN) && $user.id != $membre.id}
        <li><a href="{$admin_url}membres/supprimer.php?id={$membre.id}">Supprimer</a></li>
    {/if}
    <li class="current"><a href="{$admin_url}membres/cotisations.php?id={$membre.id}">Suivi des cotisations</a></li>
</ul>

<dl class="cotisation">
{if $cotisation}
    <dt>Cotisation obligatoire</dt>
    <dd>{$cotisation.intitule} — 
        {if $cotisation.duree}
            {$cotisation.duree} jours
        {elseif $cotisation.debut}
            du {$cotisation.debut|format_sqlite_date_to_french} au {$cotisation.fin|format_sqlite_date_to_french}
        {else}
            ponctuelle
        {/if}
        — {$cotisation.montant|escape|html_money} {$config.monnaie}
    </dd>
    <dt>À jour de cotisation ?</dt>
    <dd>
        {if !$cotisation.a_jour}
            <span class="error"><b>Non</b>, cotisation non payée</span>
        {else}
            <b class="confirm">&#10003; Oui</b>
            {if $cotisation.expiration}
                (expire le {$cotisation.expiration|format_sqlite_date_to_french})
            {/if}
        {/if}
    </dd>
{/if}
    <dt>
        {if $nb_activites == 1}
            {$nb_activites} cotisation enregistrée
        {elseif $nb_activites}
            {$nb_activites} cotisations enregistrées
        {else}
            Aucune cotisation enregistrée







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







6
7
8
9
10
11
12
























13
14
15
16
17
18
19
    {if $session->canAccess('membres', Membres::DROIT_ADMIN) && $user.id != $membre.id}
        <li><a href="{$admin_url}membres/supprimer.php?id={$membre.id}">Supprimer</a></li>
    {/if}
    <li class="current"><a href="{$admin_url}membres/cotisations.php?id={$membre.id}">Suivi des cotisations</a></li>
</ul>

<dl class="cotisation">
























    <dt>
        {if $nb_activites == 1}
            {$nb_activites} cotisation enregistrée
        {elseif $nb_activites}
            {$nb_activites} cotisations enregistrées
        {else}
            Aucune cotisation enregistrée

Modified src/templates/admin/membres/cotisations/voir.tpl from [79533ebb65] to [2daa0083bb].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
        {elseif $cotisation.debut}
            du {$cotisation.debut|format_sqlite_date_to_french} au {$cotisation.fin|format_sqlite_date_to_french}
        {else}
            ponctuelle
        {/if}
        — {$cotisation.montant|escape|html_money} {$config.monnaie}
    </dd>
    <dd>
        {if !$cats}
            <a href="?id={$cotisation.id}&amp;cats=1">Afficher les membres des catégories pour lesquelles cette cotisation est obligatoire</a>
        {else}
            <a href="?id={$cotisation.id}">Afficher seulement les membres à jour (ou qui ont déjà payé, mais ne sont plus à jour)</a>
        {/if}
    </dd>    <dt>Nombre de membres ayant cotisé</dt>
    <dd>
        {$cotisation.nb_membres}
        <small class="help">(incluant les membres des catégories cachées)</small>
    </dd>
</dl>

{if !empty($liste)}







<
<
<
<
<
<
|







18
19
20
21
22
23
24






25
26
27
28
29
30
31
32
        {elseif $cotisation.debut}
            du {$cotisation.debut|format_sqlite_date_to_french} au {$cotisation.fin|format_sqlite_date_to_french}
        {else}
            ponctuelle
        {/if}
        — {$cotisation.montant|escape|html_money} {$config.monnaie}
    </dd>






    <dt>Nombre de membres ayant cotisé</dt>
    <dd>
        {$cotisation.nb_membres}
        <small class="help">(incluant les membres des catégories cachées)</small>
    </dd>
</dl>

{if !empty($liste)}

Modified src/templates/admin/membres/fiche.tpl from [99f7b69c9c] to [c629e41ab5].

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
    {if $session->canAccess('membres', Membres::DROIT_ADMIN) && $user.id != $membre.id}
        <li><a href="{$admin_url}membres/supprimer.php?id={$membre.id}">Supprimer</a></li>
    {/if}
    <li><a href="{$admin_url}membres/cotisations.php?id={$membre.id}">Suivi des cotisations</a></li>
</ul>

<dl class="cotisation">
{if $cotisation}
    <dt>Cotisation obligatoire</dt>
    <dd>{$cotisation.intitule} — 
        {if $cotisation.duree}
            {$cotisation.duree} jours
        {elseif $cotisation.debut}
            du {$cotisation.debut|format_sqlite_date_to_french} au {$cotisation.fin|format_sqlite_date_to_french}
        {else}
            ponctuelle
        {/if}
        — {$cotisation.montant|escape|html_money} {$config.monnaie}
    </dd>
    <dt>À jour de cotisation ?</dt>
    <dd>
        {if !$cotisation.a_jour}
            <span class="error"><b>Non</b>, cotisation non payée</span>
        {else}
            <b class="confirm">&#10003; Oui</b>
            {if $cotisation.expiration}
                (expire le {$cotisation.expiration|format_sqlite_date_to_french})
            {/if}
        {/if}
    </dd>
{/if}
    <dt>
        {if $nb_activites == 1}
            {$nb_activites} cotisation enregistrée
        {elseif $nb_activites}
            {$nb_activites} cotisations enregistrées
        {else}
            Aucune cotisation enregistrée







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







6
7
8
9
10
11
12
























13
14
15
16
17
18
19
    {if $session->canAccess('membres', Membres::DROIT_ADMIN) && $user.id != $membre.id}
        <li><a href="{$admin_url}membres/supprimer.php?id={$membre.id}">Supprimer</a></li>
    {/if}
    <li><a href="{$admin_url}membres/cotisations.php?id={$membre.id}">Suivi des cotisations</a></li>
</ul>

<dl class="cotisation">
























    <dt>
        {if $nb_activites == 1}
            {$nb_activites} cotisation enregistrée
        {elseif $nb_activites}
            {$nb_activites} cotisations enregistrées
        {else}
            Aucune cotisation enregistrée

Modified src/templates/admin/mes_cotisations.tpl from [2423b2fa48] to [6c9a6778eb].

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
            Vous avez {$nb_activites} cotisation enregistrée.
        {elseif $nb_activites}
            Vous avez {$nb_activites} cotisations enregistrées.
        {else}
            Vous n'avez aucune cotisation enregistrée.
        {/if} 
    </dt>
{if $cotisation}
    <dt>Cotisation obligatoire</dt>
    <dd>{$cotisation.intitule} — 
        {if $cotisation.duree}
            {$cotisation.duree} jours
        {elseif $cotisation.debut}
            du {$cotisation.debut|format_sqlite_date_to_french} au {$cotisation.fin|format_sqlite_date_to_french}
        {else}
            ponctuelle
        {/if}
        — {$cotisation.montant|escape|html_money} {$config.monnaie}
    </dd>
    <dd>
        {if !$cotisation.a_jour}
            <b class="error">Vous n'êtes pas à jour de cotisation</b>
        {else}
            <b class="confirm">&#10003; À jour de cotisation</b>
            {if $cotisation.expiration}
                (expire le {$cotisation.expiration|format_sqlite_date_to_french})
            {/if}
        {/if}
    </dd>
{/if}
{if !empty($cotisations_membre)}
    <dt>Cotisations en cours</dt>
    {foreach from=$cotisations_membre item="co"}
    <dd>{$co.intitule} — 
        {if $co.a_jour}
            <span class="confirm">À jour</span>{if $co.expiration} — Expire le {$co.expiration|format_sqlite_date_to_french}{/if}
        {else}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







6
7
8
9
10
11
12























13
14
15
16
17
18
19
            Vous avez {$nb_activites} cotisation enregistrée.
        {elseif $nb_activites}
            Vous avez {$nb_activites} cotisations enregistrées.
        {else}
            Vous n'avez aucune cotisation enregistrée.
        {/if} 
    </dt>























{if !empty($cotisations_membre)}
    <dt>Cotisations en cours</dt>
    {foreach from=$cotisations_membre item="co"}
    <dd>{$co.intitule} — 
        {if $co.a_jour}
            <span class="confirm">À jour</span>{if $co.expiration} — Expire le {$co.expiration|format_sqlite_date_to_french}{/if}
        {else}

Modified src/www/_route.php from [c720a9392c] to [259d94156a].

7
8
9
10
11
12
13




14
15
16
17
18
19
20
}

$uri = $_SERVER['REQUEST_URI'];

if ('_route.php' === basename($uri)) {
	die('Appel interdit');
}





if (($pos = strpos($uri, '?')) !== false)
{
	$uri = substr($uri, 0, $pos);
}

if (file_exists(__DIR__ . $uri))







>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
}

$uri = $_SERVER['REQUEST_URI'];

if ('_route.php' === basename($uri)) {
	die('Appel interdit');
}

if ('favicon.ico' === basename($uri)) {
	die('');
}

if (($pos = strpos($uri, '?')) !== false)
{
	$uri = substr($uri, 0, $pos);
}

if (file_exists(__DIR__ . $uri))

Added src/www/admin/acc/_inc.php version [1ab6e238e9].















>
>
>
>
>
>
>
1
2
3
4
5
6
7
<?php

namespace Garradin;

require_once __DIR__ . '/../_inc.php';

$session->requireAccess('compta', Membres::DROIT_ACCES);

Added src/www/admin/acc/accounts/index.php version [945e0f44db].



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
namespace Garradin;

use Garradin\Accounting\Charts;
use Garradin\Accounting\Accounts;

require_once __DIR__ . '/../_inc.php';

$session->requireAccess('compta', Membres::DROIT_ADMIN);

$chart = (new Charts)->get(qg('id'));
$accounts = new Accounts;

$tpl->assign('chart', $chart);
$tpl->assign('accounts', $accounts->listForChart($chart->id()));

$tpl->display('admin/acc/accounts/index.tpl');

Added src/www/admin/acc/charts/index.php version [b524fa30f8].

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
namespace Garradin;

use Garradin\Accounting\Charts;

require_once __DIR__ . '/../_inc.php';

$session->requireAccess('compta', Membres::DROIT_ADMIN);

$charts = new Charts;

$tpl->assign('list', $charts->list());
$tpl->assign('charts_groupped', $charts->listByCountry());
$tpl->assign('country_list', Utils::getCountryList());

$tpl->display('admin/acc/charts/index.tpl');

Modified src/www/admin/compta/_inc.php from [da7b17d045] to [c1d56da526].

3
4
5
6
7
8
9
10
11
12
13
namespace Garradin;

require_once __DIR__ . '/../_inc.php';

$session->requireAccess('compta', Membres::DROIT_ACCES);

$comptes = new Compta\Comptes;

$tpl->assign('id_caisse', Compta\Comptes::CAISSE);
$tpl->assign('id_cheque_a_encaisser', Compta\Comptes::CHEQUE_A_ENCAISSER);
$tpl->assign('id_carte_a_encaisser', Compta\Comptes::CARTE_A_ENCAISSER);







<
<
<
<
3
4
5
6
7
8
9




namespace Garradin;

require_once __DIR__ . '/../_inc.php';

$session->requireAccess('compta', Membres::DROIT_ACCES);

$comptes = new Compta\Comptes;




Modified src/www/admin/compta/operations/saisir.php from [20d760aa75] to [e22f5542d2].

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
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
$session->requireAccess('compta', Membres::DROIT_ECRITURE);

$journal = new Compta\Journal;

$journal->checkExercice();

$cats = new Compta\Categories;
$banques = new Compta\Comptes_Bancaires;

$type = f('type') ?: 'recette';

if (f('save'))
{
    $form->check('compta_saisie', [
        'libelle' => 'required',
................................................................................
        }
    }
}

$tpl->assign('type', $type);

$tpl->assign('comptes', $comptes->listTree());
$tpl->assign('moyens_paiement', $cats->listMoyensPaiement());
$tpl->assign('moyen_paiement', f('moyen_paiement') ?: 'ES');
$tpl->assign('categories_depenses', $cats->getList(Compta\Categories::DEPENSES));
$tpl->assign('categories_recettes', $cats->getList(Compta\Categories::RECETTES));
$tpl->assign('comptes_bancaires', $banques->getList());
$tpl->assign('banque', f('banque'));
$tpl->assign('compte_cheque_e_encaisser', Compta\Comptes::CHEQUE_A_ENCAISSER);
$tpl->assign('compte_carte_e_encaisser', Compta\Comptes::CARTE_A_ENCAISSER);
$tpl->assign('projets', (new Compta\Projets)->getAssocList());


if (!$session->get('context_compta_date'))
{
    $exercices = new Compta\Exercices;
    $exercice = $exercices->getCurrent();

    if ($exercice->debut > time() || $exercice->fin < time())
    {
        $session->set('context_compta_date', date('Y-m-d', $exercice->debut));
    }
    else
    {
        $session->get('context_compta_date', date('Y-m-d'));
    }
}

$tpl->assign('date', $session->get('context_compta_date') ?: false);
$tpl->assign('ok', (int) qg('ok'));

$tpl->display('admin/compta/operations/saisir.tpl');







<







 







<
<


<
<
<
<
<
>



<
<
<
<
<
|
<
<
<
<
<






6
7
8
9
10
11
12

13
14
15
16
17
18
19
...
153
154
155
156
157
158
159


160
161





162
163
164
165





166





167
168
169
170
171
172
$session->requireAccess('compta', Membres::DROIT_ECRITURE);

$journal = new Compta\Journal;

$journal->checkExercice();

$cats = new Compta\Categories;


$type = f('type') ?: 'recette';

if (f('save'))
{
    $form->check('compta_saisie', [
        'libelle' => 'required',
................................................................................
        }
    }
}

$tpl->assign('type', $type);

$tpl->assign('comptes', $comptes->listTree());


$tpl->assign('categories_depenses', $cats->getList(Compta\Categories::DEPENSES));
$tpl->assign('categories_recettes', $cats->getList(Compta\Categories::RECETTES));





$tpl->assign('comptes_simples', $comptes->listSimpleTargetAccounts());

if (!$session->get('context_compta_date'))
{





    $session->set('context_compta_date', date('Y-m-d'));





}

$tpl->assign('date', $session->get('context_compta_date') ?: false);
$tpl->assign('ok', (int) qg('ok'));

$tpl->display('admin/compta/operations/saisir.tpl');

Modified src/www/admin/config/categories/modifier.php from [6a75b928b9] to [79f85734c9].

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
..
78
79
80
81
82
83
84
85
86
87
88
89
90
        'droit_wiki'                => 'in:' . $droits,
        'droit_compta'              => 'in:' . $droits,
        'droit_membres'             => 'in:' . $droits,
        'droit_config'              => sprintf('in:%s,%s', Membres::DROIT_ADMIN, Membres::DROIT_AUCUN),
        'droit_connexion'           => sprintf('in:%s,%s', Membres::DROIT_ACCES, Membres::DROIT_AUCUN),
        'droit_inscription'         => sprintf('in:%s,%s', Membres::DROIT_ACCES, Membres::DROIT_AUCUN),
        'cacher'                    => 'boolean',
        'id_cotisation_obligatoire' => 'numeric',
    ]);

    if (!$form->hasErrors())
    {
        $data = [
            'nom'           =>  f('nom'),
            'droit_wiki'    =>  (int) f('droit_wiki'),
            'droit_compta'  =>  (int) f('droit_compta'),
            'droit_config'  =>  (int) f('droit_config'),
            'droit_membres' =>  (int) f('droit_membres'),
            'droit_connexion' => (int) f('droit_connexion'),
            'droit_inscription' => (int) f('droit_inscription'),
            'cacher'        =>  (int) f('cacher'),
            'id_cotisation_obligatoire' => (int) f('id_cotisation_obligatoire'),
        ];

        // Ne pas permettre de modifier la connexion, l'accès à la config et à la gestion des membres
        // pour la catégorie du membre qui édite les catégories, sinon il pourrait s'empêcher
        // de se connecter ou n'avoir aucune catégorie avec le droit de modifier les catégories !
        if ($cat->id == $user->id_categorie)
        {
................................................................................
    }
}

$tpl->assign('cat', $cat);

$tpl->assign('readonly', $cat->id == $user->id_categorie ? 'disabled="disabled"' : '');

$cotisations = new Cotisations;
$tpl->assign('cotisations', $cotisations->listCurrent());

$tpl->assign('membres', new Membres);

$tpl->display('admin/config/categories/modifier.tpl');







<













<







 







<
<
<



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
..
76
77
78
79
80
81
82



83
84
85
        'droit_wiki'                => 'in:' . $droits,
        'droit_compta'              => 'in:' . $droits,
        'droit_membres'             => 'in:' . $droits,
        'droit_config'              => sprintf('in:%s,%s', Membres::DROIT_ADMIN, Membres::DROIT_AUCUN),
        'droit_connexion'           => sprintf('in:%s,%s', Membres::DROIT_ACCES, Membres::DROIT_AUCUN),
        'droit_inscription'         => sprintf('in:%s,%s', Membres::DROIT_ACCES, Membres::DROIT_AUCUN),
        'cacher'                    => 'boolean',

    ]);

    if (!$form->hasErrors())
    {
        $data = [
            'nom'           =>  f('nom'),
            'droit_wiki'    =>  (int) f('droit_wiki'),
            'droit_compta'  =>  (int) f('droit_compta'),
            'droit_config'  =>  (int) f('droit_config'),
            'droit_membres' =>  (int) f('droit_membres'),
            'droit_connexion' => (int) f('droit_connexion'),
            'droit_inscription' => (int) f('droit_inscription'),
            'cacher'        =>  (int) f('cacher'),

        ];

        // Ne pas permettre de modifier la connexion, l'accès à la config et à la gestion des membres
        // pour la catégorie du membre qui édite les catégories, sinon il pourrait s'empêcher
        // de se connecter ou n'avoir aucune catégorie avec le droit de modifier les catégories !
        if ($cat->id == $user->id_categorie)
        {
................................................................................
    }
}

$tpl->assign('cat', $cat);

$tpl->assign('readonly', $cat->id == $user->id_categorie ? 'disabled="disabled"' : '');




$tpl->assign('membres', new Membres);

$tpl->display('admin/config/categories/modifier.tpl');

Modified src/www/admin/index.php from [5988e390c9] to [3aa5eb7127].

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

$tpl->assign('categorie', $categorie);

$wiki = new Wiki;
$page = $wiki->getByURI($config->get('accueil_connexion'));
$tpl->assign('page', $page);

$cats = new Membres\Categories;

$categorie = $cats->get($user->id_categorie);

$cotisations = new Membres\Cotisations;

if (!empty($categorie->id_cotisation_obligatoire))
{
	$tpl->assign('cotisation', $cotisations->isMemberUpToDate($user->id, $categorie->id_cotisation_obligatoire));
}
else
{
	$tpl->assign('cotisation', false);
}

$tpl->assign('custom_css', ['wiki.css']);

$tpl->assign('banniere', Plugin::fireSignal('accueil.banniere', ['user' => $user, 'session' => $session]));

$tpl->display('admin/index.tpl');
flush();

// Si pas de cron on réalise les tâches automatisées à ce moment-là
// c'est pas idéal mais mieux que rien
if (!USE_CRON)
{
	require_once ROOT . '/cron.php';
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













9
10
11
12
13
14
15















16
17
18
19
20
21
22
23
24
25
26
27
28

$tpl->assign('categorie', $categorie);

$wiki = new Wiki;
$page = $wiki->getByURI($config->get('accueil_connexion'));
$tpl->assign('page', $page);
















$tpl->assign('custom_css', ['wiki.css']);

$tpl->assign('banniere', Plugin::fireSignal('accueil.banniere', ['user' => $user, 'session' => $session]));

$tpl->display('admin/index.tpl');
flush();

// Si pas de cron on réalise les tâches automatisées à ce moment-là
// c'est pas idéal mais mieux que rien
if (!USE_CRON)
{
	require_once ROOT . '/cron.php';
}

Modified src/www/admin/membres/cotisations.php from [d156e1e5bb] to [3c5966921b].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$cats = new Membres\Categories;

$categorie = $cats->get($membre->id_categorie);
$tpl->assign('categorie', $categorie);

$cotisations = new Membres\Cotisations;

if (!empty($categorie->id_cotisation_obligatoire))
{
	$tpl->assign('cotisation', $cotisations->isMemberUpToDate($membre->id, $categorie->id_cotisation_obligatoire));
}
else
{
	$tpl->assign('cotisation', false);
}

$tpl->assign('nb_activites', $cotisations->countForMember($membre->id));
$tpl->assign('cotisations', $cotisations->listForMember($membre->id));
$tpl->assign('cotisations_membre', $cotisations->listSubscriptionsForMember($membre->id));

$tpl->assign('membre', $membre);

$tpl->display('admin/membres/cotisations.tpl');







<
<
<
<
<
<
<
<
<







17
18
19
20
21
22
23









24
25
26
27
28
29
30
$cats = new Membres\Categories;

$categorie = $cats->get($membre->id_categorie);
$tpl->assign('categorie', $categorie);

$cotisations = new Membres\Cotisations;










$tpl->assign('nb_activites', $cotisations->countForMember($membre->id));
$tpl->assign('cotisations', $cotisations->listForMember($membre->id));
$tpl->assign('cotisations_membre', $cotisations->listSubscriptionsForMember($membre->id));

$tpl->assign('membre', $membre);

$tpl->display('admin/membres/cotisations.tpl');

Modified src/www/admin/membres/cotisations/ajout.php from [b2cc2cef01] to [5f20942e98].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    {
        throw new UserException("Ce membre n'existe pas.");
    }

    $cats = new Membres\Categories;
    $categorie = $cats->get($membre->id_categorie);
}
else
{
    $categorie = ['id_cotisation_obligatoire' => false];
}

$cotisations = new Cotisations;
$m_cotisations = new Membres\Cotisations;

$cats = new Compta\Categories;
$banques = new Compta\Comptes_Bancaires;

................................................................................
        throw new UserException("La cotisation indiquée en paramètre n'existe pas.");
    }

    $tpl->assign('default_co', $co->id);
    $tpl->assign('default_compta', $co->id_categorie_compta);
    $tpl->assign('default_amount', $co->montant);
}
elseif ($membre)
{
    if (!empty($categorie->id_cotisation_obligatoire))
    {
        $co = $cotisations->get($categorie->id_cotisation_obligatoire);

        $tpl->assign('default_co', $co->id);
        $tpl->assign('default_amount', $co->montant);
    }
}

$tpl->display('admin/membres/cotisations/ajout.tpl');







<
<
<
<







 







<
|
<
<
<
<
<
<
<
<
<

15
16
17
18
19
20
21




22
23
24
25
26
27
28
..
81
82
83
84
85
86
87

88









89
    {
        throw new UserException("Ce membre n'existe pas.");
    }

    $cats = new Membres\Categories;
    $categorie = $cats->get($membre->id_categorie);
}





$cotisations = new Cotisations;
$m_cotisations = new Membres\Cotisations;

$cats = new Compta\Categories;
$banques = new Compta\Comptes_Bancaires;

................................................................................
        throw new UserException("La cotisation indiquée en paramètre n'existe pas.");
    }

    $tpl->assign('default_co', $co->id);
    $tpl->assign('default_compta', $co->id_categorie_compta);
    $tpl->assign('default_amount', $co->montant);
}











$tpl->display('admin/membres/cotisations/ajout.tpl');

Modified src/www/admin/membres/cotisations/voir.php from [8935c9e002] to [4373893e11].

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
..
32
33
34
35
36
37
38
39
40
41

if (!$co)
{
    throw new UserException("Cette cotisation n'existe pas.");
}

$page = (int) qg('p') ?: 1;
$categories = (int) qg('cats');

$tpl->assign('cats', $categories);
$tpl->assign('page', $page);
$tpl->assign('bypage', Membres\Cotisations::ITEMS_PER_PAGE);
$tpl->assign('total', $m_cotisations->countMembersForCotisation($co->id));
$tpl->assign('pagination_url', Utils::getSelfUrl([
	'id' => $co->id,
	'o' => qg('o'),
	(qg('a') !== null ? 'a' : 'd') => '',
................................................................................
	'cats' => $categories,
]));

$tpl->assign('cotisation', $co);
$tpl->assign('order', qg('o') ?: 'date');
$tpl->assign('desc', null === qg('a'));
$tpl->assign('liste', $m_cotisations->listMembersForCotisation(
	$co->id, $categories, $page, qg('o'), null !== qg('a') ? false : true));

$tpl->display('admin/membres/cotisations/voir.tpl');







<
<
<







 







|


14
15
16
17
18
19
20



21
22
23
24
25
26
27
..
29
30
31
32
33
34
35
36
37
38

if (!$co)
{
    throw new UserException("Cette cotisation n'existe pas.");
}

$page = (int) qg('p') ?: 1;



$tpl->assign('page', $page);
$tpl->assign('bypage', Membres\Cotisations::ITEMS_PER_PAGE);
$tpl->assign('total', $m_cotisations->countMembersForCotisation($co->id));
$tpl->assign('pagination_url', Utils::getSelfUrl([
	'id' => $co->id,
	'o' => qg('o'),
	(qg('a') !== null ? 'a' : 'd') => '',
................................................................................
	'cats' => $categories,
]));

$tpl->assign('cotisation', $co);
$tpl->assign('order', qg('o') ?: 'date');
$tpl->assign('desc', null === qg('a'));
$tpl->assign('liste', $m_cotisations->listMembersForCotisation(
	$co->id, $page, qg('o'), null !== qg('a') ? false : true));

$tpl->display('admin/membres/cotisations/voir.tpl');

Modified src/www/admin/membres/fiche.php from [890dac5864] to [113fb90286].

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
$cats = new Membres\Categories;

$categorie = $cats->get($membre->id_categorie);
$tpl->assign('categorie', $categorie);

$cotisations = new Membres\Cotisations;

if (!empty($categorie->id_cotisation_obligatoire))
{
	$tpl->assign('cotisation', $cotisations->isMemberUpToDate($membre->id, $categorie->id_cotisation_obligatoire));
}
else
{
	$tpl->assign('cotisation', false);
}

$tpl->assign('nb_activites', $cotisations->countForMember($membre->id));

if ($session->canAccess('compta', Membres::DROIT_ACCES))
{
	$journal = new Compta\Journal;
	$tpl->assign('nb_operations', $journal->countForMember($membre->id));
}

$tpl->assign('membre', $membre);

$tpl->display('admin/membres/fiche.tpl');







<
<
<
<
<
<
<
<
<











20
21
22
23
24
25
26









27
28
29
30
31
32
33
34
35
36
37
$cats = new Membres\Categories;

$categorie = $cats->get($membre->id_categorie);
$tpl->assign('categorie', $categorie);

$cotisations = new Membres\Cotisations;










$tpl->assign('nb_activites', $cotisations->countForMember($membre->id));

if ($session->canAccess('compta', Membres::DROIT_ACCES))
{
	$journal = new Compta\Journal;
	$tpl->assign('nb_operations', $journal->countForMember($membre->id));
}

$tpl->assign('membre', $membre);

$tpl->display('admin/membres/fiche.tpl');

Modified src/www/admin/mes_cotisations.php from [8944c5b1e8] to [4a39980973].

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$cats = new Membres\Categories;

$categorie = $cats->get($user->id_categorie);
$tpl->assign('categorie', $categorie);

$cotisations = new Membres\Cotisations;

if (!empty($categorie->id_cotisation_obligatoire))
{
    $tpl->assign('cotisation', $cotisations->isMemberUpToDate($user->id, $categorie->id_cotisation_obligatoire));
}
else
{
    $tpl->assign('cotisation', false);
}

$tpl->assign('nb_activites', $cotisations->countForMember($user->id));
$tpl->assign('cotisations', $cotisations->listForMember($user->id));
$tpl->assign('cotisations_membre', $cotisations->listSubscriptionsForMember($user->id));

$tpl->display('admin/mes_cotisations.tpl');







<
<
<
<
<
<
<
<
<





8
9
10
11
12
13
14









15
16
17
18
19
$cats = new Membres\Categories;

$categorie = $cats->get($user->id_categorie);
$tpl->assign('categorie', $categorie);

$cotisations = new Membres\Cotisations;










$tpl->assign('nb_activites', $cotisations->countForMember($user->id));
$tpl->assign('cotisations', $cotisations->listForMember($user->id));
$tpl->assign('cotisations_membre', $cotisations->listSubscriptionsForMember($user->id));

$tpl->display('admin/mes_cotisations.tpl');

Modified src/www/admin/static/admin.css from [4d61ee3dc8] to [b23ca5b1ed].

694
695
696
697
698
699
700





701
702
703
704
705
706
707
...
734
735
736
737
738
739
740

741
742
743
744
745
746
747
....
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
    color: #fff;
    text-shadow: none;
}

table.list .actions {
    text-align: right;
}






b.money {
    font-weight: inherit;
    white-space: pre;
}

#rapport h3 {
................................................................................

#rapport td.money, #rapport th.money {
    text-align: right;
}

#rapport .compte th {
    font-weight: normal;

}

#rapport table table td {
    text-align: right;
}

#rapport .parent {
................................................................................
    margin: .2em 0 .2em 2em;
}

.catList dd.actions {
    margin: .2em 0 1em 2em;
}

ul.accountList {
    list-style-type: square;
    margin-left: 2em;
}

ul.accountList > li > h4 {
    font-weight: normal;
    font-size: 1.2em;
}

ul.accountList > li {
    margin-bottom: .8em;
}

table.accountList .niveau_2 .libelle {
    font-weight: bold;
}

table.accountList .niveau_3 .libelle { padding-left: 1em; }

table.accountList .niveau_4 .libelle { padding-left: 2em; }
table.accountList .niveau_5 .libelle { padding-left: 3em; }
table.accountList .niveau_6 .libelle { padding-left: 4em; }

table.rib { display: inline-table; vertical-align: middle; font-size: .9em; text-align: center; border-collapse: collapse; }
table.rib th, table.rib td { padding: .1em .3em; border: 1px solid #ccc; }


dl.describe {
    margin-bottom: 1em;
}

dl.describe > dt {
    font-weight: bold;







>
>
>
>
>







 







>







 







|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
>
|
|
|
<
<
<
>







694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
....
1024
1025
1026
1027
1028
1029
1030
1031





1032
1033











1034
1035
1036
1037



1038
1039
1040
1041
1042
1043
1044
1045
    color: #fff;
    text-shadow: none;
}

table.list .actions {
    text-align: right;
}

.money {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

b.money {
    font-weight: inherit;
    white-space: pre;
}

#rapport h3 {
................................................................................

#rapport td.money, #rapport th.money {
    text-align: right;
}

#rapport .compte th {
    font-weight: normal;
    padding-left: 1em;
}

#rapport table table td {
    text-align: right;
}

#rapport .parent {
................................................................................
    margin: .2em 0 .2em 2em;
}

.catList dd.actions {
    margin: .2em 0 1em 2em;
}

table.accounts tbody tr td:first-child { font-family: monospace; }





table.accounts th { font-weight: normal; }
table.accounts .account-level-1 th { font-size: 1.6em; }











table.accounts .account-level-2 > th { padding-left: 1em; font-size: 1.3em; }
table.accounts .account-level-3 > th { padding-left: 2em; }
table.accounts .account-level-4 > th { padding-left: 3em; }
table.accounts .account-level-5 > th { padding-left: 4em; }



table.accounts .account-level-6 > th { padding-left: 5em; }

dl.describe {
    margin-bottom: 1em;
}

dl.describe > dt {
    font-weight: bold;

Added src/www/admin/static/font/config.json version [8f50549389].





























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
{
  "name": "garradin",
  "css_prefix_text": "icn-",
  "css_use_suffix": false,
  "hinting": true,
  "units_per_em": 1000,
  "ascent": 850,
  "glyphs": [
    {
      "uid": "e45a3da2ebde8bc8e30a873f3bd51f30",
      "css": "eye",
      "code": 128065,
      "src": "elusive"
    },
    {
      "uid": "d218294e6f9f7191f6b0b3d1ff6239ff",
      "css": "eye-off",
      "code": 10539,
      "src": "elusive"
    },
    {
      "uid": "484363b699ea1b5c2f827fc0f62f4dca",
      "css": "search",
      "code": 128269,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M643 464Q643 361 569 288T393 214 216 288 143 464 216 641 393 714 569 641 643 464ZM929 929Q929 958 907 979T857 1000Q827 1000 807 979L616 788Q516 857 393 857 313 857 240 826T115 742 31 617 0 464 31 312 115 186 240 102 393 71 545 102 671 186 755 312 786 464Q786 587 717 687L908 878Q929 899 929 929Z",
        "width": 928.6
      },
      "search": [
        "search"
      ]
    },
    {
      "uid": "d9d608c26fff5d1d75dc959f185f034d",
      "css": "check",
      "code": 9745,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M786 519V696Q786 763 739 810T625 857H161Q94 857 47 810T0 696V232Q0 166 47 119T161 71H625Q660 71 690 85 699 89 700 98 702 108 695 114L668 142Q662 147 655 147 653 147 650 146 637 143 625 143H161Q124 143 98 169T71 232V696Q71 733 98 759T161 786H625Q662 786 688 759T714 696V555Q714 547 719 542L755 507Q761 501 768 501 771 501 775 503 786 507 786 519ZM915 246L460 700Q447 714 429 714T397 700L157 460Q143 447 143 429T157 397L218 335Q232 322 250 322T282 335L429 482 790 121Q803 108 821 108T853 121L915 182Q928 196 928 214T915 246Z",
        "width": 928.6
      },
      "search": [
        "check"
      ]
    },
    {
      "uid": "67dabb31f430a26bd27c25db8daa105b",
      "css": "user",
      "code": 128100,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M786 784Q786 851 745 890T637 929H149Q82 929 41 890T0 784Q0 754 2 726T10 665 25 605 49 550 83 505 131 475 193 464Q198 464 217 476T258 503 318 530 393 542 467 530 528 503 569 476 593 464Q627 464 655 475T703 505 737 550 761 605 776 665 784 726 786 784ZM607 286Q607 374 544 437T393 500 241 437 179 286 241 134 393 71 544 134 607 286Z",
        "width": 785.7
      },
      "search": [
        "user"
      ]
    },
    {
      "uid": "9f9457b7ef8733c515e852b738277774",
      "css": "users",
      "code": 128106,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M331 500Q241 503 183 571H108Q63 571 31 549T0 483Q0 286 69 286 73 286 94 297T148 321 214 333Q252 333 289 320 286 341 286 357 286 435 331 500ZM929 856Q929 922 888 961T780 1000H292Q224 1000 184 961T143 856Q143 826 145 798T153 737 167 676 191 622 226 577 274 547 336 536Q342 536 360 548T401 574 460 601 536 613 611 601 671 574 712 548 735 536Q770 536 798 547T845 577 880 622 904 676 919 737 927 798 929 856ZM357 143Q357 202 315 244T214 286 113 244 71 143 113 42 214 0 315 42 357 143ZM750 357Q750 446 687 509T536 571 384 509 321 357 384 206 536 143 687 206 750 357ZM1071 483Q1071 526 1040 549T963 571H888Q831 503 741 500 786 435 786 357 786 341 783 320 820 333 857 333 890 333 924 321T978 297 1002 286Q1071 286 1071 483ZM1000 143Q1000 202 958 244T857 286 756 244 714 143 756 42 857 0 958 42 1000 143Z",
        "width": 1071.4
      },
      "search": [
        "users"
      ]
    },
    {
      "uid": "13e9b9898958bd06a926490ec4c78b18",
      "css": "delete",
      "code": 10008,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M724 738Q724 760 709 776L633 852Q617 867 595 867T557 852L393 687 229 852Q213 867 191 867T153 852L77 776Q61 760 61 738T77 700L241 536 77 372Q61 356 61 334T77 296L153 220Q169 204 191 204T229 220L393 384 557 220Q573 204 595 204T633 220L709 296Q724 311 724 334T709 372L545 536 709 700Q724 715 724 738Z",
        "width": 785.7
      },
      "search": [
        "delete"
      ]
    },
    {
      "uid": "9856e9f63a26ab792b90c46148459ad7",
      "css": "plus",
      "code": 10133,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M786 411V518Q786 540 770 556T732 571H500V804Q500 826 484 841T446 857H339Q317 857 301 841T286 804V571H54Q31 571 16 556T0 518V411Q0 388 16 373T54 357H286V125Q286 103 301 87T339 71H446Q469 71 484 87T500 125V357H732Q754 357 770 373T786 411Z",
        "width": 785.7
      },
      "search": [
        "plus"
      ]
    },
    {
      "uid": "564500b6ab771051a66101066706e552",
      "css": "minus",
      "code": 10134,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M786 411V518Q786 540 770 556T732 571H54Q31 571 16 556T0 518V411Q0 388 16 373T54 357H732Q754 357 770 373T786 411Z",
        "width": 785.7
      },
      "search": [
        "minus"
      ]
    },
    {
      "uid": "ef59059d1776e2b5df2cdb61ad02a5c2",
      "css": "help",
      "code": 10067,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M393 701V835Q393 844 386 851T371 857H237Q228 857 221 851T214 835V701Q214 692 221 685T237 679H371Q379 679 386 685T393 701ZM569 366Q569 396 561 422T541 465 510 498 478 523 444 542Q421 555 406 579T391 616Q391 626 384 634T368 643H234Q226 643 220 633T214 612V586Q214 540 251 499T330 439Q363 424 377 407T391 365Q391 342 365 324T305 306Q269 306 245 322 225 336 185 386 178 395 168 395 161 395 154 391L63 321Q55 315 54 307T57 291Q146 143 316 143 361 143 406 160T487 206 546 278 569 366Z",
        "width": 571.4
      },
      "search": [
        "help"
      ]
    },
    {
      "uid": "e03a3396ad9ce1b09a85c28955799d92",
      "css": "home",
      "code": 8962,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M786 554V821Q786 836 775 847T750 857H536V643H393V857H179Q164 857 154 847T143 821V554Q143 553 143 552T143 550L464 286 785 550Q786 551 786 554ZM910 515L876 556Q871 561 864 562H862Q855 562 850 559L464 237 78 559Q71 563 65 563 58 561 53 556L18 515Q14 510 15 502T21 490L422 156Q440 141 464 141T507 156L643 270V161Q643 153 648 148T661 143H768Q776 143 781 148T786 161V388L908 490Q913 495 914 502T910 515Z",
        "width": 928.6
      },
      "search": [
        "home"
      ]
    },
    {
      "uid": "496e662a65eb5759e19b1c5d2e58a060",
      "css": "attach",
      "code": 128206,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M783 773Q783 838 739 882T630 926Q555 926 499 871L65 437Q2 373 2 286 2 198 64 136T214 74Q302 74 366 137L704 475Q709 480 709 487 709 496 692 513T666 530Q659 530 653 525L315 186Q271 143 214 143 155 143 114 185T74 286Q74 344 116 387L549 820Q584 855 630 855 666 855 689 832T713 773Q713 727 677 692L353 368Q339 354 320 354 304 354 293 365T282 392Q282 410 296 425L525 653Q531 659 531 666 531 675 513 692T487 709Q480 709 475 704L246 475Q211 441 211 392 211 346 243 314T320 282Q369 282 403 318L728 642Q783 696 783 773Z",
        "width": 785.7
      },
      "search": [
        "attach"
      ]
    },
    {
      "uid": "e5c7ed71e800e995ddfc3a195924913b",
      "css": "lock",
      "code": 128274,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M179 429H464V321Q464 262 422 220T321 179 220 220 179 321V429ZM643 482V804Q643 826 627 841T589 857H54Q31 857 16 841T0 804V482Q0 460 16 444T54 429H71V321Q71 219 145 145T321 71 498 145 571 321V429H589Q612 429 627 444T643 482Z",
        "width": 642.9
      },
      "search": [
        "lock"
      ]
    },
    {
      "uid": "f2a84f66f2d360b9c559376a275261ae",
      "css": "mail",
      "code": 9993,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M1000 396V839Q1000 876 974 902T911 929H89Q53 929 26 902T0 839V396Q25 424 56 445 258 582 334 637 366 661 385 674T438 701 499 714H501Q529 714 562 701T615 674 666 637Q761 569 944 445 976 423 1000 396ZM1000 232Q1000 276 973 316T905 385Q695 531 643 566 638 570 620 583T590 605 561 623 528 638 501 643H499Q487 643 472 638T439 623 410 605 380 583 357 566Q306 531 210 465T96 385Q61 362 31 321T0 244Q0 201 23 172T89 143H911Q947 143 973 169T1000 232Z",
        "width": 1000
      },
      "search": [
        "mail"
      ]
    },
    {
      "uid": "49aab36ecf027cc8608f81597c83d2d4",
      "css": "download",
      "code": 8659,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M714 750Q714 735 704 725T679 714 653 725 643 750 653 775 679 786 704 775 714 750ZM857 750Q857 735 847 725T821 714 796 725 786 750 796 775 821 786 847 775 857 750ZM929 625V804Q929 826 913 841T875 857H54Q31 857 16 841T0 804V625Q0 603 16 587T54 571H313L388 647Q421 679 464 679T540 647L616 571H875Q897 571 913 587T929 625ZM747 307Q757 330 739 347L489 597Q479 607 464 607T439 597L189 347Q172 330 181 307 191 286 214 286H357V36Q357 21 368 11T393 0H536Q550 0 561 11T571 36V286H714Q738 286 747 307Z",
        "width": 928.6
      },
      "search": [
        "download"
      ]
    },
    {
      "uid": "1ab77fb1c37bad79af7268c79a11b14f",
      "css": "edit",
      "code": 9998,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M203 857L253 806 122 675 71 726V786H143V857H203ZM494 339Q494 327 482 327 477 327 473 331L170 633Q166 637 166 643 166 655 179 655 184 655 188 651L491 349Q494 345 494 339ZM464 232L696 464 232 929H0V696ZM845 286Q845 315 825 336L732 429 500 196 593 104Q613 83 643 83 672 83 694 104L825 235Q845 257 845 286Z",
        "width": 857.1
      },
      "search": [
        "edit"
      ]
    },
    {
      "uid": "bf3c88e1a2208a0cf26001e0793ff403",
      "css": "print",
      "code": 9113,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M214 857H714V714H214V857ZM214 500H714V286H625Q603 286 587 270T571 232V143H214V500ZM857 536Q857 521 847 511T821 500 796 511 786 536 796 561 821 571 847 561 857 536ZM929 536V768Q929 775 923 780T911 786H786V875Q786 897 770 913T732 929H196Q174 929 159 913T143 875V786H18Q11 786 5 780T0 768V536Q0 492 32 460T107 429H143V125Q143 103 159 87T196 71H571Q594 71 621 83T663 109L748 194Q763 210 775 237T786 286V429H821Q866 429 897 460T929 536Z",
        "width": 928.6
      },
      "search": [
        "print"
      ]
    },
    {
      "uid": "4d879892b0e3a0da5d871e3df8d105e2",
      "css": "alert",
      "code": 9888,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M571 767V661Q571 653 566 648T554 643H446Q439 643 434 648T429 661V767Q429 775 434 780T446 786H554Q561 786 566 780T571 767ZM570 559L580 302Q580 296 575 292 568 286 561 286H439Q432 286 425 292 420 296 420 304L429 559Q429 564 435 568T448 571H551Q559 571 564 568T570 559ZM563 37L991 823Q1011 858 990 893 980 910 964 919T929 929H71Q53 929 36 919T10 893Q-11 858 9 823L438 37Q447 20 464 10T500 0 536 10 563 37Z",
        "width": 1000
      },
      "search": [
        "alert"
      ]
    },
    {
      "uid": "7091435c31f7a593060b9782a234db80",
      "css": "menu",
      "code": 119650,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M857 750V821Q857 836 847 846T821 857H36Q21 857 11 846T0 821V750Q0 735 11 725T36 714H821Q836 714 847 725T857 750ZM857 464V536Q857 550 847 561T821 571H36Q21 571 11 561T0 536V464Q0 450 11 439T36 429H821Q836 429 847 439T857 464ZM857 179V250Q857 265 847 275T821 286H36Q21 286 11 275T0 250V179Q0 164 11 153T36 143H821Q836 143 847 153T857 179Z",
        "width": 857.1
      },
      "search": [
        "menu"
      ]
    },
    {
      "uid": "08d8ae2e00462d737ce43e77738eee17",
      "css": "settings",
      "code": 9784,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M571 500Q571 441 530 399T429 357 328 399 286 500 328 601 429 643 530 601 571 500ZM857 439V563Q857 570 853 576T842 583L738 599Q728 629 717 650 736 677 776 727 782 733 782 740T777 753Q762 774 722 814T669 853Q662 853 655 848L578 788Q553 801 527 809 518 885 511 913 507 929 491 929H367Q359 929 353 924T347 912L331 809Q304 800 281 788L202 848Q196 853 188 853 180 853 174 847 104 783 82 753 78 748 78 740 78 734 83 728 91 716 111 691T141 651Q126 623 118 596L16 581Q9 580 5 574T0 561V437Q0 430 5 424T15 417L119 401Q127 376 141 350 118 318 81 273 75 266 75 259 75 254 80 247 95 227 135 187T188 147Q195 147 203 152L280 212Q304 199 330 191 339 115 347 87 350 72 367 72H491Q498 72 504 76T511 88L526 191Q554 200 576 212L656 152Q661 147 669 147 676 147 683 152 755 219 775 247 779 252 779 260 779 266 775 272 766 284 746 310T716 349Q730 377 739 404L841 419Q848 420 853 426T857 439Z",
        "width": 857.1
      },
      "search": [
        "settings"
      ]
    },
    {
      "uid": "b2af04a5076126cde5606aed07cfd647",
      "css": "down",
      "code": 8595,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M571 393Q571 407 561 418L311 668Q300 679 286 679T261 668L11 418Q0 407 0 393T11 368 36 357H536Q550 357 561 368T571 393Z",
        "width": 571.4
      },
      "search": [
        "down"
      ]
    },
    {
      "uid": "9a8f85e9fc8643b2587509f0e4b6cd1e",
      "css": "up",
      "code": 8593,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M571 679Q571 693 561 704T536 714H36Q21 714 11 704T0 679 11 653L261 403Q271 393 286 393T311 403L561 653Q571 664 571 679Z",
        "width": 571.4
      },
      "search": [
        "up"
      ]
    },
    {
      "uid": "fe71ca02f0de1b3624d28043ddb30c85",
      "css": "unlock",
      "code": 128275,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M929 321V464Q929 479 918 489T893 500H857Q843 500 832 489T821 464V321Q821 262 780 220T679 179 578 220 536 321V429H589Q612 429 627 444T643 482V804Q643 826 627 841T589 857H54Q31 857 16 841T0 804V482Q0 460 16 444T54 429H429V321Q429 218 502 145T679 71 855 145 929 321Z",
        "width": 928.6
      },
      "search": [
        "unlock"
      ]
    },
    {
      "uid": "56000699168af06774cd3f1646acbd5f",
      "css": "logout",
      "code": 10525,
      "src": "custom_icons",
      "selected": true,
      "svg": {
        "path": "M857 500Q857 587 823 666T732 803 595 895 429 929 262 895 126 803 34 666 0 500Q0 398 45 309T171 158Q195 140 225 144T271 172Q289 195 285 225T257 272Q203 313 173 373T143 500Q143 558 165 611T227 702 318 763 429 786 539 763 631 702 692 611 714 500Q714 432 684 373T600 272Q576 254 572 225T586 172Q603 148 633 144T686 158Q767 219 812 309T857 500ZM500 71V429Q500 458 479 479T429 500 378 479 357 429V71Q357 42 378 21T429 0 479 21 500 71Z",
        "width": 857.1
      },
      "search": [
        "logout"
      ]
    },
    {
      "uid": "474656633f79ea2f1dad59ff63f6bf07",
      "css": "star",
      "code": 9733,
      "src": "fontawesome"
    },
    {
      "uid": "f8aa663c489bcbd6e68ec8147dca841e",
      "css": "folder",
      "code": 128448,
      "src": "fontawesome"
    },
    {
      "uid": "178053298e3e5b03551d754d4b9acd8b",
      "css": "document",
      "code": 128453,
      "src": "fontawesome"
    },
    {
      "uid": "f9c3205df26e7778abac86183aefdc99",
      "css": "reset",
      "code": 8634,
      "src": "fontawesome"
    },
    {
      "uid": "eeec3208c90b7b48e804919d0d2d4a41",
      "css": "upload",
      "code": 8657,
      "src": "fontawesome"
    },
    {
      "uid": "390d6d13398cbf8c8c3c5493f7d34088",
      "css": "export",
      "code": 8631,
      "src": "entypo"
    }
  ]
}

Modified src/www/admin/static/font/garradin.css from [d980f71e5b] to [41839c4828].

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
..
55
56
57
58
59
60
61



62
63
64

65
66
67
68
69
70
71
..
77
78
79
80
81
82
83


@charset "UTF-8";

 @font-face {
  font-family: 'garradin';
  src: url('../font/garradin.eot?31180986');
  src: url('../font/garradin.eot?31180986#iefix') format('embedded-opentype'),
       url('../font/garradin.woff2?31180986') format('woff2'),
       url('../font/garradin.woff?31180986') format('woff'),
       url('../font/garradin.ttf?31180986') format('truetype'),
       url('../font/garradin.svg?31180986#garradin') format('svg');
  font-weight: normal;
  font-style: normal;
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
/*
@media screen and (-webkit-min-device-pixel-ratio:0) {
  @font-face {
    font-family: 'garradin';
    src: url('../font/garradin.svg?31180986#garradin') format('svg');
  }
}
*/
 
 [class^="icn-"]:before, [class*=" icn-"]:before {
  font-family: "garradin";
  font-style: normal;
................................................................................
 
  /* Uncomment for 3D effect */
  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
 
.icn-up:before { content: '\2191'; } /* '↑' */
.icn-down:before { content: '\2193'; } /* '↓' */



.icn-download:before { content: '\21d3'; } /* '⇓' */
.icn-home:before { content: '\2302'; } /* '⌂' */
.icn-print:before { content: '\2399'; } /* '⎙' */

.icn-check:before { content: '\2611'; } /* '☑' */
.icn-settings:before { content: '\2638'; } /* '☸' */
.icn-alert:before { content: '\26a0'; } /* '⚠' */
.icn-mail:before { content: '\2709'; } /* '✉' */
.icn-edit:before { content: '\270e'; } /* '✎' */
.icn-delete:before { content: '\2718'; } /* '✘' */
.icn-help:before { content: '\2753'; } /* '❓' */
................................................................................
.icn-eye:before { content: '👁'; } /* '\1f441' */
.icn-user:before { content: '👤'; } /* '\1f464' */
.icn-users:before { content: '👪'; } /* '\1f46a' */
.icn-attach:before { content: '📎'; } /* '\1f4ce' */
.icn-search:before { content: '🔍'; } /* '\1f50d' */
.icn-lock:before { content: '🔒'; } /* '\1f512' */
.icn-unlock:before { content: '🔓'; } /* '\1f513' */






|
|
|
|
|
|









|







 







>
>
>



>







 







>
>
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
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
..
81
82
83
84
85
86
87
88
89
@charset "UTF-8";

 @font-face {
  font-family: 'garradin';
  src: url('../font/garradin.eot?13522204');
  src: url('../font/garradin.eot?13522204#iefix') format('embedded-opentype'),
       url('../font/garradin.woff2?13522204') format('woff2'),
       url('../font/garradin.woff?13522204') format('woff'),
       url('../font/garradin.ttf?13522204') format('truetype'),
       url('../font/garradin.svg?13522204#garradin') format('svg');
  font-weight: normal;
  font-style: normal;
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
/*
@media screen and (-webkit-min-device-pixel-ratio:0) {
  @font-face {
    font-family: 'garradin';
    src: url('../font/garradin.svg?13522204#garradin') format('svg');
  }
}
*/
 
 [class^="icn-"]:before, [class*=" icn-"]:before {
  font-family: "garradin";
  font-style: normal;
................................................................................
 
  /* Uncomment for 3D effect */
  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
 
.icn-up:before { content: '\2191'; } /* '↑' */
.icn-down:before { content: '\2193'; } /* '↓' */
.icn-export:before { content: '\21b7'; } /* '↷' */
.icn-reset:before { content: '\21ba'; } /* '↺' */
.icn-upload:before { content: '\21d1'; } /* '⇑' */
.icn-download:before { content: '\21d3'; } /* '⇓' */
.icn-home:before { content: '\2302'; } /* '⌂' */
.icn-print:before { content: '\2399'; } /* '⎙' */
.icn-star:before { content: '\2605'; } /* '★' */
.icn-check:before { content: '\2611'; } /* '☑' */
.icn-settings:before { content: '\2638'; } /* '☸' */
.icn-alert:before { content: '\26a0'; } /* '⚠' */
.icn-mail:before { content: '\2709'; } /* '✉' */
.icn-edit:before { content: '\270e'; } /* '✎' */
.icn-delete:before { content: '\2718'; } /* '✘' */
.icn-help:before { content: '\2753'; } /* '❓' */
................................................................................
.icn-eye:before { content: '👁'; } /* '\1f441' */
.icn-user:before { content: '👤'; } /* '\1f464' */
.icn-users:before { content: '👪'; } /* '\1f46a' */
.icn-attach:before { content: '📎'; } /* '\1f4ce' */
.icn-search:before { content: '🔍'; } /* '\1f50d' */
.icn-lock:before { content: '🔒'; } /* '\1f512' */
.icn-unlock:before { content: '🔓'; } /* '\1f513' */
.icn-folder:before { content: '🗀'; } /* '\1f5c0' */
.icn-document:before { content: '🗅'; } /* '\1f5c5' */

Modified src/www/admin/static/font/garradin.eot from [4de801b16e] to [185dac1be8].

cannot compute difference between binary files

Modified src/www/admin/static/font/garradin.svg from [5bcfb6f494] to [78870af904].

1
2
3
4
5
6
7
8
9
10
11
12






13
14
15
16
17


18
19
20
21
22
23
24
..
49
50
51
52
53
54
55




56
57
58
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2018 by original authors @ fontello.com</metadata>
<defs>
<font id="garradin" horiz-adv-x="1000" >
<font-face font-family="garradin" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="up" unicode="&#x2191;" d="M571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" />

<glyph glyph-name="down" unicode="&#x2193;" d="M571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />







<glyph glyph-name="download" unicode="&#x21d3;" d="M714 100q0 15-10 25t-25 11-26-11-10-25 10-25 26-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />

<glyph glyph-name="home" unicode="&#x2302;" d="M786 296v-267q0-15-11-26t-25-10h-214v214h-143v-214h-214q-15 0-25 10t-11 26v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-4-7 2-12 7l-35 41q-4 5-3 13t6 12l401 334q18 15 42 15t43-15l136-114v109q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q5-5 6-12t-4-13z" horiz-adv-x="928.6" />

<glyph glyph-name="print" unicode="&#x2399;" d="M214-7h500v143h-500v-143z m0 357h500v214h-89q-22 0-38 16t-16 38v89h-357v-357z m643-36q0 15-10 25t-26 11-25-11-10-25 10-25 25-10 26 10 10 25z m72 0v-232q0-7-6-12t-12-6h-125v-89q0-22-16-38t-38-16h-536q-22 0-37 16t-16 38v89h-125q-7 0-13 6t-5 12v232q0 44 32 76t75 31h36v304q0 22 16 38t37 16h375q23 0 50-12t42-26l85-85q15-16 27-43t11-49v-143h35q45 0 76-31t32-76z" horiz-adv-x="928.6" />



<glyph glyph-name="check" unicode="&#x2611;" d="M786 331v-177q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-6-5-13-5-2 0-5 1-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v141q0 8 5 13l36 35q6 6 13 6 3 0 7-2 11-4 11-16z m129 273l-455-454q-13-14-31-14t-32 14l-240 240q-14 13-14 31t14 32l61 62q14 13 32 13t32-13l147-147 361 361q13 13 31 13t32-13l62-61q13-14 13-32t-13-32z" horiz-adv-x="928.6" />

<glyph glyph-name="settings" unicode="&#x2638;" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 15 20 15h124q7 0 13-4t7-12l15-103q28-9 50-21l80 60q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-13 0-6-4-12-9-12-29-38t-30-39q14-28 23-55l102-15q7-1 12-7t4-13z" horiz-adv-x="857.1" />

<glyph glyph-name="alert" unicode="&#x26a0;" d="M571 83v106q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-106q0-8 5-13t12-6h108q7 0 12 6t5 13z m-1 208l10 257q0 6-5 10-7 6-14 6h-122q-7 0-14-6-5-4-5-12l9-255q0-5 6-9t13-3h103q8 0 13 3t6 9z m-7 522l428-786q20-35-1-70-10-17-26-26t-35-10h-858q-18 0-35 10t-26 26q-21 35-1 70l429 786q9 17 26 27t36 10 36-10 27-27z" horiz-adv-x="1000" />

................................................................................
<glyph glyph-name="attach" unicode="&#x1f4ce;" d="M783 77q0-65-44-109t-109-44q-75 0-131 55l-434 434q-63 64-63 151 0 88 62 150t150 62q88 0 152-63l338-338q5-5 5-12 0-9-17-26t-26-17q-7 0-13 5l-338 339q-44 43-101 43-59 0-100-42t-40-101q0-58 42-101l433-433q35-35 81-35 36 0 59 23t24 59q0 46-36 81l-324 324q-14 14-33 14-16 0-27-11t-11-27q0-18 14-33l229-228q6-6 6-13 0-9-18-26t-26-17q-7 0-12 5l-229 229q-35 34-35 83 0 46 32 78t77 32q49 0 83-36l325-324q55-54 55-131z" horiz-adv-x="785.7" />

<glyph glyph-name="search" unicode="&#x1f50d;" d="M643 386q0 103-74 176t-176 74-177-74-73-176 73-177 177-73 176 73 74 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 152-31 126-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />

<glyph glyph-name="lock" unicode="&#x1f512;" d="M179 421h285v108q0 59-42 101t-101 41-101-41-41-101v-108z m464-53v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v108q0 102 74 176t176 74 177-74 73-176v-108h18q23 0 38-15t16-38z" horiz-adv-x="642.9" />

<glyph glyph-name="unlock" unicode="&#x1f513;" d="M929 529v-143q0-15-11-25t-25-11h-36q-14 0-25 11t-11 25v143q0 59-41 101t-101 41-101-41-42-101v-108h53q23 0 38-15t16-38v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h375v108q0 103 73 176t177 74 176-74 74-176z" horiz-adv-x="928.6" />




</font>
</defs>
</svg>



|








>
>
>
>
>
>





>
>







 







>
>
>
>



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
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2020 by original authors @ fontello.com</metadata>
<defs>
<font id="garradin" horiz-adv-x="1000" >
<font-face font-family="garradin" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="up" unicode="&#x2191;" d="M571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" />

<glyph glyph-name="down" unicode="&#x2193;" d="M571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />

<glyph glyph-name="export" unicode="&#x21b7;" d="M750 60l0 56 100 82 0-188q0-20-15-35t-35-15l-750 0q-20 0-35 15t-15 35l0 550q0 22 14 36t36 14l288 0q-32-24-59-49t-39-39l-10-12-130 0 0-450 650 0z m-82 348q-166 0-242-41t-160-181q0 8 1 22t9 56 22 79 44 83 70 79 107 56 149 23l0 156 332-250-332-260 0 178z" horiz-adv-x="1000" />

<glyph glyph-name="reset" unicode="&#x21ba;" d="M857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z" horiz-adv-x="857.1" />

<glyph glyph-name="upload" unicode="&#x21d1;" d="M714 29q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m143 0q0 14-10 25t-26 10-25-10-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-38t-38-16h-821q-23 0-38 16t-16 38v179q0 22 16 38t38 15h238q12-31 39-51t62-20h143q34 0 61 20t40 51h238q22 0 38-15t16-38z m-182 361q-9-22-33-22h-143v-250q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v250h-143q-23 0-33 22-9 22 8 39l250 250q10 10 25 10t25-10l250-250q18-17 8-39z" horiz-adv-x="928.6" />

<glyph glyph-name="download" unicode="&#x21d3;" d="M714 100q0 15-10 25t-25 11-26-11-10-25 10-25 26-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />

<glyph glyph-name="home" unicode="&#x2302;" d="M786 296v-267q0-15-11-26t-25-10h-214v214h-143v-214h-214q-15 0-25 10t-11 26v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-4-7 2-12 7l-35 41q-4 5-3 13t6 12l401 334q18 15 42 15t43-15l136-114v109q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q5-5 6-12t-4-13z" horiz-adv-x="928.6" />

<glyph glyph-name="print" unicode="&#x2399;" d="M214-7h500v143h-500v-143z m0 357h500v214h-89q-22 0-38 16t-16 38v89h-357v-357z m643-36q0 15-10 25t-26 11-25-11-10-25 10-25 25-10 26 10 10 25z m72 0v-232q0-7-6-12t-12-6h-125v-89q0-22-16-38t-38-16h-536q-22 0-37 16t-16 38v89h-125q-7 0-13 6t-5 12v232q0 44 32 76t75 31h36v304q0 22 16 38t37 16h375q23 0 50-12t42-26l85-85q15-16 27-43t11-49v-143h35q45 0 76-31t32-76z" horiz-adv-x="928.6" />

<glyph glyph-name="star" unicode="&#x2605;" d="M929 489q0-12-15-27l-202-197 48-279q0-4 0-12 0-11-6-19t-17-9q-10 0-22 7l-251 132-250-132q-12-7-23-7-11 0-17 9t-6 19q0 4 1 12l48 279-203 197q-14 15-14 27 0 21 31 26l280 40 126 254q11 23 27 23t28-23l125-254 280-40q32-5 32-26z" horiz-adv-x="928.6" />

<glyph glyph-name="check" unicode="&#x2611;" d="M786 331v-177q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-6-5-13-5-2 0-5 1-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v141q0 8 5 13l36 35q6 6 13 6 3 0 7-2 11-4 11-16z m129 273l-455-454q-13-14-31-14t-32 14l-240 240q-14 13-14 31t14 32l61 62q14 13 32 13t32-13l147-147 361 361q13 13 31 13t32-13l62-61q13-14 13-32t-13-32z" horiz-adv-x="928.6" />

<glyph glyph-name="settings" unicode="&#x2638;" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 15 20 15h124q7 0 13-4t7-12l15-103q28-9 50-21l80 60q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-13 0-6-4-12-9-12-29-38t-30-39q14-28 23-55l102-15q7-1 12-7t4-13z" horiz-adv-x="857.1" />

<glyph glyph-name="alert" unicode="&#x26a0;" d="M571 83v106q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-106q0-8 5-13t12-6h108q7 0 12 6t5 13z m-1 208l10 257q0 6-5 10-7 6-14 6h-122q-7 0-14-6-5-4-5-12l9-255q0-5 6-9t13-3h103q8 0 13 3t6 9z m-7 522l428-786q20-35-1-70-10-17-26-26t-35-10h-858q-18 0-35 10t-26 26q-21 35-1 70l429 786q9 17 26 27t36 10 36-10 27-27z" horiz-adv-x="1000" />

................................................................................
<glyph glyph-name="attach" unicode="&#x1f4ce;" d="M783 77q0-65-44-109t-109-44q-75 0-131 55l-434 434q-63 64-63 151 0 88 62 150t150 62q88 0 152-63l338-338q5-5 5-12 0-9-17-26t-26-17q-7 0-13 5l-338 339q-44 43-101 43-59 0-100-42t-40-101q0-58 42-101l433-433q35-35 81-35 36 0 59 23t24 59q0 46-36 81l-324 324q-14 14-33 14-16 0-27-11t-11-27q0-18 14-33l229-228q6-6 6-13 0-9-18-26t-26-17q-7 0-12 5l-229 229q-35 34-35 83 0 46 32 78t77 32q49 0 83-36l325-324q55-54 55-131z" horiz-adv-x="785.7" />

<glyph glyph-name="search" unicode="&#x1f50d;" d="M643 386q0 103-74 176t-176 74-177-74-73-176 73-177 177-73 176 73 74 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 152-31 126-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />

<glyph glyph-name="lock" unicode="&#x1f512;" d="M179 421h285v108q0 59-42 101t-101 41-101-41-41-101v-108z m464-53v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v108q0 102 74 176t176 74 177-74 73-176v-108h18q23 0 38-15t16-38z" horiz-adv-x="642.9" />

<glyph glyph-name="unlock" unicode="&#x1f513;" d="M929 529v-143q0-15-11-25t-25-11h-36q-14 0-25 11t-11 25v143q0 59-41 101t-101 41-101-41-42-101v-108h53q23 0 38-15t16-38v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h375v108q0 103 73 176t177 74 176-74 74-176z" horiz-adv-x="928.6" />

<glyph glyph-name="folder" unicode="&#x1f5c0;" d="M929 511v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />

<glyph glyph-name="document" unicode="&#x1f5c5;" d="M571 564v264q13-8 21-16l227-228q8-7 16-20h-264z m-71-18q0-22 16-37t38-16h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304z" horiz-adv-x="857.1" />
</font>
</defs>
</svg>

Modified src/www/admin/static/font/garradin.ttf from [2aa8a2bf32] to [6d17abf145].

cannot compute difference between binary files

Modified src/www/admin/static/font/garradin.woff from [ccddd0b63a] to [4cf4cf0939].

cannot compute difference between binary files

Modified src/www/admin/static/gdin_bg.png from [99cd57a4b4] to [d9ebe3bac2].

cannot compute difference between binary files

Modified src/www/admin/static/print.css from [e73e01504c] to [3d3e25b3f9].

1
2
3
4
5
6
7
8


9

10
11
12

13
14
15

16
17
18
19
20
21
22
..
39
40
41
42
43
44
45








46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@page {
    size: A4;
    margin: 1cm;
}

body {
    background: #fff;
    padding: 0;


}

header.header {
    display: none;
}

main {
    margin: 0;
}

.header h1 {
    margin: 0;
    text-align: center;
}

table.list thead {
    background: #000;
................................................................................
table.list.multi tr:nth-child(even) {
    background: inherit;
}

table.list.multi tr:nth-child(4n+1), table.list.multi tr:nth-child(4n+2) {
    background: #ddd;
}









#rapport table table {
    border: 1px solid #666;
}

#rapport .parent {
    background: #ccc;
}

.noprint {
    display: none;
}

td.actions * {
    display: none;
}

|
|





>
>

>



>



>







 







>
>
>
>
>
>
>
>












<



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
..
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
@page {
    size: A4 landscape;
    margin: 0;
}

body {
    background: #fff;
    padding: 0;
    margin: 1cm;
    font-size: 10pt;
}

header.header {
    display: none;
}

main {
    margin: 0;
}

.header h1 {
    margin: 0;
    text-align: center;
}

table.list thead {
    background: #000;
................................................................................
table.list.multi tr:nth-child(even) {
    background: inherit;
}

table.list.multi tr:nth-child(4n+1), table.list.multi tr:nth-child(4n+2) {
    background: #ddd;
}

#rapport tr {
    color: #000 !important;
}

#rapport table .parent {
    border-top: 1px dashed #666;
}

#rapport table table {
    border: 1px solid #666;
}

#rapport .parent {
    background: #ccc;
}

.noprint {
    display: none;
}

td.actions * {
    display: none;
}

Modified src/www/admin/upgrade.php from [accfe43dfe] to [6934806420].

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
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
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
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
...
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
...
312
313
314
315
316
317
318










319
320
321
322
323
324
325
</script>';

flush();

try {
    if (version_compare($v, '0.7.0', '<'))
    {
        $db->toggleForeignKeys(false);
        $db->begin();

        // Mise à jour base de données
        $db->exec(file_get_contents(ROOT . '/include/data/0.7.0.sql'));

        // Changement de syntaxe du Wiki vers SkrivML
        $wiki = new Wiki;
        $res = $db->get('SELECT id_page, contenu, revision, chiffrement FROM wiki_revisions GROUP BY id_page ORDER BY revision DESC;');

        foreach ($res as $row)
        {
................................................................................
                    'id_auteur'     =>  null,
                    'contenu'       =>  $content,
                    'modification'  =>  'Mise à jour 0.7.0 (transformation SPIP vers SkrivML)',
                ]);
            }
        }

        $db->commit();
    }

    if (version_compare($v, '0.7.2', '<'))
    {
        $db->toggleForeignKeys(false);
        $db->begin();

        // Mise à jour base de données
        $db->exec(file_get_contents(ROOT . '/include/data/0.7.2.sql'));

        $db->commit();
    }

    if (version_compare($v, '0.8.0-beta4', '<'))
    {
        // Inscription de l'appid
        $db->exec('PRAGMA application_id = ' . DB::APPID . ';');

................................................................................
        // Cecit devrait améliorer les performances de la DB
        $db->exec('PRAGMA page_size = 4096;');

        // Application du changement de taille de page
        $db->exec('VACUUM;');

        // Désactivation des foreign keys AVANT le début de la transaction
        $db->toggleForeignKeys(false);

        $db->begin();

        $db->import(ROOT . '/include/data/0.8.0.sql');

        $db->commit();

        $config = Config::getInstance();

        // Ajout champ numéro de membre
        $champs = (array) $config->get('champs_membres')->getAll();
        $presets = Membres\Champs::importPresets();

................................................................................
        // Mise à jour plan comptable: ajout comptes encaissement
        $comptes = new Compta\Comptes;
        $comptes->importPlan();
    }

    if (version_compare($v, '0.8.3', '<'))
    {
        // Désactivation des foreign keys AVANT le début de la transaction
        $db->toggleForeignKeys(false);

        $db->begin();

        $db->import(ROOT . '/include/data/0.8.3.sql');

        $db->commit();
    }

    if (version_compare($v, '0.8.4', '<'))
    {
        $db->begin();

        $db->import(ROOT . '/include/data/0.8.4.sql');

        $db->commit();
    }

    if (version_compare($v, '0.9.0-rc1', '<'))
    {
        $db->toggleForeignKeys(false);
        $db->begin();

        $db->import(ROOT . '/include/data/0.9.0.sql');

        // Correction des ID parents des comptes qui ont été mal renseignés
        // exemple : compte 512A avec "5" comme parent (c'était permis,
        // par erreur, par le formulaire d'ajout de compte dans le plan)
        // Serait probablement possible en 3-4 lignes de SQL avec
        // WITH RECURSIVE mais c'est au delà de mes compétences
        $comptes = $db->iterate('SELECT id FROM compta_comptes WHERE parent != length(id) - 1;');
................................................................................
                'limit' => '10000',
            ];

            $recherche = new Recherche;
            $recherche->add('Membres inscrits à la lettre d\'information', null, $recherche::TYPE_JSON, 'membres', $query);
        }

        $db->commit();

        $config->set('desactiver_site', false);
        $config->save();
    }

    if (version_compare($v, '0.9.1', '<'))
    {
        // Mise à jour plan comptable: ajout compte licences fédérales
        $comptes = new Compta\Comptes;
        $comptes->importPlan();

        $db->toggleForeignKeys(false);
        $db->begin();

        $db->exec('INSERT INTO "compta_categories" VALUES(NULL,-1,\'Licences fédérales\',\'Licences payées pour les adhérents (par exemple fédération sportive etc.)\',\'652\');');

        $db->import(ROOT . '/include/data/0.9.1.sql');

        $db->commit();
    }

    if (version_compare($v, '0.9.5', '<'))
    {
        $db->begin();
        // Créer les tables manquantes
        $db->import(ROOT . '/include/data/schema.sql');
        $db->commit();
    }

    if (version_compare($v, '0.9.7', '<'))
    {
        $db->begin();

        // Conversion des champs date
................................................................................

                $db->update('membres', [$key => $date], 'id = ' . (int)$row->id);
            }
        }

        $db->commit();
    }











    Utils::clearCaches();

    $config->setVersion(garradin_version());

    Static_Cache::remove('upgrade');








<
|


|







 







|




<
|


|

|







 







<
<
|

|

|







 







<
<
<
|

|

|




|

|

|




<
|

|







 







|











<
|



|

|




|

|
|







 







>
>
>
>
>
>
>
>
>
>







68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
..
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
...
123
124
125
126
127
128
129


130
131
132
133
134
135
136
137
138
139
140
141
...
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
...
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
...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
</script>';

flush();

try {
    if (version_compare($v, '0.7.0', '<'))
    {

        $db->beginSchemaUpdate();

        // Mise à jour base de données
        $db->exec(file_get_contents(ROOT . '/include/data/0.7.0_migration.sql'));

        // Changement de syntaxe du Wiki vers SkrivML
        $wiki = new Wiki;
        $res = $db->get('SELECT id_page, contenu, revision, chiffrement FROM wiki_revisions GROUP BY id_page ORDER BY revision DESC;');

        foreach ($res as $row)
        {
................................................................................
                    'id_auteur'     =>  null,
                    'contenu'       =>  $content,
                    'modification'  =>  'Mise à jour 0.7.0 (transformation SPIP vers SkrivML)',
                ]);
            }
        }

        $db->commitSchemaUpdate();
    }

    if (version_compare($v, '0.7.2', '<'))
    {

        $db->beginSchemaUpdate();

        // Mise à jour base de données
        $db->exec(file_get_contents(ROOT . '/include/data/0.7.2_migration.sql'));

        $db->commitSchemaUpdate();
    }

    if (version_compare($v, '0.8.0-beta4', '<'))
    {
        // Inscription de l'appid
        $db->exec('PRAGMA application_id = ' . DB::APPID . ';');

................................................................................
        // Cecit devrait améliorer les performances de la DB
        $db->exec('PRAGMA page_size = 4096;');

        // Application du changement de taille de page
        $db->exec('VACUUM;');

        // Désactivation des foreign keys AVANT le début de la transaction


        $db->beginSchemaUpdate();

        $db->import(ROOT . '/include/data/0.8.0_migration.sql');

        $db->commitSchemaUpdate();

        $config = Config::getInstance();

        // Ajout champ numéro de membre
        $champs = (array) $config->get('champs_membres')->getAll();
        $presets = Membres\Champs::importPresets();

................................................................................
        // Mise à jour plan comptable: ajout comptes encaissement
        $comptes = new Compta\Comptes;
        $comptes->importPlan();
    }

    if (version_compare($v, '0.8.3', '<'))
    {



        $db->beginSchemaUpdate();

        $db->import(ROOT . '/include/data/0.8.3_migration.sql');

        $db->commitSchemaUpdate();
    }

    if (version_compare($v, '0.8.4', '<'))
    {
        $db->beginSchemaUpdate();

        $db->import(ROOT . '/include/data/0.8.4_migration.sql');

        $db->commitSchemaUpdate();
    }

    if (version_compare($v, '0.9.0-rc1', '<'))
    {

        $db->beginSchemaUpdate();

        $db->import(ROOT . '/include/data/0.9.0_migration.sql');

        // Correction des ID parents des comptes qui ont été mal renseignés
        // exemple : compte 512A avec "5" comme parent (c'était permis,
        // par erreur, par le formulaire d'ajout de compte dans le plan)
        // Serait probablement possible en 3-4 lignes de SQL avec
        // WITH RECURSIVE mais c'est au delà de mes compétences
        $comptes = $db->iterate('SELECT id FROM compta_comptes WHERE parent != length(id) - 1;');
................................................................................
                'limit' => '10000',
            ];

            $recherche = new Recherche;
            $recherche->add('Membres inscrits à la lettre d\'information', null, $recherche::TYPE_JSON, 'membres', $query);
        }

        $db->commitSchemaUpdate();

        $config->set('desactiver_site', false);
        $config->save();
    }

    if (version_compare($v, '0.9.1', '<'))
    {
        // Mise à jour plan comptable: ajout compte licences fédérales
        $comptes = new Compta\Comptes;
        $comptes->importPlan();


        $db->beginSchemaUpdate();

        $db->exec('INSERT INTO "compta_categories" VALUES(NULL,-1,\'Licences fédérales\',\'Licences payées pour les adhérents (par exemple fédération sportive etc.)\',\'652\');');

        $db->import(ROOT . '/include/data/0.9.1_migration.sql');

        $db->commitSchemaUpdate();
    }

    if (version_compare($v, '0.9.5', '<'))
    {
        $db->beginSchemaUpdate();
        // Créer les tables manquantes
        $db->import(ROOT . '/include/data/0.9.5_schema.sql');
        $db->commitSchemaUpdate();
    }

    if (version_compare($v, '0.9.7', '<'))
    {
        $db->begin();

        // Conversion des champs date
................................................................................

                $db->update('membres', [$key => $date], 'id = ' . (int)$row->id);
            }
        }

        $db->commit();
    }

    if (version_compare($v, '1.0.0', '<'))
    {
        $db->beginSchemaUpdate();
        $db->import(ROOT . '/include/data/1.0.0_migration.sql');
        $db->commitSchemaUpdate();
    }

    // Vérification de la cohérence des clés étrangères
    $db->foreignKeyCheck();

    Utils::clearCaches();

    $config->setVersion(garradin_version());

    Static_Cache::remove('upgrade');

Modified src/www/index.php from [f59003a96f] to [1c65f87820].

1
2
3




4
5
6
7
8
9
10
11
12
13
<?php

namespace Garradin;





require __DIR__ . '/_inc.php';

if (Config::getInstance()->get('desactiver_site'))
{
	Utils::redirect(ADMIN_URL);
}

$squelette = new Squelette;
$squelette->dispatchURI();



>
>
>
>










1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

namespace Garradin;

if (PHP_VERSION_ID < 70200) {
	die("PHP 7.2 ou supérieur est requis.");
}

require __DIR__ . '/_inc.php';

if (Config::getInstance()->get('desactiver_site'))
{
	Utils::redirect(ADMIN_URL);
}

$squelette = new Squelette;
$squelette->dispatchURI();