3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2017 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/>.
28 * @package GaletteTests
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2017 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
34 * @link http://galette.tuxfamily.org
38 namespace Galette\Entity\test\units
;
40 use Galette\GaletteTestCase
;
43 * Contribution tests class
47 * @package GaletteTests
48 * @author Johan Cwiklinski <johan@x-tnd.be>
49 * @copyright 2017 The Galette Team
50 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
51 * @link http://galette.tuxfamily.org
54 class Contribution
extends GaletteTestCase
56 protected $seed = 95842354;
59 * Cleanup after testeach test method
61 * @param string $method Calling method
65 public function afterTestMethod($method)
67 $this->zdb
= new \Galette\Core\
Db();
68 $delete = $this->zdb
->delete(\Galette\Entity\Contribution
::TABLE
);
69 $delete->where(['info_cotis' => 'FAKER' . $this->seed
]);
70 $this->zdb
->execute($delete);
71 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
72 $delete->where(['fingerprint' => 'FAKER' . $this->seed
]);
73 $this->zdb
->execute($delete);
79 * @param string $testMethod Calling method
83 public function beforeTestMethod($testMethod)
85 parent
::beforeTestMethod($testMethod);
86 $this->initContributionsTypes();
88 $this->contrib
= new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
90 $this->adh
= new \Galette\Entity\
Adherent($this->zdb
);
91 $this->adh
->setDependencies(
93 $this->members_fields
,
99 * Create test contribution in database
103 private function createContribution()
105 $bdate = new \
DateTime(); // 2020-11-07
106 $bdate->sub(new \
DateInterval('P5M')); // 2020-06-07
107 $bdate->add(new \
DateInterval('P3D')); // 2020-06-10
109 $edate = clone $bdate;
110 $edate->add(new \
DateInterval('P1Y'));
113 'id_adh' => $this->adh
->id
,
114 'id_type_cotis' => 1,
115 'montant_cotis' => 92,
116 'type_paiement_cotis' => 3,
117 'info_cotis' => 'FAKER' . $this->seed
,
118 'date_enreg' => $bdate->format('Y-m-d'),
119 'date_debut_cotis' => $bdate->format('Y-m-d'),
120 'date_fin_cotis' => $edate->format('Y-m-d'),
122 $this->createContrib($data);
123 $this->checkContribExpected();
127 * Loads contribution from a resultset
129 * @param ResultSet $rs ResultSet
133 private function loadContribution($rs)
135 $this->adh
= new \Galette\Entity\
Contribution($this->zdb
, $this->login
, $rs);
139 * Test empty contribution
143 public function testEmpty()
145 $contrib = $this->contrib
;
146 $this->variable($contrib->id
)->isNull();
147 $this->variable($contrib->isCotis())->isNull();
148 $this->variable($contrib->is_cotis
)->isNull();
149 $this->variable($contrib->date
)->isNull();
150 $this->variable($contrib->begin_date
)->isNull();
151 $this->variable($contrib->end_date
)->isNull();
152 $this->variable($contrib->raw_date
)->isNull();
153 $this->variable($contrib->raw_begin_date
)->isNull();
154 $this->variable($contrib->raw_end_date
)->isNull();
155 $this->string($contrib->duration
)->isEmpty();
156 $this->variable($contrib->payment_type
)->isNull();
157 $this->string($contrib->spayment_type
)->isIdenticalTo('-');
158 $this->variable($contrib->model
)->isNull();
159 $this->variable($contrib->member
)->isNull();
160 $this->variable($contrib->type
)->isNull();
161 $this->variable($contrib->amount
)->isNull();
162 $this->variable($contrib->orig_amount
)->isNull();
163 $this->variable($contrib->info
)->isNull();
164 $this->variable($contrib->transaction
)->isNull();
165 $this->array($contrib->fields
)
168 \Galette\Entity\Contribution
::PK
,
169 \Galette\Entity\Adherent
::PK
,
170 \Galette\Entity\ContributionsTypes
::PK
,
172 'type_paiement_cotis',
177 $this->string($contrib->getRowClass())->isIdenticalTo('cotis-give');
178 $this->variable($contrib::getDueDate($this->zdb
, 1))->isNull();
179 $this->boolean($contrib->isTransactionPart())->isFalse();
180 $this->boolean($contrib->isTransactionPartOf(1))->isFalse();
181 $this->string($contrib->getRawType())->isIdenticalTo('donation');
182 $this->string($contrib->getTypeLabel())->isIdenticalTo('Donation');
183 $this->string($contrib->getPaymentType())->isIdenticalTo('-');
184 $this->variable($contrib->unknown_property
)->isNull();
188 * Test getter and setter special cases
192 public function testGetterSetter()
194 $contrib = $this->contrib
;
197 $contrib->begin_date
= 'not a date';
198 $this->variable($contrib->raw_begin_date
)->isNull();
199 $this->variable($contrib->begin_date
)->isNull();
201 $contrib->begin_date
= '2017-06-17';
202 $this->object($contrib->raw_begin_date
)->isInstanceOf('DateTime');
203 $this->string($contrib->begin_date
)->isIdenticalTo('2017-06-17');
205 $contrib->amount
= 'not an amount';
206 $this->variable($contrib->amount
)->isNull();
207 $contrib->amount
= 0;
208 $this->variable($contrib->amount
)->isNull();
209 $contrib->amount
= 42;
210 $this->integer($contrib->amount
)->isIdenticalTo(42);
211 $contrib->amount
= '42';
212 $this->string($contrib->amount
)->isIdenticalTo('42');
214 $contrib->type
= 'not a type';
215 $this->variable($contrib->type
)->isNull();
216 $contrib->type
= 156;
217 $this->object($contrib->type
)->isInstanceOf('\Galette\Entity\ContributionsTypes');
218 $this->boolean($contrib->type
->id
)->isFalse();
220 $this->object($contrib->type
)->isInstanceOf('\Galette\Entity\ContributionsTypes');
221 $this->variable($contrib->type
->id
)->isEqualTo(1);
223 $contrib->transaction
= 'not a transaction id';
224 $this->variable($contrib->transaction
)->isNull();
225 $contrib->transaction
= 46;
226 $this->object($contrib->transaction
)->isInstanceOf('\Galette\Entity\Transaction');
227 $this->boolean($contrib->transaction
->id
)->isFalse();
229 $contrib->member
= 'not a member';
230 $this->variable($contrib->member
)->isNull();
231 $contrib->member
= 118218;
232 $this->integer($contrib->member
)->isIdenticalTo(118218);
234 $contrib->not_a_property
= 'abcde';
235 $this->boolean(property_exists($contrib, 'not_a_property'))->isFalse();
237 $contrib->payment_type
= \Galette\Entity\PaymentType
::CASH
;
238 $this->string($contrib->getPaymentType())->isIdenticalTo('Cash');
239 $this->string($contrib->spayment_type
)->isIdenticalTo('Cash');
241 $contrib->payment_type
= \Galette\Entity\PaymentType
::CHECK
;
242 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
243 $this->string($contrib->spayment_type
)->isIdenticalTo('Check');
245 $contrib->payment_type
= \Galette\Entity\PaymentType
::OTHER
;
246 $this->string($contrib->getPaymentType())->isIdenticalTo('Other');
247 $this->string($contrib->spayment_type
)->isIdenticalTo('Other');
249 $contrib->payment_type
= \Galette\Entity\PaymentType
::CREDITCARD
;
250 $this->string($contrib->getPaymentType())->isIdenticalTo('Credit card');
251 $this->string($contrib->spayment_type
)->isIdenticalTo('Credit card');
253 $contrib->payment_type
= \Galette\Entity\PaymentType
::TRANSFER
;
254 $this->string($contrib->getPaymentType())->isIdenticalTo('Transfer');
255 $this->string($contrib->spayment_type
)->isIdenticalTo('Transfer');
257 $contrib->payment_type
= \Galette\Entity\PaymentType
::PAYPAL
;
258 $this->string($contrib->getPaymentType())->isIdenticalTo('Paypal');
259 $this->string($contrib->spayment_type
)->isIdenticalTo('Paypal');
263 * Check contributions expecteds
265 * @param Contribution $contrib Contribution instance, if any
266 * @param array $new_expecteds Changes on expected values
270 private function checkContribExpected($contrib = null, $new_expecteds = [])
272 if ($contrib === null) {
273 $contrib = $this->contrib
;
276 $date_begin = $contrib->raw_begin_date
;
277 $date_end = clone $date_begin;
278 $date_end->add(new \
DateInterval('P1Y'));
280 $this->object($contrib->raw_date
)->isInstanceOf('DateTime');
281 $this->object($contrib->raw_begin_date
)->isInstanceOf('DateTime');
282 $this->object($contrib->raw_end_date
)->isInstanceOf('DateTime');
285 'id_adh' => "{$this->adh->id}",
286 'id_type_cotis' => 1,
287 'montant_cotis' => '92',
288 'type_paiement_cotis' => '3',
289 'info_cotis' => 'FAKER' . $this->seed
,
290 'date_fin_cotis' => $date_end->format('Y-m-d'),
292 $expecteds = array_merge($expecteds, $new_expecteds);
294 $this->string($contrib->raw_end_date
->format('Y-m-d'))->isIdenticalTo($expecteds['date_fin_cotis']);
296 foreach ($expecteds as $key => $value) {
297 $property = $this->contrib
->fields
[$key]['propname'];
299 case \Galette\Entity\ContributionsTypes
::PK
:
300 $ct = $this->contrib
->type
;
301 if ($ct instanceof \Galette\Entity\ContributionsTypes
) {
302 $this->integer((int)$ct->id
)->isIdenticalTo($value);
304 $this->integer($ct)->isIdenticalTo($value);
308 $this->variable($contrib->$property)->isEqualTo($value, $property);
313 //load member from db
314 $this->adh
= new \Galette\Entity\
Adherent($this->zdb
, $this->adh
->id
);
315 //member is now up-to-date
316 $this->string($this->adh
->getRowClass())->isIdenticalTo('active cotis-ok');
317 $this->string($this->adh
->due_date
)->isIdenticalTo($this->contrib
->end_date
);
318 $this->boolean($this->adh
->isUp2Date())->isTrue();
322 * Test contribution creation
326 public function testCreation()
328 $this->getMemberOne();
329 //create contribution for member
330 $this->createContribution();
334 * Test end date retrieving
335 * This is based on some Preferences parameters
339 public function testRetrieveEndDate()
342 $orig_pref_beg_membership = $this->preferences
->pref_beg_membership
;
343 $orig_pref_membership_ext = $this->preferences
->pref_membership_ext
;
344 $orig_pref_membership_offermonths = $this->preferences
->pref_membership_offermonths
;
346 $contrib = new \Galette\Entity\
Contribution(
349 ['type' => 1] //anual fee
352 // First, check for 12 months renewal
353 $expected = new \
DateTime();
354 $expected->add(new \
DateInterval('P1Y'));
355 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
357 //unset pref_beg_membership and pref_membership_ext
358 $preferences->pref_beg_membership
= '';
359 $preferences->pref_membership_ext
= '';
363 $contrib = new \Galette\Entity\
Contribution(
366 ['type' => 1] //anual fee
370 ->isInstanceOf('RuntimeException')
371 ->hasMessage('Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!');
373 // Second, test with beginning of membership date
374 $preferences->pref_beg_membership
= '29/05';
375 $expected = new \
DateTime();
376 $expected->setDate(date('Y'), 5, 29);
377 if ($expected < new \
DateTime()) {
378 $expected->add(new \
DateInterval('P1Y'));
381 $contrib = new \Galette\Entity\
Contribution(
384 ['type' => 1] // anual fee
386 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
388 // Third, test with beginning of membership date and i2 last months offered
389 $beginning = new \
DateTime();
390 $beginning->add(new \
DateInterval('P1M'));
391 $preferences->pref_beg_membership
= $beginning->format('t/m'); // end of next month
392 $preferences->pref_membership_offermonths
= 2;
393 $expected = clone $beginning;
394 $expected->add(new \
DateInterval('P1Y'));
396 $contrib = new \Galette\Entity\
Contribution(
399 ['type' => 1] // anual fee
401 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-t'));
404 $preferences->pref_beg_membership
= $orig_pref_beg_membership;
405 $preferences->pref_membership_ext
= $orig_pref_membership_ext;
406 $preferences->pref_membership_offermonths
= $orig_pref_membership_offermonths;
410 * Test checkOverlap method
414 public function testCheckOverlap()
416 $adh = new \Galette\Entity\
Adherent($this->zdb
);
417 $adh->setDependencies(
419 $this->members_fields
,
423 $check = $adh->check(
425 'nom_adh' => 'Overlapped',
426 'date_crea_adh' => date(_T("Y-m-d")),
427 \Galette\Entity\Status
::PK
=> \Galette\Entity\Status
::DEFAULT_STATUS
,
428 'fingerprint' => 'FAKER' . $this->seed
433 if (is_array($check)) {
436 $this->boolean($check)->isTrue();
438 $store = $adh->store();
439 $this->boolean($store)->isTrue();
441 //create first contribution for member
442 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
444 $now = new \
DateTime();
445 $end_date = clone $now;
446 $end_date->add(new \
DateInterval('P1Y'));
448 \Galette\Entity\Adherent
::PK
=> $adh->id
,
449 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anual fee
450 'montant_cotis' => 20,
451 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
452 'date_enreg' => $now->format(_T("Y-m-d")),
453 'date_debut_cotis' => $now->format(_T("Y-m-d")),
454 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
455 'info_cotis' => 'FAKER' . $this->seed
458 $check = $contrib->check($data, [], []);
459 if (is_array($check)) {
462 $this->boolean($check)->isTrue();
463 $this->boolean($contrib->checkOverlap())->isTrue();
465 $store = $contrib->store();
466 $this->boolean($store)->isTrue();
468 //load member from db
469 $adh = new \Galette\Entity\
Adherent($this->zdb
, $adh->id
);
471 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
472 $begin = clone $end_date;
473 $begin->sub(new \
DateInterval('P3M'));
474 $end_date = clone $begin;
475 $end_date->add(new \
DateInterval('P1Y'));
477 \Galette\Entity\Adherent
::PK
=> $adh->id
,
478 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anual fee
479 'montant_cotis' => 20,
480 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
481 'date_enreg' => $now->format(_T("Y-m-d")),
482 'date_debut_cotis' => $begin->format(_T("Y-m-d")),
483 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
484 'info_cotis' => 'FAKER' . $this->seed
487 $check = $contrib->check($data, [], []);
488 $this->array($check)->isIdenticalTo([
489 '- Membership period overlaps period starting at ' . $now->format('Y-m-d')
493 function () use ($contrib) {
494 $store = $contrib->store();
497 ->isInstanceOf('RuntimeException')
498 ->message
->startWith('Existing errors prevents storing contribution');
502 * Test checkOverlap method that throws an exception
506 public function testCheckOverlapWException()
508 $zdb = new \mock\Galette\Core\
Db();
509 $this->calling($zdb)->execute
= function ($o) {
510 if ($o instanceof \Zend\Db\Sql\Select
) {
511 throw new \
LogicException('Error executing query!', 123);
515 $contrib = new \Galette\Entity\
Contribution($zdb, $this->login
);
516 $this->boolean($contrib->checkOverlap())->isFalse();
525 public function testGetFieldLabel()
527 $this->string($this->contrib
->getFieldLabel('montant_cotis'))
528 ->isIdenticalTo('Amount');
530 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
531 ->isIdenticalTo('Date of contribution');
533 $this->contrib
->type
= 1;
534 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
535 ->isIdenticalTo('Start date of membership');
539 * Test contribution loading
543 public function testLoad()
545 $this->login
= new \mock\Galette\Core\
Login($this->zdb
, $this->i18n
);
546 $this->calling($this->login
)->isLogged
= true;
547 $this->calling($this->login
)->isStaff
= true;
548 $this->calling($this->login
)->isAdmin
= true;
550 $this->getMemberOne();
552 //create contribution for member
553 $this->createContribution();
555 $id = $this->contrib
->id
;
556 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
558 $this->boolean($contrib->load((int)$id))->isTrue();
559 $this->checkContribExpected($contrib);
561 $this->boolean($contrib->load(1355522012))->isFalse();
565 * Test contribution removal
569 public function testRemove()
571 $this->getMemberOne();
572 $this->createContribution();
574 $id = (int)$this->contrib
->id
;
575 $this->boolean($this->contrib
->remove())->isTrue();
577 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
578 $this->boolean($this->contrib
->remove())->isFalse();