]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Repository/Contributions.php
CS: declare visibility for constants
[galette.git] / galette / lib / Galette / Repository / Contributions.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Contributions class
7 *
8 * PHP version 5
9 *
10 * Copyright © 2010-2014 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 2010-2014 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
35 */
36
37 namespace Galette\Repository;
38
39 use Analog\Analog;
40 use Laminas\Db\Sql\Expression;
41 use Galette\Core\Db;
42 use Galette\Core\Login;
43 use Galette\Core\History;
44 use Galette\Entity\Contribution;
45 use Galette\Entity\Adherent;
46 use Galette\Entity\Transaction;
47 use Galette\Entity\ContributionsTypes;
48 use Galette\Filters\ContributionsList;
49
50 /**
51 * Contributions class for galette
52 *
53 * @name Contributions
54 * @category Repository
55 * @package Galette
56 *
57 * @author Johan Cwiklinski <johan@x-tnd.be>
58 * @copyright 2009-2014 The Galette Team
59 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
60 * @link http://galette.tuxfamily.org
61 */
62 class Contributions
63 {
64 public const TABLE = Contribution::TABLE;
65 public const PK = Contribution::PK;
66
67 private $count = null;
68
69 private $sum;
70
71 /**
72 * Default constructor
73 *
74 * @param Db $zdb Database
75 * @param Login $login Login
76 * @param ContributionsList $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 ContributionsList();
85 } else {
86 $this->filters = $filters;
87 }
88 }
89
90 /**
91 * Get contributions list for a specific transaction
92 *
93 * @param int $trans_id Transaction identifier
94 *
95 * @return Contribution[]
96 */
97 public function getListFromTransaction($trans_id)
98 {
99 $this->filters->from_transaction = $trans_id;
100 return $this->getList(true);
101 }
102
103 /**
104 * Get contributions list
105 *
106 * @param bool $as_contrib return the results as an array of
107 * Contribution object.
108 * @param array $fields field(s) name(s) to get. Should be a string or
109 * an array. If null, all fields will be
110 * returned
111 * @param boolean $count true if we want to count members
112 *
113 * @return Contribution[]|ResultSet
114 */
115 public function getList($as_contrib = false, $fields = null, $count = true)
116 {
117 try {
118 $select = $this->buildSelect($fields, $count);
119
120 $this->filters->setLimits($select);
121
122 $contributions = array();
123 $results = $this->zdb->execute($select);
124 if ($as_contrib) {
125 foreach ($results as $row) {
126 $contributions[] = new Contribution($this->zdb, $this->login, $row);
127 }
128 } else {
129 $contributions = $results;
130 }
131 return $contributions;
132 } catch (\Exception $e) {
133 Analog::log(
134 'Cannot list contributions | ' . $e->getMessage(),
135 Analog::WARNING
136 );
137 return false;
138 }
139 }
140
141 /**
142 * Builds the SELECT statement
143 *
144 * @param array $fields fields list to retrieve
145 * @param bool $count true if we want to count members
146 * (not applicable from static calls), defaults to false
147 *
148 * @return string SELECT statement
149 */
150 private function buildSelect($fields, $count = false)
151 {
152 try {
153 $fieldsList = ($fields != null)
154 ? ((!is_array($fields) || count($fields) < 1) ? (array)'*'
155 : implode(', ', $fields)) : (array)'*';
156
157 $select = $this->zdb->select(self::TABLE, 'a');
158 $select->columns($fieldsList);
159
160 $select->join(
161 array('p' => PREFIX_DB . Adherent::TABLE),
162 'a.' . Adherent::PK . '= p.' . Adherent::PK
163 );
164
165 $this->buildWhereClause($select);
166 $select->order(self::buildOrderClause());
167
168 $this->calculateSum($select);
169
170 if ($count) {
171 $this->proceedCount($select);
172 }
173
174 return $select;
175 } catch (\Exception $e) {
176 Analog::log(
177 'Cannot build SELECT clause for contributions | ' . $e->getMessage(),
178 Analog::WARNING
179 );
180 return false;
181 }
182 }
183
184 /**
185 * Count contributions from the query
186 *
187 * @param Select $select Original select
188 *
189 * @return void
190 */
191 private function proceedCount($select)
192 {
193 try {
194 $countSelect = clone $select;
195 $countSelect->reset($countSelect::COLUMNS);
196 $countSelect->reset($countSelect::JOINS);
197 $countSelect->reset($countSelect::ORDER);
198 $countSelect->columns(
199 array(
200 self::PK => new Expression('COUNT(' . self::PK . ')')
201 )
202 );
203
204 $results = $this->zdb->execute($countSelect);
205 $result = $results->current();
206
207 $k = self::PK;
208 $this->count = $result->$k;
209
210 if ($this->count > 0) {
211 $this->filters->setCounter($this->count);
212 }
213 } catch (\Exception $e) {
214 Analog::log(
215 'Cannot count contributions | ' . $e->getMessage(),
216 Analog::WARNING
217 );
218 return false;
219 }
220 }
221
222 /**
223 * Calculate sum of all selected contributions
224 *
225 * @param Select $select Original select
226 *
227 * @return void
228 */
229 private function calculateSum($select)
230 {
231 try {
232 $sumSelect = clone $select;
233 $sumSelect->reset($sumSelect::COLUMNS);
234 $sumSelect->reset($sumSelect::JOINS);
235 $sumSelect->reset($sumSelect::ORDER);
236 $sumSelect->columns(
237 array(
238 'contribsum' => new Expression('SUM(montant_cotis)')
239 )
240 );
241
242 $results = $this->zdb->execute($sumSelect);
243 $result = $results->current();
244
245 $this->sum = round($result->contribsum, 2);
246 } catch (\Exception $e) {
247 Analog::log(
248 'Cannot calculate contributions sum | ' . $e->getMessage(),
249 Analog::WARNING
250 );
251 return false;
252 }
253 }
254
255 /**
256 * Builds the order clause
257 *
258 * @return string SQL ORDER clause
259 */
260 private function buildOrderClause()
261 {
262 $order = array();
263
264 switch ($this->filters->orderby) {
265 case ContributionsList::ORDERBY_DATE:
266 $order[] = 'date_enreg ' . $this->filters->ordered;
267 break;
268 case ContributionsList::ORDERBY_BEGIN_DATE:
269 $order[] = 'date_debut_cotis ' . $this->filters->ordered;
270 break;
271 case ContributionsList::ORDERBY_END_DATE:
272 $order[] = 'date_fin_cotis ' . $this->filters->ordered;
273 break;
274 case ContributionsList::ORDERBY_MEMBER:
275 $order[] = 'nom_adh ' . $this->filters->ordered;
276 $order[] = 'prenom_adh ' . $this->filters->ordered;
277 break;
278 case ContributionsList::ORDERBY_TYPE:
279 $order[] = ContributionsTypes::PK;
280 break;
281 case ContributionsList::ORDERBY_AMOUNT:
282 $order[] = 'montant_cotis ' . $this->filters->ordered;
283 break;
284 /*
285 Hum... I really do not know how to sort a query with a value that
286 is calculated code side :/
287 case ContributionsList::ORDERBY_DURATION:
288 break;*/
289 case ContributionsList::ORDERBY_PAYMENT_TYPE:
290 $order[] = 'type_paiement_cotis ' . $this->ordered;
291 break;
292 default:
293 $order[] = $this->filters->orderby . ' ' . $this->filters->ordered;
294 break;
295 }
296
297 return $order;
298 }
299
300 /**
301 * Builds where clause, for filtering on simple list mode
302 *
303 * @param Select $select Original select
304 *
305 * @return string SQL WHERE clause
306 */
307 private function buildWhereClause($select)
308 {
309 $field = 'date_debut_cotis';
310
311 switch ($this->filters->date_field) {
312 case ContributionsList::DATE_RECORD:
313 $field = 'date_enreg';
314 break;
315 case ContributionsList::DATE_END:
316 $field = 'date_fin_cotis';
317 break;
318 case ContributionsList::DATE_BEGIN:
319 default:
320 $field = 'date_debut_cotis';
321 break;
322 }
323
324 try {
325 if ($this->filters->start_date_filter != null) {
326 $d = new \DateTime($this->filters->start_date_filter);
327 $select->where->greaterThanOrEqualTo(
328 $field,
329 $d->format('Y-m-d')
330 );
331 }
332
333 if ($this->filters->end_date_filter != null) {
334 $d = new \DateTime($this->filters->end_date_filter);
335 $select->where->lessThanOrEqualTo(
336 $field,
337 $d->format('Y-m-d')
338 );
339 }
340
341 if ($this->filters->payment_type_filter !== null) {
342 $select->where->equalTo(
343 'type_paiement_cotis',
344 $this->filters->payment_type_filter
345 );
346 }
347
348 if ($this->filters->from_transaction !== false) {
349 $select->where->equalTo(
350 Transaction::PK,
351 $this->filters->from_transaction
352 );
353 }
354
355 if ($this->filters->max_amount !== null && is_int($this->filters->max_amount)) {
356 $select->where(
357 '(montant_cotis <= ' . $this->filters->max_amount .
358 ' OR montant_cotis IS NULL)'
359 );
360 }
361
362 if (!$this->login->isAdmin() && !$this->login->isStaff()) {
363 //non staff members can only view their own contributions
364 $select->where(
365 array(
366 'a.' . Adherent::PK => $this->login->id
367 )
368 );
369 } elseif ($this->filters->filtre_cotis_adh != null) {
370 $select->where(
371 'a.' . Adherent::PK . ' = ' . $this->filters->filtre_cotis_adh
372 );
373 }
374 if ($this->filters->filtre_transactions === true) {
375 $select->where('a.trans_id IS NULL');
376 }
377 } catch (\Exception $e) {
378 Analog::log(
379 __METHOD__ . ' | ' . $e->getMessage(),
380 Analog::WARNING
381 );
382 }
383 }
384
385 /**
386 * Get count for current query
387 *
388 * @return int
389 */
390 public function getCount()
391 {
392 return $this->count;
393 }
394
395 /**
396 * Get sum
397 *
398 * @return int
399 */
400 public function getSum()
401 {
402 return $this->sum;
403 }
404
405 /**
406 * Remove specified contributions
407 *
408 * @param integer|array $ids Contributions identifiers to delete
409 * @param History $hist History
410 * @param boolean $transaction True to begin a database transaction
411 *
412 * @return boolean
413 */
414 public function remove($ids, History $hist, $transaction = true)
415 {
416 $list = array();
417 if (is_numeric($ids)) {
418 //we've got only one identifier
419 $list[] = $ids;
420 } else {
421 $list = $ids;
422 }
423
424 if (is_array($list)) {
425 $res = true;
426 try {
427 if ($transaction) {
428 $this->zdb->connection->beginTransaction();
429 }
430 $select = $this->zdb->select(self::TABLE);
431 $select->where->in(self::PK, $list);
432 $contributions = $this->zdb->execute($select);
433 foreach ($contributions as $contribution) {
434 $c = new Contribution($this->zdb, $this->login, $contribution);
435 $res = $c->remove(false);
436 if ($res === false) {
437 throw new \Exception();
438 }
439 }
440 if ($transaction) {
441 $this->zdb->connection->commit();
442 }
443 $hist->add(
444 str_replace(
445 '%list',
446 print_r($list, true),
447 _T("Contributions deleted (%list)")
448 )
449 );
450 return true;
451 } catch (\Exception $e) {
452 if ($transaction) {
453 $this->zdb->connection->rollBack();
454 }
455 Analog::log(
456 'An error occurred trying to remove contributions | ' .
457 $e->getMessage(),
458 Analog::ERROR
459 );
460 return false;
461 }
462 } else {
463 //not numeric and not an array: incorrect.
464 Analog::log(
465 'Asking to remove contribution, but without providing an array or a single numeric value.',
466 Analog::WARNING
467 );
468 return false;
469 }
470 }
471 }