Overview
Comment:Add types for positive and negative result
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA1: cc06f5744a711d400cd8c8bede743ebc22783a4d
User & Date: bohwaz on 2020-11-25 18:25:10
Other Links: branch diff | manifest | tags
Context
2020-11-25
18:46
Fix issues with checkboxes check-in: c7949d172e user: bohwaz tags: dev
18:25
Add types for positive and negative result check-in: cc06f5744a user: bohwaz tags: dev
16:06
Add ability to search accounting using accounts and analytical check-in: 3abc5388d1 user: bohwaz tags: dev
Changes

Modified src/VERSION from [b6a34c055b] to [f305a995ef].

1
1.0.0-beta7
|
1
1.0.0-beta8

Added src/include/data/1.0.0-beta8_migration.sql version [ff1b70a076].





>
>
1
2
UPDATE acc_accounts SET type = 11 WHERE code = '120';
UPDATE acc_accounts SET type = 12 WHERE code = '129';

Modified src/include/data/charts/fr_1999.csv from [e341d528ba] to [38d9f67e8d].

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1063,Réserves statutaires ou contractuelles,,Passif,
1064,Réserves réglementées,,Passif,
1068,Autres réserves (dont réserves pour projet associatif),,Passif,
11,REPORT À NOUVEAU,,Passif,
110,Report à nouveau (Solde créditeur),,Passif,
119,Report à nouveau (Solde débiteur),,Passif,
12,RÉSULTAT NET DE L'EXERCICE,,Passif,
120,Résultat de l'exercice (excédent),,Passif,
129,Résultat de l'exercice (déficit),,Passif,
13,SUBVENTIONS D'INVESTISSEMENT AFFECTÉES A DES BIENS NON RENOUVELABLES,,Passif,
131,Subventions d'investissement (renouvelables),,Passif,
139,Subventions d'investissement inscrites au compte de résultat,,Passif,
14,PROVISIONS REGLEMENTÉES,,Passif,
15,PROVISIONS,,Passif,
151,Provisions pour risques,,Passif,
157,Provisions pour charges à répartir sur plusieurs exercices,,Passif,







|
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1063,Réserves statutaires ou contractuelles,,Passif,
1064,Réserves réglementées,,Passif,
1068,Autres réserves (dont réserves pour projet associatif),,Passif,
11,REPORT À NOUVEAU,,Passif,
110,Report à nouveau (Solde créditeur),,Passif,
119,Report à nouveau (Solde débiteur),,Passif,
12,RÉSULTAT NET DE L'EXERCICE,,Passif,
120,Résultat de l'exercice (excédent),,Passif,Résultat excédentaire
129,Résultat de l'exercice (déficit),,Passif,Résultat déficitaire
13,SUBVENTIONS D'INVESTISSEMENT AFFECTÉES A DES BIENS NON RENOUVELABLES,,Passif,
131,Subventions d'investissement (renouvelables),,Passif,
139,Subventions d'investissement inscrites au compte de résultat,,Passif,
14,PROVISIONS REGLEMENTÉES,,Passif,
15,PROVISIONS,,Passif,
151,Provisions pour risques,,Passif,
157,Provisions pour charges à répartir sur plusieurs exercices,,Passif,

Modified src/include/data/charts/fr_2018.csv from [f24126399c] to [7724166e91].

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
108,Dotations consomptibles,,Passif,
1081,Dotations consomptibles,,Passif,
1089,Dot. consomptibles inscrites au cpte de résul,,Passif,
11,REPORT à NOUVEAU,,Passif,
110,Report à nouveau (Solde créditeur),,Passif,
119,Report à nouveau (Solde débiteur),,Passif,
12,RÉSULTAT NET DE L'EXERCICE,,Passif,
120,Résultat de l'exercice (Excédent),,Passif,
129,Résultat de l'exercice (déficit),,Passif,
13,SUBVENTIONS D'INVESTISSEMENTS,,Passif,
131,Subventions d'équipement,,Passif,
139,Subventions inscrites au compte de résultat,,Passif,
14,PROVISIONS RÉGLEMENTÉES,,Passif,
148,Autres provisions réglementées,,Passif,
15,PROVISIONS POUR RISQUES ET CHARGES,,Passif,
151,Provisions pour risques,,Passif,







