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 each 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);
72 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
73 $delete->where(['fingerprint' => 'FAKER' . $this->seed
]);
74 $delete->where('parent_id IS NOT NULL');
75 $this->zdb
->execute($delete);
77 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
78 $delete->where(['fingerprint' => 'FAKER' . $this->seed
]);
79 $this->zdb
->execute($delete);
81 $this->cleanHistory();
87 * @param string $testMethod Calling method
91 public function beforeTestMethod($testMethod)
93 parent
::beforeTestMethod($testMethod);
94 $this->initContributionsTypes();
96 $this->contrib
= new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
98 $this->adh
= new \Galette\Entity\
Adherent($this->zdb
);
99 $this->adh
->setDependencies(
101 $this->members_fields
,
107 * Test empty contribution
111 public function testEmpty()
113 $contrib = $this->contrib
;
114 $this->variable($contrib->id
)->isNull();
115 $this->variable($contrib->isFee())->isNull();
116 $this->variable($contrib->is_cotis
)->isNull();
117 $this->variable($contrib->date
)->isNull();
118 $this->variable($contrib->begin_date
)->isNull();
119 $this->variable($contrib->end_date
)->isNull();
120 $this->variable($contrib->raw_date
)->isNull();
121 $this->variable($contrib->raw_begin_date
)->isNull();
122 $this->variable($contrib->raw_end_date
)->isNull();
123 $this->string($contrib->duration
)->isEmpty();
124 $this->variable($contrib->payment_type
)->isIdenticalTo((int)$this->preferences
->pref_default_paymenttype
);
125 $this->string($contrib->spayment_type
)->isIdenticalTo('Check');
126 $this->variable($contrib->model
)->isNull();
127 $this->variable($contrib->member
)->isNull();
128 $this->variable($contrib->type
)->isNull();
129 $this->variable($contrib->amount
)->isNull();
130 $this->variable($contrib->orig_amount
)->isNull();
131 $this->variable($contrib->info
)->isNull();
132 $this->variable($contrib->transaction
)->isNull();
133 $this->array($contrib->fields
)
136 \Galette\Entity\Contribution
::PK
,
137 \Galette\Entity\Adherent
::PK
,
138 \Galette\Entity\ContributionsTypes
::PK
,
140 'type_paiement_cotis',
145 $this->string($contrib->getRowClass())->isIdenticalTo('cotis-give');
146 $this->variable($contrib::getDueDate($this->zdb
, 1))->isNull();
147 $this->boolean($contrib->isTransactionPart())->isFalse();
148 $this->boolean($contrib->isTransactionPartOf(1))->isFalse();
149 $this->string($contrib->getRawType())->isIdenticalTo('donation');
150 $this->string($contrib->getTypeLabel())->isIdenticalTo('Donation');
151 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
152 $this->variable($contrib->unknown_property
)->isNull();
156 * Test getter and setter special cases
160 public function testGetterSetter()
162 $contrib = $this->contrib
;
165 $contrib->begin_date
= 'not a date';
166 $this->variable($contrib->raw_begin_date
)->isNull();
167 $this->variable($contrib->begin_date
)->isNull();
169 $contrib->begin_date
= '2017-06-17';
170 $this->object($contrib->raw_begin_date
)->isInstanceOf('DateTime');
171 $this->string($contrib->begin_date
)->isIdenticalTo('2017-06-17');
173 $contrib->amount
= 'not an amount';
174 $this->variable($contrib->amount
)->isNull();
175 $contrib->amount
= 0;
176 $this->variable($contrib->amount
)->isNull();
177 $contrib->amount
= 42;
178 $this->integer($contrib->amount
)->isIdenticalTo(42);
179 $contrib->amount
= '42';
180 $this->string($contrib->amount
)->isIdenticalTo('42');
182 $contrib->type
= 'not a type';
183 $this->variable($contrib->type
)->isNull();
184 $contrib->type
= 156;
185 $this->object($contrib->type
)->isInstanceOf('\Galette\Entity\ContributionsTypes');
186 $this->boolean($contrib->type
->id
)->isFalse();
188 $this->object($contrib->type
)->isInstanceOf('\Galette\Entity\ContributionsTypes');
189 $this->variable($contrib->type
->id
)->isEqualTo(1);
191 $contrib->transaction
= 'not a transaction id';
192 $this->variable($contrib->transaction
)->isNull();
193 $contrib->transaction
= 46;
194 $this->object($contrib->transaction
)->isInstanceOf('\Galette\Entity\Transaction');
195 $this->variable($contrib->transaction
->id
)->isNull();
197 $contrib->member
= 'not a member';
198 $this->variable($contrib->member
)->isNull();
199 $contrib->member
= 118218;
200 $this->integer($contrib->member
)->isIdenticalTo(118218);
202 $contrib->not_a_property
= 'abcde';
203 $this->boolean(property_exists($contrib, 'not_a_property'))->isFalse();
205 $contrib->payment_type
= \Galette\Entity\PaymentType
::CASH
;
206 $this->string($contrib->getPaymentType())->isIdenticalTo('Cash');
207 $this->string($contrib->spayment_type
)->isIdenticalTo('Cash');
209 $contrib->payment_type
= \Galette\Entity\PaymentType
::CHECK
;
210 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
211 $this->string($contrib->spayment_type
)->isIdenticalTo('Check');
213 $contrib->payment_type
= \Galette\Entity\PaymentType
::OTHER
;
214 $this->string($contrib->getPaymentType())->isIdenticalTo('Other');
215 $this->string($contrib->spayment_type
)->isIdenticalTo('Other');
217 $contrib->payment_type
= \Galette\Entity\PaymentType
::CREDITCARD
;
218 $this->string($contrib->getPaymentType())->isIdenticalTo('Credit card');
219 $this->string($contrib->spayment_type
)->isIdenticalTo('Credit card');
221 $contrib->payment_type
= \Galette\Entity\PaymentType
::TRANSFER
;
222 $this->string($contrib->getPaymentType())->isIdenticalTo('Transfer');
223 $this->string($contrib->spayment_type
)->isIdenticalTo('Transfer');
225 $contrib->payment_type
= \Galette\Entity\PaymentType
::PAYPAL
;
226 $this->string($contrib->getPaymentType())->isIdenticalTo('Paypal');
227 $this->string($contrib->spayment_type
)->isIdenticalTo('Paypal');
231 * Test contribution creation
235 public function testCreation()
237 $this->getMemberOne();
238 //create contribution for member
239 $this->createContribution();
243 * Test end date retrieving
244 * This is based on some Preferences parameters
248 public function testRetrieveEndDate()
251 $orig_pref_beg_membership = $this->preferences
->pref_beg_membership
;
252 $orig_pref_membership_ext = $this->preferences
->pref_membership_ext
;
253 $orig_pref_membership_offermonths = $this->preferences
->pref_membership_offermonths
;
255 $contrib = new \Galette\Entity\
Contribution(
258 ['type' => 1] //anual fee
261 // First, check for 12 months renewal
262 $expected = new \
DateTime();
263 $expected->add(new \
DateInterval('P1Y'));
264 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
266 //unset pref_beg_membership and pref_membership_ext
267 $preferences->pref_beg_membership
= '';
268 $preferences->pref_membership_ext
= '';
272 $contrib = new \Galette\Entity\
Contribution(
275 ['type' => 1] //anual fee
279 ->isInstanceOf('RuntimeException')
280 ->hasMessage('Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!');
282 // Second, test with beginning of membership date
283 $preferences->pref_beg_membership
= '29/05';
284 $expected = new \
DateTime();
285 $expected->setDate(date('Y'), 5, 29);
286 if ($expected < new \
DateTime()) {
287 $expected->add(new \
DateInterval('P1Y'));
290 $contrib = new \Galette\Entity\
Contribution(
293 ['type' => 1] // anual fee
295 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
297 // Third, test with beginning of membership date and i2 last months offered
298 $beginning = new \
DateTime();
299 $beginning->add(new \
DateInterval('P1M'));
300 $preferences->pref_beg_membership
= $beginning->format('t/m'); // end of next month
301 $preferences->pref_membership_offermonths
= 2;
302 $expected = clone $beginning;
303 $expected->add(new \
DateInterval('P1Y'));
305 $contrib = new \Galette\Entity\
Contribution(
308 ['type' => 1] // anual fee
310 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-t'));
313 $preferences->pref_beg_membership
= $orig_pref_beg_membership;
314 $preferences->pref_membership_ext
= $orig_pref_membership_ext;
315 $preferences->pref_membership_offermonths
= $orig_pref_membership_offermonths;
319 * Test checkOverlap method
323 public function testCheckOverlap()
325 $adh = new \Galette\Entity\
Adherent($this->zdb
);
326 $adh->setDependencies(
328 $this->members_fields
,
332 $check = $adh->check(
334 'nom_adh' => 'Overlapped',
335 'date_crea_adh' => date(_T("Y-m-d")),
336 \Galette\Entity\Status
::PK
=> \Galette\Entity\Status
::DEFAULT_STATUS
,
337 'fingerprint' => 'FAKER' . $this->seed
342 if (is_array($check)) {
345 $this->boolean($check)->isTrue();
347 $store = $adh->store();
348 $this->boolean($store)->isTrue();
350 //create first contribution for member
351 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
353 $now = new \
DateTime();
354 $end_date = clone $now;
355 $end_date->add(new \
DateInterval('P1Y'));
357 \Galette\Entity\Adherent
::PK
=> $adh->id
,
358 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anual fee
359 'montant_cotis' => 20,
360 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
361 'date_enreg' => $now->format(_T("Y-m-d")),
362 'date_debut_cotis' => $now->format(_T("Y-m-d")),
363 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
364 'info_cotis' => 'FAKER' . $this->seed
367 $check = $contrib->check($data, [], []);
368 if (is_array($check)) {
371 $this->boolean($check)->isTrue();
372 $this->boolean($contrib->checkOverlap())->isTrue();
374 $store = $contrib->store();
375 $this->boolean($store)->isTrue();
377 //load member from db
378 $adh = new \Galette\Entity\
Adherent($this->zdb
, $adh->id
);
380 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
381 $begin = clone $end_date;
382 $begin->sub(new \
DateInterval('P3M'));
383 $end_date = clone $begin;
384 $end_date->add(new \
DateInterval('P1Y'));
386 \Galette\Entity\Adherent
::PK
=> $adh->id
,
387 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anual fee
388 'montant_cotis' => 20,
389 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
390 'date_enreg' => $now->format(_T("Y-m-d")),
391 'date_debut_cotis' => $begin->format(_T("Y-m-d")),
392 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
393 'info_cotis' => 'FAKER' . $this->seed
396 $check = $contrib->check($data, [], []);
397 $this->array($check)->isIdenticalTo([
398 '- Membership period overlaps period starting at ' . $now->format('Y-m-d')
402 function () use ($contrib) {
403 $store = $contrib->store();
406 ->isInstanceOf('RuntimeException')
407 ->message
->startWith('Existing errors prevents storing contribution');
411 * Test checkOverlap method that throws an exception
415 public function testCheckOverlapWException()
417 $zdb = new \mock\Galette\Core\
Db();
418 $this->calling($zdb)->execute
= function ($o) {
419 if ($o instanceof \Zend\Db\Sql\Select
) {
420 throw new \
LogicException('Error executing query!', 123);
424 $contrib = new \Galette\Entity\
Contribution($zdb, $this->login
);
425 $this->boolean($contrib->checkOverlap())->isFalse();
434 public function testGetFieldLabel()
436 $this->string($this->contrib
->getFieldLabel('montant_cotis'))
437 ->isIdenticalTo('Amount');
439 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
440 ->isIdenticalTo('Date of contribution');
442 $this->contrib
->type
= 1;
443 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
444 ->isIdenticalTo('Start date of membership');
446 $this->string($this->contrib
->getFieldLabel('info_cotis'))
447 ->isIdenticalTo('Comments');
451 * Test contribution loading
455 public function testLoad()
457 $this->login
= new \mock\Galette\Core\
Login($this->zdb
, $this->i18n
);
458 $this->calling($this->login
)->isLogged
= true;
459 $this->calling($this->login
)->isStaff
= true;
460 $this->calling($this->login
)->isAdmin
= true;
462 $this->getMemberOne();
464 //create contribution for member
465 $this->createContribution();
467 $id = $this->contrib
->id
;
468 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
470 $this->boolean($contrib->load((int)$id))->isTrue();
471 $this->checkContribExpected($contrib);
473 $this->boolean($contrib->load(1355522012))->isFalse();
477 * Test contribution removal
481 public function testRemove()
483 $this->getMemberOne();
484 $this->createContribution();
486 $this->boolean($this->contrib
->remove())->isTrue();
488 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
489 $this->boolean($this->contrib
->remove())->isFalse();
497 public function testCan()
499 $this->getMemberOne();
500 //create contribution for member
501 $this->createContribution();
502 $contrib = $this->contrib
;
504 $this->boolean($contrib->canShow($this->login
))->isFalse();
506 //Superadmin can fully change contributions
507 $this->logSuperAdmin();
509 $this->boolean($contrib->canShow($this->login
))->isTrue();
512 $this->login
->logOut();
513 $this->boolean($this->login
->isLogged())->isFalse();
515 //Member can fully change its own contributions
516 $mdata = $this->dataAdherentOne();
517 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
518 $this->boolean($this->login
->isLogged())->isTrue();
519 $this->boolean($this->login
->isAdmin())->isFalse();
520 $this->boolean($this->login
->isStaff())->isFalse();
522 $this->boolean($contrib->canShow($this->login
))->isTrue();
525 $this->login
->logOut();
526 $this->boolean($this->login
->isLogged())->isFalse();
528 //Another member has no access
529 $this->getMemberTwo();
530 $mdata = $this->dataAdherentTwo();
531 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
532 $this->boolean($this->login
->isLogged())->isTrue();
533 $this->boolean($this->login
->isAdmin())->isFalse();
534 $this->boolean($this->login
->isStaff())->isFalse();
536 $this->boolean($contrib->canShow($this->login
))->isFalse();
538 //parents can chow change children contributions
539 $this->getMemberOne();
540 $member = $this->adh
;
541 $mdata = $this->dataAdherentOne();
543 $login = $this->login
;
544 $this->logSuperAdmin();
548 'prenom_adh' => 'Johny',
549 'parent_id' => $member->id
,
551 'login_adh' => 'child.johny.doe',
552 'fingerprint' => 'FAKER' . $this->seed
554 $child = $this->createMember($child_data);
557 //contribution for child
558 $bdate = new \
DateTime(); // 2020-11-07
559 $bdate->sub(new \
DateInterval('P5M')); // 2020-06-07
560 $bdate->add(new \
DateInterval('P3D')); // 2020-06-10
562 $edate = clone $bdate;
563 $edate->add(new \
DateInterval('P1Y'));
567 'id_type_cotis' => 1,
568 'montant_cotis' => 25,
569 'type_paiement_cotis' => 3,
570 'info_cotis' => 'FAKER' . $this->seed
,
571 'date_enreg' => $bdate->format('Y-m-d'),
572 'date_debut_cotis' => $bdate->format('Y-m-d'),
573 'date_fin_cotis' => $edate->format('Y-m-d'),
575 $ccontrib = $this->createContrib($data);
577 $this->login
->logOut();
580 $child = new \Galette\Entity\
Adherent($this->zdb
);
581 $child->enableDep('parent');
582 $this->boolean($child->load($cid))->isTrue();
584 $this->string($child->name
)->isIdenticalTo($child_data['nom_adh']);
585 $this->object($child->parent
)->isInstanceOf('\Galette\Entity\Adherent');
586 $this->integer($child->parent
->id
)->isIdenticalTo($member->id
);
587 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
589 $mdata = $this->dataAdherentOne();
590 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
591 $this->boolean($this->login
->isLogged())->isTrue();
592 $this->boolean($this->login
->isAdmin())->isFalse();
593 $this->boolean($this->login
->isStaff())->isFalse();
595 $this->boolean($ccontrib->canShow($this->login
))->isTrue();
598 $this->login
->logOut();
599 $this->boolean($this->login
->isLogged())->isFalse();