Stock.php 29.0 KB
Newer Older
_
__FresHmaN 已提交
1
<?php
S
Success Gao 已提交
2 3

/*
_
__FresHmaN 已提交
4 5 6 7 8 9 10 11 12
 * FecShop file.
 *
 * @link http://www.fecshop.com/
 * @copyright Copyright (c) 2016 FecShop Software LLC
 * @license http://www.fecshop.com/license/
 */

namespace fecshop\services\product;

13 14 15
//use fecshop\models\mongodb\Product;
//use fecshop\models\mysqldb\product\ProductFlatQty;
//use fecshop\models\mysqldb\product\ProductCustomOptionQty;
_
__FresHmaN 已提交
16 17 18 19
use fecshop\services\Service;
use Yii;

/**
S
Success Gao 已提交
20 21
 * Stock sub-service of product service.
 *
S
Success Gao 已提交
22 23
 * @method deduct($items = [])
 * @see \fecshop\services\product\Stock::actionDeduct()
S
Success Gao 已提交
24 25 26
 * @method productIsInStock($product, $qty, $custom_option_sku)
 * @see Stock::actionProductIsInStock()
 *
_
__FresHmaN 已提交
27 28 29 30 31
 * @author Terry Zhao <2358269014@qq.com>
 * @since 1.0
 */
class Stock extends Service
{
T
Terry 已提交
32
    // 零库存:也就是说库存忽略掉,产品的库存
T
Terry 已提交
33
    public $zeroInventory = false;
34

_
__FresHmaN 已提交
35 36
    // product model arr
    protected $_product_arr;
37

_
__FresHmaN 已提交
38 39
    // product items(譬如购物车信息)
    protected $_product_items;
40

_
__FresHmaN 已提交
41 42
    // 是否已经检查产品是否有库存。
    protected $_checkItemsStockStatus;
43

_
__FresHmaN 已提交
44
    //protected $CheckItemsStock
45
    
46
    protected $_flatQtyModelName = '\fecshop\models\mysqldb\product\ProductFlatQty';
47

48
    protected $_flatQtyModel;
49

50
    protected $_COQtyModelName = '\fecshop\models\mysqldb\product\ProductCustomOptionQty';
51

52 53
    protected $_COQtyModel;
    
S
Success Gao 已提交
54 55
    public function init()
    {
T
Terry 已提交
56
        parent::init();
S
Success Gao 已提交
57 58
        list($this->_flatQtyModelName, $this->_flatQtyModel) = \Yii::mapGet($this->_flatQtyModelName);
        list($this->_COQtyModelName, $this->_COQtyModel) = \Yii::mapGet($this->_COQtyModelName);
T
Terry 已提交
59 60 61 62
        $zeroInventory = Yii::$app->store->get('product','zeroInventory');
        if ($zeroInventory == Yii::$app->store->enable) {
            $this->zeroInventory = true;
        }
63
    }
64

T
Terry 已提交
65
    /**
T
Terry 已提交
66
     * @param $productIds | Array ,  字符串数组
S
Success Gao 已提交
67
     * @return  Array ,example
T
Terry 已提交
68 69 70
     * [
     *      'product_id'  => 'qty',
     * ]
71
     * 得到产品的主库存,对于Custom Option里面的库存,该函数无法获取。
T
Terry 已提交
72
     */
S
Success Gao 已提交
73 74 75
    public function getQtyByProductIds($productIds)
    {
        if (!is_array($productIds)) {
T
Terry 已提交
76 77 78
            Yii::$service->helper->errors->add('ProductIds must be Array');
            return false;
        }
T
Terry 已提交
79
        $data = $this->_flatQtyModel->find()->asArray()->where([
T
Terry 已提交
80 81 82
            'in','product_id',$productIds
        ])->all();
        $arr = [];
S
Success Gao 已提交
83 84
        foreach ($data as $one) {
            $arr[$one['product_id']] = $one['qty'];
T
Terry 已提交
85 86 87
        }
        return $arr;
    }
88 89
    