|
|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
108,Dotations consomptibles,,Passif,
1081,Dotations consomptibles,,Passif,
1089,Dot. consomptibles inscrites au cpte de résul,,Passif,
11,REPORT à NOUVEAU,,Passif,
110,Report à nouveau (Solde créditeur),,Passif,
119,Report à nouveau (Solde débiteur),,Passif,
12,RÉSULTAT NET DE L'EXERCICE,,Passif,
120,Résultat de l'exercice (excédent),,Passif,Résultat excédentaire
129,Résultat de l'exercice (déficit),,Passif,Résultat déficitaire
13,SUBVENTIONS D'INVESTISSEMENTS,,Passif,
131,Subventions d'équipement,,Passif,
139,Subventions inscrites au compte de résultat,,Passif,
14,PROVISIONS RÉGLEMENTÉES,,Passif,
148,Autres provisions réglementées,,Passif,
15,PROVISIONS POUR RISQUES ET CHARGES,,Passif,
151,Provisions pour risques,,Passif,

Modified src/include/lib/Garradin/Accounting/Accounts.php from [1d25c5443b] to [5c990f5765].

1
2
3
4
5



6
7
8
9
10
11
12
<?php

namespace Garradin\Accounting;

use Garradin\Entities\Accounting\Account;



use Garradin\CSV;
use Garradin\DB;
use Garradin\DynamicList;
use Garradin\Utils;
use KD2\DB\EntityManager;

class Accounts





>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

namespace Garradin\Accounting;

use Garradin\Entities\Accounting\Account;
use Garradin\Entities\Accounting\Line;
use Garradin\Entities\Accounting\Transaction;
use Garradin\Entities\Accounting\Year;
use Garradin\CSV;
use Garradin\DB;
use Garradin\DynamicList;
use Garradin\Utils;
use KD2\DB\EntityManager;

class Accounts
236
237
238
239
240
241
242
243











































































		return $list;
	}

	public function countByType(int $type)
	{
		return DB::getInstance()->count(Account::TABLE, 'id_chart = ? AND type = ?', $this->chart_id, $type);
	}
}


















































































|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
		return $list;
	}

	public function countByType(int $type)
	{
		return DB::getInstance()->count(Account::TABLE, 'id_chart = ? AND type = ?', $this->chart_id, $type);
	}

	public function getSingleAccountForType(int $type)
	{
		return DB::getInstance()->first('SELECT * FROM acc_accounts WHERE type = ? AND id_chart = ? LIMIT 1;', $type, $this->chart_id);
	}

/* FIXME: implement closing of accounts
	public function getClosingAccountId()
	{
		return DB::getInstance()->firstColumn('SELECT id FROM acc_accounts WHERE type = ? AND id_chart = ?;', Account::TYPE_CLOSING, $this->chart_id);
	}

	public function closeRevenueExpenseAccounts(Year $year, int $user_id)
	{
		$closing_id = $this->getClosingAccountId();

		if (!$closing_id) {
			throw new UserException('Aucun compte n\'est indiqué comme compte de clôture dans le plan comptable');
		}

		$transaction = new Transaction;
		$transaction->id_creator = $user_id;
		$transaction->id_year = $year->id();
		$transaction->type = Transaction::TYPE_ADVANCED;
		$transaction->label = 'Clôture de l\'exercice';
		$transaction->date = new \DateTime;
		$debit = 0;
		$credit = 0;

		$sql = 'SELECT a.id, SUM(l.credit - l.debit) AS sum, a.position, a.code
			FROM acc_transactions_lines l
			INNER JOIN acc_transactions t ON t.id = l.id_transaction
			INNER JOIN acc_accounts a ON a.id = l.id_account
			WHERE t.id_year = ? AND a.position IN (?, ?)
			GROUP BY a.id
			ORDER BY a.code;';

		$res = DB::getInstance()->iterate($sql, $year->id(), Account::REVENUE, Account::EXPENSE);

		foreach ($res as $row) {
			$reversed = $row->position == Account::ASSET;

			$line = new Line;
			$line->id_account = $row->id;
			$line->credit = $reversed ? abs($row->sum) : 0;
			$line->debit = !$reversed ? abs($row->sum) : 0;
			$transaction->addLine($line);

			if ($reversed) {
				$debit += abs($row->sum);
			}
			else {
				$credit += abs($row->sum);
			}
		}

		if ($debit) {
			$line = new Line;
			$line->id_account = $closing_id;
			$line->credit = 0;
			$line->debit = $debit;
			$transaction->addLine($line);
		}

		if ($credit) {
			$line = new Line;
			$line->id_account = $closing_id;
			$line->credit = $credit;
			$line->debit = 0;
			$transaction->addLine($line);
		}

		$transaction->save();
	}
*/
}

Modified src/include/lib/Garradin/Accounting/Reports.php from [68436d7eb6] to [bd1f8f1a69].

