Overview
Comment:Merge with trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | templates
Files: files | file ages | folders
SHA3-256: 6a4f6f6abc066bc6e18facd808565bcbbf2145ae91a3c19a301ef70356f77cb5
User & Date: bohwaz on 2021-12-22 22:04:13
Other Links: branch diff | manifest | tags
Context
2021-12-24
02:14
Allow to update JSON data, but for validation we need to fetch and decode JSON first check-in: 2ea97a9a6d user: bohwaz tags: templates
2021-12-22
22:04
Merge with trunk check-in: 6a4f6f6abc user: bohwaz tags: templates
19:57
Avoid duplicates when copying a service check-in: a9cf5c62d0 user: bohwaz tags: trunk, stable
2021-12-21
02:30
Duplicate after merge check-in: f9dd9435f9 user: bohwaz tags: templates
Changes

Modified src/include/lib/Garradin/Accounting/Accounts.php from [9d40c3912e] to [be892e76e5].

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
	}

	/**
	 * Return only analytical accounts
	 */
	public function listAnalytical(): array
	{
		return $this->em->DB()->getAssoc($this->em->formatQuery('SELECT id, label FROM @TABLE WHERE id_chart = ? AND type = ? ORDER BY code COLLATE NOCASE;'), $this->chart_id, Account::TYPE_ANALYTICAL);
	}

	/**
	 * Return only analytical accounts
	 */
	public function listVolunteering(): array
	{







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
	}

	/**
	 * Return only analytical accounts
	 */
	public function listAnalytical(): array
	{
		return $this->em->DB()->getAssoc($this->em->formatQuery('SELECT id, label FROM @TABLE WHERE id_chart = ? AND type = ? ORDER BY label COLLATE NOCASE;'), $this->chart_id, Account::TYPE_ANALYTICAL);
	}

	/**
	 * Return only analytical accounts
	 */
	public function listVolunteering(): array
	{

Modified src/include/lib/Garradin/Entities/Accounting/Account.php from [cacd2727a4] to [71842e7b88].

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
		$this->assert(array_key_exists($this->type, self::TYPES_NAMES), 'Type invalide');
		$this->assert(array_key_exists($this->position, self::POSITIONS_NAMES), 'Position invalide');
		$this->assert($this->user === 0 || $this->user === 1);

		parent::selfCheck();
	}

	public function listJournal(int $year_id, bool $simple = false)
	{

		$columns = self::LIST_COLUMNS;

		$tables = 'acc_transactions_lines l
			INNER JOIN acc_transactions t ON t.id = l.id_transaction
			LEFT JOIN acc_accounts b ON b.id = l.id_analytical';
		$conditions = sprintf('l.id_account = %d AND t.id_year = %d', $this->id(), $year_id);

		$sum = 0;
		$reverse = $simple && self::isReversed($this->type) ? -1 : 1;










		if ($simple) {
			unset($columns['debit']['label'], $columns['credit']['label'], $columns['line_label']);
			$columns['line_reference']['label'] = 'Réf. paiement';
			$columns['change']['select'] = sprintf($columns['change']['select'], $reverse);
		}
		else {







|

>









>
>
>
>
>
>
>
>
>







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
		$this->assert(array_key_exists($this->type, self::TYPES_NAMES), 'Type invalide');
		$this->assert(array_key_exists($this->position, self::POSITIONS_NAMES), 'Position invalide');
		$this->assert($this->user === 0 || $this->user === 1);

		parent::selfCheck();
	}

	public function listJournal(int $year_id, bool $simple = false, ?DateTimeInterface $start = null, ?DateTimeInterface $end = null)
	{
		$db = DB::getInstance();
		$columns = self::LIST_COLUMNS;

		$tables = 'acc_transactions_lines l
			INNER JOIN acc_transactions t ON t.id = l.id_transaction
			LEFT JOIN acc_accounts b ON b.id = l.id_analytical';
		$conditions = sprintf('l.id_account = %d AND t.id_year = %d', $this->id(), $year_id);

		$sum = 0;
		$reverse = $simple && self::isReversed($this->type) ? -1 : 1;

		if ($start) {
			$conditions .= sprintf(' AND t.date >= %s', $db->quote($start->format('Y-m-d')));
			$sum = $this->getSumAtDate($year_id, $start) * $reverse;
		}

		if ($end) {
			$conditions .= sprintf(' AND t.date <= %s', $db->quote($end->format('Y-m-d')));
		}

		if ($simple) {
			unset($columns['debit']['label'], $columns['credit']['label'], $columns['line_label']);
			$columns['line_reference']['label'] = 'Réf. paiement';
			$columns['change']['select'] = sprintf($columns['change']['select'], $reverse);
		}
		else {
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458


	public function getSumAtDate(int $year_id, DateTimeInterface $date, bool $reconciled_only = false): int
	{
		$sql = sprintf('SELECT SUM(l.credit) - SUM(l.debit)
			FROM acc_transactions_lines l
			INNER JOIN acc_transactions t ON t.id = l.id_transaction
			wHERE l.id_account = ? AND t.id_year = ? AND t.date < ? %s;',
			$reconciled_only ? 'AND l.reconciled = 1' : '');
		return (int) DB::getInstance()->firstColumn($sql, $this->id(), $year_id, $date->format('Y-m-d'));
	}

	public function importSimpleForm(array $translate_type_position, array $translate_type_codes, ?array $source = null)
	{
		if (null === $source) {







|







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468


	public function getSumAtDate(int $year_id, DateTimeInterface $date, bool $reconciled_only = false): int
	{
		$sql = sprintf('SELECT SUM(l.credit) - SUM(l.debit)
			FROM acc_transactions_lines l
			INNER JOIN acc_transactions t ON t.id = l.id_transaction
			WHERE l.id_account = ? AND t.id_year = ? AND t.date < ? %s;',
			$reconciled_only ? 'AND l.reconciled = 1' : '');
		return (int) DB::getInstance()->firstColumn($sql, $this->id(), $year_id, $date->format('Y-m-d'));
	}

	public function importSimpleForm(array $translate_type_position, array $translate_type_codes, ?array $source = null)
	{
		if (null === $source) {

Modified src/include/lib/Garradin/Entities/Accounting/Transaction.php from [c396fad605] to [fac4ec7e24].

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
				$account->targets_string = implode(':', $account->targets);
			}
		}

		return $details;
	}

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

		if (!$this->_related) {
			throw new \LogicException('Écriture d\'origine invalide');
		}

		$this->id_related = $this->_related->id();
		$this->label = ($this->_related->type == Transaction::TYPE_DEBT ? 'Règlement de dette : ' : 'Règlement de créance : ') . $this->_related->label;
		$this->type = $this->_related->type;

		$out = (object) [







|




|







820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
				$account->targets_string = implode(':', $account->targets);
			}
		}

		return $details;
	}

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

		if (!$this->_related) {
			return null;
		}

		$this->id_related = $this->_related->id();
		$this->label = ($this->_related->type == Transaction::TYPE_DEBT ? 'Règlement de dette : ' : 'Règlement de créance : ') . $this->_related->label;
		$this->type = $this->_related->type;

		$out = (object) [

Modified src/include/lib/Garradin/Entities/Services/Service.php from [1865b4e6a7] to [bac627a89f].

1
2
3
4
5

6
7
8
9
10
11
12
<?php

namespace Garradin\Entities\Services;

use Garradin\Config;

use Garradin\DynamicList;
use Garradin\Entity;
use Garradin\ValidationException;
use Garradin\Utils;
use Garradin\Services\Fees;

class Service extends Entity





>







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

namespace Garradin\Entities\Services;

use Garradin\Config;
use Garradin\DB;
use Garradin\DynamicList;
use Garradin\Entity;
use Garradin\ValidationException;
use Garradin\Utils;
use Garradin\Services\Fees;

class Service extends Entity
128
129
130
131
132
133
134
135







	public function expiredUsersList(): DynamicList
	{
		$list = $this->paidUsersList();
		$conditions = sprintf('su.id_service = %d AND su.expiry_date < date() AND m.id_category NOT IN (SELECT id FROM users_categories WHERE hidden = 1)', $this->id());
		$list->setConditions($conditions);
		return $list;
	}
}














|
>
>
>
>
>
>
>
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
	public function expiredUsersList(): DynamicList
	{
		$list = $this->paidUsersList();
		$conditions = sprintf('su.id_service = %d AND su.expiry_date < date() AND m.id_category NOT IN (SELECT id FROM users_categories WHERE hidden = 1)', $this->id());
		$list->setConditions($conditions);
		return $list;
	}

	public function getUsers(bool $paid_only = false) {
		$where = $paid_only ? 'AND paid = 1' : '';
		$id_field = Config::getInstance()->champ_identite;
		$sql = sprintf('SELECT su.id_user, u.%s FROM services_users su INNER JOIN membres u ON u.id = su.id_user WHERE su.id_service = ? %s;', $id_field, $where);
		return DB::getInstance()->getAssoc($sql, $this->id());
	}
}

Modified src/include/lib/Garradin/Entities/Services/Service_User.php from [70686305f9] to [9c410c5349].

41
42
43
44
45
46
47
48

49



















50
51
52
53
54
55
56
	protected $_service, $_fee;

	public function selfCheck(): void
	{
		$this->paid = (bool) $this->paid;
		$this->assert($this->id_service, 'Aucune activité spécifiée');
		$this->assert($this->id_user, 'Aucun membre spécifié');
		$this->assert($this->exists() || !DB::getInstance()->test(self::TABLE, 'id_user = ? AND id_service = ? AND date = ?', $this->id_user, $this->id_service, $this->date->format('Y-m-d')), 'Cette activité a déjà été enregistrée pour ce membre et cette date');

		$this->assert(!$this->exists() || !DB::getInstance()->test(self::TABLE, 'id_user = ? AND id_service = ? AND date = ? AND id != ?', $this->id_user, $this->id_service, $this->date->format('Y-m-d'), $this->id()), 'Cette activité a déjà été enregistrée pour ce membre et cette date');



















	}

	public function importForm(?array $source = null)
	{
		if (null === $source) {
			$source = $_POST;
		}







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







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
	protected $_service, $_fee;

	public function selfCheck(): void
	{
		$this->paid = (bool) $this->paid;
		$this->assert($this->id_service, 'Aucune activité spécifiée');
		$this->assert($this->id_user, 'Aucun membre spécifié');
		$this->assert(!$this->isDuplicate(), 'Cette activité a déjà été enregistrée pour ce membre et cette date');
	}

	public function isDuplicate(bool $using_date = true): bool
	{
		$params = [
			'id_user' => $this->id_user,
			'id_service' => $this->id_service,
		];

		if ($using_date) {
			$params['date'] = $this->date->format('Y-m-d');
		}

		if ($this->exists()) {
			$params['id'] = $this->id();
		}

		$where = array_map(fn($k) => sprintf('%s = ?', $k), array_keys($params));
		$where = implode(' AND ', $where);

		return DB::getInstance()->test(self::TABLE, $where, array_values($params));
	}

	public function importForm(?array $source = null)
	{
		if (null === $source) {
			$source = $_POST;
		}
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
		$transaction->importFromNewForm($source);
		$transaction->save();
		$transaction->linkToUser($this->id_user, $this->id());

		return $transaction;
	}

	static public function saveFromForm(int $user_id, ?array $source = null)
	{
		if (null === $source) {
			$source = $_POST;
		}

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


		$su = new self;
		$su->date = new \DateTime;
		$su->importForm($source);


		if ($su->id_fee && $su->fee()->id_account && $su->id_user) {
			$su->expected_amount = $su->fee()->getAmountForUser($su->id_user);
		}










		$su->save();

		if ($su->id_fee && $su->fee()->id_account
			&& !empty($source['amount'])
			&& !empty($source['create_payment'])) {
			try {
				$su->addPayment($user_id, $source);
			}
			catch (ValidationException $e) {
				if ($e->getMessage() == 'Il n\'est pas possible de créer ou modifier une écriture dans un exercice clôturé') {
					throw new ValidationException('Impossible d\'enregistrer l\'inscription : ce tarif d\'activité est lié à un exercice clôturé. Merci de modifier le tarif et choisir un autre exercice.', 0, $e);
				}
				else {
					throw $e;

				}
			}
		}

		$db->commit();

		return $su;
	}
}







|








>
|
|
|
>

|
|
|

>
>
>
>
>
>
>
>
>
|

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









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
		$transaction->importFromNewForm($source);
		$transaction->save();
		$transaction->linkToUser($this->id_user, $this->id());

		return $transaction;
	}

	static public function createFromForm(array $users, int $creator_id, bool $from_copy = false, ?array $source = null)
	{
		if (null === $source) {
			$source = $_POST;
		}

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

		foreach ($users as $id => $name) {
			$su = new self;
			$su->date = new \DateTime;
			$su->importForm($source);
			$su->id_user = (int) $id;

			if ($su->id_fee && $su->fee()->id_account && $su->id_user) {
				$su->expected_amount = $su->fee()->getAmountForUser($su->id_user);
			}

			if ($su->isDuplicate($from_copy ? false : true)) {
				if ($from_copy) {
					continue;
				}
				else {
					throw new ValidationException(sprintf('%s : Cette activité a déjà été enregistrée pour ce membre et cette date', $name));
				}
			}

			$su->save();

			if ($su->id_fee && $su->fee()->id_account
				&& !empty($source['amount'])
				&& !empty($source['create_payment'])) {
				try {
					$su->addPayment($creator_id, $source);
				}
				catch (ValidationException $e) {
					if ($e->getMessage() == 'Il n\'est pas possible de créer ou modifier une écriture dans un exercice clôturé') {
						throw new ValidationException('Impossible d\'enregistrer l\'inscription : ce tarif d\'activité est lié à un exercice clôturé. Merci de modifier le tarif et choisir un autre exercice.', 0, $e);
					}
					else {
						throw $e;
					}
				}
			}
		}

		$db->commit();

		return $su;
	}
}