    /**
T
Terry 已提交
90 91
     *  @param $product_id | String , mongodb中的产品id字符串
     *  @param $one | Array , data example:
92 93 94 95 96 97 98 99 100 101 102
     *  $one = [
     *      'qty'           => 44,  # sku的库存个数
     *      'custom_option' => [
     *          'red-s-s2-s3' => [
     *               'qty' => 44,
     *           ] # 淘宝模式的sku的库存格式,red-s-s2-s3代表自定义属性sku
     *      ]
     *  ]
     *  由于存在淘宝和京东模式,因此库存有两种,对于单个产品,只有一种是有效的,
     *  对于产品的淘宝和京东模式,可以参看文档:http://www.fecshop.com/doc/fecshop-guide/instructions/cn-1.0/guide-fecshop_product.html#
     */
S
Success Gao 已提交
103 104 105
    public function saveProductStock($product_id, $one)
    {
        if (!$product_id) {
106 107
            Yii::$service->helper->errors->add('save product qty error: product is empty');
        }
S
Success Gao 已提交
108
        if (!isset($one['qty'])) {
109 110
            Yii::$service->helper->errors->add('save product qty error: product qty is empty');
        }
T
Terry 已提交
111
        
112
        // 保存自定义部分的qty
S
Success Gao 已提交
113
        if (is_array($one['custom_option']) && !empty($one['custom_option'])) {
T
Terry 已提交
114
            $custom_option_qty = 0;
115 116 117
            //得到所有的产品custom option qty数据
            $co_sku_arr = $this->getProductCustomOptionSkuArr($product_id);
            $product_sku_arr = [];
S
Success Gao 已提交
118
            foreach ($one['custom_option'] as $custom_option_sku => $c_one) {
T
Terry 已提交
119
                $productCustomOptionQty = $this->_COQtyModel->find()
120 121 122 123 124 125
                    ->where([
                        'product_id' => $product_id,
                        'custom_option_sku' => $custom_option_sku,
                    ])
                    ->one();
                $product_sku_arr[] = $custom_option_sku;
S
Success Gao 已提交
126
                if (!$productCustomOptionQty['product_id']) {
127
                    $productCustomOptionQty = new $this->_COQtyModelName;
128 129 130 131
                    $productCustomOptionQty->product_id = $product_id;
                    $productCustomOptionQty->custom_option_sku = $custom_option_sku;
                }
                $productCustomOptionQty->qty = $c_one['qty'];
T
Terry 已提交
132
                $custom_option_qty += $c_one['qty'];
133 134
                $productCustomOptionQty->save();
            }
T
Terry 已提交
135 136
            // 如果是custom option,主库存 = 各个custom option 的库存的相加和
            $one['qty'] = $custom_option_qty;
S
Success Gao 已提交
137
            $delete_sku_arr = array_diff($co_sku_arr, $product_sku_arr);
138 139
            //var_dump($delete_sku_arr);
            // 删除掉产品中不存在customOptionSku对应的库存、
S
Success Gao 已提交
140
            if (!empty($delete_sku_arr) && is_array($delete_sku_arr)) {
T
Terry 已提交
141
                $this->_COQtyModel->deleteAll([
142 143 144 145 146 147
                    'and',
                    ['product_id' => $product_id],
                    ['in','custom_option_sku',$delete_sku_arr]
                ]);
            }
        }
T
Terry 已提交
148 149 150 151
        // 保存产品flat qty
        $productFlatQty = $this->_flatQtyModel->find()
            ->where(['product_id' => $product_id])
            ->one();
S
Success Gao 已提交
152
        if (!$productFlatQty['product_id']) {
T
Terry 已提交
153 154 155 156 157
            $productFlatQty = new $this->_flatQtyModelName;
            $productFlatQty->product_id = $product_id;
        }
        $productFlatQty->qty = $one['qty'];
        $productFlatQty->save();
158 159
        return true;
    }
160

161
    /**
T
Terry 已提交
162
     *  @param $product_id | String , mongodb中的产品id字符串
163 164
     *  产品做删除的时候,需要在mysql中删除掉库存
     */
S
Success Gao 已提交
165 166 167
    public function removeProductStock($product_id)
    {
        if (!$product_id) {
168 169 170
            Yii::$service->helper->errors->add('remove product qty error: product is empty');
        }
        // 保存产品flat qty
T
Terry 已提交
171
        $this->_flatQtyModel->deleteAll(['product_id' => $product_id]);
T
Terry 已提交
172
        $this->_COQtyModel->deleteAll(['product_id' => $product_id]);
173 174 175
        return true;
    }
    
_
__FresHmaN 已提交
176
    /**
S
Success Gao 已提交
177 178
     * @var array $items
     * example:
_
__FresHmaN 已提交
179 180
     * 	[
     *		[
181
     *			'product_id' => 'xxxxx',
_
__FresHmaN 已提交
182
     *			'qty' => 2,
T
Terry 已提交
183
     *          'name' => 'xxxx',
_
__FresHmaN 已提交
184 185 186
     *			'custom_option_sku' => 'cos_1',  # 存在该项,则应该到产品的
     *		],
     *		[
187
     *			'product_id' => 'yyyyy',
T
Terry 已提交
188
     *          'name' => 'xxxx',
_
__FresHmaN 已提交
189 190 191
     *			'qty' => 1,
     *		],
     *	]
192 193 194 195 196
     *  @return bool
     *  扣除产品库存。如果扣除成功,则返回true,如果返回失败,则返回false
     *
     *  **注意**:在调用该函数的时候必须使用事务,在返回false的时候要回滚。
     *  **注意**:在调用该函数的时候必须使用事务,在返回false的时候要回滚。
S
Success Gao 已提交
197
     *  **注意**:在调用该函数的时候必须使用事务,在返回false的时候要回滚。
_
__FresHmaN 已提交
198
     */
S
Success Gao 已提交
199
    protected function actionDeduct($items = [])
_
__FresHmaN 已提交
200
    {
S
Success Gao 已提交
201 202
        if (!$items) {
            // 如果 $items 为空,则去购物车取数据。
203
            $cartInfo = Yii::$service->cart->getCartInfo(true);
S
Success Gao 已提交
204
            $items = isset($cartInfo['products']) ? $cartInfo['products'] : [];
_
__FresHmaN 已提交
205
        }
T
Terry 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
        // 如果items为空,则返回
        if (!is_array($items) || empty($items)) {
            Yii::$service->helper->errors->add('cart products is empty');
            return false;
        }    
        // 查看产品的状态,上下架状态,以及产品库存检查是否够用。
        foreach ($items as $k=>$item) {
            $product_id        = $item['product_id'];
            $sale_qty           = (int)$item['qty'];
            $custom_option_sku  = $item['custom_option_sku'];
            $product = Yii::$service->product->getByPrimaryKey($product_id);
            // 购物车中的产品已经被删除,则会查询不到
            if (!$product['sku']) {
                Yii::$service->helper->errors->add('product: [ {product_id} ] is not exist', ['product_id' => $product_id]);
                return false;
            } 
            $status = $this->productIsInStock($product, $sale_qty, $custom_option_sku);
            if (!$status) {
                return false;
            }
        } 
T
Terry 已提交
227 228 229 230
        /**
         * $this->checkItemsStock 函数检查产品是否都是上架状态
         * 如果满足上架状态 && 零库存为1,则直接返回。
         */
T
Terry 已提交
231 232
        if ($this->zeroInventory) {
            return true; // 零库存模式 不会更新产品库存。
T
Terry 已提交
233
        }
234
        
_
__FresHmaN 已提交
235
        // 开始扣除库存。
T
Terry 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
        foreach ($items as $k=>$item) {
            $product_id         = $item['product_id'];
            $sale_qty           = (int)$item['qty'];
            $product_name       = Yii::$service->store->getStoreAttrVal($item['product_name'], 'name');
            $custom_option_sku  = $item['custom_option_sku'];
            if ($product_id && $sale_qty) {
                // 应对高并发库存超卖的控制,扣除库存的时候,加上qty个数的查询,不满足查询条件则不扣除库存
                $updateColumns = $this->_flatQtyModel->updateAllCounters(
                    ['qty' => 0 - $sale_qty],
                    ['and', ['product_id' => $product_id], ['>=', 'qty', $sale_qty]]
                );
                if (empty($updateColumns)) {// 上面更新sql返回的更新行数如果为0,则说明更新失败,产品不存在,或者产品库存不够
                    Yii::$service->helper->errors->add('product: [ {product_name} ] is stock out', ['product_name' => $product_name]);
                    return false;
                }
                // 对于custom option(淘宝模式)的库存扣除
                if ($custom_option_sku) {
                    $updateColumns = $this->_COQtyModel->updateAllCounters(
                        ['qty' => 0 - $sale_qty],
                        [
                            'and',
                            [
                                'custom_option_sku' => $custom_option_sku,
                                'product_id'        => $product_id
                            ],
                            ['>=','qty',$sale_qty]
                        ]
T
Terry 已提交
263 264
                    );
                    if (empty($updateColumns)) {// 上面更新sql返回的更新行数如果为0,则说明更新失败,产品不存在,或者产品库存不够
S
Success Gao 已提交
265
                        Yii::$service->helper->errors->add('product: [ {product_name} ] is stock out', ['product_name' => $product_name]);
T
Terry 已提交
266 267
                        return false;
                    }
T
Terry 已提交
268 269 270 271 272 273 274
                }
            }
        }
        
        return true;
    }
    
T
Terry 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
    
