Test Failed
Pull Request — master (#40)
by Бабичев
03:32
created

CartPay   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 218
rs 10
c 0
b 0
f 0
wmc 24

11 Methods

Rating   Name   Duplication   Size   Complexity  
A safeRefundCart() 0 6 2
A safeRefundGiftCart() 0 6 2
A refundCart() 0 37 5
A forceRefundCart() 0 3 1
A forceRefundGiftCart() 0 3 1
A safePayCart() 0 6 2
A payFreeCart() 0 17 3
A refundGiftCart() 0 3 1
A forcePayCart() 0 3 1
A payCart() 0 28 4
A paid() 0 18 2
1
<?php
2
3
namespace Bavix\Wallet\Traits;
4
5
use Bavix\Wallet\Exceptions\ProductEnded;
6
use Bavix\Wallet\Interfaces\Product;
7
use Bavix\Wallet\Models\Transfer;
8
use Bavix\Wallet\Objects\Cart;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Eloquent\ModelNotFoundException;
11
use Illuminate\Support\Facades\DB;
12
13
trait CartPay
14
{
15
16
    use HasWallet;
17
18
    /**
19
     * @param Cart $cart
20
     * @return Transfer[]
21
     */
22
    public function payFreeCart(Cart $cart): array
23
    {
24
        $results = [];
25
        foreach ($cart->getItems() as $product) {
26
            if (!$product->canBuy($this)) {
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Interfaces\Product::canBuy(). ( Ignorable by Annotation )

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

26
            if (!$product->canBuy(/** @scrutinizer ignore-type */ $this)) {
Loading history...
27
                throw new ProductEnded(trans('wallet::errors.product_stock'));
0 ignored issues
show
Bug introduced by
It seems like trans('wallet::errors.product_stock') can also be of type array; however, parameter $message of Bavix\Wallet\Exceptions\...uctEnded::__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

27
                throw new ProductEnded(/** @scrutinizer ignore-type */ trans('wallet::errors.product_stock'));
Loading history...
28
            }
29
30
            $results[] = $this->transfer(
31
                $product,
32
                0,
33
                $product->getMetaProduct(),
34
                Transfer::STATUS_PAID
35
            );
36
        }
37
38
        return $results;
39
    }
40
41
    /**
42
     * @param Cart $cart
43
     * @param bool $force
44
     * @return Transfer[]
45
     */
46
    public function safePayCart(Cart $cart, bool $force = null): array
47
    {
48
        try {
49
            return $this->payCart($cart, $force);
50
        } catch (\Throwable $throwable) {
51
            return [];
52
        }
53
    }
54
55
    /**
56
     * @param Cart $cart
57
     * @param bool $force
58
     * @return Transfer[]
59
     * @throws
60
     */
61
    public function payCart(Cart $cart, bool $force = null): array
62
    {
63
        $results = [];
64
        foreach ($cart->getItems() as $product) {
65
            if (!$product->canBuy($this, $force)) {
0 ignored issues
show
Bug introduced by
$this of type Bavix\Wallet\Traits\CartPay is incompatible with the type Bavix\Wallet\Interfaces\Customer expected by parameter $customer of Bavix\Wallet\Interfaces\Product::canBuy(). ( Ignorable by Annotation )

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

65
            if (!$product->canBuy(/** @scrutinizer ignore-type */ $this, $force)) {
Loading history...
66
                throw new ProductEnded(trans('wallet::errors.product_stock'));
0 ignored issues
show
Bug introduced by
It seems like trans('wallet::errors.product_stock') can also be of type array; however, parameter $message of Bavix\Wallet\Exceptions\...uctEnded::__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

66
                throw new ProductEnded(/** @scrutinizer ignore-type */ trans('wallet::errors.product_stock'));
Loading history...
67
            }
68
69
            if ($force) {
70
                $results[] = $this->forceTransfer(
71
                    $product,
72
                    $product->getAmountProduct(),
73
                    $product->getMetaProduct(),
74
                    Transfer::STATUS_PAID
75
                );
76
77
                continue;
78
            }
79
80
            $results[] = $this->transfer(
81
                $product,
82
                $product->getAmountProduct(),
83
                $product->getMetaProduct(),
84
                Transfer::STATUS_PAID
85
            );
86
        }
87
88
        return $results;
89
    }
90
91
    /**
92
     * @param Cart $cart
93
     * @return Transfer[]
94
     * @throws
95
     */
96
    public function forcePayCart(Cart $cart): array
97
    {
98
        return $this->payCart($cart, true);
99
    }
100
101
    /**
102
     * @param Cart $cart
103
     * @param bool $force
104
     * @param bool $gifts
105
     * @return bool
106
     */
107
    public function safeRefundCart(Cart $cart, bool $force = null, bool $gifts = null): bool
108
    {
109
        try {
110
            return $this->refundCart($cart, $force, $gifts);
111
        } catch (\Throwable $throwable) {
112
            return false;
113
        }
114
    }
115
116
    /**
117
     * @param Cart $cart
118
     * @param bool $force
119
     * @param bool $gifts
120
     * @return bool
121
     * @throws
122
     */
123
    public function refundCart(Cart $cart, bool $force = null, bool $gifts = null): bool
124
    {
125
        $results = true;
126
        foreach ($cart->getItems() as $product) {
127
128
            $transfer = $this->paid($product, $gifts);
129
130
            if (!$transfer) {
131
                throw (new ModelNotFoundException())
132
                    ->setModel($this->transfers()->getMorphClass());
133
            }
134
135
            $results = $results && DB::transaction(function () use ($product, $transfer, $force) {
136
                $transfer->load('withdraw.wallet');
137
138
                if ($force) {
139
                    $product->forceTransfer(
140
                        $transfer->withdraw->wallet,
141
                        $transfer->deposit->amount,
142
                        $product->getMetaProduct()
143
                    );
144
                } else {
145
                    $product->transfer(
146
                        $transfer->withdraw->wallet,
147
                        $transfer->deposit->amount,
148
                        $product->getMetaProduct()
149
                    );
150
                }
151
152
                return $transfer->update([
153
                    'status' => Transfer::STATUS_REFUND,
154
                    'status_last' => $transfer->status,
155
                ]);
156
            });
157
        }
158
159
        return $results;
160
    }
161
162
    /**
163
     * @param Cart $cart
164
     * @param bool $gifts
165
     * @return bool
166
     * @throws
167
     */
168
    public function forceRefundCart(Cart $cart, bool $gifts = null): bool
169
    {
170
        return $this->refundCart($cart, true, $gifts);
171
    }
172
173
    /**
174
     * @param Cart $cart
175
     * @param bool $force
176
     * @return bool
177
     */
178
    public function safeRefundGiftCart(Cart $cart, bool $force = null): bool
179
    {
180
        try {
181
            return $this->refundGiftCart($cart, $force);
182
        } catch (\Throwable $throwable) {
183
            return false;
184
        }
185
    }
186
187
    /**
188
     * @param Cart $cart
189
     * @param bool $force
190
     * @return bool
191
     * @throws
192
     */
193
    public function refundGiftCart(Cart $cart, bool $force = null): bool
194
    {
195
        return $this->refundCart($cart, $force, true);
196
    }
197
198
    /**
199
     * @param Cart $cart
200
     * @return bool
201
     * @throws
202
     */
203
    public function forceRefundGiftCart(Cart $cart): bool
204
    {
205
        return $this->refundGiftCart($cart, true);
206
    }
207
208
    /**
209
     * @param Product $product
210
     * @param bool $gifts
211
     * @return null|Transfer
212
     */
213
    public function paid(Product $product, bool $gifts = null): ?Transfer
214
    {
215
        $status = [Transfer::STATUS_PAID];
216
        if ($gifts) {
217
            $status[] = Transfer::STATUS_GIFT;
218
        }
219
220
        /**
221
         * @var Model $product
222
         * @var Transfer $query
223
         */
224
        $query = $this->transfers();
225
        return $query
226
            ->where('to_type', $product->getMorphClass())
227
            ->where('to_id', $product->getKey())
228
            ->whereIn('status', $status)
229
            ->orderBy('id', 'desc')
230
            ->first();
231
    }
232
233
}
234