Passed
Pull Request — master (#40)
by Бабичев
05:11
created

HasWallet::getBalanceAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Bavix\Wallet\Traits;
4
5
use Bavix\Wallet\Exceptions\BalanceIsEmpty;
6
use Bavix\Wallet\Exceptions\InsufficientFunds;
7
use Bavix\Wallet\Interfaces\Wallet;
8
use Bavix\Wallet\Models\Transaction;
9
use Bavix\Wallet\Models\Transfer;
10
use Bavix\Wallet\Models\Wallet as WalletModel;
11
use Bavix\Wallet\Objects\Bring;
12
use Bavix\Wallet\Objects\Operation;
13
use Bavix\Wallet\Services\CommonService;
14
use Bavix\Wallet\Services\ProxyService;
15
use Bavix\Wallet\Services\WalletService;
16
use Illuminate\Database\Eloquent\Relations\MorphMany;
17
use Illuminate\Database\Eloquent\Relations\MorphOne;
18
use Illuminate\Support\Collection;
19
use Illuminate\Support\Facades\DB;
20
use Throwable;
21
use function app;
22
use function config;
23
use function current;
24
25
/**
26
 * Trait HasWallet
27
 *
28
 * @package Bavix\Wallet\Traits
29
 *
30
 * @property-read WalletModel $wallet
31
 * @property-read Collection|WalletModel[] $wallets
32
 * @property-read int $balance
33
 */
34
trait HasWallet
35
{
36
37
    /**
38
     * The input means in the system
39
     *
40
     * @param int $amount
41
     * @param array|null $meta
42
     * @param bool $confirmed
43
     *
44
     * @return Transaction
45
     */
46 33
    public function deposit(int $amount, ?array $meta = null, bool $confirmed = true): Transaction
47
    {
48
        return DB::transaction(function () use ($amount, $meta, $confirmed) {
49 33
            return app(CommonService::class)
50 33
                ->deposit($this, $amount, $meta, $confirmed);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $wallet of Bavix\Wallet\Services\CommonService::deposit(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

50
                ->deposit(/** @scrutinizer ignore-type */ $this, $amount, $meta, $confirmed);
Loading history...
51 33
        });
52
    }
53
54
    /**
55
     * Magic laravel framework method, makes it
56
     *  possible to call property balance
57
     *
58
     * Example:
59
     *  $user1 = User::first()->load('wallet');
60
     *  $user2 = User::first()->load('wallet');
61
     *
62
     * Without static:
63
     *  var_dump($user1->balance, $user2->balance); // 100 100
64
     *  $user1->deposit(100);
65
     *  $user2->deposit(100);
66
     *  var_dump($user1->balance, $user2->balance); // 200 200
67
     *
68
     * With static:
69
     *  var_dump($user1->balance, $user2->balance); // 100 100
70
     *  $user1->deposit(100);
71
     *  var_dump($user1->balance); // 200
72
     *  $user2->deposit(100);
73
     *  var_dump($user2->balance); // 300
74
     *
75
     * @return int
76
     * @throws
77
     */
78 42
    public function getBalanceAttribute(): int
79
    {
80 42
        return app(WalletService::class)->getBalance($this);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $object of Bavix\Wallet\Services\WalletService::getBalance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
        return app(WalletService::class)->getBalance(/** @scrutinizer ignore-type */ $this);
Loading history...
81
    }
82
83
    /**
84
     * all user actions on wallets will be in this method
85
     *
86
     * @return MorphMany
87
     */
88 32
    public function transactions(): MorphMany
89
    {
90 32
        return ($this instanceof WalletModel ? $this->holder : $this)
91 32
            ->morphMany(config('wallet.transaction.model'), 'payable');
0 ignored issues
show
Bug introduced by
It seems like morphMany() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

91
            ->/** @scrutinizer ignore-call */ morphMany(config('wallet.transaction.model'), 'payable');
Loading history...
92
    }
93
94
    /**
95
     * This method ignores errors that occur when transferring funds
96
     *
97
     * @param Wallet $wallet
98
     * @param int $amount
99
     * @param array|null $meta
100
     * @return null|Transfer
101
     */
102 3
    public function safeTransfer(Wallet $wallet, int $amount, ?array $meta = null): ?Transfer
103
    {
104
        try {
105 3
            return $this->transfer($wallet, $amount, $meta);
106 3
        } catch (Throwable $throwable) {
107 3
            return null;
108
        }
109
    }
110
111
    /**
112
     * A method that transfers funds from host to host
113
     *
114
     * @param Wallet $wallet
115
     * @param int $amount
116
     * @param array|null $meta
117
     * @return Transfer
118
     * @throws
119
     */
120 6
    public function transfer(Wallet $wallet, int $amount, ?array $meta = null): Transfer
121
    {
122 6
        app(CommonService::class)->verifyWithdraw($this, $amount);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $wallet of Bavix\Wallet\Services\Co...rvice::verifyWithdraw(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

122
        app(CommonService::class)->verifyWithdraw(/** @scrutinizer ignore-type */ $this, $amount);
Loading history...
123 6
        return $this->forceTransfer($wallet, $amount, $meta);
124
    }
125
126
    /**
127
     * Withdrawals from the system
128
     *
129
     * @param int $amount
130
     * @param array|null $meta
131
     * @param bool $confirmed
132
     *
133
     * @return Transaction
134
     */
135 26
    public function withdraw(int $amount, ?array $meta = null, bool $confirmed = true): Transaction
136
    {
137 26
        app(CommonService::class)->verifyWithdraw($this, $amount);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $wallet of Bavix\Wallet\Services\Co...rvice::verifyWithdraw(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

137
        app(CommonService::class)->verifyWithdraw(/** @scrutinizer ignore-type */ $this, $amount);
Loading history...
138 19
        return $this->forceWithdraw($amount, $meta, $confirmed);
139
    }
140
141
    /**
142
     * Checks if you can withdraw funds
143
     *
144
     * @param int $amount
145
     * @return bool
146
     */
147 30
    public function canWithdraw(int $amount): bool
148
    {
149 30
        return $this->balance >= $amount;
150
    }
151
152
    /**
153
     * Forced to withdraw funds from system
154
     *
155
     * @param int $amount
156
     * @param array|null $meta
157
     * @param bool $confirmed
158
     *
159
     * @return Transaction
160
     */
161 19
    public function forceWithdraw(int $amount, ?array $meta = null, bool $confirmed = true): Transaction
162
    {
163
        return DB::transaction(function () use ($amount, $meta, $confirmed) {
164 19
            return app(CommonService::class)
165 19
                ->forceWithdraw($this, $amount, $meta, $confirmed);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $wallet of Bavix\Wallet\Services\Co...ervice::forceWithdraw(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
                ->forceWithdraw(/** @scrutinizer ignore-type */ $this, $amount, $meta, $confirmed);
Loading history...
166
167 19
        });
168
    }
169
170
    /**
171
     * the forced transfer is needed when the user does not have the money and we drive it.
172
     * Sometimes you do. Depends on business logic.
173
     *
174
     * @param Wallet $wallet
175
     * @param int $amount
176
     * @param array|null $meta
177
     * @return Transfer
178
     */
179 6
    public function forceTransfer(Wallet $wallet, int $amount, ?array $meta = null): Transfer
180
    {
181
        return DB::transaction(function () use ($amount, $wallet, $meta) {
182 6
            return app(CommonService::class)
183 6
                ->forceTransfer($this, $wallet, $amount, $meta);
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $from of Bavix\Wallet\Services\Co...ervice::forceTransfer(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

183
                ->forceTransfer(/** @scrutinizer ignore-type */ $this, $wallet, $amount, $meta);
Loading history...
184 6
        });
185
    }
186
187
    /**
188
     * the transfer table is used to confirm the payment
189
     * this method receives all transfers
190
     *
191
     * @return MorphMany
192
     */
193 13
    public function transfers(): MorphMany
194
    {
195 13
        return app(WalletService::class)
196 13
            ->getWallet($this)
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\HasWallet is incompatible with the type Bavix\Wallet\Interfaces\Wallet expected by parameter $object of Bavix\Wallet\Services\WalletService::getWallet(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

196
            ->getWallet(/** @scrutinizer ignore-type */ $this)
Loading history...
197 13
            ->morphMany(config('wallet.transfer.model'), 'from');
198
    }
199
200
    /**
201
     * Get default Wallet
202
     * this method is used for Eager Loading
203
     *
204
     * @return MorphOne|WalletModel
205
     */
206 42
    public function wallet(): MorphOne
207
    {
208 42
        return ($this instanceof WalletModel ? $this->holder : $this)
209 42
            ->morphOne(config('wallet.wallet.model'), 'holder')
0 ignored issues
show
Bug introduced by
It seems like morphOne() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
            ->/** @scrutinizer ignore-call */ morphOne(config('wallet.wallet.model'), 'holder')
Loading history...
210 42
            ->where('slug', config('wallet.wallet.default.slug'))
211 42
            ->withDefault([
212 42
                'name' => config('wallet.wallet.default.name'),
213 42
                'slug' => config('wallet.wallet.default.slug'),
214 42
                'balance' => 0,
215
            ]);
216
    }
217
218
}
219