    /**
     * @var array $items
     * example:
     * [
     *		[
     *			'sku' => '22221',
     *			'qty' => 2,
     *			'custom_option_sku' => 'black-s',  # 存在该项,则应该到产品的
     *		],
     *		[
     *			'sku' => 'op0002',
     *			'qty' => -1,
     *		],
     *	]
     *  @return bool
     *  通过累加和累减的方式更新产品库存,通过累加和累减的方式如果扣除成功,则返回true,如果返回失败,则返回false
     *  如果库存为正数,则累加,如果库存为负数,则累减。
     *  一般是api的方式更新库存。  
     *
     *  **注意**:在调用该函数的时候必须使用事务,在返回false的时候要回滚。
     *  **注意**:在调用该函数的时候必须使用事务,在返回false的时候要回滚。
     *  **注意**:在调用该函数的时候必须使用事务,在返回false的时候要回滚。
     */
    protected function actionUpdatebybase($items = [])
    {
        if (empty($items) || !is_array($items)) {
            Yii::$service->helper->errors->add('param items is not array or is empty');
            
            return false;
        }
        
        
        // 查看产品的状态,上下架状态,以及产品库存检查是否够用。
        foreach ($items as $k=>$item) {
            $sku        = $item['sku'];
            $sale_qty           = (int)$item['qty'];
            $custom_option_sku  = $item['custom_option_sku'];
            $product = Yii::$service->product->getBySku($sku);
            // 购物车中的产品已经被删除,则会查询不到
            if (!$product['sku']) {
                Yii::$service->helper->errors->add('product: [ {sku} ] is not exist', ['sku' => $sku]);
                
                return false;
            } 
            $status = $this->productIsInStock($product, $sale_qty, $custom_option_sku, false);
            if (!$status) {
                
                return false;
            }
            $primaryKey = Yii::$service->product->getPrimaryKey();
            $items[$k]['product_id'] = (string)$product[$primaryKey];
            
            
        } 
        
        /**
         * $this->checkItemsStock 函数检查产品是否都是上架状态
         * 如果满足上架状态 && 零库存为1,则直接返回。
         */
        if ($this->zeroInventory) {
            
            return true; // 零库存模式 不会更新产品库存。
        }
        
        // 开始扣除库存。
        foreach ($items as $k=>$item) {
            $sku         = $item['sku'];
            $product_id         = $item['product_id'];
            $sale_qty           = (int)$item['qty'];
            $custom_option_sku  = $item['custom_option_sku'];
            if ($product_id && $sale_qty) {
                // 应对高并发库存超卖的控制,扣除库存的时候,加上qty个数的查询,不满足查询条件则不扣除库存
                
                $updateColumns = $this->_flatQtyModel->updateAllCounters(
                    ['qty' => $sale_qty],
                    ['and', ['product_id' => $product_id], ['>=', 'qty', 0 - $sale_qty]]
                );
                
                if (empty($updateColumns)) {// 上面更新sql返回的更新行数如果为0,则说明更新失败,产品不存在,或者产品库存不够
                    Yii::$service->helper->errors->add('product: [ {sku} ] is stock out', ['sku' => $sku]);
                    
                    return false;
                }
                // 对于custom option(淘宝模式)的库存扣除
                if ($custom_option_sku) {
                    $updateColumns = $this->_COQtyModel->updateAllCounters(
                        ['qty' => $sale_qty],
                        [
                            'and',
                            [
                                'custom_option_sku' => $custom_option_sku,
                                'product_id'        => $product_id
                            ],
                            ['>=', 'qty', 0 - $sale_qty]
                        ]
                    );
                    if (empty($updateColumns)) {// 上面更新sql返回的更新行数如果为0,则说明更新失败,产品不存在,或者产品库存不够
                        Yii::$service->helper->errors->add('product: [ {sku} ] is stock out', ['sku' => $sku]);
                        
                        return false;
                    }
                }
            }
        }
        
        return true;
    }
    
T
Terry 已提交
384
    /**
T
Terry 已提交
385
     * @param $product_items | Array , example:
T
Terry 已提交
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
     * 	[
     *		[
     *			'product_id' => 'xxxxx',
     *			'qty' => 2,
     *			'custom_option_sku' => 'cos_1',  # 存在该项,则应该到产品的
     *		],
     *		[
     *			'product_id' => 'yyyyy',
     *			'qty' => 1,
     *		],
     *	]
     * @return bool
     *              返还产品库存。如果在返还过程中产品不存在,也不会返回false
     */
    protected function actionReturnQty($product_items)
    {
        if ($this->zeroInventory) {
            return true; // 零库存模式不扣产品库存,也不需要返还库存。
        }
        // 开始扣除库存。
        if (is_array($product_items) && !empty($product_items)) {
            foreach ($product_items as $k=>$item) {
                $product_id         = $item['product_id'];
                $sale_qty           = $item['qty'];
                $custom_option_sku  = $item['custom_option_sku'];
                if ($product_id && $sale_qty) {
                    $updateColumns = $this->_flatQtyModel->updateAllCounters(['qty' => $sale_qty], ['product_id' => $product_id]);
S
Success Gao 已提交
413
                    if ($custom_option_sku) {
T
Terry 已提交
414 415 416 417 418 419 420 421 422 423 424
                        // 对于custom option(淘宝模式)的库存扣除
                        $updateColumns = $this->_COQtyModel->updateAllCounters(['qty' => $sale_qty], ['product_id' => $product_id,'custom_option_sku' => $custom_option_sku]);
                    }
                }
            }
        }

        return true;
    }

