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 contribution update
247 public function testUpdate()
249 $this->getMemberOne();
250 //create contribution for member
251 $bdate = new \
DateTime(); // 2020-11-07
252 $bdate->sub(new \
DateInterval('P5M')); // 2020-06-07
253 $bdate->add(new \
DateInterval('P3D')); // 2020-06-10
255 $edate = clone $bdate;
256 $edate->add(new \
DateInterval('P1Y'));
259 'id_adh' => $this->adh
->id
,
260 'id_type_cotis' => 4, //donation
261 'montant_cotis' => 12,
262 'type_paiement_cotis' => 3,
263 'info_cotis' => 'FAKER' . $this->seed
,
264 'date_enreg' => $bdate->format('Y-m-d'),
265 'date_debut_cotis' => $bdate->format('Y-m-d'),
266 'date_fin_cotis' => $edate->format('Y-m-d'),
268 $this->createContrib($data);
269 $this->array($this->contrib
->getRequired())->isIdenticalTo([
270 'id_type_cotis' => 1,
273 'date_debut_cotis' => 1,
274 'date_fin_cotis' => 0,
278 $this->logSuperAdmin();
280 'id_adh' => $this->adh
->id
,
281 'id_type_cotis' => 4, //donation
282 'montant_cotis' => 1280,
283 'type_paiement_cotis' => 4,
284 'info_cotis' => 'FAKER' . $this->seed
,
285 'date_enreg' => $bdate->format('Y-m-d'),
286 'date_debut_cotis' => $bdate->format('Y-m-d'),
287 'date_fin_cotis' => $edate->format('Y-m-d'),
290 $check = $this->contrib
->check($data, [], []);
291 if (is_array($check)) {
294 $this->boolean($check)->isTrue();
296 $store = $this->contrib
->store();
297 $this->boolean($store)->isTrue();
299 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
, $this->contrib
->id
);
300 $this->variable($contrib->amount
)->isIdenticalTo(1280);
304 * Test end date retrieving
305 * This is based on some Preferences parameters
309 public function testRetrieveEndDate()
312 $orig_pref_beg_membership = $this->preferences
->pref_beg_membership
;
313 $orig_pref_membership_ext = $this->preferences
->pref_membership_ext
;
314 $orig_pref_membership_offermonths = $this->preferences
->pref_membership_offermonths
;
316 $contrib = new \Galette\Entity\
Contribution(
319 ['type' => 1] //annual fee
322 // First, check for 12 months renewal
323 $expected = new \
DateTime();
324 $expected->add(new \
DateInterval('P1Y'));
325 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
327 //unset pref_beg_membership and pref_membership_ext
328 $preferences->pref_beg_membership
= '';
329 $preferences->pref_membership_ext
= '';
333 $contrib = new \Galette\Entity\
Contribution(
336 ['type' => 1] //annual fee
340 ->isInstanceOf('RuntimeException')
341 ->hasMessage('Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!');
343 // Second, test with beginning of membership date
344 $preferences->pref_beg_membership
= '29/05';
345 $expected = new \
DateTime();
346 $expected->setDate(date('Y'), 5, 29);
347 if ($expected < new \
DateTime()) {
348 $expected->add(new \
DateInterval('P1Y'));
351 $contrib = new \Galette\Entity\
Contribution(
354 ['type' => 1] // annual fee
356 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-d'));
358 // Third, test with beginning of membership date and i2 last months offered
359 $beginning = new \
DateTime();
360 $beginning->add(new \
DateInterval('P1M'));
361 $preferences->pref_beg_membership
= $beginning->format('t/m'); // end of next month
362 $preferences->pref_membership_offermonths
= 2;
363 $expected = clone $beginning;
364 $expected->add(new \
DateInterval('P1Y'));
366 $contrib = new \Galette\Entity\
Contribution(
369 ['type' => 1] // annual fee
371 $this->string($contrib->end_date
)->isIdenticalTo($expected->format('Y-m-t'));
374 $preferences->pref_beg_membership
= $orig_pref_beg_membership;
375 $preferences->pref_membership_ext
= $orig_pref_membership_ext;
376 $preferences->pref_membership_offermonths
= $orig_pref_membership_offermonths;
380 * Test checkOverlap method
384 public function testCheckOverlap()
386 $adh = new \Galette\Entity\
Adherent($this->zdb
);
387 $adh->setDependencies(
389 $this->members_fields
,
393 $check = $adh->check(
395 'nom_adh' => 'Overlapped',
396 'date_crea_adh' => date(_T("Y-m-d")),
397 \Galette\Entity\Status
::PK
=> \Galette\Entity\Status
::DEFAULT_STATUS
,
398 'fingerprint' => 'FAKER' . $this->seed
403 if (is_array($check)) {
406 $this->boolean($check)->isTrue();
408 $store = $adh->store();
409 $this->boolean($store)->isTrue();
411 //create first contribution for member
412 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
414 $now = new \
DateTime();
415 $end_date = clone $now;
416 $end_date->add(new \
DateInterval('P1Y'));
418 \Galette\Entity\Adherent
::PK
=> $adh->id
,
419 \Galette\Entity\ContributionsTypes
::PK
=> 1, //annual fee
420 'montant_cotis' => 20,
421 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
422 'date_enreg' => $now->format(_T("Y-m-d")),
423 'date_debut_cotis' => $now->format(_T("Y-m-d")),
424 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
425 'info_cotis' => 'FAKER' . $this->seed
428 $check = $contrib->check($data, [], []);
429 if (is_array($check)) {
432 $this->boolean($check)->isTrue();
433 $this->boolean($contrib->checkOverlap())->isTrue();
435 $store = $contrib->store();
436 $this->boolean($store)->isTrue();
438 //load member from db
439 $adh = new \Galette\Entity\
Adherent($this->zdb
, $adh->id
);
441 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
442 $begin = clone $end_date;
443 $begin->sub(new \
DateInterval('P3M'));
444 $end_date = clone $begin;
445 $end_date->add(new \
DateInterval('P1Y'));
447 \Galette\Entity\Adherent
::PK
=> $adh->id
,
448 \Galette\Entity\ContributionsTypes
::PK
=> 1, //anunal fee
449 'montant_cotis' => 20,
450 'type_paiement_cotis' => \Galette\Entity\PaymentType
::CHECK
,
451 'date_enreg' => $now->format(_T("Y-m-d")),
452 'date_debut_cotis' => $begin->format(_T("Y-m-d")),
453 'date_fin_cotis' => $end_date->format(_T("Y-m-d")),
454 'info_cotis' => 'FAKER' . $this->seed
457 $check = $contrib->check($data, [], []);
458 $this->array($check)->isIdenticalTo([
459 '- Membership period overlaps period starting at ' . $now->format('Y-m-d')
463 function () use ($contrib) {
464 $store = $contrib->store();
467 ->isInstanceOf('RuntimeException')
468 ->message
->startWith('Existing errors prevents storing contribution');
472 * Test checkOverlap method that throws an exception
476 public function testCheckOverlapWException()
478 $zdb = new \mock\Galette\Core\
Db();
479 $this->calling($zdb)->execute
= function ($o) {
480 if ($o instanceof \Zend\Db\Sql\Select
) {
481 throw new \
LogicException('Error executing query!', 123);
485 $contrib = new \Galette\Entity\
Contribution($zdb, $this->login
);
486 $this->boolean($contrib->checkOverlap())->isFalse();
495 public function testGetFieldLabel()
497 $this->string($this->contrib
->getFieldLabel('montant_cotis'))
498 ->isIdenticalTo('Amount');
500 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
501 ->isIdenticalTo('Date of contribution');
503 $this->contrib
->type
= 1;
504 $this->string($this->contrib
->getFieldLabel('date_debut_cotis'))
505 ->isIdenticalTo('Start date of membership');
507 $this->string($this->contrib
->getFieldLabel('info_cotis'))
508 ->isIdenticalTo('Comments');
512 * Test contribution loading
516 public function testLoad()
518 $this->login
= new \mock\Galette\Core\
Login($this->zdb
, $this->i18n
);
519 $this->calling($this->login
)->isLogged
= true;
520 $this->calling($this->login
)->isStaff
= true;
521 $this->calling($this->login
)->isAdmin
= true;
523 $this->getMemberOne();
525 //create contribution for member
526 $this->createContribution();
528 $id = $this->contrib
->id
;
529 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
531 $this->boolean($contrib->load((int)$id))->isTrue();
532 $this->checkContribExpected($contrib);
534 $this->boolean($contrib->load(1355522012))->isFalse();
538 * Test contribution removal
542 public function testRemove()
544 $this->getMemberOne();
545 $this->createContribution();
547 $this->boolean($this->contrib
->remove())->isTrue();
549 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
550 $this->boolean($this->contrib
->remove())->isFalse();
558 public function testCan()
560 $this->getMemberOne();
561 //create contribution for member
562 $this->createContribution();
563 $contrib = $this->contrib
;
565 $this->boolean($contrib->canShow($this->login
))->isFalse();
567 //Superadmin can fully change contributions
568 $this->logSuperAdmin();
570 $this->boolean($contrib->canShow($this->login
))->isTrue();
573 $this->login
->logOut();
574 $this->boolean($this->login
->isLogged())->isFalse();
576 //Member can fully change its own contributions
577 $mdata = $this->dataAdherentOne();
578 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
579 $this->boolean($this->login
->isLogged())->isTrue();
580 $this->boolean($this->login
->isAdmin())->isFalse();
581 $this->boolean($this->login
->isStaff())->isFalse();
583 $this->boolean($contrib->canShow($this->login
))->isTrue();
586 $this->login
->logOut();
587 $this->boolean($this->login
->isLogged())->isFalse();
589 //Another member has no access
590 $this->getMemberTwo();
591 $mdata = $this->dataAdherentTwo();
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($contrib->canShow($this->login
))->isFalse();
599 //parents can chow change children contributions
600 $this->getMemberOne();
601 $member = $this->adh
;
602 $mdata = $this->dataAdherentOne();
604 $login = $this->login
;
605 $this->logSuperAdmin();
609 'prenom_adh' => 'Johny',
610 'parent_id' => $member->id
,
612 'login_adh' => 'child.johny.doe',
613 'fingerprint' => 'FAKER' . $this->seed
615 $child = $this->createMember($child_data);
618 //contribution for child
619 $bdate = new \
DateTime(); // 2020-11-07
620 $bdate->sub(new \
DateInterval('P5M')); // 2020-06-07
621 $bdate->add(new \
DateInterval('P3D')); // 2020-06-10
623 $edate = clone $bdate;
624 $edate->add(new \
DateInterval('P1Y'));
628 'id_type_cotis' => 1,
629 'montant_cotis' => 25,
630 'type_paiement_cotis' => 3,
631 'info_cotis' => 'FAKER' . $this->seed
,
632 'date_enreg' => $bdate->format('Y-m-d'),
633 'date_debut_cotis' => $bdate->format('Y-m-d'),
634 'date_fin_cotis' => $edate->format('Y-m-d'),
636 $ccontrib = $this->createContrib($data);
638 $this->login
->logOut();
641 $child = new \Galette\Entity\
Adherent($this->zdb
);
642 $child->enableDep('parent');
643 $this->boolean($child->load($cid))->isTrue();
645 $this->string($child->name
)->isIdenticalTo($child_data['nom_adh']);
646 $this->object($child->parent
)->isInstanceOf('\Galette\Entity\Adherent');
647 $this->integer($child->parent
->id
)->isIdenticalTo($member->id
);
648 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
650 $mdata = $this->dataAdherentOne();
651 $this->boolean($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']))->isTrue();
652 $this->boolean($this->login
->isLogged())->isTrue();
653 $this->boolean($this->login
->isAdmin())->isFalse();
654 $this->boolean($this->login
->isStaff())->isFalse();
656 $this->boolean($ccontrib->canShow($this->login
))->isTrue();
659 $this->login
->logOut();
660 $this->boolean($this->login
->isLogged())->isFalse();