123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- <?php
- /*
- * FecShop file.
- *
- * @link http://www.fecshop.com/
- * @copyright Copyright (c) 2016 FecShop Software LLC
- * @license http://www.fecshop.com/license/
- */
- namespace fecshop\services\cart;
- use fecshop\services\Service;
- use Yii;
- /**
- * Cart services. 对购物车产品操作的具体实现部分。
- * @author Terry Zhao <2358269014@qq.com>
- * @since 1.0
- */
- class QuoteItem extends Service
- {
- public $itemDefaultActiveStatus = 1;
- public $activeStatus = 1;
- public $noActiveStatus = 2;
-
- protected $_my_cart_item; // 购物车cart item 对象
- protected $_cart_product_info;
-
- protected $_itemModelName = '\fecshop\models\mysqldb\cart\Item';
- /**
- * @var \fecshop\models\mysqldb\cart\Item
- */
- protected $_itemModel;
-
- public function init()
- {
- parent::init();
- list($this->_itemModelName, $this->_itemModel) = Yii::mapGet($this->_itemModelName);
- }
-
- /**
- * 将某个产品加入到购物车中。
- * 在添加到 cart_item 表后,更新购物车中产品的总数。
- * @param array $item
- * @return mixed
- * example:
- * $item = [
- * 'product_id' => 22222,
- * 'custom_option_sku' => red-xxl,
- * 'qty' => 22,
- * 'sku' => 'xxxx',
- * ];
- */
- public function addItem($item)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- if (!$cart_id) {
- Yii::$service->cart->quote->createCart();
- $cart_id = Yii::$service->cart->quote->getCartId();
- }
- // 查看是否存在此产品,如果存在,则相加个数
- if (!isset($item['product_id']) || empty($item['product_id'])) {
- Yii::$service->helper->errors->add('add to cart error, product id is empty');
- return false;
- }
- $where = [
- 'cart_id' => $cart_id,
- 'product_id' => $item['product_id'],
- ];
- if (isset($item['custom_option_sku']) && !empty($item['custom_option_sku'])) {
- $where['custom_option_sku'] = $item['custom_option_sku'];
- }
- if (isset($item['customsize']) && !empty($item['customsize'])) {
- $where['customsize'] = $item['customsize'];
- }
- /** @var \fecshop\models\mysqldb\cart\Item $item_one */
- $item_one = $this->_itemModel->find()->where($where)->one();
- if ($item_one['cart_id']) {
- $item_one->active = $this->itemDefaultActiveStatus;
- $item_one->qty = $item['qty'] + $item_one['qty'];
- $item_one->save();
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- } else {
- $item_one = new $this->_itemModelName;
- $item_one->store = Yii::$service->store->currentStore;
- $item_one->cart_id = $cart_id;
- $item_one->created_at = time();
- $item_one->updated_at = time();
- $item_one->product_id = $item['product_id'];
- $item_one->customsize = $item['customsize'];
- $item_one->qty = $item['qty'];
- $item_one->active = $this->itemDefaultActiveStatus;
- $item_one->custom_option_sku = ($item['custom_option_sku'] ? $item['custom_option_sku'] : '');
- $item_one->save();
- // 重新计算购物车的数量,并写入 sales_flat_cart 表存储
- Yii::$service->cart->quote->computeCartInfo();
- }
-
- $item['afterAddQty'] = $item_one->qty;
- $this->sendTraceAddToCartInfoByApi($item);
- return true;
- }
- /**
- * @param $item | Array, example:
- * $item = [
- * 'product_id' => 22222,
- * 'custom_option_sku' => red-xxl,
- * 'qty' => 22, // 添加购物车的产品个数
- * 'sku' => 'xxxx',
- * 'afterAddQty' => 33, // 添加后,该产品在sku中的个数,这个个数是为了计算购物车中产品的价格
- * ];
- * 将加入购物车的操作,加入trace
- */
- public function sendTraceAddToCartInfoByApi($item)
- {
- if (Yii::$service->page->trace->traceJsEnable) {
- $product_price_arr = Yii::$service->product->price->getCartPriceByProductId($item['product_id'], $item['afterAddQty'], $item['custom_option_sku'], 2);
- $base_product_price = isset($product_price_arr['base_price']) ? $product_price_arr['base_price'] : 0;
- // $price = $base_product_price * $item['qty'];
- $trace_cart_info = [
- [
- 'sku' => $item['sku'],
- 'price' => $base_product_price,
- 'qty' => $item['qty'],
- ]
- ];
- Yii::$service->page->trace->sendTraceAddToCartInfoByApi($trace_cart_info);
- }
- }
- /**
- * @param $item | Array, example:
- * $item = [
- * 'product_id' => 22222,
- * 'custom_option_sku' => red-xxl,
- * 'qty' => 22,
- * ];
- * @return boolean;
- * 将购物车中的某个产品更改个数,更改后的个数就是上面qty的值。
- * @deprecated 该函数已经被遗弃
- */
- /*
- public function changeItemQty($item)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- // 查看是否存在此产品,如果存在,则更改
- $item_one = $this->_itemModel->find()->where([
- 'cart_id' => $cart_id,
- 'product_id' => $item['product_id'],
- 'custom_option_sku' => $item['custom_option_sku'],
- ])->one();
- if ($item_one['cart_id']) {
- $item_one->qty = $item['qty'];
- $item_one->save();
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- return true;
- } else {
- Yii::$service->helper->errors->add('This product is not available in the shopping cart');
- return false;
- }
- }
- */
- /**
- * 通过quoteItem表,计算得到所有产品的总数
- * 得到购物车中产品的总数,不要使用这个函数,这个函数的作用:
- * 在购物车中产品有变动后,使用这个函数得到产品总数,更新购物车中
- * 的产品总数。
- */
- public function getItemAllQty()
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- $item_qty = 0;
- if ($cart_id) {
- $data = $this->_itemModel->find()->asArray()->where([
- 'cart_id' => $cart_id,
- ])->all();
- if (is_array($data) && !empty($data)) {
- foreach ($data as $one) {
- $item_qty += $one['qty'];
- }
- }
- }
- return $item_qty;
- }
-
- /**
- * 通过quoteItem表,计算得到所有产品的总数
- * 得到购物车中产品的总数,不要使用这个函数,这个函数的作用:
- * 在购物车中产品有变动后,使用这个函数得到产品总数,更新购物车中
- * 的产品总数。
- */
- public function getActiveItemQty()
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- $item_qty = 0;
- if ($cart_id) {
- $data = $this->_itemModel->find()->asArray()->where([
- 'cart_id' => $cart_id,
- 'active' => $this->activeStatus,
- ])->all();
- if (is_array($data) && !empty($data)) {
- foreach ($data as $one) {
- $item_qty += $one['qty'];
- }
- }
- }
- return $item_qty;
- }
- /**
- * @param $activeProduct | boolean , 是否只要active的产品
- * @return array , foramt:
- * [
- * 'products' => $products, # 产品详细信息,详情参看代码中的$products。
- * 'product_total' => $product_total, # 产品的当前货币总额
- * 'base_product_total' => $base_product_total,# 产品的基础货币总额
- * 'product_weight'=> $product_weight, # 蟾皮的总重量、
- * ]
- * 得到当前购物车的产品信息,具体参看上面的example array。
- */
- public function getCartProductInfo($activeProduct = true)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- $products = [];
- $product_total = 0;
- $product_weight = 0;
- $product_volume_weight = 0;
- $base_product_total = 0;
- $product_volume = 0;
- $product_qty_total = 0;
- if ($cart_id) {
- if (!isset($this->_cart_product_info[$cart_id])) {
- $data = $this->_itemModel->find()->where([
- 'cart_id' => $cart_id,
- ])->all();
- if (is_array($data) && !empty($data)) {
- foreach ($data as $one) {
- $active = $one['active'];
- if ($activeProduct && ($active != $this->activeStatus)) {
- continue;
- }
- $product_id = $one['product_id'];
- $product_one = Yii::$service->product->getByPrimaryKey($product_id);
- if ($product_one['_id']) {
- $qty = $one['qty'];
-
- $custom_option_sku = $one['custom_option_sku'];
- $customsize = $one['customsize'];
- $product_price_arr = Yii::$service->product->price->getCartPriceByProductId($product_id, $qty, $custom_option_sku, 2);
- $curr_product_price = isset($product_price_arr['curr_price']) ? $product_price_arr['curr_price'] : 0;
- $base_product_price = isset($product_price_arr['base_price']) ? $product_price_arr['base_price'] : 0;
- $product_price = isset($curr_product_price['value']) ? $curr_product_price['value'] : 0;
- $product_row_price = $product_price * $qty;
- $base_product_row_price = $base_product_price * $qty;
-
- $volume = Yii::$service->shipping->getVolume($product_one['long'], $product_one['width'], $product_one['high']);
- $p_pv = $volume * $qty;
- $p_wt = $product_one['weight'] * $qty;
- $p_vwt = $product_one['volume_weight'] * $qty;
-
- if ($active == $this->activeStatus) {
- $product_total += $product_row_price;
- $base_product_total += $base_product_row_price;
- $product_weight += $p_wt;
- $product_volume_weight += $p_vwt;
- $product_volume += $p_pv;
- $product_qty_total += $qty;
- }
- $productSpuOptions = $this->getProductSpuOptions($product_one);
- $products[] = [
- 'item_id' => $one['item_id'],
- 'active' => $active,
- 'product_id' => $product_id,
- 'sku' => $product_one['sku'],
- 'name' => Yii::$service->store->getStoreAttrVal($product_one['name'], 'name'),
- 'qty' => $qty,
- 'custom_option_sku' => $custom_option_sku,
- 'customsize' => $customsize,
- 'product_price' => $product_price,
- 'product_row_price' => $product_row_price,
- 'base_product_price' => $base_product_price,
- 'base_product_row_price'=> $base_product_row_price,
- 'product_name' => $product_one['name'],
- 'product_weight' => $product_one['weight'],
- 'product_row_weight'=> $p_wt,
- 'product_volume_weight' => $product_one['volume_weight'],
- 'product_row_volume_weight' => $p_vwt,
- 'product_volume' => $volume,
- 'product_row_volume' => $p_pv,
- 'product_url' => $product_one['url_key'],
- 'product_image' => $product_one['image'],
- 'custom_option' => $product_one['custom_option'],
- 'spu_options' => $productSpuOptions,
- ];
- }
- }
- $this->_cart_product_info[$cart_id] = [
- 'products' => $products,
- 'product_qty_total' => $product_qty_total,
- 'product_total' => $product_total,
- 'base_product_total' => $base_product_total,
- 'product_weight' => $product_weight,
- 'product_volume_weight' => $product_volume_weight,
- 'product_volume' => $product_volume,
-
- ];
- }
- }
- return $this->_cart_product_info[$cart_id];
- }
- }
- /**
- * @param $productOb | Object,类型:\fecshop\models\mongodb\Product
- * 得到产品的spu对应的属性以及值。
- * 概念 - spu options:当多个产品是同一个spu,但是不同的sku的时候,他们的产品表里面的
- * spu attr 的值是不同的,譬如对应鞋子,size 和 color 就是spu attr,对于同一款鞋子,他们
- * 是同一个spu,对于尺码,颜色不同的鞋子,是不同的sku,他们的spu attr 就是 color 和 size。
- */
- protected function getProductSpuOptions($productOb)
- {
- $custom_option_info_arr = [];
- if (isset($productOb['attr_group']) && !empty($productOb['attr_group'])) {
- $productAttrGroup = $productOb['attr_group'];
- Yii::$service->product->addGroupAttrs($productAttrGroup);
- $productOb = Yii::$service->product->getByPrimaryKey((string) $productOb['_id']);
- $spuArr = Yii::$service->product->getSpuAttr($productAttrGroup);
- if (is_array($spuArr) && !empty($spuArr)) {
- foreach ($spuArr as $spu_attr) {
- if (isset($productOb[$spu_attr]) && !empty($productOb[$spu_attr])) {
- // 进行翻译。
- $spu_attr_label = Yii::$service->page->translate->__($spu_attr);
- $spu_attr_val = Yii::$service->page->translate->__($productOb[$spu_attr]);
- $custom_option_info_arr[$spu_attr_label] = $spu_attr_val;
- }
- }
- }
- }
- return $custom_option_info_arr;
- }
- /**
- * @param $item_id | Int , quoteItem表的id
- * @return bool
- * 将这个item_id对应的产品个数+1.
- */
- public function addOneItem($item_id)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- if ($cart_id) {
- $one = $this->_itemModel->find()->where([
- 'cart_id' => $cart_id,
- 'item_id' => $item_id,
- ])->one();
- $product_id = $one['product_id'];
- if ($one['item_id'] && $product_id) {
- $product = Yii::$service->product->getByPrimaryKey($product_id);
- $changeQty = Yii::$service->cart->getCartQty($product['package_number'], 1);
- $one['qty'] = $one['qty'] + $changeQty;
- $one->save();
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- $item = [
- 'product_id' => $product_id,
- 'custom_option_sku' => $one['custom_option_sku'],
- 'qty' => $changeQty,
- 'sku' => $product['sku'],
- 'afterAddQty' => $one['qty'],
- ];
- // 购物车数据加1
- $this->sendTraceAddToCartInfoByApi($item);
- return true;
- }
- }
- return false;
- }
- /**
- * @param $item_id | Int , quoteItem表的id
- * @return bool
- * 将这个item_id对应的产品个数-1.
- */
- public function lessOneItem($item_id)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- if ($cart_id) {
- $one = $this->_itemModel->find()->where([
- 'cart_id' => $cart_id,
- 'item_id' => $item_id,
- ])->one();
- $product_id = $one['product_id'];
- $product = Yii::$service->product->getByPrimaryKey($one['product_id']);
- $changeQty = Yii::$service->cart->getCartQty($product['package_number'], 1);
- $lessedQty = $one['qty'] - $changeQty;
- $min_sales_qty = 1;
- if ($product['min_sales_qty'] && $product['min_sales_qty'] >= 2) {
- $min_sales_qty = $product['min_sales_qty'];
- }
- if ($lessedQty < $min_sales_qty) {
- Yii::$service->helper->errors->add('product less buy qty is {min_sales_qty}', ['min_sales_qty' => $product['min_sales_qty']]);
-
- return false;
- }
-
- if ($one['item_id']) {
- if ($one['qty'] > 1) {
- $one['qty'] = $lessedQty;
- $one->save();
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- return true;
- }
- }
- }
- return false;
- }
- /**
- * @param $item_id | Int , quoteItem表的id
- * @return bool
- * 将这个item_id对应的产品删除
- */
- public function removeItem($item_id)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- if ($cart_id) {
- $one = $this->_itemModel->find()->where([
- 'cart_id' => $cart_id,
- 'item_id' => $item_id,
- ])->one();
- if ($one['item_id']) {
- $one->delete();
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- return true;
- }
- }
- return false;
- }
-
- /**
- * @param $item_id | Int , quoteItem表的id
- * @return bool
- * 将这个item_id对应的产品个数+1.
- */
- public function selectOneItem($item_id, $checked)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- if ($cart_id) {
- $one = $this->_itemModel->find()->where([
- 'cart_id' => $cart_id,
- 'item_id' => $item_id,
- ])->one();
- $product_id = $one['product_id'];
- if ($one['item_id'] && $product_id) {
- //$product = Yii::$service->product->getByPrimaryKey($product_id);
- //$changeQty = Yii::$service->cart->getCartQty($product['package_number'], 1);
- //$one['qty'] = $one['qty'] + $changeQty;
- if ($checked == true) {
- $one->active = $this->activeStatus;
- } else {
- $one->active = $this->noActiveStatus;
- }
- $one->save();
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- return true;
- }
- }
- return false;
- }
-
- /**
- * @param $item_id | Int , quoteItem表的id
- * @return bool
- * 将这个item_id对应的产品个数+1.
- */
- public function selectAllItem($checked)
- {
- $cart_id = Yii::$service->cart->quote->getCartId();
- if ($cart_id) {
- $active = $this->noActiveStatus;
- if ($checked == true) {
- $active = $this->activeStatus;
- }
- $updateCount = $this->_itemModel->updateAll(
- ['active' => $active],
- ['cart_id' => $cart_id]
- );
- if ($updateCount > 0) {
- Yii::$service->cart->quote->computeCartInfo();
- }
-
- return true;
- }
- return false;
- }
-
- /**
- * @param $cart_id | int 购物车id
- * 删除购物车中的所有的active产品。对于noActive产品保留
- * 注意:清空购物车并不是清空所有信息,仅仅是清空用户购物车中的产品。
- * 另外,购物车的数目更改后,需要更新cart中产品个数的信息。
- */
- public function removeNoActiveItemsByCartId($cart_id = '')
- {
- if (!$cart_id) {
- $cart_id = Yii::$service->cart->quote->getCartId();
- }
- if ($cart_id) {
- $columns = $this->_itemModel->deleteAll([
- 'cart_id' => $cart_id,
- 'active' => $this->activeStatus,
- ]);
- if ($columns > 0) {
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo();
- return true;
- }
- }
- }
- /** 废弃,改为 removeNoActiveItemsByCartId(),因为购物车改为勾选下单方式。
- * @param $cart_id | int 购物车id
- * 删除购物车中的所有产品。
- * 注意:清空购物车并不是清空所有信息,仅仅是清空用户购物车中的产品。
- * 另外,购物车的数目更改后,需要更新cart中产品个数的信息。
- */
- public function removeItemByCartId($cart_id = '')
- {
- if (!$cart_id) {
- $cart_id = Yii::$service->cart->quote->getCartId();
- }
- if ($cart_id) {
- $items = $this->_itemModel->deleteAll([
- 'cart_id' => $cart_id,
- //'item_id' => $item_id,
- ]);
- // 重新计算购物车的数量
- Yii::$service->cart->quote->computeCartInfo(0);
- }
- return true;
- }
- /**
- * @param $new_cart_id | int 更新后的cart_id
- * @param $cart_id | int 更新前的cart_id
- * 删除购物车中的所有产品。
- * 这里仅仅更改cart表的cart_id, 而不会做其他任何事情。
- */
- public function updateCartId($new_cart_id, $cart_id)
- {
- if ($cart_id && $new_cart_id) {
- $this->_itemModel->updateAll(
- ['cart_id' => $new_cart_id], // $attributes
- ['cart_id' => $cart_id] // $condition
- );
- // 重新计算购物车的数量
- //Yii::$service->cart->quote->computeCartInfo();
- return true;
- }
- return false;
- }
- }
|