]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Repository/Transactions.php
8c103d8883f3d3250eab6a5953899b03f30b536f
[galette.git] / galette / lib / Galette / Repository / Transactions.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Transactions class
7 *
8 * PHP version 5
9 *
10 * Copyright © 2011-2021 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Repository
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2011-2021 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.7dev - 2011-07-31
35 */
36
37 namespace Galette\Repository;
38
39 use Throwable;
40 use Analog\Analog;
41 use Laminas\Db\Sql\Expression;
42 use Galette\Entity\Transaction;
43 use Galette\Entity\Adherent;
44 use Galette\Core\Db;
45 use Galette\Core\Login;
46 use Galette\Core\History;
47 use Galette\Filters\TransactionsList;
48
49 /**
50 * Transactions class for galette
51 *
52 * @name Transactions
53 * @category Repository
54 * @package Galette
55 *
56 * @author Johan Cwiklinski <johan@x-tnd.be>
57 * @copyright 2011-2021 The Galette Team
58 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
59 * @link http://galette.tuxfamily.org
60 */
61 class Transactions
62 {
63 public const TABLE = Transaction::TABLE;
64 public const PK = Transaction::PK;
65
66 private $count = null;
67 private $zdb;
68 private $login;
69 private $filters;
70
71 /**
72 * Default constructor
73 *
74 * @param Db $zdb Database
75 * @param Login $login Login
76 * @param TransactionsList $filters Filtering
77 */
78 public function __construct(Db $zdb, Login $login, $filters = null)
79 {
80 $this->zdb = $zdb;
81 $this->login = $login;
82
83 if ($filters === null) {
84 $this->filters = new TransactionsList();
85 } else {
86 $this->filters = $filters;
87 }
88 }
89
90 /**
91 * Get transactions list
92 *
93 * @param bool $as_trans return the results as an array of
94 * Transaction object.
95 * @param array $fields field(s) name(s) to get. Should be a string or
96 * an array. If null, all fields will be returned
97 * @param boolean $count true if we want to count members
98 *
99 * @return Transaction[]|ResultSet
100 */
101 public function getList($as_trans = false, $fields = null, $count = true)
102 {
103 try {
104 $select = $this->buildSelect($fields, $count);
105 $this->filters->setLimits($select);
106
107 $transactions = array();
108 $results = $this->zdb->execute($select);
109 if ($as_trans) {
110 foreach ($results as $row) {
111 $transactions[] = new Transaction($this->zdb, $this->login, $row);
112 }
113 } else {
114 $transactions = $results;
115 }
116 return $transactions;
117 } catch (Throwable $e) {
118 Analog::log(
119 'Cannot list transactions | ' . $e->getMessage(),
120 Analog::WARNING
121 );
122 return false;
123 }
124 }
125
126 /**
127 * Builds the SELECT statement
128 *
129 * @param array $fields fields list to retrieve
130 * @param bool $count true if we want to count members
131 * (not applicable from static calls), defaults to false
132 *
133 * @return string SELECT statement
134 */
135 private function buildSelect($fields, $count = false)
136 {
137 try {
138 $fieldsList = ($fields != null)
139 ? ((!is_array($fields) || count($fields) < 1) ? (array)'*'
140 : implode(', ', $fields)) : (array)'*';
141
142 $select = $this->zdb->select(self::TABLE, 't');
143 $select->columns(
144 array(
145 'trans_date',
146 'trans_id',
147 'trans_desc',
148 'id_adh',
149 'trans_amount'
150 )
151 )->join(
152 array('a' => PREFIX_DB . Adherent::TABLE),
153 't.' . Adherent::PK . '=' . 'a.' . Adherent::PK,
154 array('nom_adh', 'prenom_adh')
155 );
156
157 $this->buildWhereClause($select);
158 $select->order(self::buildOrderClause());
159
160 if ($count) {
161 $this->proceedCount($select);
162 }
163
164 return $select;
165 } catch (Throwable $e) {
166 Analog::log(
167 'Cannot build SELECT clause for transactions | ' . $e->getMessage(),
168 Analog::WARNING
169 );
170 return false;
171 }
172 }
173
174 /**
175 * Count transactions from the query
176 *
177 * @param Select $select Original select
178 *
179 * @return void
180 */
181 private function proceedCount($select)
182 {
183 try {
184 $countSelect = clone $select;
185 $countSelect->reset($countSelect::COLUMNS);
186 $countSelect->reset($countSelect::ORDER);
187 $countSelect->reset($countSelect::JOINS);
188 $countSelect->columns(
189 array(
190 self::PK => new Expression('COUNT(' . self::PK . ')')
191 )
192 );
193
194 $results = $this->zdb->execute($countSelect);
195 $result = $results->current();
196
197 $k = self::PK;
198 $this->count = $result->$k;
199 if ($this->count > 0) {
200 $this->filters->setCounter($this->count);
201 }
202 } catch (Throwable $e) {
203 Analog::log(
204 'Cannot count transactions | ' . $e->getMessage(),
205 Analog::WARNING
206 );
207 return false;
208 }
209 }
210
211 /**
212 * Builds the order clause
213 *
214 * @return string SQL ORDER clause
215 */
216 private function buildOrderClause()
217 {
218 $order = array();
219
220 switch ($this->filters->orderby) {
221 case TransactionsList::ORDERBY_ID:
222 $order[] = Transaction::PK . ' ' . $this->filters->ordered;
223 break;
224 case TransactionsList::ORDERBY_DATE:
225 $order[] = 'trans_date' . ' ' . $this->filters->ordered;
226 break;
227 case TransactionsList::ORDERBY_MEMBER:
228 $order[] = 'nom_adh' . ' ' . $this->filters->ordered;
229 $order[] = 'prenom_adh' . ' ' . $this->filters->ordered;
230 break;
231 case TransactionsList::ORDERBY_AMOUNT:
232 $order[] = 'trans_amount' . ' ' . $this->filters->ordered;
233 break;
234 default:
235 $order[] = $this->filters->orderby . ' ' . $this->filters->ordered;
236 break;
237 }
238
239 return $order;
240 }
241
242 /**
243 * Builds where clause, for filtering on simple list mode
244 *
245 * @param Select $select Original select
246 *
247 * @return string SQL WHERE clause
248 */
249 private function buildWhereClause($select)
250 {
251 try {
252 if ($this->filters->start_date_filter != null) {
253 $d = new \DateTime($this->filters->start_date_filter);
254 $select->where->greaterThanOrEqualTo(
255 'trans_date',
256 $d->format('Y-m-d')
257 );
258 }
259
260 if ($this->filters->end_date_filter != null) {
261 $d = new \DateTime($this->filters->end_date_filter);
262 $select->where->lessThanOrEqualTo(
263 'trans_date',
264 $d->format('Y-m-d')
265 );
266 }
267
268 $member_clause = null;
269 if ($this->filters->filtre_cotis_adh != null) {
270 $member_clause = [$this->filters->filtre_cotis_adh];
271 if (!$this->login->isAdmin() && !$this->login->isStaff() && $this->filters->filtre_cotis_adh != $this->login->id) {
272 $member = new Adherent(
273 $this->zdb,
274 (int)$this->filters->filtre_cotis_adh,
275 [
276 'picture' => false,
277 'groups' => false,
278 'dues' => false,
279 'parent' => true
280 ]
281 );
282 if (
283 !$member->hasParent() ||
284 $member->hasParent() && $member->parent->id != $this->login->id
285 ) {
286 Analog::log(
287 'Trying to display transactions for member #' . $member->id .
288 ' without appropriate ACLs',
289 Analog::WARNING
290 );
291 $member_clause = [$this->login->id];
292 }
293 }
294 } elseif ($this->filters->filtre_cotis_children !== false) {
295 $member_clause = [$this->login->id];
296 $member = new Adherent(
297 $this->zdb,
298 (int)$this->filters->filtre_cotis_children,
299 [
300 'picture' => false,
301 'groups' => false,
302 'dues' => false,
303 'children' => true
304 ]
305 );
306 foreach ($member->children as $child) {
307 $member_clause[] = $child->id;
308 }
309 } elseif (!$this->login->isAdmin() && !$this->login->isStaff()) {
310 $member_clause = $this->login->id;
311 }
312
313 if ($member_clause !== null) {
314 $select->where(
315 array(
316 't.' . Adherent::PK => $member_clause
317 )
318 );
319 }
320 } catch (Throwable $e) {
321 Analog::log(
322 __METHOD__ . ' | ' . $e->getMessage(),
323 Analog::WARNING
324 );
325 }
326 }
327
328 /**
329 * Get count for current query
330 *
331 * @return int
332 */
333 public function getCount()
334 {
335 return $this->count;
336 }
337
338 /**
339 * Remove specified transactions
340 *
341 * @param interger|array $ids Transactions identifiers to delete
342 * @param History $hist History
343 *
344 * @return boolean
345 */
346 public function remove($ids, History $hist)
347 {
348 $list = array();
349 if (is_numeric($ids)) {
350 //we've got only one identifier
351 $list[] = $ids;
352 } else {
353 $list = $ids;
354 }
355
356 if (is_array($list)) {
357 $res = true;
358 try {
359 $this->zdb->connection->beginTransaction();
360
361 $select = $this->zdb->select(self::TABLE);
362 $select->where->in(self::PK, $list);
363
364 $results = $this->zdb->execute($select);
365 foreach ($results as $transaction) {
366 $c = new Transaction($this->zdb, $this->login, $transaction);
367 $res = $c->remove($hist, false);
368 if ($res === false) {
369 throw new \Exception();
370 }
371 }
372 $this->zdb->connection->commit();
373 $hist->add(
374 "Transactions deleted (" . print_r($list, true) . ')'
375 );
376 return true;
377 } catch (Throwable $e) {
378 $this->zdb->connection->rollBack();
379 Analog::log(
380 'An error occurred trying to remove transactions | ' .
381 $e->getMessage(),
382 Analog::ERROR
383 );
384 return false;
385 }
386 } else {
387 //not numeric and not an array: incorrect.
388 Analog::log(
389 'Asking to remove transaction, but without providing ' .
390 'an array or a single numeric value.',
391 Analog::WARNING
392 );
393 return false;
394 }
395 }
396 }