Overview
Comment:Improve UI of transaction form
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA1: 3b5a383cf700c1c40d7048a41305bcb885919671
User & Date: bohwaz on 2020-11-07 16:32:48
Other Links: branch diff | manifest | tags
Context
2020-11-07
16:33
Add new form element: large radio button check-in: e6f38916c7 user: bohwaz tags: dev
16:32
Improve UI of transaction form check-in: 3b5a383cf7 user: bohwaz tags: dev
16:28
Wording: opération -> écriture check-in: 9e365d31e2 user: bohwaz tags: dev
Changes

Modified src/include/lib/Garradin/Entities/Accounting/Transaction.php from [fd44b7703c] to [33a9541a79].

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
		return EntityManager::findOneById(Year::class, $this->id_year);
	}

	public function listFiles()
	{
		return Fichiers::listLinkedFiles(Fichiers::LIEN_COMPTA, $this->id());
	}









	public function updateLinkedUsers(array $users)
	{
		$db = EntityManager::getInstance(self::class)->DB();

		$db->begin();

		$sql = sprintf('DELETE FROM acc_transactions_users WHERE id_transaction = ? AND %s;', $db->where('id_user', 'NOT IN', $users));
		$db->preparedQuery($sql, $this->id());

		foreach ($users as $id) {
			$db->preparedQuery('INSERT OR IGNORE INTO acc_transactions_users (id_transaction, id_user) VALUES (?, ?);', $this->id(), $id);
		}

		$db->commit();
	}

	public function listLinkedUsers()
	{
		$db = EntityManager::getInstance(self::class)->DB();
		$identity_column = Config::getInstance()->get('champ_identite');
		$sql = sprintf('SELECT m.id, m.%s AS identity FROM membres m INNER JOIN acc_transactions_users l ON l.id_user = m.id WHERE l.id_transaction = ?;', $identity_column);
		return $db->get($sql, $this->id());
	}

	public function listLinkedUsersAssoc()
	{
		$db = EntityManager::getInstance(self::class)->DB();
		$identity_column = Config::getInstance()->get('champ_identite');
		$sql = sprintf('SELECT m.id, m.%s AS identity FROM membres m INNER JOIN acc_transactions_users l ON l.id_user = m.id WHERE l.id_transaction = ?;', $identity_column);
		return $db->getAssoc($sql, $this->id());
	}

	static public function getTypesDetails()
	{
		$details = [


			[
				[
					'label' => 'Type de recette',
					'targets' => [Account::TYPE_REVENUE],
					'position' => 'credit',
				],
				[
					'label' => 'Compte d\'encaissement',
					'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
					'position' => 'debit',
				],
			],
			[





				[
					'label' => 'Type de dépense',
					'targets' => [Account::TYPE_EXPENSE],
					'position' => 'debit',
				],
				[
					'label' => 'Compte de décaissement',
					'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
					'position' => 'credit',
				],
			],
			[
				[
					'label' => 'De',
					'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
					'position' => 'debit',
				],
				[
					'label' => 'Vers',
					'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
					'position' => 'credit',
				],
			],
			// Debt (dette)
			[
				[
					'label' => 'Compte de tiers',
					'targets' => [Account::TYPE_THIRD_PARTY],
					'position' => 'credit',
				],
				[
					'label' => 'Type de dette (dépense)',
					'targets' => [Account::TYPE_EXPENSE],
					'position' => 'debit',
				],
			],
			// Credit (créance)
			[




				[
					'label' => 'Compte de tiers',
					'targets' => [Account::TYPE_THIRD_PARTY],
					'position' => 'debit',
				],
				[
					'label' => 'Type de créance (recette)',
					'targets' => [Account::TYPE_REVENUE],
					'position' => 'credit',
				],
			],


		];






		$out = [];

		foreach ($details as $k => $accounts) {
			$d = (object) [

				'id' => $k+1,


				'label' => self::TYPES_NAMES[$k+1],

				'accounts' => [],
			];

			foreach ($accounts as $account) {


				$account['targets'] = implode(':', $account['targets']);
				$d->accounts[] = (object) $account;

			}

			$out[$d->id] = $d;
		}

		return $out;
	}

	public function payOffFrom(int $id): self
	{
		$this->_related = EntityManager::findOneById(self::class, $id);

		if (!$this->_related) {







>
>
>
>
>
>
>
>







|













|














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

|
>
>
|
|
>

|
<
|
<
|







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
		return EntityManager::findOneById(Year::class, $this->id_year);
	}

	public function listFiles()
	{
		return Fichiers::listLinkedFiles(Fichiers::LIEN_COMPTA, $this->id());
	}

	public function linkToUser(int $user_id, ?int $service_id = null)
	{
		$db = EntityManager::getInstance(self::class)->DB();

		return $db->preparedQuery('INSERT OR IGNORE INTO acc_transactions_users (id_transaction, id_user, id_service_user) VALUES (?, ?, ?);',
			$this->id(), $user_id, $service_id);
	}

	public function updateLinkedUsers(array $users)
	{
		$db = EntityManager::getInstance(self::class)->DB();

		$db->begin();

		$sql = sprintf('DELETE FROM acc_transactions_users WHERE id_transaction = ? AND id_service_user IS NULL AND %s;', $db->where('id_user', 'NOT IN', $users));
		$db->preparedQuery($sql, $this->id());

		foreach ($users as $id) {
			$db->preparedQuery('INSERT OR IGNORE INTO acc_transactions_users (id_transaction, id_user) VALUES (?, ?);', $this->id(), $id);
		}

		$db->commit();
	}

	public function listLinkedUsers()
	{
		$db = EntityManager::getInstance(self::class)->DB();
		$identity_column = Config::getInstance()->get('champ_identite');
		$sql = sprintf('SELECT m.id, m.%s AS identity, l.id_service_user FROM membres m INNER JOIN acc_transactions_users l ON l.id_user = m.id WHERE l.id_transaction = ?;', $identity_column);
		return $db->get($sql, $this->id());
	}

	public function listLinkedUsersAssoc()
	{
		$db = EntityManager::getInstance(self::class)->DB();
		$identity_column = Config::getInstance()->get('champ_identite');
		$sql = sprintf('SELECT m.id, m.%s AS identity FROM membres m INNER JOIN acc_transactions_users l ON l.id_user = m.id WHERE l.id_transaction = ?;', $identity_column);
		return $db->getAssoc($sql, $this->id());
	}

	static public function getTypesDetails()
	{
		$details = [
			self::TYPE_REVENUE => [
				'accounts' => [
						[

						'label' => 'De',
						'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
						'position' => 'debit',
					],
					[
						'label' => 'Vers',
						'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
						'position' => 'credit',
					],
				],

				'label' => self::TYPES_NAMES[self::TYPE_REVENUE],
				'help' => null,
			],
			self::TYPE_EXPENSE => [
				'accounts' => [
					[
						'label' => 'Type de dépense',
						'targets' => [Account::TYPE_EXPENSE],
						'position' => 'debit',
					],
					[
						'label' => 'Compte de décaissement',
						'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
						'position' => 'credit',
					],
				],


				'label' => self::TYPES_NAMES[self::TYPE_EXPENSE],

				'help' => null,
			],

			self::TYPE_DEBT => [

				'accounts' => [




					[
						'label' => 'Compte de tiers',
						'targets' => [Account::TYPE_THIRD_PARTY],
						'position' => 'credit',
					],
					[
						'label' => 'Type de dette (dépense)',
						'targets' => [Account::TYPE_EXPENSE],
						'position' => 'debit',
					],
				],
				'label' => self::TYPES_NAMES[self::TYPE_DEBT],

				'help' => 'Quand l\'association doit de l\'argent à un membre ou un fournisseur',
			],
			self::TYPE_CREDIT => [
				'accounts' => [
					[
						'label' => 'Compte de tiers',
						'targets' => [Account::TYPE_THIRD_PARTY],
						'position' => 'debit',
					],
					[
						'label' => 'Type de créance (recette)',
						'targets' => [Account::TYPE_REVENUE],
						'position' => 'credit',
					],
				],
				'label' => self::TYPES_NAMES[self::TYPE_CREDIT],
				'help' => 'Quand un membre ou un fournisseur doit de l\'argent à l\'association',
			],
			self::TYPE_ADVANCED => [
				'accounts' => [
					[
						'label' => 'Type de recette',
						'targets' => [Account::TYPE_REVENUE],
						'position' => 'credit',
					],
					[
						'label' => 'Compte d\'encaissement',

						'targets' => [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING],
						'position' => 'debit',
					],
				],
				'label' => self::TYPES_NAMES[self::TYPE_ADVANCED],
				'help' => 'Choisir les comptes du plan comptable, ventiler une écriture sur plusieurs comptes, etc.',
			],
		];

		foreach ($details as $key => &$type) {
			$type = (object) $type;
			$type->id = $key;
			foreach ($type->accounts as &$account) {
				$account = (object) $account;
				$account->targets_string = implode(':', $account->targets);
			}
		}



		return $details;
	}

	public function payOffFrom(int $id): self
	{
		$this->_related = EntityManager::findOneById(self::class, $id);

		if (!$this->_related) {

Modified src/templates/acc/transactions/new.tpl from [079d9cc5d7] to [b9180f9b59].

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

{include file="acc/_year_select.tpl"}

<form method="post" action="{$self_url_no_qs}" enctype="multipart/form-data" data-focus="1">
	{form_errors}

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

	{if $payoff_for}
		<input type="hidden" name="type" value="{$transaction::TYPE_PAYOFF}" />
		<input type="hidden" name="payoff_for" value="{$payoff_for.id}" />
		<fieldset>
			<legend>{if $payoff_for->type == $transaction::TYPE_DEBT}Règlement de dette{else}Règlement de créance{/if}</legend>
			<dl>
				<dt>Écriture d'origine</dt>
				<dd><a class="num" href="{$admin_url}acc/transactions/details.php?id={$payoff_for.id}">#{$payoff_for.id}</a></dd>
				{input type="list" target="acc/charts/accounts/selector.php?targets=%s&chart=%d"|args:$payoff_targets,$chart_id name="account_payoff" label="Compte de règlement" required=1}
			</dl>
		</fieldset>
	{else}
		<fieldset>
			<legend>Type d'écriture</legend>
			<dl>

				{input type="radio" name="type" value=$transaction::TYPE_REVENUE default=-1 source=$transaction label="Recette"}
				{input type="radio" name="type" value=$transaction::TYPE_EXPENSE default=-1 source=$transaction label="Dépense"}
				{input type="radio" name="type" value=$transaction::TYPE_TRANSFER default=-1 source=$transaction label="Virement" help="Faire un virement entre comptes, déposer des espèces en banque, etc."}
				{input type="radio" name="type" value=$transaction::TYPE_DEBT default=-1 source=$transaction label="Dette" help="Quand l'association doit de l'argent à un membre ou un fournisseur"}
				{input type="radio" name="type" value=$transaction::TYPE_CREDIT default=-1 source=$transaction label="Créance" help="Quand un membre ou un fournisseur doit de l'argent à l'association"}
				{input type="radio" name="type" value=$transaction::TYPE_ADVANCED default=-1 source=$transaction label="Saisie avancée" help="Choisir les comptes du plan comptable, ventiler une écriture sur plusieurs comptes, etc."}





			</dl>
		</fieldset>
	{/if}

	<fieldset>
		<legend>Informations</legend>
		<dl>
			{input type="date" name="date" default=$date label="Date" required=1 source=$transaction}
			{input type="text" name="label" label="Libellé" required=1 source=$transaction}
			{input type="text" name="reference" label="Numéro de pièce comptable" help="Numéro de facture, de note de frais, etc."}
		</dl>
		<dl data-types="all-but-advanced">
			{input type="money" name="amount" label="Montant" required=1 default=$amount}
		</dl>
	</fieldset>

	{if !$payoff_for}

		{foreach from=$types item="type"}
			<fieldset data-types="t{$type.id}">
				<legend>{$type.label}</legend>
				<dl>
				{foreach from=$type.accounts key="key" item="account"}
					{input type="list" target="acc/charts/accounts/selector.php?targets=%s&chart=%d"|args:$account.targets,$chart_id name="account_%d_%d"|args:$type.id,$key label=$account.label required=1}
				{/foreach}
				</dl>
			</fieldset>
		{/foreach}
	{/if}

	{* Saisie avancée *}









|
|


















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


















|




|







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

{include file="acc/_year_select.tpl"}

<form method="post" action="{$self_url_no_qs}" enctype="multipart/form-data" data-focus="1">
	{form_errors}

	{if $ok}
		<p class="block confirm">
			L'écriture numéro <a href="details.php?id={$ok}">{$ok}</a> a été ajoutée.
			(<a href="details.php?id={$ok}">Voir l'écriture</a>)
		</p>
	{/if}

	{if $payoff_for}
		<input type="hidden" name="type" value="{$transaction::TYPE_PAYOFF}" />
		<input type="hidden" name="payoff_for" value="{$payoff_for.id}" />
		<fieldset>
			<legend>{if $payoff_for->type == $transaction::TYPE_DEBT}Règlement de dette{else}Règlement de créance{/if}</legend>
			<dl>
				<dt>Écriture d'origine</dt>
				<dd><a class="num" href="{$admin_url}acc/transactions/details.php?id={$payoff_for.id}">#{$payoff_for.id}</a></dd>
				{input type="list" target="acc/charts/accounts/selector.php?targets=%s&chart=%d"|args:$payoff_targets,$chart_id name="account_payoff" label="Compte de règlement" required=1}
			</dl>
		</fieldset>
	{else}
		<fieldset>
			<legend>Type d'écriture</legend>
			<dl>
			{foreach from=$types_details item="type"}
				<label class="radio-btn">
					{input type="radio" name="type" value=$type.id source=$transaction}

					<div>
						<h3>{$type.label}</h3>
						{if !empty($type.help)}
							<p>{$type.help}</p>
						{/if}
					</div>
				</label>
			{/foreach}
			</dl>
		</fieldset>
	{/if}

	<fieldset>
		<legend>Informations</legend>
		<dl>
			{input type="date" name="date" default=$date label="Date" required=1 source=$transaction}
			{input type="text" name="label" label="Libellé" required=1 source=$transaction}
			{input type="text" name="reference" label="Numéro de pièce comptable" help="Numéro de facture, de note de frais, etc."}
		</dl>
		<dl data-types="all-but-advanced">
			{input type="money" name="amount" label="Montant" required=1 default=$amount}
		</dl>
	</fieldset>

	{if !$payoff_for}

		{foreach from=$types_details item="type"}
			<fieldset data-types="t{$type.id}">
				<legend>{$type.label}</legend>
				<dl>
				{foreach from=$type.accounts key="key" item="account"}
					{input type="list" target="acc/charts/accounts/selector.php?targets=%s&chart=%d"|args:$account.targets_string,$chart_id name="account_%d_%d"|args:$type.id,$key label=$account.label required=1}
				{/foreach}
				</dl>
			</fieldset>
		{/foreach}
	{/if}

	{* Saisie avancée *}

Modified src/www/admin/acc/transactions/new.php from [f020545b0c] to [1707c5a857].

13
14
15
16
17
18
19

20
21
22
23
24
25
26
	Utils::redirect(ADMIN_URL . 'acc/years/?msg=OPEN');
}

$chart = $current_year->chart();
$accounts = $chart->accounts();

$transaction = new Transaction;

$lines = [[], []];
$amount = 0;
$payoff_for = qg('payoff_for') ?: f('payoff_for');

// Quick pay-off for debts and credits, directly from a debt/credit details page
if ($id = $payoff_for) {
	$payoff_for = $transaction->payOffFrom($id);







>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	Utils::redirect(ADMIN_URL . 'acc/years/?msg=OPEN');
}

$chart = $current_year->chart();
$accounts = $chart->accounts();

$transaction = new Transaction;
$transaction->type = -1;
$lines = [[], []];
$amount = 0;
$payoff_for = qg('payoff_for') ?: f('payoff_for');

// Quick pay-off for debts and credits, directly from a debt/credit details page
if ($id = $payoff_for) {
	$payoff_for = $transaction->payOffFrom($id);
71
72
73
74
75
76
77
78
79
80
81
82
}

$tpl->assign('date', $session->get('acc_last_date') ?: $current_year->start_date->format('d/m/Y'));
$tpl->assign(compact('transaction', 'payoff_for', 'amount', 'lines'));
$tpl->assign('payoff_targets', implode(':', [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING]));
$tpl->assign('ok', (int) qg('ok'));

$tpl->assign('types', Transaction::getTypesDetails());
$tpl->assign('chart_id', $chart->id());

$tpl->assign('analytical_accounts', ['' => '-- Aucun'] + $accounts->listAnalytical());
$tpl->display('acc/transactions/new.tpl');







|




72
73
74
75
76
77
78
79
80
81
82
83
}

$tpl->assign('date', $session->get('acc_last_date') ?: $current_year->start_date->format('d/m/Y'));
$tpl->assign(compact('transaction', 'payoff_for', 'amount', 'lines'));
$tpl->assign('payoff_targets', implode(':', [Account::TYPE_BANK, Account::TYPE_CASH, Account::TYPE_OUTSTANDING]));
$tpl->assign('ok', (int) qg('ok'));

$tpl->assign('types_details', Transaction::getTypesDetails());
$tpl->assign('chart_id', $chart->id());

$tpl->assign('analytical_accounts', ['' => '-- Aucun'] + $accounts->listAnalytical());
$tpl->display('acc/transactions/new.tpl');