Modified src/include/lib/Garradin/UserTemplate/CommonModifiers.php from [ff55855833] to [ec639e95ae].

401
402
403
404
405
406
407







408
409
410
411
412
413
414
415

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

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








		if ($type == 'select') {
			$input = sprintf('<select %s>', $attributes_string);

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

			$input .= '</select>';







>
>
>
>
>
>
>
|







401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

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

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

		if ($type == 'radio-btn') {
			$radio = self::formInput(array_merge($params, ['type' => 'radio', 'label' => null, 'help' => null]));
			$out = sprintf('<dd class="radio-btn">%s
				<label for="f_%s_%s"><div><h3>%s</h3>%s</div></label>
			</dd>', $radio, htmlspecialchars($name), htmlspecialchars($value), htmlspecialchars($label), isset($params['help']) ? '<p>' . htmlspecialchars($params['help']) . '</p>' : '');
			return $out;
		}
		elseif ($type == 'select') {
			$input = sprintf('<select %s>', $attributes_string);

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

			$input .= '</select>';

Modified src/include/lib/Garradin/UserTemplate/Functions.php from [733e4434da] to [99cd2b0ba8].

54
55
56
57
58
59
60



61








62
63
64
65
66
67
68
69
70
71
72
73
			throw new Brindille_Exception('Unique document name could not be found');
		}

		if (empty($params['name']) || !ctype_alnum($params['name'])) {
			throw new Brindille_Exception('Missing or invalid index name');
		}




		if (empty($params['columns'])) {








			throw new Brindille_Exception('Missing or invalid index columns');
		}

		$db = DB::getInstance();
		$db->exec(sprintf('CREATE INDEX IF NOT EXISTS documents_%s_%s ON documents_data (document, %s);', $id, $params['name'], $params['columns']));
	}

	static public function save(array $params, Brindille $tpl, int $line): void
	{
		$id = Utils::basename(Utils::dirname($tpl->_tpl_path));

		if (!$id) {







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



<
|







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
			throw new Brindille_Exception('Unique document name could not be found');
		}

		if (empty($params['name']) || !ctype_alnum($params['name'])) {
			throw new Brindille_Exception('Missing or invalid index name');
		}

		$indexes = ['document'];
		$db = DB::getInstance();

		if (empty($params['column'])) {
			$indexes[] = sprintf('json_extract(value, %s)', $db->quote($params['column']));
		}

		if (empty($params['expression'])) {
			$indexes[] = $params['expression'];
		}

		if (count($indexes) == 1) {
			throw new Brindille_Exception('Missing or invalid index columns');
		}


		$db->exec(sprintf('CREATE INDEX IF NOT EXISTS documents_%s_%s ON documents_data (%s);', $id, implode(',', $indexes)));
	}

	static public function save(array $params, Brindille $tpl, int $line): void
	{
		$id = Utils::basename(Utils::dirname($tpl->_tpl_path));

		if (!$id) {
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
	}

	static public function signature_url(): string
	{
		$file = Config::getInstance()->file('signature');

		if (!$file) {
			return '';
		}

		return 'data:image/png;base64,' . base64_encode($file->fetch());
	}

	static public function include(array $params, UserTemplate $ut, int $line): void
	{







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	}

	static public function signature_url(): string
	{
		$file = Config::getInstance()->file('signature');

		if (!$file) {
			return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
		}

		return 'data:image/png;base64,' . base64_encode($file->fetch());
	}

	static public function include(array $params, UserTemplate $ut, int $line): void
	{

Modified src/include/lib/Garradin/Utils.php from [74b0fa5592] to [1fb8515d7b].

55
56
57
58
59
60
61




62
63
64
65
66
67
68
69



70
71
72
73
74
75
76
        'Fri' => 'ven',
        'Sat' => 'sam',
        'Sun' => 'dim',
    ];

    static public function get_datetime($ts)
    {




        if (is_object($ts) && $ts instanceof \DateTimeInterface) {
            return $ts;
        }
        elseif (is_numeric($ts)) {
            $ts = new \DateTime('@' . $ts);
            $ts->setTimezone(new \DateTimeZone(date_default_timezone_get()));
            return $ts;
        }



        elseif (strlen($ts) == 10) {
            return \DateTime::createFromFormat('!Y-m-d', $ts);
        }
        elseif (strlen($ts) == 19) {
            return \DateTime::createFromFormat('Y-m-d H:i:s', $ts);
        }
        else {







>
>
>
>








>
>
>







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
        'Fri' => 'ven',
        'Sat' => 'sam',
        'Sun' => 'dim',
    ];

    static public function get_datetime($ts)
    {
        if (null === $ts) {
            return null;
        }

        if (is_object($ts) && $ts instanceof \DateTimeInterface) {
            return $ts;
        }
        elseif (is_numeric($ts)) {
            $ts = new \DateTime('@' . $ts);
            $ts->setTimezone(new \DateTimeZone(date_default_timezone_get()));
            return $ts;
        }
        elseif (preg_match('!^\d{2}/\d{2}/\d{4}$!', $ts)) {
            return \DateTime::createFromFormat('!d/m/Y', $ts);
        }
        elseif (strlen($ts) == 10) {
            return \DateTime::createFromFormat('!Y-m-d', $ts);
        }
        elseif (strlen($ts) == 19) {
            return \DateTime::createFromFormat('Y-m-d H:i:s', $ts);
        }
        else {

Modified src/include/lib/dependencies.list from [e9b8ffa0d9] to [aa4290a8f6].

10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
KD2/FossilInstaller.php
KD2/HTTP.php
KD2/Graphics/Image.php
KD2/Graphics/QRCode.php
KD2/Graphics/SVG/Pie.php
KD2/Graphics/SVG/Plot.php
KD2/Graphics/SVG/Bar.php

KD2/Office/Calc/Writer.php
KD2/Security.php
KD2/Security_OTP.php
KD2/SimpleDiff.php
KD2/SkrivLite.php
KD2/Smartyer.php
KD2/SMTP.php
KD2/Translate.php
KD2/UserSession.php
KD2/ZipWriter.php
Parsedown.php







>











10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
KD2/FossilInstaller.php
KD2/HTTP.php
KD2/Graphics/Image.php
KD2/Graphics/QRCode.php
KD2/Graphics/SVG/Pie.php
KD2/Graphics/SVG/Plot.php
KD2/Graphics/SVG/Bar.php
KD2/JSONSchema.php
KD2/Office/Calc/Writer.php
KD2/Security.php
KD2/Security_OTP.php
KD2/SimpleDiff.php
KD2/SkrivLite.php
KD2/Smartyer.php
KD2/SMTP.php
KD2/Translate.php
KD2/UserSession.php
KD2/ZipWriter.php
Parsedown.php

Modified src/templates/acc/accounts/journal.tpl from [92b1619c26] to [f4432495e8].

61
62
63
64
65
66
67







68
69
















70
71
72
73
74
75
76
			{linkbutton href="!acc/transactions/new.php?account=%d"|args:$account.id label="Saisir une écriture dans ce compte" shape="plus"}
		{/if}
		</aside>
		<ul>
			<li{if $simple} class="current"{/if}><a href="?id={$account.id}&amp;simple=1&amp;year={$year.id}">Vue simplifiée</a></li>
			<li{if !$simple} class="current"{/if}><a href="?id={$account.id}&amp;simple=0&amp;year={$year.id}">Vue comptable</a></li>
		</ul>







	</nav>
{/if}

















<form method="post" action="{$admin_url}acc/transactions/actions.php">

{include file="common/dynamic_list_head.tpl" check=$can_edit}

	{foreach from=$list->iterate() item="line"}
		<tr>







>
>
>
>
>
>
>


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







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
			{linkbutton href="!acc/transactions/new.php?account=%d"|args:$account.id label="Saisir une écriture dans ce compte" shape="plus"}
		{/if}
		</aside>
		<ul>
			<li{if $simple} class="current"{/if}><a href="?id={$account.id}&amp;simple=1&amp;year={$year.id}">Vue simplifiée</a></li>
			<li{if !$simple} class="current"{/if}><a href="?id={$account.id}&amp;simple=0&amp;year={$year.id}">Vue comptable</a></li>
		</ul>

	{if !$filter.start && !$filter.end}
	<aside>
		{linkbutton shape="search" href="?start=1" label="Filtrer" onclick="g.toggle('#filterForm', true); this.remove(); return false;"}
	</aside>
	{/if}

	</nav>
{/if}

<form method="get" action="{$self_url}"{if !$filter.start && !$filter.end} class="hidden"{/if} id="filterForm">
	<fieldset>
		<legend>Filtrer par date</legend>
		<p>
			Du
			{input type="date" name="start" source=$filter default=$year.start_date}
			au
			{input type="date" name="end" source=$filter default=$year.end_date}
			<input type="hidden" name="id" value="{$account.id}" />
			<input type="hidden" name="year" value="{$year.id}" />
			<input type="hidden" name="simple" value="{$simple}" />
			<input type="submit" value="Filtrer" />
		</p>
	</fieldset>
</form>

<form method="post" action="{$admin_url}acc/transactions/actions.php">

{include file="common/dynamic_list_head.tpl" check=$can_edit}

	{foreach from=$list->iterate() item="line"}
		<tr>
111
112
113
114
115
116
117

118
119



120
121
122
123
124
125
126
	</tbody>
	<tfoot>
		<tr>
			{if $can_edit}
				<td class="check"><input type="checkbox" value="Tout cocher / décocher" id="f_all2" /><label for="f_all2"></label></td>
			{/if}
			{if !$simple}<td></td>{/if}

			<td colspan="3">Solde</td>
			<td class="money">{$sum|raw|money:false}</td>



			{if !$simple}<td></td>{/if}
			<td class="actions" colspan="5">
				{if $can_edit}
					<em>Pour les écritures cochées :</em>
					<input type="hidden" name="from" value="{$self_url}" />
					<input type="hidden" name="year" value="{$year.id}" />
					{csrf_field key="projects_action"}







>
|
|
>
>
>







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	</tbody>
	<tfoot>
		<tr>
			{if $can_edit}
				<td class="check"><input type="checkbox" value="Tout cocher / décocher" id="f_all2" /><label for="f_all2"></label></td>
			{/if}
			{if !$simple}<td></td>{/if}
			{if null !== $sum}
				<td colspan="3">Solde</td>
				<td class="money">{$sum|raw|money:false}</td>
			{else}
				<td colspan="4"></td>
			{/if}
			{if !$simple}<td></td>{/if}
			<td class="actions" colspan="5">
				{if $can_edit}
					<em>Pour les écritures cochées :</em>
					<input type="hidden" name="from" value="{$self_url}" />
					<input type="hidden" name="year" value="{$year.id}" />
					{csrf_field key="projects_action"}

Modified src/templates/admin/membres/_list_actions.tpl from [70c6941282] to [b514dbed79].

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
						<option value="">— Choisir une action à effectuer —</option>
						<option value="move">Changer de catégorie</option>
						<option value="template">Générer des documents</option>
						{if !isset($export) || $export != false}
						<option value="csv">Exporter en tableau CSV</option>
						<option value="ods">Exporter en classeur Office</option>
						{/if}
						<option value="delete">Supprimer</option>
					</select>
					<noscript>
						<input type="submit" value="OK" />
					</noscript>
				</td>
			</tr>
		</tfoot>







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
						<option value="">— Choisir une action à effectuer —</option>
						<option value="move">Changer de catégorie</option>
						<option value="template">Générer des documents</option>
						{if !isset($export) || $export != false}
						<option value="csv">Exporter en tableau CSV</option>
						<option value="ods">Exporter en classeur Office</option>
						{/if}
						<option value="delete">Supprimer le membre</option>
					</select>
					<noscript>
						<input type="submit" value="OK" />
					</noscript>
				</td>
			</tr>
		</tfoot>

Modified src/templates/admin/membres/fiche.tpl from [858a55f227] to [56a79db109].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    </dd>
    {/foreach}
    <dd>
        {if count($services)}
            {linkbutton href="!services/user/?id=%d"|args:$membre.id label="Liste des inscriptions aux activités" shape="menu"}
        {/if}
        {if $session->canAccess($session::SECTION_USERS, $session::ACCESS_WRITE)}
            {linkbutton href="!services/user/add.php?user=%d"|args:$membre.id label="Inscrire à une activité" shape="plus"}
        {/if}
    </dd>
    {if count($services)}
    <dd>
        {linkbutton shape="alert" label="Liste des rappels envoyés" href="!services/reminders/user.php?id=%d"|args:$membre.id}
    </dd>
    {/if}







|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    </dd>
    {/foreach}
    <dd>
        {if count($services)}
            {linkbutton href="!services/user/?id=%d"|args:$membre.id label="Liste des inscriptions aux activités" shape="menu"}
        {/if}
        {if $session->canAccess($session::SECTION_USERS, $session::ACCESS_WRITE)}
            {linkbutton href="!services/user/subscribe.php?user=%d"|args:$membre.id label="Inscrire à une activité" shape="plus"}
        {/if}
    </dd>
    {if count($services)}
    <dd>
        {linkbutton shape="alert" label="Liste des rappels envoyés" href="!services/reminders/user.php?id=%d"|args:$membre.id}
    </dd>
    {/if}

Modified src/templates/services/user/_service_user_form.tpl from [10a2edc910] to [75a8977fdd].

1
2
3
4
5
6
7
8
9
10
11
12
<?php
assert(isset($create) && is_bool($create));
assert(isset($has_past_services) && is_bool($has_past_services));
assert(isset($current_only) && is_bool($current_only));
assert(!empty($user_name) && !empty($user_id));
assert(isset($form_url) && is_string($form_url));
assert(isset($today) && $today instanceof \DateTimeInterface);
assert($create === false || isset($account_targets));
assert(isset($grouped_services) && is_array($grouped_services));
?>

<form method="post" action="{$self_url}" data-focus="1" data-create="{$create|escape:json}">




<







1
2
3
4

5
6
7
8
9
10
11
<?php
assert(isset($create) && is_bool($create));
assert(isset($has_past_services) && is_bool($has_past_services));
assert(isset($current_only) && is_bool($current_only));

assert(isset($form_url) && is_string($form_url));
assert(isset($today) && $today instanceof \DateTimeInterface);
assert($create === false || isset($account_targets));
assert(isset($grouped_services) && is_array($grouped_services));
?>

<form method="post" action="{$self_url}" data-focus="1" data-create="{$create|escape:json}">
20
21
22
23
24
25
26

27


28









29
30
31
32
33
34
35
	</nav>
	{/if}

	<fieldset>
		<legend>Inscrire un membre à une activité</legend>

		<dl>

			<dt>Membre sélectionné</dt>


			<dd><h3>{$user_name}</h3><input type="hidden" name="id_user" value="{$user_id}" /></dd>










			<dt><label for="f_service_ID">Activité</label> <b>(obligatoire)</b></dt>

			{foreach from=$grouped_services item="service"}
				<dd class="radio-btn">
					{input type="radio" name="id_service" value=$service.id data-duration=$service.duration data-expiry=$service.expiry_date|date_short label=null source=$service_user}
					<label for="f_id_service_{$service.id}">







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







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
	</nav>
	{/if}

	<fieldset>
		<legend>Inscrire un membre à une activité</legend>

		<dl>
		{if $create && $users}
			<dt>Membres inscrits</dt>
			{if count($users) <= 10}
				{foreach from=$users key="id" item="name"}
				<dd>{$name}<input type="hidden" name="users[{$id}]" value="{$name}" /></dd>
				{/foreach}
			{else}
				<dd>{$users|count} membres sélectionnés</dd>
			{/if}
		{elseif $create && $copy_service}
			<dt>Recopier depuis l'activité</dt>
			<dd><strong>{$copy_service.label}</strong><input type="hidden" name="copy_service" value="{$copy_service.id}" /></dd>
			<dd><em>{if $copy_service_only_paid}(seulement les inscriptions marquées comme payées){else}(toutes les inscriptions){/if}</em><input type="hidden" name="copy_service_only_paid" value="{$copy_service_only_paid}" /></dd>
		{/if}

			<dt><label for="f_service_ID">Activité</label> <b>(obligatoire)</b></dt>

			{foreach from=$grouped_services item="service"}
				<dd class="radio-btn">
					{input type="radio" name="id_service" value=$service.id data-duration=$service.duration data-expiry=$service.expiry_date|date_short label=null source=$service_user}
					<label for="f_id_service_{$service.id}">
65
66
67
68
69
70
71
72
73
74
75


76
77


78
79
80
81
82
83
84
			{foreach from=$service.fees key="service_id" item="fee"}
			<dd class="radio-btn">
				{input type="radio" name="id_fee" value=$fee.id data-user-amount=$fee.user_amount data-account=$fee.id_account data-year=$fee.id_year label=null source=$service_user }
				<label for="f_id_fee_{$fee.id}">
					<div>
						<h3>{$fee.label}</h3>
						<p>
							{if !$fee.user_amount}
								prix libre ou gratuit
							{elseif $fee.user_amount && $fee.formula}
								<strong>{$fee.user_amount|raw|money_currency}</strong> (montant calculé)


							{elseif $fee.user_amount}
								<strong>{$fee.user_amount|raw|money_currency}</strong>


							{/if}
						</p>
						{if $fee.description}
						<p class="help">
							{$fee.description|escape|nl2br}
						</p>
						{/if}







<
<
|

>
>


>
>







76
77
78
79
80
81
82


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
			{foreach from=$service.fees key="service_id" item="fee"}
			<dd class="radio-btn">
				{input type="radio" name="id_fee" value=$fee.id data-user-amount=$fee.user_amount data-account=$fee.id_account data-year=$fee.id_year label=null source=$service_user }
				<label for="f_id_fee_{$fee.id}">
					<div>
						<h3>{$fee.label}</h3>
						<p>


							{if $fee.user_amount && $fee.formula}
								<strong>{$fee.user_amount|raw|money_currency}</strong> (montant calculé)
							{elseif $fee.formula}
								montant calculé, variable selon les membres
							{elseif $fee.user_amount}
								<strong>{$fee.user_amount|raw|money_currency}</strong>
							{else}
								prix libre ou gratuit
							{/if}
						</p>
						{if $fee.description}
						<p class="help">
							{$fee.description|escape|nl2br}
						</p>
						{/if}
118
119
120
121
122
123
124
125
126
127
128
129
130
	</fieldset>
	{/if}

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}

		{if $create}
			{button type="submit" name="save_and_add_payment" class="accounting" label="Enregistrer et ajouter un autre règlement" shape="plus"}
		{/if}
	</p>

</form>







|





131
132
133
134
135
136
137
138
139
140
141
142
143
	</fieldset>
	{/if}

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}

		{if $create && $users && count($users) == 1}
			{button type="submit" name="save_and_add_payment" class="accounting" label="Enregistrer et ajouter un autre règlement" shape="plus"}
		{/if}
	</p>

</form>

Modified src/templates/services/user/add.tpl from [e38a83f3e8] to [027f0b9b0f].

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
{include file="admin/_head.tpl" title="Inscrire à une activité" current="membres/services"}

{include file="services/_nav.tpl" current="save" fee=null service=null}

{form_errors}

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

	<fieldset>
		<legend>Inscrire un membre à une activité</legend>
		<dl>




			{input type="list" name="user" required=1 label="Sélectionner un membre" default=$selected_user target="membres/selector.php"}












		</dl>
	</fieldset>

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="next" label="Continuer" shape="right" class="main"}
	</p>
</form>
{else}







	{include file="services/user/_service_user_form.tpl" create=true}




{/if}


{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
{include file="admin/_head.tpl" title="Inscrire à une activité" current="membres/services"}

{include file="services/_nav.tpl" current="save" fee=null service=null}

{form_errors}


<form method="post" action="subscribe.php" data-focus="button">

	<fieldset>
		<legend>Inscrire à une activité</legend>
		<dl>
			{input type="radio-btn" name="choice" value="1" label="Sélectionner des membres" default=1}
			{input type="radio-btn" name="choice" value="2" label="Recopier depuis une activité" help="Utile si vous avez une cotisation par année civile par exemple : copie les membres inscrits l'année précédente dans la nouvelle année."}
		</dl>
	</fieldset>

	<fieldset class="c1">
		<legend>Inscrire des membres</legend>
		<dl>
			{input type="list" name="users" required=true label="Membres à inscrire" target="membres/selector.php" multiple=true}
		</dl>
	</fieldset>

	<fieldset class="c2">
		<legend>Recopier depuis une activité</legend>
		<dl>
			{input type="select" name="copy_service" label="Activité à recopier" options=$services required=true}
			{input type="checkbox" name="copy_service_only_paid" value="1" label="Ne recopier que les membres dont l'inscription est payée"}
		</dl>
	</fieldset>

	<p class="submit">

		{button type="submit" name="next" label="Continuer" shape="right" class="main"}
	</p>
</form>

<script type="text/javascript">
{literal}
function selectChoice() {
	let choice = $('#f_choice_1').form.choice.value;
	g.toggle('.c1', choice == 1);
	g.toggle('.c2', choice == 2);
}


selectChoice();
$('#f_choice_1').onchange = selectChoice;
$('#f_choice_2').onchange = selectChoice;
{/literal}
</script>

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

Modified src/templates/services/user/index.tpl from [0bde5bd459] to [43943e4257].

1
2
3
4
5
6
7
8
9
10
11
12
{include file="admin/_head.tpl" title="%s — Inscriptions aux activités et cotisations"|args:$user.identite current="membres/services"}

<p>
	{linkbutton href="!membres/fiche.php?id=%d"|args:$user.id label="Retour à la fiche membre" shape="user"}
	{linkbutton href="!services/user/add.php?user=%d"|args:$user.id label="Inscrire à une activité" shape="plus"}
</p>

{form_errors}

<dl class="cotisation">
	<dt>Statut des inscriptions</dt>
	{foreach from=$services item="service"}




|







1
2
3
4
5
6
7
8
9
10
11
12
{include file="admin/_head.tpl" title="%s — Inscriptions aux activités et cotisations"|args:$user.identite current="membres/services"}

<p>
	{linkbutton href="!membres/fiche.php?id=%d"|args:$user.id label="Retour à la fiche membre" shape="user"}
	{linkbutton href="!services/user/subscribe.php?user=%d"|args:$user.id label="Inscrire à une activité" shape="plus"}
</p>

{form_errors}

<dl class="cotisation">
	<dt>Statut des inscriptions</dt>
	{foreach from=$services item="service"}

Added src/templates/services/user/subscribe.tpl version [8f9805b504].



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
{include file="admin/_head.tpl" title="Inscrire à une activité" current="membres/services"}

{include file="services/_nav.tpl" current="save" fee=null service=null}

{form_errors}

{include file="services/user/_service_user_form.tpl" create=true}

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

Modified src/www/admin/acc/accounts/journal.php from [da00ba6416] to [af0fa51c71].

47
48
49
50
51
52
53




54
55
56
57



58


59
60
61
$simple = qg('simple');

// Use simplified view for favourite accounts
if (null === $simple) {
	$simple = (bool) $account->type;
}





$list = $account->listJournal($year_id, $simple);
$list->setTitle(sprintf('Journal - %s - %s', $account->code, $account->label));
$list->loadFromQueryString();




$sum = $account->getSum($year_id, $simple);


$tpl->assign(compact('simple', 'year', 'account', 'list', 'sum', 'can_edit'));

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







>
>
>
>
|



>
>
>
|
>
>
|


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
$simple = qg('simple');

// Use simplified view for favourite accounts
if (null === $simple) {
	$simple = (bool) $account->type;
}

$filter = new \stdClass;
$filter->start = Utils::get_datetime(qg('start'));
$filter->end = Utils::get_datetime(qg('end'));

$list = $account->listJournal($year_id, $simple, $filter->start, $filter->end);
$list->setTitle(sprintf('Journal - %s - %s', $account->code, $account->label));
$list->loadFromQueryString();

$sum = null;

if (!$filter->start && !$filter->end) {
	$sum = $account->getSum($year_id, $simple);
}

$tpl->assign(compact('simple', 'year', 'account', 'list', 'sum', 'can_edit', 'filter'));

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

Modified src/www/admin/services/user/_form.php from [355c6ae19e] to [9911775664].

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

<?php

namespace Garradin;

use Garradin\Services\Services;


if (!defined('\Garradin\ROOT')) {
	die();
}

assert(isset($tpl, $form_url));

$current_only = !qg('past_services');







$grouped_services = Services::listGroupedWithFees($user_id, $current_only);

if (!count($grouped_services)) {
	Utils::redirect($form_url . 'past_services=' . (int) $current_only);
}

if (!isset($count_all)) {
	$count_all = Services::count();
}

$has_past_services = count($grouped_services) != $count_all;

$today = new \DateTime;

$tpl->assign([
	'custom_js' => ['service_form.js'],
]);

$tpl->assign(compact('form_url', 'today', 'grouped_services', 'user_name', 'user_id', 'current_only', 'has_past_services'));












|



>
>
>
>
>
>
|

















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

namespace Garradin;

use Garradin\Services\Services;


if (!defined('\Garradin\ROOT')) {
	die();
}

assert(isset($tpl, $form_url, $create));

$current_only = !qg('past_services');

// If there is only one user selected we can calculate the amount
$single_user_id = isset($users) && count($users) == 1 ? key($users) : null;
$copy_service ??= null;
$copy_service_only_paid ??= null;
$users ??= null;

$grouped_services = Services::listGroupedWithFees($single_user_id, $current_only);

if (!count($grouped_services)) {
	Utils::redirect($form_url . 'past_services=' . (int) $current_only);
}

if (!isset($count_all)) {
	$count_all = Services::count();
}

$has_past_services = count($grouped_services) != $count_all;

$today = new \DateTime;

$tpl->assign([
	'custom_js' => ['service_form.js'],
]);

$tpl->assign(compact('form_url', 'today', 'grouped_services', 'current_only', 'has_past_services',
	'create', 'copy_service', 'copy_service_only_paid', 'users'));

Modified src/www/admin/services/user/add.php from [614b57c4f4] to [1b2cc90329].

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

use Garradin\Services\Services;
use Garradin\Entities\Services\Service_User;
use Garradin\Entities\Accounting\Account;
use Garradin\Entities\Accounting\Transaction;

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

$session->requireAccess($session::SECTION_USERS, $session::ACCESS_WRITE);

// This controller allows to either select a user if none has been provided in the query string
// or subscribe a user to an activity (create a new Service_User entity)
// If $user_id is null then the form is just a select to choose a user

$count_all = Services::count();

if (!$count_all) {
	Utils::redirect(ADMIN_URL . 'services/?CREATE');
}

$user_id = qg('user');

if (!$user_id && ($user_id = f('user'))) {
	$user_id = @key($user_id);
}

if (!$user_id) {
	$user_id = f('id_user');
}

$user_id = (int) $user_id ?: null;
$user_name = $user_id ? (new Membres)->getNom($user_id) : null;

if (!$user_name) {
	$user_id = null;
}

$form_url  = sprintf('?user=%d&', $user_id);
$csrf_key = 'service_save';

// Only load the form if a user has been selected
if ($user_id) {
	require __DIR__ . '/_form.php';
}

$form->runIf(f('save') || f('save_and_add_payment'), function () use ($session) {
	$su = Service_User::saveFromForm($session->getUser()->id);

	if (f('save_and_add_payment')) {
		$url = ADMIN_URL . 'services/user/payment.php?id=' . $su->id;
	}
	else {
		$url = ADMIN_URL . 'services/user/?id=' . $su->id_user;
	}

	Utils::redirect($url);
}, $csrf_key);

$selected_user = $user_name ? [$user_id => $user_name] : null;

$types_details = Transaction::getTypesDetails();
$account_targets = $types_details[Transaction::TYPE_REVENUE]->accounts[1]->targets_string;

$service_user = null;

$tpl->assign(compact('csrf_key', 'selected_user', 'account_targets', 'service_user', 'user_id'));

$tpl->display('services/user/add.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
<?php
namespace Garradin;

use Garradin\Services\Services;




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

$session->requireAccess($session::SECTION_USERS, $session::ACCESS_WRITE);

// This controller allows to either select a user if none has been provided in the query string
// or subscribe a user to an activity (create a new Service_User entity)
// If $user_id is null then the form is just a select to choose a user

$count_all = Services::count();

if (!$count_all) {
	Utils::redirect(ADMIN_URL . 'services/?CREATE');
}


$services = Services::listAssoc();











































$tpl->assign(compact('services'));

$tpl->display('services/user/add.tpl');

Modified src/www/admin/services/user/edit.php from [b0b3db3c77] to [f09c2d97e9].

10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
$su = Services_User::get((int) qg('id'));

if (!$su) {
	throw new UserException("Cette inscription n'existe pas");
}

$csrf_key = 'su_edit_' . $su->id();
$user_id = $su->id_user;
$user_name = (new Membres)->getNom($user_id);
$form_url = sprintf('edit.php?id=%d&', $su->id());


require __DIR__ . '/_form.php';

$form->runIf('save', function () use ($su) {
	$su->importForm();
	$su->save();
}, $csrf_key, ADMIN_URL . 'services/user/?id=' . $user_id);

$service_user = $su;

$tpl->assign(compact('csrf_key', 'service_user'));

$tpl->display('services/user/edit.tpl');







<
|

>






|






10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$su = Services_User::get((int) qg('id'));

if (!$su) {
	throw new UserException("Cette inscription n'existe pas");
}

$csrf_key = 'su_edit_' . $su->id();

$users = [$su->id_user => (new Membres)->getNom($su->id_user)];
$form_url = sprintf('edit.php?id=%d&', $su->id());
$create = false;

require __DIR__ . '/_form.php';

$form->runIf('save', function () use ($su) {
	$su->importForm();
	$su->save();
}, $csrf_key, ADMIN_URL . 'services/user/?id=' . $su->id_user);

$service_user = $su;

$tpl->assign(compact('csrf_key', 'service_user'));

$tpl->display('services/user/edit.tpl');

Added src/www/admin/services/user/subscribe.php version [72bcfd51bb].

























































































































































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

use Garradin\Services\Services;
use Garradin\Entities\Services\Service_User;
use Garradin\Entities\Accounting\Account;
use Garradin\Entities\Accounting\Transaction;

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

$session->requireAccess($session::SECTION_USERS, $session::ACCESS_WRITE);

// This controller allows to either select a user if none has been provided in the query string
// or subscribe a user to an activity (create a new Service_User entity)
// If $user_id is null then the form is just a select to choose a user

$count_all = Services::count();

if (!$count_all) {
	Utils::redirect(ADMIN_URL . 'services/?CREATE');
}

$users = null;
$copy_service = null;
$copy_service_only_paid = null;

if (qg('user') && ($name = (new Membres)->getNom((int)qg('user')))) {
	$users = [(int)qg('user') => $name];
}
elseif (f('users') && is_array(f('users'))) {
	$users = f('users');
	$users = array_filter($users, 'intval', \ARRAY_FILTER_USE_KEY);
}
elseif (f('copy_service')
	&& $copy_service = Services::get((int)f('copy_service'))) {
	$copy_service_only_paid = (bool) f('copy_service_only_paid');
}
else {
	throw new UserException('Aucun membre n\'a été sélectionné');
}

$form_url = '?';
$csrf_key = 'service_save';
$create = true;

// Only load the form if a user has been selected
require __DIR__ . '/_form.php';

$form->runIf(f('save') || f('save_and_add_payment'), function () use ($session, $users, $copy_service, $copy_service_only_paid) {
	if ($copy_service) {
		$users = $copy_service->getUsers($copy_service_only_paid);
	}

	$su = Service_User::createFromForm($users, $session->getUser()->id, $copy_service ? true : false);

	if (count($users) > 1) {
		$url = ADMIN_URL . 'services/details.php?id=' . $su->id_service;
	}
	elseif (f('save_and_add_payment')) {
		$url = ADMIN_URL . 'services/user/payment.php?id=' . $su->id;
	}
	else {
		$url = ADMIN_URL . 'services/user/?id=' . $su->id_user;
	}

	Utils::redirect($url);
}, $csrf_key);

$types_details = Transaction::getTypesDetails();
$account_targets = $types_details[Transaction::TYPE_REVENUE]->accounts[1]->targets_string;

$service_user = null;

$tpl->assign(compact('csrf_key', 'users', 'account_targets', 'service_user'));

$tpl->display('services/user/subscribe.tpl');

Modified src/www/admin/static/styles/05-navigation.css from [d3ea311406] to [2228a1d3bc].

49
50
51
52
53
54
55
56

57
    text-decoration: underline;
    border-bottom: none;
}

nav.tabs aside {
    float: right;
    max-width: 50%;
    text-align: right

}







|
>

49
50
51
52
53
54
55
56
57
58
    text-decoration: underline;
    border-bottom: none;
}

nav.tabs aside {
    float: right;
    max-width: 50%;
    text-align: right;
    clear: right;
}

Modified src/www/admin/web/page.php from [7684223213] to [fa91cc041f].

1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
<?php

namespace Garradin;

use Garradin\Web\Web;
use Garradin\Entities\Web\Page;

require_once __DIR__ . '/_inc.php';





$page = Web::get(qg('p'));

if (!$page) {
	throw new UserException('Page inconnue');
}









>
>
>
>







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

namespace Garradin;

use Garradin\Web\Web;
use Garradin\Entities\Web\Page;

require_once __DIR__ . '/_inc.php';

if (!qg('p')) {
	throw new UserException('Page inconnue');
}

$page = Web::get(qg('p'));

if (!$page) {
	throw new UserException('Page inconnue');
}