Overview
Comment:Fonctionnalité rapprochement bancaire
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2fe1c3aa3e7a6d08562910c620a1f24e0b974b4b
User & Date: bohwaz on 2015-02-18 19:16:16
Other Links: manifest | tags
Context
2015-02-19
06:52
Gestion des listes à cocher/décocher plus propre (et passage de l'indentation en tabs) check-in: 9e3b4eda67 user: bohwaz tags: trunk
2015-02-18
19:16
Fonctionnalité rapprochement bancaire check-in: 2fe1c3aa3e user: bohwaz tags: trunk
18:33
Page qui n'existe plus check-in: 12a1739463 user: bohwaz tags: trunk
Changes

Modified src/include/data/0.7.0.sql from [cbca4aa3a3] to [03c2810d89].

1
2
3
4
5
6
7
8








9
10
11
12
13
14
15
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 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 NOT NULL, -- Type MIME








>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 NOT NULL, -- Type MIME

Modified src/include/data/schema.sql from [52605cc884] to [7deb0e0ac2].

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
-- Si le contenu est chiffré, la recherche n'affiche pas de contenu
CREATE TRIGGER 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_fichiers (
    id INTEGER PRIMARY KEY,
    id_page INTEGER NOT NULL,
    nom TEXT,
    hash TEXT,

    FOREIGN KEY (id_page) REFERENCES wiki_pages (id) -- Clé externe obligatoire
);

CREATE INDEX wiki_fichiers_id_page ON wiki_fichiers (id_page);

CREATE TABLE wiki_suivi
-- Suivi des pages
(
    id_membre INTEGER NOT NULL,
    id_page INTEGER NOT NULL,

    PRIMARY KEY (id_membre, id_page),







<
<
<
<
<
<
<
<
<
<
<







164
165
166
167
168
169
170











171
172
173
174
175
176
177
-- Si le contenu est chiffré, la recherche n'affiche pas de contenu
CREATE TRIGGER 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),
319
320
321
322
323
324
325








326
327
328
329
330
331
332
-- 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 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 NOT NULL, -- Type MIME







>
>
>
>
>
>
>
>







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
-- 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 NOT NULL, -- Type MIME

Modified src/include/lib/Garradin/Compta/Exercices.php from [f31307da50] to [d46db9407d].

268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
        return $db->simpleQuerySingle('SELECT *, strftime(\'%s\', debut) AS debut,
            strftime(\'%s\', fin) AS fin FROM compta_exercices WHERE id = ?;', true, (int)$id);
    }

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

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







|







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
        return $db->simpleQuerySingle('SELECT *, strftime(\'%s\', debut) AS debut,
            strftime(\'%s\', fin) AS fin FROM compta_exercices WHERE id = ?;', true, (int)$id);
    }

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

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

Added src/include/lib/Garradin/Compta/Rapprochement.php version [426c8449ed].











































































































































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

namespace Garradin\Compta;

use \Garradin\DB;
use \Garradin\Utils;
use \Garradin\UserException;
use \Garradin\Compta\Journal;
use \Garradin\Compta\Comptes_Bancaires;

class Rapprochement
{
    public function getJournal($compte, $debut, $fin)
    {
        $db = DB::getInstance();

        $exercice = $db->querySingle('SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1;');

        $query = '
        	SELECT j.*, strftime(\'%s\', j.date) AS date, 
            	(CASE WHEN j.compte_debit = :compte THEN j.montant ELSE -(j.montant) END) AS solde,
            	r.date
            FROM compta_journal AS j
            	LEFT JOIN compta_rapprochement AS r ON r.operation = j.id
            WHERE (compte_debit = :compte OR compte_credit = :compte) AND id_exercice = :exercice
            	AND j.date >= :debut AND j.date <= :fin
            ORDER BY date ASC;';

        $result = $db->simpleStatementFetch($query, DB::ASSOC, [
        	'compte'	=>	$compte,
        	'debut'		=>	$debut,
        	'fin'		=>	$fin,
        	'exercice'	=>	$exercice
        ]);

        $solde = 0.0;

        foreach ($result as &$row)
        {
            $solde += $row['solde'];
            $row['solde'] = $solde;
        }

        return $result;
    }

    public function record($compte, $operations, $auteur)
    {
    	if (!is_array($operations))
    	{
    		throw new \UnexpectedValueException('$operations doit être un tableau.');
    	}

    	$db = DB::getInstance();
    	$db->exec('BEGIN;');
    	$st = $db->prepare('INSERT OR REPLACE INTO compta_rapprochement (operation, auteur) 
    		VALUES (:operation, :auteur);');
    	$st->bindValue(':auteur', (int)$auteur, \SQLITE3_INTEGER);

    	foreach ($operations as $row)
    	{
    		$st->bindValue(':operation', (int)$row, \SQLITE3_INTEGER);
    		$st->execute();
    	}

    	$db->exec('END;');
    	return true;
    }
}

Modified src/include/lib/Garradin/DB.php from [7406e12909] to [7e56a5c401].

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    }

    public function getArgType($arg, $name = '')
    {
        switch (gettype($arg))
        {
            case 'double':
                return SQLITE3_FLOAT;
            case 'integer':
            case 'boolean':
                return SQLITE3_INTEGER;
            case 'NULL':
                return SQLITE3_NULL;
            case 'string':
                return SQLITE3_TEXT;
            default:
                throw new \InvalidArgumentException('Argument '.$name.' is of invalid type '.gettype($arg));
        }
    }

    public function simpleStatement($query, $args = [])
    {







|


|

|

|







152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    }

    public function getArgType($arg, $name = '')
    {
        switch (gettype($arg))
        {
            case 'double':
                return \SQLITE3_FLOAT;
            case 'integer':
            case 'boolean':
                return \SQLITE3_INTEGER;
            case 'NULL':
                return \SQLITE3_NULL;
            case 'string':
                return \SQLITE3_TEXT;
            default:
                throw new \InvalidArgumentException('Argument '.$name.' is of invalid type '.gettype($arg));
        }
    }

    public function simpleStatement($query, $args = [])
    {
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

    public function escapeAuto($value, $name = '')
    {
        $type = $this->getArgType($value, $name);

        switch ($type)
        {
            case SQLITE3_FLOAT:
                return floatval($value);
            case SQLITE3_INTEGER:
                return intval($value);
            case SQLITE3_NULL:
                return 'NULL';
            case SQLITE3_TEXT:
                return '\'' . $this->escapeString($value) . '\'';
        }
    }

    /**
     * Simple INSERT query
     */







|

|

|

|







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

    public function escapeAuto($value, $name = '')
    {
        $type = $this->getArgType($value, $name);

        switch ($type)
        {
            case \SQLITE3_FLOAT:
                return floatval($value);
            case \SQLITE3_INTEGER:
                return intval($value);
            case \SQLITE3_NULL:
                return 'NULL';
            case \SQLITE3_TEXT:
                return '\'' . $this->escapeString($value) . '\'';
        }
    }

    /**
     * Simple INSERT query
     */

Modified src/templates/admin/compta/banques/rapprocher.tpl from [c2cc21d617] to [d798562d82].

1
2
3
4
5
6
7
8















9












































10
{include file="admin/_head.tpl" title="Rapprochement — `$compte.id`" current="compta/banques" js=1}

<ul class="actions">
    <li><a href="{$www_url}admin/compta/banques/">Comptes bancaires</a></li>
    <li><a href="{$www_url}admin/compta/comptes/journal.php?id={Garradin\Compta\Comptes::CAISSE}&amp;suivi">Journal de caisse</a></li>
    <li class="current"><a href="{$admin_url}compta/banques/rapprochement.php?id={$compte.id|escape}">Rapprochement</a></li>
</ul>





























































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








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

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

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
{include file="admin/_head.tpl" title="Rapprochement — `$compte.id`" current="compta/banques" js=1}

<ul class="actions">
    <li><a href="{$www_url}admin/compta/banques/">Comptes bancaires</a></li>
    <li><a href="{$www_url}admin/compta/comptes/journal.php?id={Garradin\Compta\Comptes::CAISSE}&amp;suivi">Journal de caisse</a></li>
    <li class="current"><a href="{$admin_url}compta/banques/rapprochement.php?id={$compte.id|escape}">Rapprochement</a></li>
</ul>

<form method="get" action="{$self_url|escape}">
    <fieldset>
        <legend>Période de rapprochement</legend>
        <dl>
            <dt><label for="f_debut">Début</label></dt>
            <dd><input type="date" name="debut" id="f_debut" value="{form_field name='debut' default=$debut}" /></dd>
            <dt><label for="f_fin">Fin</label></dt>
            <dd><input type="date" name="fin" id="f_fin" value="{form_field name='fin' default=$fin}" /></dd>
        </dl>
        <p>
            <input type="hidden" name="id" value="{$compte.id|escape}" />
            <input type="submit" value="Afficher" />
        </p>
    </fieldset>
</form>

<table class="list">
    <colgroup>
        <col width="3%" />
        <col width="3%" />
        <col width="12%" />
        <col width="10%" />
        <col width="12%" />
        <col />
    </colgroup>
    <thead>
        <tr>
            <td></td>
            <td></td>
            <td>Date</td>
            <td>Montant</td>
            <td>Solde cumulé</td>
            <th>Libellé</th>
        </tr>
    </thead>
    <tbody>
    {foreach from=$journal item="ligne"}
        <tr>
            <td class="num"><a href="{$admin_url}compta/operations/voir.php?id={$ligne.id|escape}">{$ligne.id|escape}</a></td>
            <td class="actions">
            {if $user.droits.compta >= Garradin\Membres::DROIT_ADMIN}
                <a class="icn" href="{$admin_url}compta/operations/modifier.php?id={$ligne.id|escape}" title="Modifier cette opération">✎</a>
            {/if}
            </td>
            <td>{$ligne.date|date_fr:'d/m/Y'|escape}</td>
            <td>{if $ligne.compte_credit == $compte.id}-{else}+{/if}{$ligne.montant|html_money}</td>
            <td>{$ligne.solde|html_money}</td>
            <th>{$ligne.libelle|escape}</th>
        </tr>
    {/foreach}
    </tbody>
    <tfoot>
        <tr>
            <td colspan="3"></td>
            <th>Solde</th>
            <td colspan="2">{*{$solde|html_money} {$config.monnaie|escape}*}</td>
        </tr>
    </tfoot>
</table>

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

Added src/www/admin/compta/banques/rapprocher.php version [84f2a86f78].































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php
namespace Garradin;

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

if ($user['droits']['compta'] < Membres::DROIT_ADMIN)
{
    throw new UserException("Vous n'avez pas le droit d'accéder à cette page.");
}

$banques = new Compta\Comptes_Bancaires;
$rapprochement = new Compta\Rapprochement;
$exercices = new Compta\Exercices;
$exercice = $exercices->getCurrent();

$compte = $banques->get(Utils::get('id'));

if (!$compte)
{
    throw new UserException("Le compte demandé n'existe pas.");
}

$error = false;

if (Utils::post('save'))
{
    if (!Utils::CSRF_check('compta_rapprocher_' . $compte['id']))
    {
        $error = 'Une erreur est survenue, merci de renvoyer le formulaire.';
    }
    else
    {
        try
        {
            $rapprochement->record($compte['id'], Utils::post('rapprocher'), $user['id']);
            Utils::redirect('/admin/compta/banques/rapprocher.php?id=');
        }
        catch (UserException $e)
        {
            $error = $e->getMessage();
        }
	}
}

$debut = Utils::get('debut');
$fin = Utils::get('fin');

if ($debut && $fin)
{
    if (!Utils::checkDate($debut) || !Utils::checkDate($fin))
    {
        $error = 'La date donnée est invalide.';
        $debut = $fin = false;
    }
    else if (strtotime($debut) < $exercice['debut'])
    {
        $debut = date('Y-m-d', $exercice['debut']);
    }
    else if (strtotime($fin) > $exercice['fin'])
    {
        $fin = date('Y-m-d', $exercice['fin']);
    }
}

if (!$debut || !$fin)
{
    $date = $exercice['fin'];
    $debut = date('Y-m-01', $date);
    $fin = date('Y-m-31', $date);
}

$tpl->assign('compte', $compte);
$tpl->assign('debut', $debut);
$tpl->assign('fin', $fin);
$tpl->assign('journal', $rapprochement->getJournal($compte['id'], $debut, $fin));

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

$tpl->display('admin/compta/banques/rapprocher.tpl');