Test Failed
Push — master ( 23cc6e...476483 )
by Alexey
05:28
created

Cart::checkPrices()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 3
nop 0
dl 0
loc 13
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Cart
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2015 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
12
namespace Ecommerce;
13
/**
14
 * Class Cart
15
 *
16
 * @property int $id
17
 * @property int $user_id
18
 * @property int $cart_status_id
19
 * @property int $delivery_id
20
 * @property int $paytype_id
21
 * @property int $card_item_id
22
 * @property bool $warehouse_block
23
 * @property bool $payed
24
 * @property string $comment
25
 * @property bool $exported
26
 * @property string $complete_data
27
 * @property string $date_status
28
 * @property string $date_last_activ
29
 * @property string $date_create
30
 *
31
 * @property \Users\User $user
32
 * @property \Ecommerce\Cart\Item[] $cartItems
33
 * @property \Ecommerce\Cart\Event[] $events
34
 * @property \Ecommerce\Cart\Status $status
35
 * @property \Ecommerce\Delivery $delivery
36
 * @property \Ecommerce\PayType $payType
37
 * @property \Ecommerce\Cart\Info[] $infos
38
 * @property \Ecommerce\Cart\DeliveryInfo[] $deliveryInfos
39
 * @property \Ecommerce\Cart\Extra[] $extras
40
 * @property \Ecommerce\Card\Item $card
41
 * @property \Money\Pay[] $pays
42
 * @property \Ecommerce\Cart\Discount[] $discounts
43
 */
