Skip to content

Commit c27f2ad

Browse files
authored
Merge pull request #419 from bavix/credit
[7.x] Credit Limits
2 parents 798dd98 + a0c74cc commit c27f2ad

File tree

6 files changed

+93
-13
lines changed

6 files changed

+93
-13
lines changed

src/Models/Wallet.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* @property null|array $meta
3939
* @property int $decimal_places
4040
* @property \Bavix\Wallet\Interfaces\Wallet $holder
41+
* @property string $credit
4142
* @property string $currency
4243
*/
4344
class Wallet extends Model implements Customer, WalletFloat, Confirmable, Exchangeable
@@ -109,7 +110,7 @@ public function setNameAttribute(string $name): void
109110
public function refreshBalance(): bool
110111
{
111112
return app(AtomicServiceInterface::class)->block($this, function () {
112-
$whatIs = $this->balance;
113+
$whatIs = $this->getBalanceAttribute();
113114
$balance = $this->getAvailableBalanceAttribute();
114115
if (app(MathServiceInterface::class)->compare($whatIs, $balance) === 0) {
115116
return true;
@@ -157,6 +158,11 @@ public function holder(): MorphTo
157158
return $this->morphTo();
158159
}
159160

161+
public function getCreditAttribute(): string
162+
{
163+
return (string) ($this->meta['credit'] ?? '0');
164+
}
165+
160166
public function getCurrencyAttribute(): string
161167
{
162168
return $this->meta['currency'] ?? Str::upper($this->slug);

src/Services/ConsistencyService.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,41 @@ public function checkPositive($amount): void
5353
public function checkPotential(Wallet $object, $amount, bool $allowZero = false): void
5454
{
5555
$wallet = $this->castService->getWallet($object, false);
56+
$balance = $this->mathService->add($wallet->getBalanceAttribute(), $wallet->getCreditAttribute());
5657

57-
if (($this->mathService->compare($amount, 0) !== 0) && !$wallet->getBalanceAttribute()) {
58+
if (($this->mathService->compare($amount, 0) !== 0) && ($this->mathService->compare($balance, 0) === 0)) {
5859
throw new BalanceIsEmpty(
5960
$this->translatorService->get('wallet::errors.wallet_empty'),
6061
ExceptionInterface::BALANCE_IS_EMPTY
6162
);
6263
}
6364

64-
if (!$wallet->canWithdraw($amount, $allowZero)) {
65+
if (!$this->canWithdraw($balance, $amount, $allowZero)) {
6566
throw new InsufficientFunds(
6667
$this->translatorService->get('wallet::errors.insufficient_funds'),
6768
ExceptionInterface::INSUFFICIENT_FUNDS
6869
);
6970
}
7071
}
7172

73+
/**
74+
* @param float|int|string $balance
75+
* @param float|int|string $amount
76+
*/
77+
public function canWithdraw($balance, $amount, bool $allowZero = false): bool
78+
{
79+
$mathService = app(MathServiceInterface::class);
80+
81+
/**
82+
* Allow buying for free with a negative balance.
83+
*/
84+
if ($allowZero && !$mathService->compare($amount, 0)) {
85+
return true;
86+
}
87+
88+
return $mathService->compare($balance, $amount) >= 0;
89+
}
90+
7291
/**
7392
* @param TransferLazyDtoInterface[] $objects
7493
*

src/Services/ConsistencyServiceInterface.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ public function checkPositive($amount): void;
2727
*/
2828
public function checkPotential(Wallet $object, $amount, bool $allowZero = false): void;
2929

30+
/**
31+
* @param float|int|string $balance
32+
* @param float|int|string $amount
33+
*/
34+
public function canWithdraw($balance, $amount, bool $allowZero = false): bool;
35+
3036
/**
3137
* @param TransferLazyDtoInterface[] $objects
3238
*

src/Traits/HasWallet.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,11 @@ public function withdraw($amount, ?array $meta = null, bool $confirmed = true):
179179
*/
180180
public function canWithdraw($amount, bool $allowZero = false): bool
181181
{
182-
$math = app(MathServiceInterface::class);
182+
$mathService = app(MathServiceInterface::class);
183+
$wallet = app(CastServiceInterface::class)->getWallet($this);
184+
$balance = $mathService->add($this->getBalanceAttribute(), $wallet->getCreditAttribute());
183185

184-
/**
185-
* Allow buying for free with a negative balance.
186-
*/
187-
if ($allowZero && !$math->compare($amount, 0)) {
188-
return true;
189-
}
190-
191-
return $math->compare($this->balance, $amount) >= 0;
186+
return app(ConsistencyServiceInterface::class)->canWithdraw($balance, $amount, $allowZero);
192187
}
193188

194189
/**

src/Traits/HasWalletFloat.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,6 @@ public function getBalanceFloatAttribute()
161161
$decimalPlacesValue = $wallet->decimal_places;
162162
$decimalPlaces = $math->powTen($decimalPlacesValue);
163163

164-
return $math->div($wallet->balance, $decimalPlaces, $decimalPlacesValue);
164+
return $math->div($wallet->getBalanceAttribute(), $decimalPlaces, $decimalPlacesValue);
165165
}
166166
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bavix\Wallet\Test\Units\Domain;
6+
7+
use Bavix\Wallet\Test\Infra\Factories\UserMultiFactory;
8+
use Bavix\Wallet\Test\Infra\Models\UserMulti;
9+
use Bavix\Wallet\Test\Infra\TestCase;
10+
11+
/**
12+
* @internal
13+
*/
14+
class CreditWalletTest extends TestCase
15+
{
16+
public function testCreditLimit(): void
17+
{
18+
/** @var UserMulti $user */
19+
$user = UserMultiFactory::new()->create();
20+
$wallet = $user->createWallet([
21+
'name' => 'Credit USD',
22+
'slug' => 'credit-usd',
23+
'meta' => ['credit' => 10000, 'currency' => 'USD'],
24+
]);
25+
26+
$transaction = $wallet->deposit(1000);
27+
self::assertNotNull($transaction);
28+
29+
self::assertSame(1000, $wallet->balanceInt);
30+
self::assertSame(10., (float) $wallet->balanceFloat);
31+
32+
$transaction = $wallet->withdraw(10000);
33+
self::assertNotNull($transaction);
34+
self::assertSame(-9000, $wallet->balanceInt);
35+
}
36+
37+
public function testCreditLimitBalanceZero(): void
38+
{
39+
/** @var UserMulti $user */
40+
$user = UserMultiFactory::new()->create();
41+
$wallet = $user->createWallet([
42+
'name' => 'Credit USD',
43+
'slug' => 'credit-usd',
44+
'meta' => ['credit' => 10000, 'currency' => 'USD'],
45+
]);
46+
47+
self::assertSame(0, $wallet->balanceInt);
48+
self::assertSame(0., (float) $wallet->balanceFloat);
49+
50+
$transaction = $wallet->withdraw(10000);
51+
self::assertNotNull($transaction);
52+
self::assertSame(-10000, $wallet->balanceInt);
53+
}
54+
}

0 commit comments

Comments
 (0)