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

CartPay   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Test Coverage

Coverage 95.06%

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 218
ccs 77
cts 81
cp 0.9506
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 2
    public function payFreeCart(Cart $cart): array
23
    {
24 2
        $results = [];
25 2
        foreach ($cart->getItems() as $product) {
26 2
            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 1
                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 2
            $results[] = $this->transfer(
31 2
                $product,
32 2
                0,
33 2
                $product->getMetaProduct(),
34 2
                Transfer::STATUS_PAID
35
            );
36
        }
37
38 2
        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 7
    public function payCart(Cart $cart, bool $force = null): array
62
    {
63 7
        $results = [];
64 7
        foreach ($cart->getItems() as $product) {
65 7
            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 2
                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 7
            if ($force) {
70 1
                $results[] = $this->forceTransfer(
71 1
                    $product,
72 1
                    $product->getAmountProduct(),
73 1
                    $product->getMetaProduct(),
74 1
                    Transfer::STATUS_PAID
75
                );
76
77 1
                continue;
78
            }
79
80 6
            $results[] = $this->transfer(
81 6
                $product,
82 6
                $product->getAmountProduct(),
83 6
                $product->getMetaProduct(),
84 6
                Transfer::STATUS_PAID
85
            );
86
        }
87
88 7
        return $results;
89
    }
90
91
    /**
92
     * @param Cart $cart
93
     * @return Transfer[]
94
     * @throws
95
     */
96 1
    public function forcePayCart(Cart $cart): array
97
    {
98 1
        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 3
    public function safeRefundCart(Cart $cart, bool $force = null, bool $gifts = null): bool
108
    {
109
        try {
110 3
            return $this->refundCart($cart, $force, $gifts);
111 3
        } catch (\Throwable $throwable) {
112 3
            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 6
    public function refundCart(Cart $cart, bool $force = null, bool $gifts = null): bool
124
    {
125 6
        $results = true;
126 6
        foreach ($cart->getItems() as $product) {
127
128 6
            $transfer = $this->paid($product, $gifts);
129
130 6
            if (!$transfer) {
131 2
                throw (new ModelNotFoundException())
132 2
                    ->setModel($this->transfers()->getMorphClass());
133
            }
134
135
            $results = $results && DB::transaction(function () use ($product, $transfer, $force) {
136 6
                $transfer->load('withdraw.wallet');
137
138 6
                if ($force) {
139 2
                    $product->forceTransfer(
140 2
                        $transfer->withdraw->wallet,
141 2
                        $transfer->deposit->amount,
142 2
                        $product->getMetaProduct()
143
                    );
144
                } else {
145 6
                    $product->transfer(
146 6
                        $transfer->withdraw->wallet,
147 6
                        $transfer->deposit->amount,
148 6
                        $product->getMetaProduct()
149
                    );
150
                }
151
152 6
                return $transfer->update([
153 6
                    'status' => Transfer::STATUS_REFUND,
154 6
                    'status_last' => $transfer->status,
155
                ]);
156 6
            });
157
        }
158
159 6
        return $results;
160
    }
161
162
    /**
163
     * @param Cart $cart
164
     * @param bool $gifts
165
     * @return bool
166
     * @throws
167
     */
168 1
    public function forceRefundCart(Cart $cart, bool $gifts = null): bool
169
    {
170 1
        return $this->refundCart($cart, true, $gifts);
171
    }
172
173
    /**
174
     * @param Cart $cart
175
     * @param bool $force
176
     * @return bool
177
     */
178 1
    public function safeRefundGiftCart(Cart $cart, bool $force = null): bool
179
    {
180
        try {
181 1
            return $this->refundGiftCart($cart, $force);
182 1
        } catch (\Throwable $throwable) {
183 1
            return false;
184
        }
185
    }
186
187
    /**
188
     * @param Cart $cart
189
     * @param bool $force
190
     * @return bool
191
     * @throws
192
     */
193 1
    public function refundGiftCart(Cart $cart, bool $force = null): bool
194
    {
195 1
        return $this->refundCart($cart, $force, true);
196
    }
197
198
    /**
199
     * @param Cart $cart
200
     * @return bool
201
     * @throws
202
     */
203 1
    public function forceRefundGiftCart(Cart $cart): bool
204
    {
205 1
        return $this->refundGiftCart($cart, true);
206
    }
207
208
    /**
209
     * @param Product $product
210
     * @param bool $gifts
211
     * @return null|Transfer
212
     */
213 10
    public function paid(Product $product, bool $gifts = null): ?Transfer
214
    {
215 10
        $status = [Transfer::STATUS_PAID];
216 10
        if ($gifts) {
217 2
            $status[] = Transfer::STATUS_GIFT;
218
        }
219
220
        /**
221
         * @var Model $product
222
         * @var Transfer $query
223
         */
224 10
        $query = $this->transfers();
225
        return $query
226 10
            ->where('to_type', $product->getMorphClass())
227 10
            ->where('to_id', $product->getKey())
228 10
            ->whereIn('status', $status)
229 10
            ->orderBy('id', 'desc')
230 10
            ->first();
231
    }
232
233
}
234