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