44
class Cart extends \Model {
45
46
    public static $objectName = 'Корзины';
47
48
    public static function indexes() {
49
        return [
50
            'ecommerce_cartStatusBlock' => [
51
                'type' => 'INDEX',
52
                'cols' => [
53
                    'cart_cart_status_id',
54
                    'cart_warehouse_block'
55
                ]
56
            ],
57
            'ecommerce_cartStats' => [
58
                'type' => 'INDEX',
59
                'cols' => [
60
                    'cart_cart_status_id',
61
                ]
62
            ],
63
            'ecommerce_cartBlock' => [
64
                'type' => 'INDEX',
65
                'cols' => [
66
                    'cart_warehouse_block'
67
                ]
68
            ],
69
        ];
70
    }
71
72
    public static function relations() {
73
        return [
74
            'user' => [
75
                'model' => 'Users\User',
76
                'col' => 'user_id'
77
            ],
78
            'cartItems' => [
79
                'type' => 'many',
80
                'model' => 'Ecommerce\Cart\Item',
81
                'col' => 'cart_id',
82
            ],
83
            'events' => [
84
                'type' => 'many',
85
                'model' => 'Ecommerce\Cart\Event',
86
                'col' => 'cart_id',
87
            ],
88
            'status' => [
89
                'model' => 'Ecommerce\Cart\Status',
90
                'col' => 'cart_status_id'
91
            ],
92
            'delivery' => [
93
                'model' => 'Ecommerce\Delivery',
94
                'col' => 'delivery_id'
95
            ],
96
            'payType' => [
97
                'model' => 'Ecommerce\PayType',
98
                'col' => 'paytype_id'
99
            ],
100
            'infos' => [
101
                'type' => 'many',
102
                'model' => 'Ecommerce\Cart\Info',
103
                'col' => 'cart_id',
104
                'resultKey' => 'useradds_field_id'
105
            ],
106
            'deliveryInfos' => [
107
                'type' => 'many',
108
                'model' => 'Ecommerce\Cart\DeliveryInfo',
109
                'col' => 'cart_id',
110
                'resultKey' => 'delivery_field_id'
111
            ],
112
            'extras' => [
113
                'type' => 'many',
114
                'model' => 'Ecommerce\Cart\Extra',
115
                'col' => 'cart_id'
116
            ],
117
            'card' => [
118
                'model' => 'Ecommerce\Card\Item',
119
                'col' => 'card_item_id'
120
            ],
121
            'pays' => [
122
                'type' => 'many',
123
                'model' => 'Money\Pay',
124
                'col' => 'data'
125
            ],
126
            'discounts' => [
127
                'type' => 'relModel',
128
                'relModel' => 'Ecommerce\Cart\Discount',
129
                'model' => 'Ecommerce\Discount',
130
            ]
131
        ];
132
    }
133
134
    public function beforeDelete() {
135
        foreach ($this->cartItems as $cartItem) {
136
            $cartItem->delete();
137
        }
138
        foreach ($this->infos as $info) {
139
            $info->delete();
140
        }
141
        foreach ($this->extras as $extra) {
142
            $extra->delete();
143
        }
144
        foreach ($this->events as $event) {
145
            $event->delete();
146
        }
147
    }
148
149
    public static $labels = [
150
        'user_id' => 'Пользователь',
151
        'cart_status_id' => 'Статус',
152
        'delivery_id' => 'Доставка',
153
        'comment' => 'Комментарий',
154
        'bonus_used' => 'Выгодные рубли',
155
        'complete_data' => 'Время заказа',
156
        'info' => 'Информация',
157
        'items' => 'Товары',
158
        'paytype_id' => 'Способ оплаты',
159
        'payed' => 'Оплачен',
160
        'exported' => 'Выгружено',
161
        'warehouse_block' => 'Блокировка товаров',
162
        'extra' => 'Доп.',
163
        'card_item_id' => 'Дисконтная карта',
164
        'info' => 'Информация',
165
        'contacts' => 'Информация',
166
        'pay' => 'Счета',
167
        'sums' => 'Суммы',
168
        'deliveryInfo' => 'Для доставки',
169
        'discount' => 'Скидки',
170
    ];
171
    public static $cols = [
172
        //Основные параметры
173
        'user_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'user'],
174
        'cart_status_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'status'],
175
        'delivery_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'delivery'],
176
        'paytype_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'payType'],
177
        'card_item_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'card'],
178
        'warehouse_block' => ['type' => 'bool'],
179
        'payed' => ['type' => 'bool'],
180
        'comment' => ['type' => 'textarea'],
181
        //Системные
182
        'exported' => ['type' => 'bool'],
183
        'complete_data' => ['type' => 'dateTime', 'null' => true, 'emptyValue' => null],
184
        'date_status' => ['type' => 'dateTime', 'null' => true, 'emptyValue' => null],
185
        'date_last_activ' => ['type' => 'dateTime', 'null' => true, 'emptyValue' => null],
186
        'date_create' => ['type' => 'dateTime'],
187
        //Виджеты
188
        'sums' => [
189
            'type' => 'void',
190
            'view' => [
191
                'type' => 'widget',
192
                'widget' => 'Ecommerce\adminSums',
193
            ],
194
        ],
195
        'contacts' => [
196
            'type' => 'void',
197
            'view' => [
198
                'type' => 'widget',
199
                'widget' => 'Ecommerce\admin/contacts',
200
            ],
201
        ],
202
        //Менеджеры
203
        'extra' => ['type' => 'dataManager', 'relation' => 'extras'],
204
        'pay' => ['type' => 'dataManager', 'relation' => 'pays'],
205
        'items' => ['type' => 'dataManager', 'relation' => 'cartItems'],
206
        'info' => ['type' => 'dataManager', 'relation' => 'infos'],
207
        'deliveryInfo' => ['type' => 'dataManager', 'relation' => 'deliveryInfos'],
208
        'discount' => ['type' => 'dataManager', 'relation' => 'discounts'],
209
    ];
210
    public static $dataManagers = [
211
        'manager' => [
212
            'cols' => [
213
                'contacts',
214
                'items',
215
                'extra',
216
                'discount',
217
                'sums',
218
                'cart_status_id',
219
                'delivery_id',
220
                'deliveryInfo',
221
                'payed',
222
                'pay',
223
                'complete_data',
224
            ],
225
            'sortable' => [
226
                'cart_status_id',
227
                'delivery_id',
228
                'payed',
229
                'complete_data',
230
            ],
231
            'filters' => [
232
                'cart_status_id',
233
                'delivery_id',
234
                'payed',
235
                'complete_data',
236
            ],
237
            'preSort' => [
238
                'complete_data' => 'desc'
239
            ],
240
            'actions' => [
241
                'Ecommerce\CloseCartBtn', 'Open', 'Edit', 'Delete'
242
            ]
243
        ]
244
    ];
245
246
    public static function itemName($item) {
247
        return $item->pk() . '. ' . $item->name();
248
    }
249
250
    public static $forms = [
251
        'manager' => [
252
            'inputs' => [
253
                'userSearch' => [
254
                    'type' => 'search',
255
                    'source' => 'relation',
256
                    'relation' => 'user',
257
                    'label' => 'Покупатель',
258
                    'cols' => [
259
                        'info:first_name',
260
                        'info:last_name',
261
                        'info:middle_name',
262
                        'mail'
263
                    ],
264
                    'col' => 'user_id',
265
                    'required' => true,
266
                    'showCol' => [
267
                        'type' => 'staticMethod',
268
                        'class' => 'Ecommerce\Cart',
269
                        'method' => 'itemName',
270
                    ],
271
                ],
272
                'cardSearch' => [
273
                    'type' => 'search',
274
                    'source' => 'relation',
275
                    'relation' => 'card',
276
                    'label' => 'Дисконтная карта',
277
                    'cols' => [
278
                        'code',
279
                        'user:info:first_name',
280
                        'user:info:last_name',
281
                        'user:info:middle_name',
282
                        'user:mail'
283
                    ],
284
                    'col' => 'card_item_id',
285
                ],
286
            ],
287
            'map' => [
288
                ['userSearch', 'cart_status_id'],
289
                ['paytype_id', 'delivery_id'],
290
                ['cardSearch', 'comment'],
291
                ['warehouse_block', 'complete_data'],
292
                ['payed'],
293
                ['items'],
294
                ['extra'],
295
                ['pay'],
296
                ['info'],
297
                ['deliveryInfo']
298
            ]
299
        ],
300
    ];
301
302
    public function checkStage() {
303
        $sum = $this->itemsSum();
304
        $stages = Cart\Stage::getList(['order' => ['sum', 'asc']]);
305
        $groups = [];
306
        foreach ($stages as $stage) {
307
            if ($sum->greater(new \Money\Sums([$stage->currency_id => $stage->sum])) || $sum->equal(new \Money\Sums([$stage->currency_id => $stage->sum]))) {
308
                $groups[$stage->group] = $stage;
309
            }
310
        }
311
        $discounts = Cart\Discount::getList(['where' => ['cart_id', $this->id]]);
312
        foreach ($discounts as $discount) {
313
            if (!isset($groups[$discount->group]) && $discount->auto) {
314
                $discount->delete();
315
            }
316
            if (isset($groups[$discount->group]) && $groups[$discount->group]->type == 'discount') {
317
                $discount->discount_id = $groups[$discount->group]->value;
318
                $discount->save();
319
                unset($groups[$discount->group]);
320
            }
321
        }
322
        foreach ($groups as $group) {
323
            if ($group && $group->type == 'discount') {
324
                $rel = $this->addRelation('discounts', $group->value);
325
                $rel->auto = true;
326
                $rel->group = 'discount';
327
                $rel->save();
328
            }
329
        }
330
    }
331
332
    public function needDelivery() {
333
        foreach ($this->cartItems as $cartItem) {
334
            if ((!$cartItem->item->type && !empty(\App::$cur->ecommerce->config['defaultNeedDelivery'])) || ($cartItem->item->type && $cartItem->item->type->delivery)) {
335
                return true;
336
            }
337
        }
338
        return false;
339
    }
340
341
    public function deliverySum() {
342
        $sum = new \Money\Sums([0 => 0]);
343
        if ($this->delivery && $this->needDelivery()) {
344
            $sums = $this->itemsSum();
345
            $deliveryPrice = new \Money\Sums([$this->delivery->currency_id => $this->delivery->max_cart_price]);
346
            if ($this->delivery->max_cart_price && $sums->greater($deliveryPrice) || $sums->equal($deliveryPrice)) {
347
                $sum->sums = [$this->delivery->currency_id => 0];
348
            } else if ($this->delivery->prices) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->delivery->prices of type Ecommerce\Delivery\Price[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
349
                foreach ($this->delivery->prices(['order' => ['cart_price', 'asc']]) as $delPrice) {
350
                    $deliveryPrice = new \Money\Sums([$delPrice->currency_id => $delPrice->cart_price]);
351
                    if ($sums->greater($deliveryPrice) || $sums->equal($deliveryPrice)) {
352
                        $sum->sums = [$delPrice->currency_id => $delPrice->price];
353
                    }
354
                }
355
                if (!$sum->sums) {
356
                    $sum->sums = [$this->delivery->currency_id => $this->delivery->price];
357
                }
358
            } else {
359
                if (!$this->delivery->provider) {
0 ignored issues
show
Bug introduced by
The property provider does not seem to exist. Did you mean delivery_provider_id?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
360
                    $sum->sums = [$this->delivery->currency_id => $this->delivery->price];
361
                } else {
362
                    $className = 'Ecommerce\DeliveryProvider\\' . $this->delivery->provider->object;
0 ignored issues
show
Bug introduced by
The property provider does not seem to exist. Did you mean delivery_provider_id?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
363
                    $sum = $className::calcPrice($this);
364
                }
365
            }
366
        }
367
        return $sum;
368
    }
369
370
    public function hasDiscount() {
371
        return (bool) $this->card || $this->discounts;
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->discounts of type Ecommerce\Cart\Discount[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
372
    }
373
374
    public function discountSum() {
375
        $sums = [];
376
        foreach ($this->cartItems as $cartItem) {
377
            $sums[$cartItem->price->currency_id] = isset($sums[$cartItem->price->currency_id]) ? $sums[$cartItem->price->currency_id] + $cartItem->discount() * $cartItem->count : $cartItem->discount() * $cartItem->count;
378
        }
379
        return new \Money\Sums($sums);
380
    }
381
382
    public function finalSum() {
383
        $sums = $this->itemsSum();
384
        $sums = $sums->minus($this->discountSum());
385
        $sums = $sums->plus($this->deliverySum());
386
        return $sums;
387
    }
388
389
    public function itemsSum() {
390
        $cart = Cart::get($this->id);
391
        $sums = [];
392
        foreach ($cart->cartItems as $cartItem) {
393
            if (!$cartItem->price) {
394
                continue;
395
            }
396
            $sums[$cartItem->price->currency_id] = isset($sums[$cartItem->price->currency_id]) ? $sums[$cartItem->price->currency_id] + $cartItem->price->price * $cartItem->count : $cartItem->price->price * $cartItem->count;
397
        }
398
        return new \Money\Sums($sums);
399
    }
400
401
    public function checkPrices() {
402
        $change = false;
403
        foreach ($this->cartItems as $cartItem) {
404
            if ($cartItem->price && !$cartItem->price->checkUserAccess()) {
405
                $newPrice = $cartItem->price->offer->getPrice();
406
                $cartItem->item_offer_price_id = $newPrice->id;
407
                $cartItem->save();
408
                $cartItem->loadRelation('price');
409
                $change = true;
410
            }
411
        }
412
        return $change;
413
    }
414
415
    public function addItem($offer_price_id, $count = 1, $final_price = 0) {
416
        $price = Item\Offer\Price::get((int) $offer_price_id);
417
418
        if (!$price) {
419
            return false;
420
        }
421
422
        if ($count <= 0) {
423
            $count = 1;
424
        }
425
426
        $cartItem = new Cart\Item();
427
        $cartItem->cart_id = $this->id;
428
        $cartItem->item_id = $price->offer->item->id;
429
        $cartItem->count = $count;
430
        $cartItem->item_offer_price_id = $price->id;
431
        $cartItem->final_price = $final_price ? $final_price : $price->price;
432
        $cartItem->save();
433
        return true;
434
    }
435
436
    public function calc($save = true) {
437
        if ($save) {
438
            $this->save();
439
        }
440
    }
441
442
}
443