19
20
21
22
23
24
25





26
27
28
29
30
31
32
			$where[] = sprintf('t.id_year = %d', $criterias['year']);
		}

		if (!empty($criterias['position'])) {
			$db = DB::getInstance();
			$where[] = $db->where('position', $criterias['position']);
		}






		if (!empty($criterias['type'])) {
			$db = DB::getInstance();
			$criterias['type'] = array_map('intval', (array)$criterias['type']);
			$where[] = sprintf('a.type IN (%s)', implode(',', $criterias['type']));
		}








>
>
>
>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
			$where[] = sprintf('t.id_year = %d', $criterias['year']);
		}

		if (!empty($criterias['position'])) {
			$db = DB::getInstance();
			$where[] = $db->where('position', $criterias['position']);
		}

		if (!empty($criterias['exclude_position'])) {
			$db = DB::getInstance();
			$where[] = $db->where('position', 'NOT IN', $criterias['exclude_position']);
		}

		if (!empty($criterias['type'])) {
			$db = DB::getInstance();
			$criterias['type'] = array_map('intval', (array)$criterias['type']);
			$where[] = sprintf('a.type IN (%s)', implode(',', $criterias['type']));
		}

Modified src/include/lib/Garradin/Entities/Accounting/Account.php from [1bca263694] to [1d8cfae373].

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

	const TYPE_ANALYTICAL = 7;
	const TYPE_VOLUNTEERING = 8;

	const TYPE_OPENING = 9;
	const TYPE_CLOSING = 10;




	const TYPES_NAMES = [
		'',
		'Banque',
		'Caisse',
		'Attente d\'encaissement',
		'Tiers',
		'Dépenses',
		'Recettes',
		'Analytique',
		'Bénévolat',
		'Ouverture',
		'Clôture',


	];

	const LIST_COLUMNS = [
		'id' => [
			'select' => 't.id',
			'label' => 'N°',
		],







>
>
>












>
>







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

	const TYPE_ANALYTICAL = 7;
	const TYPE_VOLUNTEERING = 8;

	const TYPE_OPENING = 9;
	const TYPE_CLOSING = 10;

	const TYPE_POSITIVE_RESULT = 11;
	const TYPE_NEGATIVE_RESULT = 12;

	const TYPES_NAMES = [
		'',
		'Banque',
		'Caisse',
		'Attente d\'encaissement',
		'Tiers',
		'Dépenses',
		'Recettes',
		'Analytique',
		'Bénévolat',
		'Ouverture',
		'Clôture',
		'Résultat excédentaire',
		'Résultat déficitaire',
	];

	const LIST_COLUMNS = [
		'id' => [
			'select' => 't.id',
			'label' => 'N°',
		],

Modified src/include/lib/Garradin/Entities/Accounting/Year.php from [afd92ba302] to [efb670bde0].

55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
			$this->assert(
				!$db->test(Transaction::TABLE, 'id_year = ? AND date > ?', $this->id(), $this->end_date->format('Y-m-d')),
				'Des mouvements de cet exercice ont une date postérieure à la date de fin de l\'exercice.'
			);
		}
	}

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

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

	}

	public function delete(): bool
	{
		// Manual delete of transactions, as there is a voluntary safeguard in SQL: no cascade
		DB::getInstance()->preparedQuery('DELETE FROM acc_transactions WHERE id_year = ?;', $this->id());








|






>







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
			$this->assert(
				!$db->test(Transaction::TABLE, 'id_year = ? AND date > ?', $this->id(), $this->end_date->format('Y-m-d')),
				'Des mouvements de cet exercice ont une date postérieure à la date de fin de l\'exercice.'
			);
		}
	}

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

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

	public function delete(): bool
	{
		// Manual delete of transactions, as there is a voluntary safeguard in SQL: no cascade
		DB::getInstance()->preparedQuery('DELETE FROM acc_transactions WHERE id_year = ?;', $this->id());

Modified src/include/lib/Garradin/Upgrade.php from [bd7307d7a2] to [7caefda8d3].

70
71
72
73
74
75
76







77
78
79
80
81
82
83

			if (version_compare($v, '1.0.0-beta1', '>=') && version_compare($v, '1.0.0-beta6', '<'))
			{
				$db->beginSchemaUpdate();
				$db->import(ROOT . '/include/data/1.0.0-beta6_migration.sql');
				$db->commitSchemaUpdate();
			}








			// Vérification de la cohérence des clés étrangères
			$db->foreignKeyCheck();

			Utils::clearCaches();

			$config->setVersion(garradin_version());







>
>
>
>
>
>
>







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

			if (version_compare($v, '1.0.0-beta1', '>=') && version_compare($v, '1.0.0-beta6', '<'))
			{
				$db->beginSchemaUpdate();
				$db->import(ROOT . '/include/data/1.0.0-beta6_migration.sql');
				$db->commitSchemaUpdate();
			}

			if (version_compare($v, '1.0.0-beta6', '>=') && version_compare($v, '1.0.0-beta8', '<'))
			{
				$db->beginSchemaUpdate();
				$db->import(ROOT . '/include/data/1.0.0-beta8_migration.sql');
				$db->commitSchemaUpdate();
			}

			// Vérification de la cohérence des clés étrangères
			$db->foreignKeyCheck();

			Utils::clearCaches();

			$config->setVersion(garradin_version());

Modified src/www/admin/acc/years/balance.php from [24b0d4e73b] to [1c5fd61cf1].

1
2
3

4
5
6
7
8
9
10
<?php
namespace Garradin;


use Garradin\Entities\Accounting\Transaction;
use Garradin\Accounting\Reports;
use Garradin\Accounting\Years;

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

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



>







1
2
3
4
5
6
7
8
9
10
11
<?php
namespace Garradin;

use Garradin\Entities\Accounting\Account;
use Garradin\Entities\Accounting\Transaction;
use Garradin\Accounting\Reports;
use Garradin\Accounting\Years;

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

$session->requireAccess('compta', Membres::DROIT_ADMIN);
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
	if (!$previous_year) {
		throw new UserException('Année précédente invalide');
	}
}


