Skip to content

Commit 4fda8dc

Browse files
committed
coverage 100%
1 parent 8570ed7 commit 4fda8dc

File tree

2 files changed

+109
-7
lines changed

2 files changed

+109
-7
lines changed

src/Traits/CanConfirm.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,33 @@ trait CanConfirm
4545
*/
4646
public function confirm(Transaction $transaction): bool
4747
{
48-
// Check if the wallet has enough money
48+
// Execute the confirmation process within an atomic block to ensure data consistency.
4949
return app(AtomicServiceInterface::class)->block($this, function () use ($transaction): bool {
50+
// Check if the transaction is already confirmed.
51+
// If it is, throw an exception.
52+
if ($transaction->confirmed) {
53+
// Why is there a check here without calling refresh?
54+
// It's because this check can be performed in force confirm again.
55+
throw new ConfirmedInvalid(
56+
// Get the error message from the translator service.
57+
app(TranslatorServiceInterface::class)->get('wallet::errors.confirmed_invalid'),
58+
// Set the error code to CONFIRMED_INVALID.
59+
ExceptionInterface::CONFIRMED_INVALID
60+
);
61+
}
62+
63+
// Check if the transaction type is withdrawal.
5064
if ($transaction->type === Transaction::TYPE_WITHDRAW) {
51-
// Check if the wallet has enough money
65+
// Check if the wallet has enough money to cover the withdrawal amount.
5266
app(ConsistencyServiceInterface::class)->checkPotential(
53-
// Get the wallet
67+
// Get the wallet.
5468
app(CastServiceInterface::class)->getWallet($this),
55-
// Negative amount
69+
// Negate the withdrawal amount to check for sufficient funds.
5670
app(MathServiceInterface::class)->negative($transaction->amount)
5771
);
5872
}
5973

60-
// Force confirm the transaction
74+
// Force confirm the transaction.
6175
return $this->forceConfirm($transaction);
6276
});
6377
}
@@ -118,7 +132,7 @@ public function resetConfirm(Transaction $transaction): bool
118132
// Reset the confirmation of the transaction in a single database transaction
119133
return app(AtomicServiceInterface::class)->block($this, function () use ($transaction) {
120134
// Check if the transaction is already confirmed
121-
if (! $transaction->confirmed) {
135+
if (! $transaction->refresh()->confirmed) {
122136
throw new UnconfirmedInvalid(
123137
// If the transaction is not confirmed, throw an `UnconfirmedInvalid` exception
124138
app(TranslatorServiceInterface::class)->get('wallet::errors.unconfirmed_invalid'),
@@ -195,7 +209,7 @@ public function forceConfirm(Transaction $transaction): bool
195209
// Attempt to confirm the transaction in a single database transaction
196210
return app(AtomicServiceInterface::class)->block($this, function () use ($transaction) {
197211
// Check if the transaction is already confirmed
198-
if ($transaction->confirmed) {
212+
if ($transaction->refresh()->confirmed) {
199213
throw new ConfirmedInvalid(
200214
app(TranslatorServiceInterface::class)->get('wallet::errors.confirmed_invalid'),
201215
ExceptionInterface::CONFIRMED_INVALID

tests/Units/Domain/ConfirmTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ public function testSafe(): void
6767
self::assertFalse($transaction->confirmed);
6868
}
6969

70+
public function testSafeConfirmedInvalid(): void
71+
{
72+
/** @var Buyer $buyer */
73+
$buyer = BuyerFactory::new()->create();
74+
$wallet = $buyer->wallet;
75+
76+
self::assertSame(0, $wallet->balanceInt);
77+
78+
$transaction = $wallet->forceWithdraw(1000, ['desc' => 'confirmed']);
79+
80+
self::assertSame(-1000, $wallet->balanceInt);
81+
self::assertTrue($transaction->confirmed);
82+
self::assertTrue($transaction->getKey() > 0);
83+
84+
self::assertTrue($wallet->safeConfirm($transaction));
85+
self::assertSame(-1000, $wallet->balanceInt);
86+
self::assertTrue($transaction->confirmed);
87+
}
88+
7089
public function testSafeResetConfirm(): void
7190
{
7291
/** @var Buyer $buyer */
@@ -127,6 +146,25 @@ public function testForce(): void
127146
self::assertTrue($transaction->confirmed);
128147
}
129148

149+
public function testForceConfirmedInvalid(): void
150+
{
151+
$this->expectException(ConfirmedInvalid::class);
152+
$this->expectExceptionCode(ExceptionInterface::CONFIRMED_INVALID);
153+
$this->expectExceptionMessageStrict(trans('wallet::errors.confirmed_invalid'));
154+
155+
/** @var Buyer $buyer */
156+
$buyer = BuyerFactory::new()->create();
157+
$wallet = $buyer->wallet;
158+
159+
self::assertSame(0, $wallet->balanceInt);
160+
161+
$transaction = $wallet->forceWithdraw(1000);
162+
self::assertSame(-1000, $wallet->balanceInt);
163+
self::assertTrue($transaction->confirmed);
164+
165+
$wallet->forceConfirm($transaction);
166+
}
167+
130168
public function testUnconfirmed(): void
131169
{
132170
/** @var Buyer $buyer */
@@ -198,6 +236,31 @@ public function testSafeUnconfirmed(): void
198236
self::assertTrue($wallet->safeResetConfirm($transaction));
199237
}
200238

239+
public function testSafeUnconfirmedWalletOwnerInvalid(): void
240+
{
241+
/**
242+
* @var Buyer $buyer1
243+
* @var Buyer $buyer2
244+
**/
245+
[$buyer1, $buyer2] = BuyerFactory::times(2)->create();
246+
$wallet1 = $buyer1->wallet;
247+
$wallet2 = $buyer2->wallet;
248+
249+
self::assertTrue($wallet1->saveOrFail());
250+
self::assertTrue($wallet2->saveOrFail());
251+
252+
self::assertSame(0, $wallet1->balanceInt);
253+
self::assertSame(0, $wallet2->balanceInt);
254+
255+
$transaction1 = $wallet1->deposit(1000, null, true);
256+
self::assertSame(1000, $wallet1->balanceInt);
257+
self::assertTrue($transaction1->confirmed);
258+
259+
self::assertFalse($wallet2->safeResetConfirm($transaction1));
260+
self::assertSame(1000, $wallet1->balanceInt);
261+
self::assertTrue($transaction1->confirmed);
262+
}
263+
201264
public function testWalletOwnerInvalid(): void
202265
{
203266
$this->expectException(WalletOwnerInvalid::class);
@@ -223,6 +286,31 @@ public function testWalletOwnerInvalid(): void
223286
$secondWallet->confirm($transaction);
224287
}
225288

289+
public function testForceWalletOwnerInvalid(): void
290+
{
291+
$this->expectException(WalletOwnerInvalid::class);
292+
$this->expectExceptionCode(ExceptionInterface::WALLET_OWNER_INVALID);
293+
$this->expectExceptionMessageStrict(trans('wallet::errors.owner_invalid'));
294+
295+
/**
296+
* @var Buyer $first
297+
* @var Buyer $second
298+
*/
299+
[$first, $second] = BuyerFactory::times(2)->create();
300+
$firstWallet = $first->wallet;
301+
$secondWallet = $second->wallet;
302+
303+
self::assertSame(0, $firstWallet->balanceInt);
304+
305+
$transaction = $firstWallet->deposit(1000, [
306+
'desc' => 'unconfirmed',
307+
], false);
308+
self::assertSame(0, $firstWallet->balanceInt);
309+
self::assertFalse($transaction->confirmed);
310+
311+
$secondWallet->forceConfirm($transaction);
312+
}
313+
226314
public function testUserConfirm(): void
227315
{
228316
/** @var UserConfirm $userConfirm */

0 commit comments

Comments
 (0)