Table::removeBlock()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
nc 2
nop 2
dl 0
loc 20
c 0
b 0
f 0
cc 2
rs 9.9
1
<?php
2
3
/**
4
 * @namespace
5
 */
6
7
namespace Application\Wallets;
8
9
use Application\Options\Table as OptionsTable;
0 ignored issues
show
Bug introduced by
The type Application\Options\Table was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Application\Transactions\Table as TransactionsTable;
11
use Application\Users\Table as UsersTable;
0 ignored issues
show
Bug introduced by
The type Application\Users\Table was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Application\Wallets\Exceptions\InsufficientFundsException;
13
use Application\Wallets\Exceptions\WalletsException;
14
use Bluz\Proxy\Db;
0 ignored issues
show
Bug introduced by
The type Bluz\Proxy\Db was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
16
/**
17
 * Class Table for `wallets`
18
 *
19
 * @package  Application\Wallets
20
 *
21
 * @method   static Row findRow($primaryKey)
22
 * @see      \Bluz\Db\Table::findRow()
23
 * @method   static Row findRowWhere($whereList)
24
 * @see      \Bluz\Db\Table::findRowWhere()
25
 *
26
 * @author   Anton Shevchuk
27
 * @created  2017-10-19 15:21:27
28
 */
29
class Table extends \Bluz\Db\Table
0 ignored issues
show
Bug introduced by
The type Bluz\Db\Table was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
{
31
    /**
32
     * @var string
33
     */
34
    protected $name = 'wallets';
35
36
    protected $rowClass = Row::class;
37
38
    /**
39
     * Primary key(s)
40
     * @var array
41
     */
42
    protected $primary = ['userId'];
43
44
    /**
45
     * init
46
     *
47
     * @return void
48
     */
49
    public function init(): void
50
    {
51
        $this->linkTo('userId', 'Users', 'id');
52
    }
53
54
    /**
55
     * getWallet
56
     *
57
     * @param int $userId
58
     *
59
     * @return \Application\Wallets\Row
60
     * @throws \Bluz\Db\Exception\DbException
61
     */
62
    public static function getWallet(int $userId)
63
    {
64
        $wallet = self::findRowWhere(['userId' => $userId]);
65
        if (!$wallet) {
0 ignored issues
show
introduced by
$wallet is of type Application\Wallets\Row, thus it always evaluated to true.
Loading history...
66
            $wallet = self::create(['userId' => $userId, 'amount' => 0]);
67
            $wallet->save();
68
69
            // workaround for https://github.com/bluzphp/framework/issues/447
70
            $wallet->userId = $userId;
71
        }
72
        return $wallet;
73
    }
74
75
    /**
76
     * Add Debit record
77
     *
78
     * @param int $userId
79
     * @param int $amount
80
     *
81
     * @return \Application\Wallets\Row|bool
82
     */
83
    public static function addDebit(int $userId, int $amount)
84
    {
85
        return Db::transaction(function () use ($userId, $amount) {
86
            $wallet = self::getWallet($userId);
87
88
            $row = TransactionsTable::create(
89
                [
90
                    'userId' => $userId,
91
                    'amount' => $amount,
92
                    'type' => TransactionsTable::TYPE_DEBIT
93
                ]
94
            );
95
            $row->save();
96
97
            $wallet->amount += $amount;
98
            $wallet->save();
99
100
            return $row;
101
        });
102
    }
103
104
    /**
105
     * Add Credit record
106
     *
107
     * @param int $userId
108
     * @param int $amount
109
     *
110
     * @return \Application\Wallets\Row|bool
111
     */
112
    public static function addCredit(int $userId, int $amount)
113
    {
114
        return Db::transaction(function () use ($userId, $amount) {
115
116
            $wallet = self::getWallet($userId);
117
            if ($wallet->amount - $wallet->blocked < $amount) {
118
                throw new InsufficientFundsException();
119
            }
120
121
            $row = TransactionsTable::create(
122
                [
123
                    'walletId' => $wallet->id,
124
                    'amount' => $amount,
125
                    'type' => TransactionsTable::TYPE_CREDIT
126
                ]
127
            );
128
            $row->save();
129
130
            $wallet->amount -= $amount;
131
            $wallet->save();
132
133
            return $row;
134
        });
135
    }
136
137
    /**
138
     * Block some money
139
     *
140
     * @param int $userId
141
     * @param int $amount
142
     *
143
     * @return bool
144
     * @throws InsufficientFundsException
145
     * @throws \Bluz\Common\Exception\ConfigurationException
146
     * @throws \Bluz\Db\Exception\DbException
147
     * @throws \Bluz\Db\Exception\InvalidPrimaryKeyException
148
     * @throws \Bluz\Db\Exception\TableNotFoundException
149
     */
150
    public static function addBlock(int $userId, int $amount): bool
151
    {
152
        $wallet = self::getWallet($userId);
153
        if ($wallet->amount - $wallet->blocked < $amount) {
154
            throw new InsufficientFundsException();
155
        }
156
157
        $row = TransactionsTable::create(
158
            [
159
                'walletId' => $wallet->id,
160
                'amount' => $amount,
161
                'type' => TransactionsTable::TYPE_BLOCK
162
            ]
163
        );
164
        $row->save();
165
166
        $wallet->blocked += $amount;
167
        return $wallet->save();
168
    }
169
170
    /**
171
     * Add Credit record
172
     *
173
     * @param int $userId
174
     * @param int $amount
175
     *
176
     * @return bool
177
     * @throws \Bluz\Common\Exception\ConfigurationException
178
     * @throws \Bluz\Db\Exception\DbException
179
     * @throws \Bluz\Db\Exception\InvalidPrimaryKeyException
180
     * @throws \Bluz\Db\Exception\TableNotFoundException
181
     */
182
    public static function removeBlock(int $userId, int $amount): bool
183
    {
184
        $wallet = self::getWallet($userId);
185
186
        $row = TransactionsTable::create(
187
            [
188
                'walletId' => $wallet->id,
189
                'amount' => $amount,
190
                'type' => TransactionsTable::TYPE_UNBLOCK
191
            ]
192
        );
193
        $row->save();
194
195
        if ($wallet->blocked < $amount) {
196
            $wallet->blocked = 0;
197
        } else {
198
            $wallet->blocked -= $amount;
199
        }
200
201
        return $wallet->save();
202
    }
203
204
    /**
205
     * Send money from wallet to wallet
206
     *
207
     * @param int $fromUserId
208
     * @param int $toUserId
209
     * @param int $amount
210
     *
211
     * @return \Application\Wallets\Row|bool
212
     * @throws InsufficientFundsException
213
     * @throws WalletsException
214
     * @throws \Bluz\Db\Exception\DbException
215
     */
216
    public static function send(int $fromUserId, int $toUserId, int $amount)
217
    {
218
        if ($amount < 0) {
219
            throw new WalletsException('Amount is lower than zero');
220
        }
221
222
        $fromWallet = self::getWallet($fromUserId);
223
224
        if ($fromWallet->amount - $fromWallet->blocked < $amount) {
225
            throw new InsufficientFundsException();
226
        }
227
228
        return Db::transaction(function () use ($fromWallet, $toUserId, $amount) {
229
            // Credit
230
            $creditTransaction = TransactionsTable::create();
231
            $creditTransaction->userId = $fromWallet->userId;
232
            $creditTransaction->amount = $amount;
233
            $creditTransaction->type = TransactionsTable::TYPE_CREDIT;
234
            $creditTransaction->save();
235
236
            $fromWallet->amount -= $amount;
237
            $fromWallet->save();
238
239
            // System percent
240
            $systemAmount = ceil(OptionsTable::get('percent') / 100 * $amount);
241
            $ownerAmount = $amount - $systemAmount;
242
243
            // Debit to system
244
            $transaction = TransactionsTable::create();
245
            $transaction->userId = UsersTable::SYSTEM_USER;
246
            $transaction->amount = $systemAmount;
247
            $transaction->type = TransactionsTable::TYPE_DEBIT;
248
            $transaction->save();
249
250
            // Debit to owner
251
            $debitTransaction = TransactionsTable::create();
252
            $debitTransaction->userId = $toUserId;
253
            $debitTransaction->amount = $ownerAmount;
254
            $debitTransaction->type = TransactionsTable::TYPE_DEBIT;
255
            $debitTransaction->save();
256
257
            $toWallet = self::getWallet($toUserId);
258
            $toWallet->amount += $ownerAmount;
259
            $toWallet->save();
260
        });
261
    }
262
}
263