if ($previous_year) {
	$lines = Reports::getClosingSumsWithAccounts(['year' => $previous_year->id()]);

	if ($previous_year->id_chart != $year->id_chart) {
		$chart_change = true;
		$codes = [];

		foreach ($lines as $line) {
			$codes[] = $line->code;
		}

		$matching_accounts = $year->accounts()->listForCodes($codes);
	}


























	foreach ($lines as $k => &$line) {
		$line->credit = $line->sum > 0 ? $line->sum : 0;
		$line->debit = $line->sum < 0 ? abs($line->sum) : 0;

		if ($chart_change) {
			if (array_key_exists($line->code, $matching_accounts)) {







|











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







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
	if (!$previous_year) {
		throw new UserException('Année précédente invalide');
	}
}


if ($previous_year) {
	$lines = Reports::getClosingSumsWithAccounts(['year' => $previous_year->id(), 'exclude_position' => [Account::EXPENSE, Account::REVENUE]]);

	if ($previous_year->id_chart != $year->id_chart) {
		$chart_change = true;
		$codes = [];

		foreach ($lines as $line) {
			$codes[] = $line->code;
		}

		$matching_accounts = $year->accounts()->listForCodes($codes);
	}

	// Append result
	$result = Reports::getResult(['year' => $previous_year->id()]);

	if ($result > 0) {
		$account = $year->accounts()->getSingleAccountForType(Account::TYPE_POSITIVE_RESULT);
	}
	else {
		$account = $year->accounts()->getSingleAccountForType(Account::TYPE_NEGATIVE_RESULT);
	}

	if (!$account) {
		$account = (object) [
			'id' => null,
			'code' => null,
			'label' => 'Résultat de l\'exercice',
		];
	}

	$lines[] = (object) [
		'sum' => $result,
		'id' => $account->id,
		'code' => $account->code,
		'label' => $account->label,
	];

	foreach ($lines as $k => &$line) {
		$line->credit = $line->sum > 0 ? $line->sum : 0;
		$line->debit = $line->sum < 0 ? abs($line->sum) : 0;

		if ($chart_change) {
			if (array_key_exists($line->code, $matching_accounts)) {

Modified src/www/admin/acc/years/close.php from [b388dca412] to [c2cd93158e].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$rules = [
	'end_date' => 'date_format:d/m/Y|required',
];

if (f('close') && $form->check('acc_years_close_' . $year->id()))
{
	try {
		$year->close();
		$year->save();
		$session->set('acc_year', null);

		Utils::redirect(ADMIN_URL . 'acc/years/');
	}
	catch (UserException $e)
	{







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$rules = [
	'end_date' => 'date_format:d/m/Y|required',
];

if (f('close') && $form->check('acc_years_close_' . $year->id()))
{
	try {
		$year->close($user->id);
		$year->save();
		$session->set('acc_year', null);

		Utils::redirect(ADMIN_URL . 'acc/years/');
	}
	catch (UserException $e)
	{