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);
85 * @param string $testMethod Calling method
89 public function beforeTestMethod($testMethod)
91 parent
::beforeTestMethod($testMethod);
92 $this->initContributionsTypes();
94 $this->contrib
= new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
96 $this->adh
= new \Galette\Entity\
Adherent($this->zdb
);
97 $this->adh
->setDependencies(
99 $this->members_fields
,
105 * Test empty contribution
109 public function testEmpty()
111 $contrib = $this->contrib
;
112 $this->variable($contrib->id
)->isNull();
113 $this->variable($contrib->isFee())->isNull();
114 $this->variable($contrib->is_cotis
)->isNull();
115 $this->variable($contrib->date
)->isNull();
116 $this->variable($contrib->begin_date
)->isNull();
117 $this->variable($contrib->end_date
)->isNull();
118 $this->variable($contrib->raw_date
)->isNull();
119 $this->variable($contrib->raw_begin_date
)->isNull();
120 $this->variable($contrib->raw_end_date
)->isNull();
121 $this->string($contrib->duration
)->isEmpty();
122 $this->variable($contrib->payment_type
)->isIdenticalTo((int)$this->preferences
->pref_default_paymenttype
);
123 $this->string($contrib->spayment_type
)->isIdenticalTo('Check');
124 $this->variable($contrib->model
)->isNull();
125 $this->variable($contrib->member
)->isNull();
126 $this->variable($contrib->type
)->isNull();
127 $this->variable($contrib->amount
)->isNull();
128 $this->variable($contrib->orig_amount
)->isNull();
129 $this->variable($contrib->info
)->isNull();
130 $this->variable($contrib->transaction
)->isNull();
131 $this->array($contrib->fields
)
134 \Galette\Entity\Contribution
::PK
,
135 \Galette\Entity\Adherent
::PK
,
136 \Galette\Entity\ContributionsTypes
::PK
,
138 'type_paiement_cotis',
143 $this->string($contrib->getRowClass())->isIdenticalTo('cotis-give');
144 $this->variable($contrib::getDueDate($this->zdb
, 1))->isNull();
145 $this->boolean($contrib->isTransactionPart())->isFalse();
146 $this->boolean($contrib->isTransactionPartOf(1))->isFalse();
147 $this->string($contrib->getRawType())->isIdenticalTo('donation');
148 $this->string($contrib->getTypeLabel())->isIdenticalTo('Donation');
149 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
150 $this->variable($contrib->unknown_property
)->isNull();
154 * Test getter and setter special cases
158 public function testGetterSetter()
160 $contrib = $this->contrib
;
163 $contrib->begin_date
= 'not a date';
164 $this->variable($contrib->raw_begin_date
)->isNull();
165 $this->variable($contrib->begin_date
)->isNull();
167 $contrib->begin_date
= '2017-06-17';
168 $this->object($contrib->raw_begin_date
)->isInstanceOf('DateTime');
169 $this->string($contrib->begin_date
)->isIdenticalTo('2017-06-17');
171 $contrib->amount
= 'not an amount';
172 $this->variable($contrib->amount
)->isNull();
173 $contrib->amount
= 0;
174 $this->variable($contrib->amount
)->isNull();
175 $contrib->amount
= 42;
176 $this->integer($contrib->amount
)->isIdenticalTo(42);
177 $contrib->amount
= '42';
178 $this->string($contrib->amount
)->isIdenticalTo('42');
180 $contrib->type
= 'not a type';
181 $this->variable($contrib->type
)->isNull();
182 $contrib->type
= 156;
183 $this->object($contrib->type
)->isInstanceOf('\Galette\Entity\ContributionsTypes');
184 $this->boolean($contrib->type
->id
)->isFalse();
186 $this->object($contrib->type
)->isInstanceOf('\Galette\Entity\ContributionsTypes');
187 $this->variable($contrib->type
->id
)->isEqualTo(1);
189 $contrib->transaction
= 'not a transaction id';
190 $this->variable($contrib->transaction
)->isNull();
191 $contrib->transaction
= 46;
192 $this->object($contrib->transaction
)->isInstanceOf('\Galette\Entity\Transaction');
193 $this->variable($contrib->transaction
->id
)->isNull();
195 $contrib->member
= 'not a member';
196 $this->variable($contrib->member
)->isNull();
197 $contrib->member
= 118218;
198 $this->integer($contrib->member
)->isIdenticalTo(118218);
200 $contrib->not_a_property
= 'abcde';
201 $this->boolean(property_exists($contrib, 'not_a_property'))->isFalse();
203 $contrib->payment_type
= \Galette\Entity\PaymentType
::CASH
;
204 $this->string($contrib->getPaymentType())->isIdenticalTo('Cash');
205 $this->string($contrib->spayment_type
)->isIdenticalTo('Cash');
207 $contrib->payment_type
= \Galette\Entity\PaymentType
::CHECK
;
208 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
209 $this->string($contrib->spayment_type
)->isIdenticalTo('Check');
211 $contrib->payment_type
= \Galette\Entity\PaymentType
::OTHER
;
212 $this->string($contrib->getPaymentType())->isIdenticalTo('Other');
213 $this->string($contrib->spayment_type
)->isIdenticalTo('Other');
215 $contrib->payment_type
= \Galette\Entity\PaymentType
::CREDITCARD
;
216 $this->string($contrib->getPaymentType())->isIdenticalTo('Credit card');
217 $this->string($contrib->spayment_type
)->isIdenticalTo('Credit card');
219 $contrib->payment_type
= \Galette\Entity\PaymentType
::TRANSFER
;
220 $this->string($contrib->getPaymentType())->isIdenticalTo('Transfer');
221 $this->string($contrib->spayment_type
)->isIdenticalTo('Transfer');
223 $contrib->payment_type
= \Galette\Entity\PaymentType
::PAYPAL
;
224 $this->string($contrib->getPaymentType())->isIdenticalTo('Paypal');
225 $this->string($contrib->spayment_type
)->isIdenticalTo('Paypal');
229 * Test contribution creation
233 public function testCreation()
235 $this->getMemberOne();
236 //create contribution for member
237 $this->createContribution();
241 * Test end date retrieving
242 * This is based on some Preferences parameters
246 public function testRetrieveEndDate()
249 $orig_pref_beg_membership = $this->preferences
->pref_beg_membership
;
250 $orig_pref_membership_ext = $this->preferences
->pref_membership_ext
;
251 $orig_pref_membership_offermonths = $this->preferences
->pref_membership_offermonths
;
253 $contrib = new \Galette\Entity\
Contribution(
256 ['type' => 1] //anual fee
259 // First, check for 12 months renewal
260 $expected = new \
DateTime();
261 $expected->add(new \
DateInterval('P1Y'));
262 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
264 //unset pref_beg_membership and pref_membership_ext
265 $preferences->pref_beg_membership
= '';
266 $preferences->pref_membership_ext
= '';
270 $contrib = new \Galette\Entity\
Contribution(
273 ['type' => 1] //anual fee
277 ->isInstanceOf('RuntimeException')
278 ->hasMessage('Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!');
280 // Second, test with beginning of membership date
281 $preferences->pref_beg_membership
= '29/05';
282 $expected = new \
DateTime();
283 $expected->setDate(date('Y'), 5, 29);
284 if ($expected < new \
DateTime()) {
285 $expected->add(new \
DateInterval('P1Y'));
288 $contrib = new \Galette\Entity\
Contribution(
291 ['type' => 1] // anual fee
293 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
295 // Third, test with beginning of membership date and i2 last months offered
296 $beginning = new \
DateTime();
297 $beginning->add(new \
DateInterval('P1M'));
298 $preferences->pref_beg_membership
= $beginning->format('t/m'); // end of next month
299 $preferences->pref_membership_offermonths
= 2;
300 $expected = clone $beginning;
301 $expected->add(new \
DateInterval('P1Y'));
303 $contrib = new \Galette\Entity\
Contribution(
306 ['type' => 1] // anual fee
308 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-t'));
311 $preferences->pref_beg_membership
= $orig_pref_beg_membership;
312 $preferences->pref_membership_ext
= $orig_pref_membership_ext;
313 $preferences->pref_membership_offermonths
= $orig_pref_membership_offermonths;
317 * Test checkOverlap method
321 public function testCheckOverlap()
323 $adh = new \Galette\Entity\
Adherent($this->zdb
);
324 $adh->setDependencies(
326 $this->members_fields
,
330 $check = $adh->check(
332 'nom_adh' => 'Overlapped',
333 'date_crea_adh' => date(_T("Y-m-d")),
334 \Galette\Entity\Status
::PK
=> \Galette\Entity\Status
::DEFAULT_STATUS
,
335 'fingerprint' => 'FAKER' . $this->seed
340 if (is_array($check)) {
343 $this->boolean($check)->isTrue();
345 $store = $adh->store();
346 $this->boolean($store)->isTrue();
348 //create first contribution for member
349 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
351 $now = new \
DateTime();
352 $end_date = clone $now;
353 $end_date->add(new \
DateInterval('P1Y'));
355 \Galette\Entity\Adherent
::PK
=> $adh->id
,
356 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anual fee
357 'montant_cotis' => 20,
358 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
359 'date_enreg' => $now->format(_T("Y-m-d")),
360 'date_debut_cotis' => $now->format(_T("Y-m-d")),
361 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
362 'info_cotis' => 'FAKER' . $this->seed
365 $check = $contrib->check($data, [], []);
366 if (is_array($check)) {
369 $this->boolean($check)->isTrue();
370 $this->boolean($contrib->checkOverlap())->isTrue();
372 $store = $contrib->store();
373 $this->boolean($store)->isTrue();
375 //load member from db
376 $adh = new \Galette\Entity\
Adherent($this->zdb
, $adh->id
);
378 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
379 $begin = clone $end_date;
380 $begin->sub(new \
DateInterval('P3M'));
381 $end_date = clone $begin;
382 $end_date->add(new \
DateInterval('P1Y'));
384 \Galette\Entity\Adherent
::PK
=> $adh->id
,
385 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anual fee
386 'montant_cotis' => 20,
387 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
388 'date_enreg' => $now->format(_T("Y-m-d")),
389 'date_debut_cotis' => $begin->format(_T("Y-m-d")),
390 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
391 'info_cotis' => 'FAKER' . $this->seed
394 $check = $contrib->check($data, [], []);
395 $this->array($check)->isIdenticalTo([
396 '- Membership period overlaps period starting at ' . $now->format('Y-m-d')
400 function () use ($contrib) {
401 $store = $contrib->store();
404 ->isInstanceOf('RuntimeException')
405 ->message
->startWith('Existing errors prevents storing contribution');
409 * Test checkOverlap method that throws an exception
413 public function testCheckOverlapWException()
415 $zdb = new \mock\Galette\Core\
Db();
416 $this->calling($zdb)->execute
= function ($o) {
417 if ($o instanceof \Zend\Db\Sql\Select
) {
418 throw new \
LogicException('Error executing query!', 123);
422 $contrib = new \Galette\Entity\
Contribution($zdb, $this->login
);
423 $this->boolean($contrib->checkOverlap())->isFalse();
432 public function testGetFieldLabel()
434 $this->string($this->contrib
->getFieldLabel('montant_cotis'))
435 ->isIdenticalTo('Amount');
437 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
438 ->isIdenticalTo('Date of contribution');
440 $this->contrib
->type
= 1;
441 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
442 ->isIdenticalTo('Start date of membership');
444 $this->string($this->contrib
->getFieldLabel('info_cotis'))
445 ->isIdenticalTo('Comments');
449 * Test contribution loading
453 public function testLoad()
455 $this->login
= new \mock\Galette\Core\
Login($this->zdb
, $this->i18n
);
456 $this->calling($this->login
)->isLogged
= true;
457 $this->calling($this->login
)->isStaff
= true;
458 $this->calling($this->login
)->isAdmin
= true;
460 $this->getMemberOne();
462 //create contribution for member
463 $this->createContribution();
465 $id = $this->contrib
->id
;
466 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
468 $this->boolean($contrib->load((int)$id))->isTrue();
469 $this->checkContribExpected($contrib);
471 $this->boolean($contrib->load(1355522012))->isFalse();
475 * Test contribution removal
479 public function testRemove()
481 $this->getMemberOne();
482 $this->createContribution();
484 $this->boolean($this->contrib
->remove())->isTrue();
486 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
487 $this->boolean($this->contrib
->remove())->isFalse();
495 public function testCan()
497 $this->getMemberOne();
498 //create contribution for member
499 $this->createContribution();
500 $contrib = $this->contrib
;
502 $this->boolean($contrib->canShow($this->login
))->isFalse();
504 //Superadmin can fully change contributions
505 $this->login
->logAdmin('superadmin', $this->preferences
);
506 $this->boolean($this->login
->isLogged())->isTrue();
507 $this->boolean($this->login
->isSuperAdmin())->isTrue();
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->login
->logAdmin('superadmin', $this->preferences
);
545 $this->boolean($this->login
->isLogged())->isTrue();
546 $this->boolean($this->login
->isSuperAdmin())->isTrue();
550 'prenom_adh' => 'Johny',
551 'parent_id' => $member->id
,
553 'login_adh' => 'child.johny.doe',
554 'fingerprint' => 'FAKER' . $this->seed
556 $child = $this->createMember($child_data);
559 //contribution for child
560 $bdate = new \
DateTime(); // 2020-11-07
561 $bdate->sub(new \
DateInterval('P5M')); // 2020-06-07
562 $bdate->add(new \
DateInterval('P3D')); // 2020-06-10
564 $edate = clone $bdate;
565 $edate->add(new \
DateInterval('P1Y'));
569 'id_type_cotis' => 1,
570 'montant_cotis' => 25,
571 'type_paiement_cotis' => 3,
572 'info_cotis' => 'FAKER' . $this->seed
,
573 'date_enreg' => $bdate->format('Y-m-d'),
574 'date_debut_cotis' => $bdate->format('Y-m-d'),
575 'date_fin_cotis' => $edate->format('Y-m-d'),
577 $ccontrib = $this->createContrib($data);
579 $this->login
->logOut();
582 $child = new \Galette\Entity\
Adherent($this->zdb
);
583 $child->enableDep('parent');
584 $this->boolean($child->load($cid))->isTrue();
586 $this->string($child->name
)->isIdenticalTo($child_data['nom_adh']);
587 $this->object($child->parent
)->isInstanceOf('\Galette\Entity\Adherent');
588 $this->integer($child->parent
->id
)->isIdenticalTo($member->id
);
589 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
591 $mdata = $this->dataAdherentOne();
592 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
593 $this->boolean($this->login
->isLogged())->isTrue();
594 $this->boolean($this->login
->isAdmin())->isFalse();
595 $this->boolean($this->login
->isStaff())->isFalse();
597 $this->boolean($ccontrib->canShow($this->login
))->isTrue();
600 $this->login
->logOut();
601 $this->boolean($this->login
->isLogged())->isFalse();