    /**
T
Terry 已提交
425 426 427
     * @param $product | Object,  Product Model
     * @param $sale_qty | Int 需要出售的个数
     * @param $custom_option_sku | String 产品custom option sku
428
     * @param $checkDbQty | boolean, 是否检查商品库存?如果为false,则不对库存进行检查。
T
Terry 已提交
429 430 431
     * @return bool
     *  查看产品库存
     */
T
Terry 已提交
432
    protected function actionProductIsInStock($product, $sale_qty, $custom_option_sku, $checkDbQty = true)
T
Terry 已提交
433
    {
T
Terry 已提交
434
        $productPrimaryKey = Yii::$service->product->getPrimaryKey();
T
Terry 已提交
435
        $is_in_stock = $product['is_in_stock'];
T
Terry 已提交
436
        $product_id = $product[$productPrimaryKey];
T
Terry 已提交
437 438 439 440
        $product_name       = Yii::$service->store->getStoreAttrVal($product['name'], 'name');
        // 查看产品状态(产品如果disabled,则意味产品被清除)
        if ($product['status'] != Yii::$service->product->getEnableStatus()) {
            Yii::$service->helper->errors->add('product: [ {product_name} ] status is not active', ['product_name' => $product_name]);
T
Terry 已提交
441
            
T
Terry 已提交
442 443 444 445
            return false;
        }
        // 零库存模式 && 产品是上架状态 直接返回true
        if ($this->zeroInventory && $this->checkOnShelfStatus($is_in_stock)) {
T
Terry 已提交
446
            
T
Terry 已提交
447 448 449
            return true; // 零库存模式不扣产品库存,也不需要返还库存。
        }
        // 查看产品的上下架状态
T
Terry 已提交
450
        if (!$this->checkOnShelfStatus($is_in_stock)) {
T
Terry 已提交
451 452
            Yii::$service->helper->errors->add(
                'Product Id: {product_id}, The product has off the shelf',
453
                ['product_id' => $product[$productPrimaryKey]]
T
Terry 已提交
454
            );
T
Terry 已提交
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
            
            return false;
        }
        // 如果不检查数据库里面的库存,那么直接返回true
        if (!$checkDbQty) {
            
            return true;
        }
        if ($custom_option_sku) {
            $productCustomOptionQty = $this->_COQtyModel->find()->where([
                'product_id'        => $product_id,
                'custom_option_sku' => $custom_option_sku
            ])->one();
            if (!$productCustomOptionQty['qty']) {
                Yii::$service->helper->errors->add('product: [ {product_name} ] is stock out', ['product_name' => $product_name]);
                
                return false;
            }
            if ($productCustomOptionQty['qty'] < $sale_qty) {
                Yii::$service->helper->errors->add('product: [ {product_name} ] is stock out', ['product_name' => $product_name]);
                
                return false;
            }
        } else {
            $productFlatQty = $this->_flatQtyModel->find()->where([
                'product_id' => $product_id
            ])->one();
482
            
T
Terry 已提交
483
            if (!$productFlatQty['qty']) {
T
Terry 已提交
484
                $productName = Yii::$service->store->getStoreAttrVal($product['name'], 'name');
T
Terry 已提交
485
                Yii::$service->helper->errors->add(
T
stock  
Terry 已提交
486
                    'Product Name: {product_name} , The product is not in stock',
T
Terry 已提交
487
                    ['product_name' => $productName]
T
Terry 已提交
488 489 490 491 492 493 494
                );
                
                return false;
            }    
            if ($productFlatQty['qty'] < $sale_qty) {
                Yii::$service->helper->errors->add(
                        'Product Id: {product_id}, Product inventory is less than [{sale_qty}]',
495
                        ['product_id' => $product[$productPrimaryKey], 'sale_qty' => $sale_qty]
T
Terry 已提交
496 497 498
                    );
                return false;
            }
_
__FresHmaN 已提交
499
        }
500
 
T
Terry 已提交
501
        return true;
_
__FresHmaN 已提交
502
    }
T
Terry 已提交
503
    
T
Terry 已提交
504
    
T
Terry 已提交
505
    /**
T
Terry 已提交
506
     * @param $items | Array , example:
T
Terry 已提交
507 508 509 510 511 512 513 514 515 516 517
     * 	[
     *		[
     *			'product_id' => 'xxxxx',
     *			'qty' => 2,
     *			'custom_option_sku' => 'cos_1',  # 存在该项,则应该到产品的
     *		],
     *		[
     *			'product_id' => 'yyyyy',
     *			'qty' => 1,
     *		],
     *	]
T
Terry 已提交
518
     *  @return Mix 有库存返回的数据格式如下:
T
Terry 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
     *    [
     *        'stockStatus'           => 1,
     *        'outStockProducts'    => '',
     *    ];
     *    无库存返回的数据格式,2代表库存返回失败
     *    [
     *        'stockStatus'           => 2,
     *         库存不足的产品数组。
     *        'outStockProducts'    => [
     *            [
     *                'product_id'        => $product_id,
     *                'custom_option_sku' => '',
     *                'stock_qty'         => 0,
     *           ],
     *            [
     *                'product_id'        => $product_id,
     *                'custom_option_sku' => $custom_option_sku,
     *                'stock_qty'         => $productCustomOptionM['qty'],
     *            ],
S
Success Gao 已提交
538
     *
T
Terry 已提交
539 540
     *        ],
     *    ];
T
Terry 已提交
541
     *    购物车没有产品返回null
T
Terry 已提交
542 543 544 545
     *
     */
    protected function actionCheckItemsQty()
    {
546
        $cartInfo = Yii::$service->cart->getCartInfo(true);
T
Terry 已提交
547 548 549 550 551
        $items = isset($cartInfo['products']) ? $cartInfo['products'] : '';
        $outStockProducts = [];
        // 开始扣除库存。
        if (is_array($items) && !empty($items)) {
            foreach ($items as $k=>$item) {
T
Terry 已提交
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
                $product_id               = $item['product_id'];
                $item_product_name  = $item['product_name'];
                $sale_qty                  = (int)$item['qty'];
                $custom_option_sku   = $item['custom_option_sku'];
                $product = Yii::$service->product->getByPrimaryKey($product_id);
                // 产品是否存在判断
                if (!$product['sku']) {
                    $outStockProducts[] = [
                        'product_id'        => $product_id,
                        'product_name'      => $item_product_name,
                        'custom_option_sku' => $custom_option_sku,
                        'stock_qty'         => 0,
                    ];
                }
                $product_name       = Yii::$service->store->getStoreAttrVal($product['name'], 'name');
                $is_in_stock            = $product['is_in_stock'];
                // 查看产品状态(产品如果disabled,则意味产品被清除)
                if ($product['status'] != Yii::$service->product->getEnableStatus()) {
                    $outStockProducts[] = [
                        'product_id'        => $product_id,
                        'product_name'      => $product_name,
                        'custom_option_sku' => $custom_option_sku,
                        'stock_qty'         => 0,
                    ];
                }
                // 零库存模式 && 产品是上架状态 不需要继续判断库存
                if ($this->zeroInventory && $this->checkOnShelfStatus($is_in_stock)) {
                    continue;
                }
                // 产品的个数判断
T
Terry 已提交
582
                if ($product_id && $sale_qty) {
S
Success Gao 已提交
583
                    if (!$custom_option_sku) {
T
Terry 已提交
584
                        $productM = $this->_flatQtyModel->find()->where([
T
Terry 已提交
585 586 587
                            'product_id' => $product_id
                        ])->one();

S
Success Gao 已提交
588
                        if ($productM['qty']) {
T
Terry 已提交
589
                            //echo $productM['qty'].'####'.$sale_qty.'<br>';
S
Success Gao 已提交
590
                            if ($productM['qty'] < $sale_qty) {
T
Terry 已提交
591 592 593 594 595 596 597
                                $outStockProducts[] = [
                                    'product_id'        => $product_id,
                                    'custom_option_sku' => '',
                                    'product_name'      => $product_name,
                                    'stock_qty'         => $productM['qty'],
                                ];
                            }
S
Success Gao 已提交
598
                        } else {
T
Terry 已提交
599 600 601 602 603 604 605
                            $outStockProducts[] = [
                                'product_id'        => $product_id,
                                'custom_option_sku' => '',
                                'product_name'      => $product_name,
                                'stock_qty'         => 0,
                            ];
                        }
S
Success Gao 已提交
606
                    } else {
T
Terry 已提交
607
                        $productCustomOptionM = $this->_COQtyModel->find()->where([
T
Terry 已提交
608 609 610 611
                            'product_id'        => $product_id,
                            'custom_option_sku' => $custom_option_sku,
                        ])->one();
                        
S
Success Gao 已提交
612 613
                        if ($productCustomOptionM['qty']) {
                            if ($productCustomOptionM['qty'] < $sale_qty) {
T
Terry 已提交
614 615 616 617 618 619 620
                                $outStockProducts[] = [
                                    'product_id'        => $product_id,
                                    'custom_option_sku' => $custom_option_sku,
                                    'product_name'      => $product_name,
                                    'stock_qty'         => $productCustomOptionM['qty'],
                                ];
                            }
S
Success Gao 已提交
621
                        } else {
T
Terry 已提交
622 623 624 625 626 627 628 629 630 631
                            $outStockProducts[] = [
                                'product_id'        => $product_id,
                                'product_name'      => $product_name,
                                'custom_option_sku' => $custom_option_sku,
                                'stock_qty'         => 0,
                            ];
                        }
                    }
                }
            }
S
Success Gao 已提交
632
            if (empty($outStockProducts)) {
T
Terry 已提交
633 634 635
                return [
                    'stockStatus'           => 1,
                    'outStockProducts'    => '',
S
Success Gao 已提交
636 637
                ];
            } else {
T
Terry 已提交
638 639 640 641 642
                return [
                    'stockStatus'           => 2,
                    'outStockProducts'    => $outStockProducts,
                ];
            }
S
Success Gao 已提交
643
        } else {
T
Terry 已提交
644
            Yii::$service->helper->errors->add('cart products is empty');
T
Terry 已提交
645
            return null;
T
Terry 已提交
646 647
        }
    }
648

T
Terry 已提交
649
    
_
__FresHmaN 已提交
650 651

