4 * Copyright © 2003-2024 The Galette Team
6 * This file is part of Galette (https://galette.eu).
8 * Galette is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * Galette is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
22 namespace Galette\Entity\test\units
;
24 use Galette\GaletteTestCase
;
27 * Transaction tests class
29 * @author Johan Cwiklinski <johan@x-tnd.be>
31 class Transaction
extends GaletteTestCase
33 protected int $seed = 95842354;
34 /** @var \Galette\Entity\Transaction */
35 private \Galette\Entity\Transaction
$transaction;
38 * Cleanup after each test method
42 public function tearDown(): void
46 $this->zdb
= new \Galette\Core\
Db();
48 //first, remove contributions
49 $delete = $this->zdb
->delete(\Galette\Entity\Contribution
::TABLE
);
50 $delete->where(['info_cotis' => 'FAKER' . $this->seed
]);
51 $this->zdb
->execute($delete);
53 //then, remove transactions
54 $delete = $this->zdb
->delete(\Galette\Entity\Transaction
::TABLE
);
55 $delete->where(['trans_desc' => 'FAKER' . $this->seed
]);
56 $this->zdb
->execute($delete);
58 //remove members with parents
59 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
60 $delete->where(['fingerprint' => 'FAKER' . $this->seed
]);
61 $delete->where('parent_id IS NOT NULL');
62 $this->zdb
->execute($delete);
64 //remove all others members
65 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
66 $delete->where(['fingerprint' => 'FAKER' . $this->seed
]);
67 $this->zdb
->execute($delete);
75 public function setUp(): void
78 $this->initContributionsTypes();
80 $this->contrib
= new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
81 $this->transaction
= new \Galette\Entity\
Transaction($this->zdb
, $this->login
);
83 $this->adh
= new \Galette\Entity\
Adherent($this->zdb
);
84 $this->adh
->setDependencies(
86 $this->members_fields
,
92 * Create test transaction in database
96 private function createTransaction()
98 $date = new \
DateTime(); // 2020-11-07
100 'id_adh' => $this->adh
->id
,
101 'trans_date' => $date->format('Y-m-d'),
102 'trans_amount' => 92,
103 'trans_desc' => 'FAKER' . $this->seed
106 $this->transaction
= new \Galette\Entity\
Transaction($this->zdb
, $this->login
);
107 $check = $this->transaction
->check($data, [], []);
108 if (is_array($check)) {
111 $this->assertTrue($check);
113 $store = $this->transaction
->store($this->history
);
114 $this->assertTrue($store);
116 return $this->transaction
;
120 * Test empty transaction
124 public function testEmpty()
126 $this->assertNull($this->transaction
->id
);
127 $this->assertEquals(date('Y-m-d'), $this->transaction
->date
);
128 $this->assertNull($this->transaction
->amount
);
129 $this->assertNull($this->transaction
->description
);
131 $this->assertSame((double)0, $this->transaction
->getDispatchedAmount());
132 $this->assertSame((double)0, $this->transaction
->getMissingAmount());
133 $this->assertSame('transaction-normal', $this->transaction
->getRowClass());
134 $this->assertCount(6, $this->transaction
->fields
);
135 $this->assertArrayHasKey(\Galette\Entity\Transaction
::PK
, $this->transaction
->fields
);
136 $this->assertArrayHasKey(\Galette\Entity\Adherent
::PK
, $this->transaction
->fields
);
137 $this->assertArrayHasKey('trans_date', $this->transaction
->fields
);
138 $this->assertArrayHasKey('trans_amount', $this->transaction
->fields
);
139 $this->assertArrayHasKey('trans_desc', $this->transaction
->fields
);
140 $this->assertArrayHasKey('type_paiement_trans', $this->transaction
->fields
);
142 $this->assertEquals(false, $this->transaction
->unknown_property
);
146 * Test getter and setter special cases
150 public function testGetterSetter()
152 $transaction = $this->transaction
;
155 $data = ['trans_date' => 'mypassword'];
156 $expected = ['- Wrong date format (Y-m-d) for Date!'];
157 $check = $transaction->check($data, [], []);
158 $this->assertSame($expected, $check);
161 $data = ['trans_date' => '1999-01-01'];
162 $check = $transaction->check($data, [], []);
163 $this->assertTrue($check);
164 $this->assertSame('1999-01-01', $transaction->date
);
167 $data = ['trans_amount' => 'mypassword'];
168 $expected = ['- The amount must be an integer!'];
169 $check = $transaction->check($data, [], []);
170 $this->assertSame($expected, $check);
172 //set a correct amount
173 $data = ['trans_amount' => 1256];
174 $check = $transaction->check($data, ['trans_amount' => 1], []);
175 $this->assertTrue($check);
176 $this->assertSame(1256.00, $transaction->amount
);
178 //set a bad description
179 $data = ['trans_desc' => 'this is a very long description that should give an error; because the length of transaction description is limited to 150 characters long, even if this is quite hard to find something to write.'];
180 $expected = ['- Transaction description must be 150 characters long maximum.'];
181 $check = $transaction->check($data, [], []);
182 $this->assertSame($expected, $check);
186 * Test transaction creation
190 public function testCreation()
192 $this->getMemberOne();
193 //create transaction for member
194 $this->createTransaction();
198 * Test transaction update
202 public function testUpdate()
204 $this->getMemberOne();
205 //create transaction for member
206 $this->createTransaction();
208 $this->logSuperAdmin();
212 $check = $this->transaction
->check($data, [], []);
213 if (is_array($check)) {
216 $this->assertTrue($check);
218 $store = $this->transaction
->store($this->history
);
219 $this->assertTrue($store);
221 $transaction = new \Galette\Entity\
Transaction($this->zdb
, $this->login
, $this->transaction
->id
);
222 $this->assertSame(42.00, $transaction->amount
);
230 public function testGetFieldLabel()
234 $this->transaction
->getFieldLabel('trans_amount')
239 $this->transaction
->getFieldLabel('trans_date')
244 $this->transaction
->getFieldLabel('trans_desc')
249 $this->transaction
->getFieldLabel(\Galette\Entity\Adherent
::PK
)
254 * Test transaction loading
258 public function testLoad()
260 $this->login
= $this->getMockBuilder(\Galette\Core\Login
::class)
261 ->setConstructorArgs(array($this->zdb
, new \Galette\Core\
I18n()))
262 ->onlyMethods(array('isLogged', 'isAdmin', 'isStaff'))
264 $this->login
->method('isLogged')->willReturn(true);
265 $this->login
->method('isAdmin')->willReturn(true);
266 $this->login
->method('isStaff')->willReturn(true);
268 $this->getMemberOne();
270 //create transaction for member
271 $this->createTransaction();
273 $id = $this->transaction
->id
;
274 $transaction = new \Galette\Entity\
Transaction($this->zdb
, $this->login
);
276 $this->assertTrue($transaction->load((int)$id));
277 $this->assertFalse($transaction->load(1355522012));
281 * Test transaction removal
285 public function testRemove()
287 $this->logSuperAdmin();
289 $this->getMemberOne();
290 $this->createTransaction();
292 $tid = $this->transaction
->id
;
293 $this->assertTrue($this->transaction
->load($tid));
294 $this->assertTrue($this->transaction
->remove($this->history
));
295 $this->assertFalse($this->transaction
->load($tid));
296 $this->assertFalse($this->transaction
->remove($this->history
));
304 public function testCan()
306 $this->getMemberOne();
307 //create transaction for member
308 $this->createTransaction();
309 $transaction = $this->transaction
;
311 $this->assertFalse($transaction->canShow($this->login
));
313 //Superadmin can fully change transactions
314 $this->logSuperAdmin();
316 $this->assertTrue($transaction->canShow($this->login
));
319 $this->login
->logOut();
320 $this->assertFalse($this->login
->isLogged());
322 //Member can fully change its own transactions
323 $mdata = $this->dataAdherentOne();
324 $this->assertTrue($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']));
325 $this->assertTrue($this->login
->isLogged());
326 $this->assertFalse($this->login
->isAdmin());
327 $this->assertFalse($this->login
->isStaff());
329 $this->assertTrue($transaction->canShow($this->login
));
332 $this->login
->logOut();
333 $this->assertFalse($this->login
->isLogged());
335 //Another member has no access
336 $this->getMemberTwo();
337 $mdata = $this->dataAdherentTwo();
338 $this->assertTrue($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']));
339 $this->assertTrue($this->login
->isLogged());
340 $this->assertFalse($this->login
->isAdmin());
341 $this->assertFalse($this->login
->isStaff());
343 $this->assertFalse($transaction->canShow($this->login
));
345 //parents can chow change children transactions
346 $this->getMemberOne();
347 $member = $this->adh
;
348 $mdata = $this->dataAdherentOne();
350 $login = $this->login
;
351 $this->logSuperAdmin();
355 'prenom_adh' => 'Johny',
356 'parent_id' => $member->id
,
358 'login_adh' => 'child.johny.doe',
359 'fingerprint' => 'FAKER' . $this->seed
361 $child = $this->createMember($child_data);
364 //transaction for child
365 $date = new \
DateTime(); // 2020-11-07
369 'trans_date' => $date->format('Y-m-d'),
370 'trans_amount' => 92,
371 'trans_desc' => 'FAKER' . $this->seed
374 $ctransaction = new \Galette\Entity\
Transaction($this->zdb
, $this->login
);
375 $check = $ctransaction->check($data, [], []);
376 if (is_array($check)) {
379 $this->assertTrue($check);
381 $store = $ctransaction->store($this->history
);
382 $this->assertTrue($store);
384 $this->login
->logOut();
387 $child = new \Galette\Entity\
Adherent($this->zdb
);
388 $child->enableDep('parent');
389 $this->assertTrue($child->load($cid));
391 $this->assertSame($child_data['nom_adh'], $child->name
);
392 $this->assertInstanceOf('\Galette\Entity\Adherent', $child->parent
);
393 $this->assertSame($member->id
, $child->parent
->id
);
394 $this->assertTrue($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']));
396 $mdata = $this->dataAdherentOne();
397 $this->assertTrue($this->login
->login($mdata['login_adh'], $mdata['mdp_adh']));
398 $this->assertTrue($this->login
->isLogged());
399 $this->assertFalse($this->login
->isAdmin());
400 $this->assertFalse($this->login
->isStaff());
402 $this->assertTrue($ctransaction->canShow($this->login
));
405 $this->login
->logOut();
406 $this->assertFalse($this->login
->isLogged());
414 public function testTransaction(): void
416 $this->logSuperAdmin();
417 $this->getMemberOne();
418 //create transaction for member
419 $this->createTransaction();
422 $tid = $this->transaction
->id
;
424 //create a contribution attached to transaction
425 $bdate = new \
DateTime(); // 2020-11-07
426 $bdate->sub(new \
DateInterval('P5M')); // 2020-06-07
427 $bdate->add(new \
DateInterval('P3D')); // 2020-06-10
429 $edate = clone $bdate;
430 $edate->add(new \
DateInterval('P1Y'));
433 'id_adh' => $this->adh
->id
,
434 'id_type_cotis' => 1,
435 'montant_cotis' => 25,
436 'type_paiement_cotis' => 3,
437 'info_cotis' => 'FAKER' . $this->seed
,
438 'date_enreg' => $bdate->format('Y-m-d'),
439 'date_debut_cotis' => $bdate->format('Y-m-d'),
440 'date_fin_cotis' => $edate->format('Y-m-d'),
441 \Galette\Entity\Transaction
::PK
=> $tid
443 $contrib = $this->createContrib($data);
444 $contribs_ids[] = $contrib->id
;
446 $this->assertTrue($contrib->isTransactionPart());
447 $this->assertTrue($contrib->isTransactionPartOf($this->transaction
->id
));
451 $this->transaction
->getDispatchedAmount()
455 $this->transaction
->getMissingAmount()
457 $this->assertSame('transaction-uncomplete', $this->transaction
->getRowClass());
459 //complete the transaction
461 'id_adh' => $this->adh
->id
,
462 'id_type_cotis' => 4, //donation
463 'montant_cotis' => 67,
464 'type_paiement_cotis' => 3,
465 'info_cotis' => 'FAKER' . $this->seed
,
466 'date_enreg' => $bdate->format('Y-m-d'),
467 'date_debut_cotis' => $bdate->format('Y-m-d'),
468 'date_fin_cotis' => $edate->format('Y-m-d'),
469 \Galette\Entity\Transaction
::PK
=> $tid
471 $contrib = $this->createContrib($data);
472 $contribs_ids[] = $contrib->id
;
474 $this->assertTrue($contrib->isTransactionPart());
475 $this->assertTrue($contrib->isTransactionPartOf($this->transaction
->id
));
476 $this->assertFalse($contrib->isFee());
477 $this->assertSame('Donation', $contrib->getTypeLabel());
478 $this->assertSame('donation', $contrib->getRawType());
483 $this->transaction
->getDispatchedAmount()
487 $this->transaction
->getMissingAmount()
489 $this->assertSame('transaction-normal', $this->transaction
->getRowClass());
493 'id_adh' => $this->adh
->id
,
494 'id_type_cotis' => 4, //donation
495 'montant_cotis' => 36,
496 'type_paiement_cotis' => 3,
497 'info_cotis' => 'FAKER' . $this->seed
,
498 'date_enreg' => $bdate->format('Y-m-d'),
499 'date_debut_cotis' => $bdate->format('Y-m-d'),
500 'date_fin_cotis' => $edate->format('Y-m-d'),
501 \Galette\Entity\Transaction
::PK
=> $tid
503 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
);
504 $check = $contrib->check($data, [], []);
505 $this->assertSame(['- Sum of all contributions exceed corresponding transaction amount.'], $check);
507 $contrib_id = $contribs_ids[0];
508 $contrib = new \Galette\Entity\
Contribution($this->zdb
, $this->login
, $contrib_id);
509 $this->assertTrue($contrib->unsetTransactionPart($this->zdb
, $this->login
, $tid, $contrib_id));
513 $this->transaction
->getDispatchedAmount()
517 $this->transaction
->getMissingAmount()
519 $this->assertSame('transaction-uncomplete', $this->transaction
->getRowClass());
521 $this->assertTrue($contrib->setTransactionPart($this->zdb
, $tid, $contrib_id));
525 $this->transaction
->getDispatchedAmount()
529 $this->transaction
->getMissingAmount()
531 $this->assertSame('transaction-normal', $this->transaction
->getRowClass());
533 //delete transaction, and ensures all contributions has been removed as well
534 $this->assertTrue($this->transaction
->remove($this->history
));
535 $this->assertFalse($this->transaction
->load($tid));
536 foreach ($contribs_ids as $contrib_id) {
537 $this->assertFalse($this->contrib
->load($contrib_id));