Passed
Push — master ( 16f2ad...0b7e9e )
by Бабичев
01:40 queued 12s
created

WalletService::decimalPlacesValue()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Bavix\Wallet\Services;
4
5
use Bavix\Wallet\Exceptions\AmountInvalid;
6
use Bavix\Wallet\Interfaces\Customer;
7
use Bavix\Wallet\Interfaces\Discount;
8
use Bavix\Wallet\Interfaces\Mathable;
9
use Bavix\Wallet\Interfaces\MinimalTaxable;
10
use Bavix\Wallet\Interfaces\Storable;
11
use Bavix\Wallet\Interfaces\Taxable;
12
use Bavix\Wallet\Interfaces\Wallet;
13
use Bavix\Wallet\Models\Wallet as WalletModel;
14
use Bavix\Wallet\Traits\HasWallet;
15
use function app;
16
17
class WalletService
18
{
19
20
    /**
21
     * @param Wallet $customer
22
     * @param Wallet $product
23
     * @return int
24
     */
25 50
    public function discount(Wallet $customer, Wallet $product): int
26
    {
27 50
        if ($customer instanceof Customer && $product instanceof Discount) {
28 20
            return $product->getPersonalDiscount($customer);
29
        }
30
31
        // without discount
32 40
        return 0;
33
    }
34
35
    /**
36
     * @param Wallet $object
37
     * @return int
38
     */
39 59
    public function decimalPlacesValue(Wallet $object): int
40
    {
41 59
        return $this->getWallet($object)->decimal_places ?: 2;
42
    }
43
44
    /**
45
     * @param Wallet $object
46
     * @return string
47
     */
48 14
    public function decimalPlaces(Wallet $object): string
49
    {
50 14
        return app(Mathable::class)
51 14
            ->pow(10, $this->decimalPlacesValue($object));
52
    }
53
54
    /**
55
     * Consider the fee that the system will receive.
56
     *
57
     * @param Wallet $wallet
58
     * @param int $amount
59
     * @return float|int
60
     */
61 51
    public function fee(Wallet $wallet, $amount)
62
    {
63 51
        $fee = 0;
64 51
        $math = app(Mathable::class);
65 51
        if ($wallet instanceof Taxable) {
66 14
            $placesValue = $this->decimalPlacesValue($wallet);
67 14
            $fee = $math->floor(
68 14
                $math->div(
69 14
                    $math->mul($amount, $wallet->getFeePercent(), 0),
70 14
                    100,
71 14
                    $placesValue
72
                )
73
            );
74
        }
75
76
        /**
77
         * Added minimum commission condition
78
         *
79
         * @see https://github.com/bavix/laravel-wallet/issues/64#issuecomment-514483143
80
         */
81 51
        if ($wallet instanceof MinimalTaxable) {
82 1
            $minimal = $wallet->getMinimalFee();
83 1
            if (app(Mathable::class)->compare($fee, $minimal) === -1) {
84 1
                $fee = $minimal;
85
            }
86
        }
87
88 51
        return $fee;
89
    }
90
91
    /**
92
     * The amount of checks for errors
93
     *
94
     * @param int $amount
95
     * @throws
96
     */
97 100
    public function checkAmount($amount): void
98
    {
99 100
        if (app(Mathable::class)->compare($amount, 0) === -1) {
100 3
            throw new AmountInvalid(trans('wallet::errors.price_positive'));
0 ignored issues
show
Bug introduced by
It seems like trans('wallet::errors.price_positive') can also be of type array and array; however, parameter $message of Bavix\Wallet\Exceptions\...tInvalid::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

100
            throw new AmountInvalid(/** @scrutinizer ignore-type */ trans('wallet::errors.price_positive'));
Loading history...
101
        }
102 97
    }
103
104
    /**
105
     * @param Wallet $object
106
     * @param bool $autoSave
107
     * @return WalletModel
108
     */
109 119
    public function getWallet(Wallet $object, bool $autoSave = true): WalletModel
110
    {
111
        /**
112
         * @var WalletModel $wallet
113
         */
114 119
        $wallet = $object;
115
116 119
        if (!($object instanceof WalletModel)) {
117
            /**
118
             * @var HasWallet $object
119
             */
120 81
            $wallet = $object->wallet;
121
        }
122
123 119
        if ($autoSave) {
124 119
            $wallet->exists or $wallet->save();
125
        }
126
127 119
        return $wallet;
128
    }
129
130
    /**
131
     * @param WalletModel $wallet
132
     * @return bool
133
     */
134 18
    public function refresh(WalletModel $wallet): bool
135
    {
136
        return app(LockService::class)->lock($this, __FUNCTION__, static function () use ($wallet) {
137 18
            $math = app(Mathable::class);
138 18
            app(Storable::class)->getBalance($wallet);
139 18
            $whatIs = $wallet->balance;
140 18
            $balance = $wallet->getAvailableBalance();
141 18
            $wallet->balance = $balance;
142
143 18
            return app(Storable::class)->setBalance($wallet, $balance) &&
0 ignored issues
show
Bug introduced by
It seems like $balance can also be of type double; however, parameter $amount of Bavix\Wallet\Interfaces\Storable::setBalance() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

143
            return app(Storable::class)->setBalance($wallet, /** @scrutinizer ignore-type */ $balance) &&
Loading history...
144 18
                (!$math->compare($whatIs, $balance) || $wallet->save());
145 18
        });
146
    }
147
148
}
149