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;
246 if ($this->count
> 0) {
247 $this->filters
->setCounter($this->count
);
249 } catch (Throwable
$e) {
251 'Cannot count contributions | ' . $e->getMessage(),
259 * Calculate sum of all selected contributions
261 * @param Select $select Original select
265 private function calculateSum(Select
$select)
268 $sumSelect = clone $select;
269 $sumSelect->reset($sumSelect::COLUMNS
);
270 $sumSelect->reset($sumSelect::JOINS
);
271 $sumSelect->reset($sumSelect::ORDER
);
274 'contribsum' => new Expression('SUM(montant_cotis)')
278 $results = $this->zdb
->execute($sumSelect);
279 $result = $results->current();
280 if ($result->contribsum
) {
281 $this->sum
= round($result->contribsum
, 2);
283 } catch (Throwable
$e) {
285 'Cannot calculate contributions sum | ' . $e->getMessage(),
293 * Builds the order clause
295 * @return array SQL ORDER clauses
297 private function buildOrderClause()
301 switch ($this->filters
->orderby
) {
302 case ContributionsList
::ORDERBY_ID
:
303 $order[] = Contribution
::PK
. ' ' . $this->filters
->ordered
;
305 case ContributionsList
::ORDERBY_DATE
:
306 $order[] = 'date_enreg ' . $this->filters
->ordered
;
308 case ContributionsList
::ORDERBY_BEGIN_DATE
:
309 $order[] = 'date_debut_cotis ' . $this->filters
->ordered
;
311 case ContributionsList
::ORDERBY_END_DATE
:
312 $order[] = 'date_fin_cotis ' . $this->filters
->ordered
;
314 case ContributionsList
::ORDERBY_MEMBER
:
315 $order[] = 'nom_adh ' . $this->filters
->ordered
;
316 $order[] = 'prenom_adh ' . $this->filters
->ordered
;
318 case ContributionsList
::ORDERBY_TYPE
:
319 $order[] = ContributionsTypes
::PK
;
321 case ContributionsList
::ORDERBY_AMOUNT
:
322 $order[] = 'montant_cotis ' . $this->filters
->ordered
;
325 Hum... I really do not know how to sort a query with a value that
326 is calculated code side :/
327 case ContributionsList::ORDERBY_DURATION:
329 case ContributionsList
::ORDERBY_PAYMENT_TYPE
:
330 $order[] = 'type_paiement_cotis ' . $this->filters
->ordered
;
333 $order[] = $this->filters
->orderby
. ' ' . $this->filters
->ordered
;
341 * Builds where clause, for filtering on simple list mode
343 * @param Select $select Original select
347 private function buildWhereClause(Select
$select)
349 $field = 'date_debut_cotis';
351 switch ($this->filters
->date_field
) {
352 case ContributionsList
::DATE_RECORD
:
353 $field = 'date_enreg';
355 case ContributionsList
::DATE_END
:
356 $field = 'date_fin_cotis';
358 case ContributionsList
::DATE_BEGIN
:
360 $field = 'date_debut_cotis';
364 if (isset($this->current_selection
)) {
365 $select->where
->in('a.' . self
::PK
, $this->current_selection
);
369 if ($this->filters
->start_date_filter
!= null) {
370 $d = new \
DateTime($this->filters
->rstart_date_filter
);
371 $select->where
->greaterThanOrEqualTo(
377 if ($this->filters
->end_date_filter
!= null) {
378 $d = new \
DateTime($this->filters
->rend_date_filter
);
379 $select->where
->lessThanOrEqualTo(
385 if ($this->filters
->payment_type_filter
!== null) {
386 $select->where
->equalTo(
387 'type_paiement_cotis',
388 $this->filters
->payment_type_filter
392 if ($this->filters
->from_transaction
!== false) {
393 $select->where
->equalTo(
395 $this->filters
->from_transaction
399 if ($this->filters
->max_amount
!== null && is_int($this->filters
->max_amount
)) {
401 '(montant_cotis <= ' . $this->filters
->max_amount
.
402 ' OR montant_cotis IS NULL)'
406 $member_clause = null;
407 if ($this->filters
->filtre_cotis_adh
!= null) {
408 $member_clause = [$this->filters
->filtre_cotis_adh
];
409 if (!$this->login
->isAdmin() && !$this->login
->isStaff() && $this->filters
->filtre_cotis_adh
!= $this->login
->id
) {
410 $member = new Adherent(
412 (int)$this->filters
->filtre_cotis_adh
,
421 !$member->hasParent() ||
422 $member->hasParent() && $member->parent
->id
!= $this->login
->id
425 'Trying to display contributions for member #' . $member->id
.
426 ' without appropriate ACLs',
429 $this->filters
->filtre_cotis_adh
= $this->login
->id
;
430 $member_clause = [$this->login
->id
];
433 } elseif ($this->filters
->filtre_cotis_children
!== false) {
434 $member_clause = [$this->login
->id
];
435 $member = new Adherent(
437 (int)$this->filters
->filtre_cotis_children
,
445 foreach ($member->children
as $child) {
446 $member_clause[] = $child->id
;
448 } elseif (!$this->login
->isAdmin() && !$this->login
->isStaff()) {
449 //non staff members can only view their own contributions
450 $member_clause = $this->login
->id
;
453 if ($member_clause !== null) {
456 'a.' . Adherent
::PK
=> $member_clause
461 if ($this->filters
->filtre_transactions
=== true) {
462 $select->where('a.trans_id IS NULL');
464 } catch (Throwable
$e) {
466 __METHOD__
. ' | ' . $e->getMessage(),
474 * Get count for current query
478 public function getCount()
488 public function getSum()
494 * Remove specified contributions
496 * @param integer|array $ids Contributions identifiers to delete
497 * @param History $hist History
498 * @param boolean $transaction True to begin a database transaction
502 public function remove($ids, History
$hist, $transaction = true)
505 if (is_numeric($ids)) {
506 //we've got only one identifier
512 if (is_array($list)) {
515 $this->zdb
->connection
->beginTransaction();
517 $select = $this->zdb
->select(self
::TABLE
);
518 $select->where
->in(self
::PK
, $list);
519 $contributions = $this->zdb
->execute($select);
520 foreach ($contributions as $contribution) {
521 $c = new Contribution($this->zdb
, $this->login
, $contribution);
522 $res = $c->remove(false);
523 if ($res === false) {
524 throw new \
Exception();
528 $this->zdb
->connection
->commit();
533 print_r($list, true),
534 _T("Contributions deleted (%list)")
538 } catch (Throwable
$e) {
540 $this->zdb
->connection
->rollBack();
543 'An error occurred trying to remove contributions | ' .
550 //not numeric and not an array: incorrect.
552 'Asking to remove contribution, but without providing an array or a single numeric value.',