3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2010-2023 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
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.
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.
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/>.
27 * @category Repository
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2010-2023 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 - 2010-03-11
37 namespace Galette\Repository
;
42 use Laminas\Db\Sql\Expression
;
44 use Galette\Core\Login
;
45 use Galette\Core\History
;
46 use Galette\Entity\Contribution
;
47 use Galette\Entity\Adherent
;
48 use Galette\Entity\Transaction
;
49 use Galette\Entity\ContributionsTypes
;
50 use Galette\Filters\ContributionsList
;
51 use Laminas\Db\Sql\Select
;
54 * Contributions class for galette
57 * @category Repository
60 * @author Johan Cwiklinski <johan@x-tnd.be>
61 * @copyright 2009-2023 The Galette Team
62 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
63 * @link http://galette.tuxfamily.org
67 public const TABLE
= Contribution
::TABLE
;
68 public const PK
= Contribution
::PK
;
70 private $filters = false;
71 private $count = null;
76 private $current_selection;
81 * @param Db $zdb Database
82 * @param Login $login Login
83 * @param ContributionsList $filters Filtering
85 public function __construct(Db
$zdb, Login
$login, $filters = null)
88 $this->login
= $login;
90 if ($filters === null) {
91 $this->filters
= new ContributionsList();
93 $this->filters
= $filters;
98 * Get contributions list for a specific transaction
100 * @param int $trans_id Transaction identifier
102 * @return Contribution[]|ArrayObject
104 public function getListFromTransaction($trans_id)
106 $this->filters
->from_transaction
= $trans_id;
107 return $this->getList(true);
111 * Get contributions list for a specific transaction
113 * @param array $ids an array of members id that has been selected
114 * @param bool $as_contrib return the results as an array of
115 * @param array $fields field(s) name(s) to get. Should be a string or
116 * an array. If null, all fields will be
118 * @param boolean $count true if we want to count members
120 * @return Contribution[]|ArrayObject[]|false
122 public function getArrayList(array $ids, bool $as_contrib = false, array $fields = null, bool $count = true)
124 if (count($ids) < 1) {
125 Analog
::log('No contribution selected.', Analog
::INFO
);
129 $this->current_selection
= $ids;
130 $list = $this->getList($as_contrib, $fields, $count);
132 foreach ($list as $entry) {
133 $array_list[] = $entry;
139 * Get contributions list
141 * @param bool $as_contrib return the results as an array of
142 * Contribution object.
143 * @param array $fields field(s) name(s) to get. Should be a string or
144 * an array. If null, all fields will be
146 * @param boolean $count true if we want to count members
148 * @return Contribution[]|ArrayObject
150 public function getList($as_contrib = false, $fields = null, $count = true)
153 $select = $this->buildSelect($fields, $count);
155 $this->filters
->setLimits($select);
157 $contributions = array();
158 $results = $this->zdb
->execute($select);
160 foreach ($results as $row) {
161 $contributions[] = new Contribution($this->zdb
, $this->login
, $row);
164 $contributions = $results;
166 return $contributions;
167 } catch (Throwable
$e) {
169 'Cannot list contributions | ' . $e->getMessage(),
177 * Builds the SELECT statement
179 * @param array $fields fields list to retrieve
180 * @param bool $count true if we want to count members
181 * (not applicable from static calls), defaults to false
183 * @return string SELECT statement
185 private function buildSelect($fields, $count = false)
188 $fieldsList = ($fields != null)
189 ?
((!is_array($fields) ||
count($fields) < 1) ?
(array)'*'
190 : implode(', ', $fields)) : (array)'*';
192 $select = $this->zdb
->select(self
::TABLE
, 'a');
193 $select->columns($fieldsList);
196 array('p' => PREFIX_DB
. Adherent
::TABLE
),
197 'a.' . Adherent
::PK
. '= p.' . Adherent
::PK
,
201 $this->buildWhereClause($select);
202 $select->order(self
::buildOrderClause());
204 $this->calculateSum($select);
207 $this->proceedCount($select);
211 } catch (Throwable
$e) {
213 'Cannot build SELECT clause for contributions | ' . $e->getMessage(),
221 * Count contributions from the query
223 * @param Select $select Original select
227 private function proceedCount(Select
$select)
230 $countSelect = clone $select;
231 $countSelect->reset($countSelect::COLUMNS
);
232 $countSelect->reset($countSelect::JOINS
);
233 $countSelect->reset($countSelect::ORDER
);
234 $countSelect->columns(
236 self
::PK
=> new Expression('COUNT(' . self
::PK
. ')')
240 $results = $this->zdb
->execute($countSelect);
241 $result = $results->current();
244 $this->count
= $result->$k;
245 $this->filters
->setCounter($this->count
);
246 } catch (Throwable
$e) {
248 'Cannot count contributions | ' . $e->getMessage(),
256 * Calculate sum of all selected contributions
258 * @param Select $select Original select
262 private function calculateSum(Select
$select)
265 $sumSelect = clone $select;
266 $sumSelect->reset($sumSelect::COLUMNS
);
267 $sumSelect->reset($sumSelect::JOINS
);
268 $sumSelect->reset($sumSelect::ORDER
);
271 'contribsum' => new Expression('SUM(montant_cotis)')
275 $results = $this->zdb
->execute($sumSelect);
276 $result = $results->current();
277 if ($result->contribsum
) {
278 $this->sum
= round($result->contribsum
, 2);
280 } catch (Throwable
$e) {
282 'Cannot calculate contributions sum | ' . $e->getMessage(),
290 * Builds the order clause
292 * @return array SQL ORDER clauses
294 private function buildOrderClause()
298 switch ($this->filters
->orderby
) {
299 case ContributionsList
::ORDERBY_ID
:
300 $order[] = Contribution
::PK
. ' ' . $this->filters
->ordered
;
302 case ContributionsList
::ORDERBY_DATE
:
303 $order[] = 'date_enreg ' . $this->filters
->ordered
;
305 case ContributionsList
::ORDERBY_BEGIN_DATE
:
306 $order[] = 'date_debut_cotis ' . $this->filters
->ordered
;
308 case ContributionsList
::ORDERBY_END_DATE
:
309 $order[] = 'date_fin_cotis ' . $this->filters
->ordered
;
311 case ContributionsList
::ORDERBY_MEMBER
:
312 $order[] = 'nom_adh ' . $this->filters
->ordered
;
313 $order[] = 'prenom_adh ' . $this->filters
->ordered
;
315 case ContributionsList
::ORDERBY_TYPE
:
316 $order[] = ContributionsTypes
::PK
;
318 case ContributionsList
::ORDERBY_AMOUNT
:
319 $order[] = 'montant_cotis ' . $this->filters
->ordered
;
322 Hum... I really do not know how to sort a query with a value that
323 is calculated code side :/
324 case ContributionsList::ORDERBY_DURATION:
326 case ContributionsList
::ORDERBY_PAYMENT_TYPE
:
327 $order[] = 'type_paiement_cotis ' . $this->filters
->ordered
;
330 $order[] = $this->filters
->orderby
. ' ' . $this->filters
->ordered
;
338 * Builds where clause, for filtering on simple list mode
340 * @param Select $select Original select
344 private function buildWhereClause(Select
$select)
346 $field = 'date_debut_cotis';
348 switch ($this->filters
->date_field
) {
349 case ContributionsList
::DATE_RECORD
:
350 $field = 'date_enreg';
352 case ContributionsList
::DATE_END
:
353 $field = 'date_fin_cotis';
355 case ContributionsList
::DATE_BEGIN
:
357 $field = 'date_debut_cotis';
361 if (isset($this->current_selection
)) {
362 $select->where
->in('a.' . self
::PK
, $this->current_selection
);
366 if ($this->filters
->start_date_filter
!= null) {
367 $d = new \
DateTime($this->filters
->rstart_date_filter
);
368 $select->where
->greaterThanOrEqualTo(
374 if ($this->filters
->end_date_filter
!= null) {
375 $d = new \
DateTime($this->filters
->rend_date_filter
);
376 $select->where
->lessThanOrEqualTo(
382 if ($this->filters
->payment_type_filter
!== null) {
383 $select->where
->equalTo(
384 'type_paiement_cotis',
385 $this->filters
->payment_type_filter
389 if ($this->filters
->from_transaction
!== false) {
390 $select->where
->equalTo(
392 $this->filters
->from_transaction
396 if ($this->filters
->max_amount
!== null && is_int($this->filters
->max_amount
)) {
398 '(montant_cotis <= ' . $this->filters
->max_amount
.
399 ' OR montant_cotis IS NULL)'
403 $member_clause = null;
404 if ($this->filters
->filtre_cotis_adh
!= null) {
405 $member_clause = [$this->filters
->filtre_cotis_adh
];
406 if (!$this->login
->isAdmin() && !$this->login
->isStaff() && $this->filters
->filtre_cotis_adh
!= $this->login
->id
) {
407 $member = new Adherent(
409 (int)$this->filters
->filtre_cotis_adh
,
418 !$member->hasParent() ||
419 $member->hasParent() && $member->parent
->id
!= $this->login
->id
422 'Trying to display contributions for member #' . $member->id
.
423 ' without appropriate ACLs',
426 $this->filters
->filtre_cotis_adh
= $this->login
->id
;
427 $member_clause = [$this->login
->id
];
430 } elseif ($this->filters
->filtre_cotis_children
!== false) {
431 $member_clause = [$this->login
->id
];
432 $member = new Adherent(
434 (int)$this->filters
->filtre_cotis_children
,
442 foreach ($member->children
as $child) {
443 $member_clause[] = $child->id
;
445 } elseif (!$this->login
->isAdmin() && !$this->login
->isStaff()) {
446 //non staff members can only view their own contributions
447 $member_clause = $this->login
->id
;
450 if ($member_clause !== null) {
453 'a.' . Adherent
::PK
=> $member_clause
458 if ($this->filters
->filtre_transactions
=== true) {
459 $select->where('a.trans_id IS NULL');
461 } catch (Throwable
$e) {
463 __METHOD__
. ' | ' . $e->getMessage(),
471 * Get count for current query
475 public function getCount()
485 public function getSum()
491 * Remove specified contributions
493 * @param integer|array $ids Contributions identifiers to delete
494 * @param History $hist History
495 * @param boolean $transaction True to begin a database transaction
499 public function remove($ids, History
$hist, $transaction = true)
502 if (is_numeric($ids)) {
503 //we've got only one identifier
509 if (is_array($list)) {
512 $this->zdb
->connection
->beginTransaction();
514 $select = $this->zdb
->select(self
::TABLE
);
515 $select->where
->in(self
::PK
, $list);
516 $contributions = $this->zdb
->execute($select);
517 foreach ($contributions as $contribution) {
518 $c = new Contribution($this->zdb
, $this->login
, $contribution);
519 $res = $c->remove(false);
520 if ($res === false) {
521 throw new \
Exception();
525 $this->zdb
->connection
->commit();
530 print_r($list, true),
531 _T("Contributions deleted (%list)")
535 } catch (Throwable
$e) {
537 $this->zdb
->connection
->rollBack();
540 'An error occurred trying to remove contributions | ' .
547 //not numeric and not an array: incorrect.
549 'Asking to remove contribution, but without providing an array or a single numeric value.',