]> git.agnieray.net Git - galette.git/blob - tests/Galette/Entity/tests/units/Contribution.php
b2b80fd8515255c8c45b5360345d54d0ebc292c9
[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
82 /**
83 * Set up tests
84 *
85 * @param string $testMethod Calling method
86 *
87 * @return void
88 */
89 public function beforeTestMethod($testMethod)
90 {
91 parent::beforeTestMethod($testMethod);
92 $this->initContributionsTypes();
93
94 $this->contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
95
96 $this->adh = new \Galette\Entity\Adherent($this->zdb);
97 $this->adh->setDependencies(
98 $this->preferences,
99 $this->members_fields,
100 $this->history
101 );
102 }
103
104 /**
105 * Test empty contribution
106 *
107 * @return void
108 */
109 public function testEmpty()
110 {
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)
132 ->hasSize(11)
133 ->hasKeys([
134 \Galette\Entity\Contribution::PK,
135 \Galette\Entity\Adherent::PK,
136 \Galette\Entity\ContributionsTypes::PK,
137 'montant_cotis',
138 'type_paiement_cotis',
139 'info_cotis',
140 'date_debut_cotis'
141 ]);
142
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();
151 }
152
153 /**
154 * Test getter and setter special cases
155 *
156 * @return void
157 */
158 public function testGetterSetter()
159 {
160 $contrib = $this->contrib;
161
162 //set a bad date
163 $contrib->begin_date = 'not a date';
164 $this->variable($contrib->raw_begin_date)->isNull();
165 $this->variable($contrib->begin_date)->isNull();
166
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');
170
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');
179
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();
185 $contrib->type = 1;
186 $this->object($contrib->type)->isInstanceOf('\Galette\Entity\ContributionsTypes');
187 $this->variable($contrib->type->id)->isEqualTo(1);
188
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();
194
195 $contrib->member = 'not a member';
196 $this->variable($contrib->member)->isNull();
197 $contrib->member = 118218;
198 $this->integer($contrib->member)->isIdenticalTo(118218);
199
200 $contrib->not_a_property = 'abcde';
201 $this->boolean(property_exists($contrib, 'not_a_property'))->isFalse();
202
203 $contrib->payment_type = \Galette\Entity\PaymentType::CASH;
204 $this->string($contrib->getPaymentType())->isIdenticalTo('Cash');
205 $this->string($contrib->spayment_type)->isIdenticalTo('Cash');
206
207 $contrib->payment_type = \Galette\Entity\PaymentType::CHECK;
208 $this->string($contrib->getPaymentType())->isIdenticalTo('Check');
209 $this->string($contrib->spayment_type)->isIdenticalTo('Check');
210
211 $contrib->payment_type = \Galette\Entity\PaymentType::OTHER;
212 $this->string($contrib->getPaymentType())->isIdenticalTo('Other');
213 $this->string($contrib->spayment_type)->isIdenticalTo('Other');
214
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');
218
219 $contrib->payment_type = \Galette\Entity\PaymentType::TRANSFER;
220 $this->string($contrib->getPaymentType())->isIdenticalTo('Transfer');
221 $this->string($contrib->spayment_type)->isIdenticalTo('Transfer');
222
223 $contrib->payment_type = \Galette\Entity\PaymentType::PAYPAL;
224 $this->string($contrib->getPaymentType())->isIdenticalTo('Paypal');
225 $this->string($contrib->spayment_type)->isIdenticalTo('Paypal');
226 }
227
228 /**
229 * Test contribution creation
230 *
231 * @return void
232 */
233 public function testCreation()
234 {
235 $this->getMemberOne();
236 //create contribution for member
237 $this->createContribution();
238 }
239
240 /**
241 * Test end date retrieving
242 * This is based on some Preferences parameters
243 *
244 * @return void
245 */
246 public function testRetrieveEndDate()
247 {
248 global $preferences;
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;
252
253 $contrib = new \Galette\Entity\Contribution(
254 $this->zdb,
255 $this->login,
256 ['type' => 1] //anual fee
257 );
258
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'));
263
264 //unset pref_beg_membership and pref_membership_ext
265 $preferences->pref_beg_membership = '';
266 $preferences->pref_membership_ext = '';
267
268 $this->exception(
269 function () {
270 $contrib = new \Galette\Entity\Contribution(
271 $this->zdb,
272 $this->login,
273 ['type' => 1] //anual fee
274 );
275 }
276 )
277 ->isInstanceOf('RuntimeException')
278 ->hasMessage('Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!');
279
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'));
286 }
287
288 $contrib = new \Galette\Entity\Contribution(
289 $this->zdb,
290 $this->login,
291 ['type' => 1] // anual fee
292 );
293 $this->string($contrib->end_date)->isIdenticalTo($expected->format('Y-m-d'));
294
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'));
302
303 $contrib = new \Galette\Entity\Contribution(
304 $this->zdb,
305 $this->login,
306 ['type' => 1] // anual fee
307 );
308 $this->string($contrib->end_date)->isIdenticalTo($expected->format('Y-m-t'));
309
310 //reset
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;
314 }
315
316 /**
317 * Test checkOverlap method
318 *
319 * @return void
320 */
321 public function testCheckOverlap()
322 {
323 $adh = new \Galette\Entity\Adherent($this->zdb);
324 $adh->setDependencies(
325 $this->preferences,
326 $this->members_fields,
327 $this->history
328 );
329
330 $check = $adh->check(
331 [
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
336 ],
337 [],
338 []
339 );
340 if (is_array($check)) {
341 var_dump($check);
342 }
343 $this->boolean($check)->isTrue();
344
345 $store = $adh->store();
346 $this->boolean($store)->isTrue();
347
348 //create first contribution for member
349 $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
350
351 $now = new \DateTime();
352 $end_date = clone $now;
353 $end_date->add(new \DateInterval('P1Y'));
354 $data = [
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
363 ];
364
365 $check = $contrib->check($data, [], []);
366 if (is_array($check)) {
367 var_dump($check);
368 }
369 $this->boolean($check)->isTrue();
370 $this->boolean($contrib->checkOverlap())->isTrue();
371
372 $store = $contrib->store();
373 $this->boolean($store)->isTrue();
374
375 //load member from db
376 $adh = new \Galette\Entity\Adherent($this->zdb, $adh->id);
377
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'));
383 $data = [
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
392 ];
393
394 $check = $contrib->check($data, [], []);
395 $this->array($check)->isIdenticalTo([
396 '- Membership period overlaps period starting at ' . $now->format('Y-m-d')
397 ]);
398
399 $this->exception(
400 function () use ($contrib) {
401 $store = $contrib->store();
402 }
403 )
404 ->isInstanceOf('RuntimeException')
405 ->message->startWith('Existing errors prevents storing contribution');
406 }
407
408 /**
409 * Test checkOverlap method that throws an exception
410 *
411 * @return void
412 */
413 public function testCheckOverlapWException()
414 {
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);
419 }
420 };
421
422 $contrib = new \Galette\Entity\Contribution($zdb, $this->login);
423 $this->boolean($contrib->checkOverlap())->isFalse();
424 }
425
426
427 /**
428 * Test fields labels
429 *
430 * @return void
431 */
432 public function testGetFieldLabel()
433 {
434 $this->string($this->contrib->getFieldLabel('montant_cotis'))
435 ->isIdenticalTo('Amount');
436
437 $this->string($this->contrib->getFieldLabel('date_debut_cotis'))
438 ->isIdenticalTo('Date of contribution');
439
440 $this->contrib->type = 1;
441 $this->string($this->contrib->getFieldLabel('date_debut_cotis'))
442 ->isIdenticalTo('Start date of membership');
443
444 $this->string($this->contrib->getFieldLabel('info_cotis'))
445 ->isIdenticalTo('Comments');
446 }
447
448 /**
449 * Test contribution loading
450 *
451 * @return void
452 */
453 public function testLoad()
454 {
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;
459
460 $this->getMemberOne();
461
462 //create contribution for member
463 $this->createContribution();
464
465 $id = $this->contrib->id;
466 $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
467
468 $this->boolean($contrib->load((int)$id))->isTrue();
469 $this->checkContribExpected($contrib);
470
471 $this->boolean($contrib->load(1355522012))->isFalse();
472 }
473
474 /**
475 * Test contribution removal
476 *
477 * @return void
478 */
479 public function testRemove()
480 {
481 $this->getMemberOne();
482 $this->createContribution();
483
484 $this->boolean($this->contrib->remove())->isTrue();
485
486 $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login);
487 $this->boolean($this->contrib->remove())->isFalse();
488 }
489
490 /**
491 * Test can* methods
492 *
493 * @return void
494 */
495 public function testCan()
496 {
497 $this->getMemberOne();
498 //create contribution for member
499 $this->createContribution();
500 $contrib = $this->contrib;
501
502 $this->boolean($contrib->canShow($this->login))->isFalse();
503
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();
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->login->logAdmin('superadmin', $this->preferences);
545 $this->boolean($this->login->isLogged())->isTrue();
546 $this->boolean($this->login->isSuperAdmin())->isTrue();
547
548 $child_data = [
549 'nom_adh' => 'Doe',
550 'prenom_adh' => 'Johny',
551 'parent_id' => $member->id,
552 'attach' => true,
553 'login_adh' => 'child.johny.doe',
554 'fingerprint' => 'FAKER' . $this->seed
555 ];
556 $child = $this->createMember($child_data);
557 $cid = $child->id;
558
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
563
564 $edate = clone $bdate;
565 $edate->add(new \DateInterval('P1Y'));
566
567 $data = [
568 'id_adh' => $cid,
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'),
576 ];
577 $ccontrib = $this->createContrib($data);
578
579 $this->login->logOut();
580
581 //load child from db
582 $child = new \Galette\Entity\Adherent($this->zdb);
583 $child->enableDep('parent');
584 $this->boolean($child->load($cid))->isTrue();
585
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();
590
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();
596
597 $this->boolean($ccontrib->canShow($this->login))->isTrue();
598
599 //logout
600 $this->login->logOut();
601 $this->boolean($this->login->isLogged())->isFalse();
602 }
603 }