    /**
T
Terry 已提交
652
     * @param $is_in_stock | Int,  状态
_
__FresHmaN 已提交
653 654 655 656 657
     * @return bool
     *              检查产品是否是上架上台
     */
    protected function actionCheckOnShelfStatus($is_in_stock)
    {
T
Terry 已提交
658
        if ($is_in_stock === 1) {
_
__FresHmaN 已提交
659 660 661 662 663
            return true;
        }

        return false;
    }
664 665
    
    /**
T
Terry 已提交
666
     * @param $product_id | String
667 668
     * 得到产品的库存个数(Flat Qty)
     */
S
Success Gao 已提交
669 670
    public function getProductFlatQty($product_id)
    {
T
Terry 已提交
671
        $productFlatQty = $this->_flatQtyModel->find()->asArray()
672 673 674
            ->where([
                'product_id' => $product_id
            ])->one();
S
Success Gao 已提交
675
        if (isset($productFlatQty['qty'])) {
676
            return $productFlatQty['qty'] ? $productFlatQty['qty'] : 0;
S
Success Gao 已提交
677
        } else {
678 679 680 681 682
            return 0;
        }
    }
    
    /**
T
Terry 已提交
683 684
     * @param $product_id | String
     * @param $onlySku | boolean  返回数组是否只有 $custom_option_sku
685 686
     * 得到产品的custom option 部分的库存
     */
S
Success Gao 已提交
687 688
    public function getProductCustomOptionQty($product_id, $onlySku=false)
    {
T
Terry 已提交
689
        $arr = $this->_COQtyModel->find()->asArray()
690 691 692 693
            ->where([
                'product_id' => $product_id
            ])->all();
        $r_arr = [];
S
Success Gao 已提交
694 695
        if (is_array($arr)) {
            foreach ($arr as $one) {
696 697 698 699 700 701 702 703
                $custom_option_sku = $one['custom_option_sku'];
                $qty = $one['qty'];
                $r_arr[$custom_option_sku] = $qty;
            }
        }
        
        return $r_arr;
    }
704

705
    /**
T
Terry 已提交
706
     * @param $product_id | String
707 708
     * 得到产品的所有custom_option_sku 数组
     */
S
Success Gao 已提交
709 710
    public function getProductCustomOptionSkuArr($product_id)
    {
T
Terry 已提交
711
        $arr = $this->_COQtyModel->find()->asArray()
712 713 714 715
            ->where([
                'product_id' => $product_id
            ])->all();
        $sku_arr = [];
S
Success Gao 已提交
716 717
        if (is_array($arr)) {
            foreach ($arr as $one) {
718 719 720 721 722 723 724
                $sku_arr[] = $one['custom_option_sku'];
            }
        }
        return $sku_arr;
    }
    
    /**
T
Terry 已提交
725
     * @param $product_id | String
726 727
     * 得到产品的custom option 部分,相应的$custom_option_sku的库存
     */
S
Success Gao 已提交
728 729
    public function getProductCustomOptionSkuQty($product_id, $custom_option_sku)
    {
T
Terry 已提交
730
        $productCustomOptionQty = $this->_COQtyModel->find()->asArray()
731 732 733 734
            ->where([
                'product_id' => $product_id,
                'custom_option_sku' => $custom_option_sku
            ])->one();
S
Success Gao 已提交
735
        if (isset($productCustomOptionQty['qty'])) {
736
            return $productCustomOptionQty['qty'];
S
Success Gao 已提交
737
        } else {
738 739 740
            return 0;
        }
    }
_
__FresHmaN 已提交
741
}