]> git.agnieray.net Git - galette.git/blob - tests/Galette/Entity/tests/units/Contribution.php
Factorize
[galette.git] / tests / Galette / Entity / tests / units / Contribution.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Contribution tests
7 *
8 * PHP version 5
9 *
10 * Copyright © 2017 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 Entity
28 * @package GaletteTests
29 *
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
33 * @version SVN: $Id$
34 * @link http://galette.tuxfamily.org
35 * @since 2017-06-11
36 */
37
38 namespace Galette\Entity\test\units;
39
40 use Galette\GaletteTestCase;
41
42 /**
43 * Contribution tests class
44 *
45 * @category Entity
46 * @name Contribution
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
52 * @since 2017-06-11
53 */
54 class Contribution extends GaletteTestCase
55 {
56 protected $seed = 95842354;
57
58 /**
59 * Cleanup after each test method
60 *
61 * @param string $method Calling method
62 *
63 * @return void
64 */
65 public function afterTestMethod($method)
66 {
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
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);
76
77 $delete = $this->zdb->delete(\Galette\Entity\Adherent::TABLE);
78 $delete->where(['fingerprint' => 'FAKER' . $this->seed]);
79 $this->zdb->execute($delete);
80
81 $this->cleanHistory();
82 }
83
84 /**
85 * Set up tests
86 *
87 * @param string $testMethod Calling method
88 *
89 * @return void
90 */
91 public function beforeTestMethod($testMethod)
92 {
93 parent::beforeTestMethod($testMethod);
94 $this->initContributionsTypes();
95
96 $this->contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
97
98 $this->adh = new \Galette\Entity\Adherent($this->zdb);
99 $this->adh->setDependencies(
100 $this->preferences,
101 $this->members_fields,
102 $this->history
103 );
104 }
105
106 /**
107 * Test empty contribution
108 *
109 * @return void
110 */
111 public function testEmpty()
112 {
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)
134 ->hasSize(11)
135 ->hasKeys([
136 \Galette\Entity\Contribution::PK,
137 \Galette\Entity\Adherent::PK,
138 \Galette\Entity\ContributionsTypes::PK,
139 'montant_cotis',
140 'type_paiement_cotis',
141 'info_cotis',
142 'date_debut_cotis'
143 ]);
144
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();
153 }
154
155 /**
156 * Test getter and setter special cases
157 *
158 * @return void
159 */
160 public function testGetterSetter()
161 {
162 $contrib = $this->contrib;
163
164 //set a bad date
165 $contrib->begin_date = 'not a date';
166 $this->variable($contrib->raw_begin_date)->isNull();
167 $this->variable($contrib->begin_date)->isNull();
168
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');
172
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');
181
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();
187 $contrib->type = 1;
188 $this->object($contrib->type)->isInstanceOf('\Galette\Entity\ContributionsTypes');
189 $this->variable($contrib->type->id)->isEqualTo(1);
190
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();
196
197 $contrib->member = 'not a member';
198 $this->variable($contrib->member)->isNull();
199 $contrib->member = 118218;
200 $this->integer($contrib->member)->isIdenticalTo(118218);
201
202 $contrib->not_a_property = 'abcde';
203 $this->boolean(property_exists($contrib, 'not_a_property'))->isFalse();
204
205 $contrib->payment_type = \Galette\Entity\PaymentType::CASH;
206 $this->string($contrib->getPaymentType())->isIdenticalTo('Cash');
207 $this->string($contrib->spayment_type)->isIdenticalTo('Cash');
208
209 $contrib->payment_type = \Galette\Entity\PaymentType::CHECK;
210 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
211 $this->string($contrib->spayment_type)->isIdenticalTo('Check');
212
213 $contrib->payment_type = \Galette\Entity\PaymentType::OTHER;
214 $this->string($contrib->getPaymentType())->isIdenticalTo('Other');
215 $this->string($contrib->spayment_type)->isIdenticalTo('Other');
216
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');
220
221 $contrib->payment_type = \Galette\Entity\PaymentType::TRANSFER;
222 $this->string($contrib->getPaymentType())->isIdenticalTo('Transfer');
223 $this->string($contrib->spayment_type)->isIdenticalTo('Transfer');
224
225 $contrib->payment_type = \Galette\Entity\PaymentType::PAYPAL;
226 $this->string($contrib->getPaymentType())->isIdenticalTo('Paypal');
227 $this->string($contrib->spayment_type)->isIdenticalTo('Paypal');
228 }
229
230 /**
231 * Test contribution creation
232 *
233 * @return void
234 */
235 public function testCreation()
236 {
237 $this->getMemberOne();
238 //create contribution for member
239 $this->createContribution();
240 }
241
242 /**
243 * Test end date retrieving
244 * This is based on some Preferences parameters
245 *
246 * @return void
247 */
248 public function testRetrieveEndDate()
249 {
250 global $preferences;
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;
254
255 $contrib = new \Galette\Entity\Contribution(
256 $this->zdb,
257 $this->login,
258 ['type' => 1] //anual fee
259 );
260
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'));
265
266 //unset pref_beg_membership and pref_membership_ext
267 $preferences->pref_beg_membership = '';
268 $preferences->pref_membership_ext = '';
269
270 $this->exception(
271 function () {
272 $contrib = new \Galette\Entity\Contribution(
273 $this->zdb,
274 $this->login,
275 ['type' => 1] //anual fee
276 );
277 }
278 )
279 ->isInstanceOf('RuntimeException')
280 ->hasMessage('Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!');
281
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'));
288 }
289
290 $contrib = new \Galette\Entity\Contribution(
291 $this->zdb,
292 $this->login,
293 ['type' => 1] // anual fee
294 );
295 $this->string($contrib->end_date)->isIdenticalTo($expected->format('Y-m-d'));
296
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'));
304
305 $contrib = new \Galette\Entity\Contribution(
306 $this->zdb,
307 $this->login,
308 ['type' => 1] // anual fee
309 );
310 $this->string($contrib->end_date)->isIdenticalTo($expected->format('Y-m-t'));
311
312 //reset
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;
316 }
317
318 /**
319 * Test checkOverlap method
320 *
321 * @return void
322 */
323 public function testCheckOverlap()
324 {
325 $adh = new \Galette\Entity\Adherent($this->zdb);
326 $adh->setDependencies(
327 $this->preferences,
328 $this->members_fields,
329 $this->history
330 );
331
332 $check = $adh->check(
333 [
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
338 ],
339 [],
340 []
341 );
342 if (is_array($check)) {
343 var_dump($check);
344 }
345 $this->boolean($check)->isTrue();
346
347 $store = $adh->store();
348 $this->boolean($store)->isTrue();
349
350 //create first contribution for member
351 $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
352
353 $now = new \DateTime();
354 $end_date = clone $now;
355 $end_date->add(new \DateInterval('P1Y'));
356 $data = [
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
365 ];
366
367 $check = $contrib->check($data, [], []);
368 if (is_array($check)) {
369 var_dump($check);
370 }
371 $this->boolean($check)->isTrue();
372 $this->boolean($contrib->checkOverlap())->isTrue();
373
374 $store = $contrib->store();
375 $this->boolean($store)->isTrue();
376
377 //load member from db
378 $adh = new \Galette\Entity\Adherent($this->zdb, $adh->id);
379
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'));
385 $data = [
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
394 ];
395
396 $check = $contrib->check($data, [], []);
397 $this->array($check)->isIdenticalTo([
398 '- Membership period overlaps period starting at ' . $now->format('Y-m-d')
399 ]);
400
401 $this->exception(
402 function () use ($contrib) {
403 $store = $contrib->store();
404 }
405 )
406 ->isInstanceOf('RuntimeException')
407 ->message->startWith('Existing errors prevents storing contribution');
408 }
409
410 /**
411 * Test checkOverlap method that throws an exception
412 *
413 * @return void
414 */
415 public function testCheckOverlapWException()
416 {
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);
421 }
422 };
423
424 $contrib = new \Galette\Entity\Contribution($zdb, $this->login);
425 $this->boolean($contrib->checkOverlap())->isFalse();
426 }
427
428
429 /**
430 * Test fields labels
431 *
432 * @return void
433 */
434 public function testGetFieldLabel()
435 {
436 $this->string($this->contrib->getFieldLabel('montant_cotis'))
437 ->isIdenticalTo('Amount');
438
439 $this->string($this->contrib->getFieldLabel('date_debut_cotis'))
440 ->isIdenticalTo('Date of contribution');
441
442 $this->contrib->type = 1;
443 $this->string($this->contrib->getFieldLabel('date_debut_cotis'))
444 ->isIdenticalTo('Start date of membership');
445
446 $this->string($this->contrib->getFieldLabel('info_cotis'))
447 ->isIdenticalTo('Comments');
448 }
449
450 /**
451 * Test contribution loading
452 *
453 * @return void
454 */
455 public function testLoad()
456 {
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;
461
462 $this->getMemberOne();
463
464 //create contribution for member
465 $this->createContribution();
466
467 $id = $this->contrib->id;
468 $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
469
470 $this->boolean($contrib->load((int)$id))->isTrue();
471 $this->checkContribExpected($contrib);
472
473 $this->boolean($contrib->load(1355522012))->isFalse();
474 }
475
476 /**
477 * Test contribution removal
478 *
479 * @return void
480 */
481 public function testRemove()
482 {
483 $this->getMemberOne();
484 $this->createContribution();
485
486 $this->boolean($this->contrib->remove())->isTrue();
487
488 $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
489 $this->boolean($this->contrib->remove())->isFalse();
490 }
491
492 /**
493 * Test can* methods
494 *
495 * @return void
496 */
497 public function testCan()
498 {
499 $this->getMemberOne();
500 //create contribution for member
501 $this->createContribution();
502 $contrib = $this->contrib;
503
504 $this->boolean($contrib->canShow($this->login))->isFalse();
505
506 //Superadmin can fully change contributions
507 $this->logSuperAdmin();
508
509 $this->boolean($contrib->canShow($this->login))->isTrue();
510
511 //logout
512 $this->login->logOut();
513 $this->boolean($this->login->isLogged())->isFalse();
514
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();
521
522 $this->boolean($contrib->canShow($this->login))->isTrue();
523
524 //logout
525 $this->login->logOut();
526 $this->boolean($this->login->isLogged())->isFalse();
527
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();
535
536 $this->boolean($contrib->canShow($this->login))->isFalse();
537
538 //parents can chow change children contributions
539 $this->getMemberOne();
540 $member = $this->adh;
541 $mdata = $this->dataAdherentOne();
542 global $login;
543 $login = $this->login;
544 $this->logSuperAdmin();
545
546 $child_data = [
547 'nom_adh' => 'Doe',
548 'prenom_adh' => 'Johny',
549 'parent_id' => $member->id,
550 'attach' => true,
551 'login_adh' => 'child.johny.doe',
552 'fingerprint' => 'FAKER' . $this->seed
553 ];
554 $child = $this->createMember($child_data);
555 $cid = $child->id;
556
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
561
562 $edate = clone $bdate;
563 $edate->add(new \DateInterval('P1Y'));
564
565 $data = [
566 'id_adh' => $cid,
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'),
574 ];
575 $ccontrib = $this->createContrib($data);
576
577 $this->login->logOut();
578
579 //load child from db
580 $child = new \Galette\Entity\Adherent($this->zdb);
581 $child->enableDep('parent');
582 $this->boolean($child->load($cid))->isTrue();
583
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();
588
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();
594
595 $this->boolean($ccontrib->canShow($this->login))->isTrue();
596
597 //logout
598 $this->login->logOut();
599 $this->boolean($this->login->isLogged())->isFalse();
600 }
601 }