CartListForm.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\client\models\v1;
  8. use app\models\ActivityNewUser;
  9. use app\models\ActivityNewUserGoods;
  10. use app\models\Attr;
  11. use app\models\AttrGroup;
  12. use app\models\Cart;
  13. use app\models\DeliveryRules;
  14. use app\models\Md;
  15. use app\models\MdGroupActivities;
  16. use app\models\MdGroupActivitiesGoods;
  17. use app\models\Option;
  18. use app\models\SeckillActivity;
  19. use app\models\SeckillActivityGoods;
  20. use app\modules\client\models\v1\common\CommonGoods;
  21. use app\models\Goods;
  22. use app\models\Mch;
  23. use app\models\MdGoods;
  24. use yii\base\Model;
  25. use yii\data\Pagination;
  26. use app\models\Coupon;
  27. use app\models\Level;
  28. use app\modules\client\models\v1\order\OrderForm;
  29. use yii\helpers\VarDumper;
  30. class CartListForm extends Model
  31. {
  32. public $store_id;
  33. public $user_id;
  34. public $page;
  35. public $limit;
  36. public $list;
  37. public $cart_id_list;
  38. public $mch_list;
  39. public function rules()
  40. {
  41. return [
  42. [['page', 'limit'], 'integer'],
  43. [['page',], 'default', 'value' => 1],
  44. [['limit',], 'default', 'value' => 1000],
  45. ];
  46. }
  47. public function search($params = [])
  48. {
  49. $query = Cart::find()->where(['store_id' => $this->store_id, 'user_id' => $this->user_id, 'is_delete' => 0, 'type' => (int)$params['type']]);
  50. if (get_md_id() > 0) {
  51. $md_id = get_md_id();
  52. } else {
  53. $md_id = [-1, 0];
  54. }
  55. $query->andWhere(['md_id' => $md_id]);
  56. if (!empty($this->cart_id_list)) {
  57. $query->andWhere(['in', 'id', $this->cart_id_list]);
  58. }
  59. $count = $query->count();
  60. $pagination = new Pagination(['totalCount' => $count, 'page' => $this->page - 1, 'pageSize' => 10000,]);
  61. /* @var Cart[] $list */
  62. $list = $query->orderBy('goods_id DESC')->limit($pagination->limit)->offset($pagination->offset)->all();
  63. $new_list = [];
  64. $mch_list = [];//入驻商的商品
  65. $goods_id_list = []; // 平台购物车商品ids
  66. $mch_data = [];
  67. $platform_profit_strategy = Option::get('platform_profit_strategy', 0, 'store')['value'];
  68. $platform_profit_strategy = json_decode($platform_profit_strategy, true);
  69. foreach ($list as $item) {
  70. $goods = Goods::findOne([
  71. 'id' => $item->goods_id,
  72. 'is_delete' => 0,
  73. 'status' => 1,
  74. ]);
  75. if (!$goods) {
  76. continue;
  77. }
  78. //加价保护start
  79. if (!empty($platform_profit_strategy) && $goods->cloud_goods_id > 0) {
  80. if (intval($platform_profit_strategy['is_risk_control'])) {
  81. //开启风控
  82. $id = \Yii::$app->cache->get('risk_control_model_id_' . $item->goods_id);
  83. if ($id && !\Yii::$app->queue->isDone($id)) {//\Yii::$app->queue->status($id)
  84. \Yii::$app->queue->remove($id);
  85. }
  86. $id =\queue_push(new \app\jobs\RiskControlModelJob(['goods_id' => $item->goods_id]));
  87. \Yii::$app->cache->set('risk_control_model_id_' . $item->goods_id, $id);
  88. }
  89. }
  90. //加价保护END
  91. $goods_id_list[] = $item->goods_id;
  92. $attr_list = Attr::find()->alias('a')
  93. ->select('ag.attr_group_name,a.attr_name,')
  94. ->leftJoin(['ag' => AttrGroup::tableName()], 'a.attr_group_id=ag.id')
  95. ->where(['a.id' => json_decode($item->attr, true)])
  96. ->asArray()->all();
  97. // 门店逻辑
  98. $attr = $goods->attr;
  99. $price = $goods->price;
  100. $status = $goods->status;
  101. // 独立运营门店不参与活动 团购活动需要写在判断门店之前
  102. $activityModel = MdGroupActivitiesGoods::find()->alias('mgag')->leftJoin(['mga'=>MdGroupActivities::tableName()],'mga.id=mgag.activities_id')->where(['goods_id'=>$goods->id,'mgag.is_delete'=>0])->andWhere(['>=','mga.end_time',time()])->andWhere(['mga.is_delete'=>0])->asArray()->select('mgag.*,mga.start_time,mga.end_time')->one();
  103. if($activityModel){
  104. $attr = $activityModel['attr'];
  105. $price = $activityModel['price'];
  106. }
  107. if (get_md_id()) {
  108. $md = Md::findOne(get_md_id());
  109. if ($md->is_single) {
  110. $md_goods = MdGoods::findOne(['goods_id' => $goods->id, 'md_id' => get_md_id()]);
  111. if ($md_goods) {
  112. $attr = $md_goods->attr;
  113. $price = $md_goods->price;
  114. $status = $md_goods->status;
  115. }
  116. }
  117. }
  118. $goodsData = [
  119. 'attr' => $attr,
  120. 'price' => $price,
  121. 'is_level' => $goods->is_level,
  122. 'use_attr' => $goods->use_attr,
  123. ];
  124. $goods_attr_info = CommonGoods::currentGoodsAttr($goodsData, (array) json_decode($item->attr, true));
  125. $attr_num = intval(empty($goods_attr_info['num']) ? 0 : $goods_attr_info['num']);
  126. $goods_pic = isset($goods_attr_info['pic']) && !empty($goods_attr_info['pic']) ? $goods_attr_info['pic'] : $goods->cover_pic;
  127. //秒杀逻辑
  128. //通过商品查找进行中的活动
  129. // $seckill_activity_goods = SeckillActivityGoods::find()->alias('sag')->where(['sag.goods_id' => $item->goods_id])
  130. // ->leftJoin(['sg' => SeckillActivity::tableName()], 'sg.id = sag.activity_id')
  131. // ->andWhere(['AND', ['>', 'sg.end_time', time()], ['<', 'sg.start_time', time()], ['sg.is_delete' => 0, 'sag.is_delete' => 0, 'sg.store_id' => get_store_id()]])
  132. // ->select('sg.id, sg.end_time, sag.attr, sag.use_attr, sg.self_limit_num, sag.seckill_num, sag.seckill_price, sag.sale_num')->asArray()->one();
  133. // $price = 0;
  134. // if (!empty($seckill_activity_goods)) {
  135. //
  136. //// $seckill_activity_goods['end_time'] = date("m月d日 H:s", $seckill_activity_goods['end_time']);
  137. // //如果商品使用规格 且 已经查找到活动
  138. //// if ((int)$goods->use_attr === 1 && !empty($seckill_activity_goods['attr'])) {
  139. // //解码
  140. // $seckill_activity_goods['attr'] = $sag_attrs = json_decode($seckill_activity_goods['attr'], true);
  141. //
  142. // //获取设置的商品秒杀规格id数组与购物车添加的规格id数组比较
  143. // $sag_attrs = array_column($sag_attrs, 'attr_list');
  144. // //假设没有对应的规格信息
  145. // $open = false;
  146. // foreach ($sag_attrs as $index => $sag_attr) {
  147. //
  148. // $sag_attr_id = array_column($sag_attr, 'attr_id');
  149. // //与购物车添加的规格id数组比较
  150. // if (empty(array_diff($sag_attr_id, json_decode($item->attr, true)))) {
  151. // $price = $seckill_activity_goods['attr'][$index]['seckill_price'];
  152. // $open = true;
  153. // }
  154. // }
  155. // //没有对应的规格信息,则前端不传递秒杀信息
  156. // if (!$open) {
  157. // $seckill_activity_goods = [];
  158. // }
  159. //// } else {
  160. //// $price = $seckill_activity_goods['seckill_price'];
  161. //// }
  162. // }
  163. //配送时间逻辑
  164. $delivery_rules = DeliveryRules::find()->where(['id' => $goods->delivery_rules_id, 'is_delete' => 0, 'status' => 1, 'store_id' => get_store_id()])->select('type, times, days, name')->asArray()->one();
  165. if ($delivery_rules) {
  166. $days = "下单" . $delivery_rules['days'] . "天后";
  167. $delivery_rules['times'] =
  168. (int)$delivery_rules['type'] === 1 ? $days : date("m月d日 H:i:s", $delivery_rules['times']);
  169. $delivery_rules['type'] .= '';
  170. }
  171. $price = $goods_attr_info['level_price'];
  172. //新人专享活动
  173. $activityAt = ActivityNewUser::activityAt($goods->store_id);
  174. $open = false;
  175. if ($activityAt) {
  176. $goods_ext = ActivityNewUserGoods::findOne(['activity_id' => $activityAt->id, 'goods_id' => $goods->id, 'is_delete' => 0]);
  177. if ($goods_ext) {
  178. $ext_attrs = json_decode($goods_ext->attr, true);
  179. $attr_list_ = json_decode($item->attr, true);
  180. foreach($ext_attrs as $ext_attr){
  181. $ext_attr_id = array_column($ext_attr['attr_list'], 'attr_id');
  182. sort($ext_attr_id);
  183. sort($attr_list_);
  184. //与购物车添加的规格id数组比较
  185. // array_splice($this->attr_list, 0, 1);
  186. if (empty(array_diff($ext_attr_id, $attr_list_))) {
  187. $ext_price = $ext_attr['price'];
  188. $open = true;
  189. }
  190. }
  191. $buy_limit = $activityAt->buy_limit;
  192. if ($open) {
  193. if ($buy_limit && $buy_limit > 0) {
  194. //部分享受优惠
  195. $goodsNum = intval(Goods::getBuyNum(get_user(), $goods->id));
  196. $diff_num = $buy_limit - $goodsNum; // 1 只有$diff_num件享受新人价格
  197. if ($diff_num > 0) {
  198. $buy_num = $item->num - $diff_num;//1 - 5
  199. if ($buy_num > 0) {
  200. $price = ($diff_num * $ext_price) + ($buy_num * $price);
  201. } else {
  202. $price = $item->num * $ext_price;
  203. }
  204. }
  205. }else{
  206. //全部享受优惠
  207. $price = $ext_price * $item->num;
  208. }
  209. // $price = sprintf('%.2f', $price / $item->num);
  210. }
  211. }
  212. }
  213. if (!$open) {
  214. $price = ($price * $item->num) ?: doubleval(empty($goods_attr_info['price']) ? $goods->price : $goods_attr_info['price']) * $item->num;
  215. }
  216. $attrData = json_decode($goods['attr'], true);
  217. $firstAttrItem = reset($attrData);
  218. $member1 = 0;
  219. if (get_user()->level < 0) {
  220. if (!empty($firstAttrItem['member1'])) {
  221. $member1 = $firstAttrItem['member1'];
  222. } else {
  223. $findLevel = Level::find()
  224. ->where(['status' => 1, 'is_delete' => 0, 'store_id' => $this->store_id,])
  225. ->andWhere(['>', 'id', get_user()->level])
  226. ->one();
  227. $unitPrice = $goods->price;
  228. $quantity = $item->num;
  229. $totalPrice = $unitPrice * $quantity;
  230. if (!empty($findLevel)) {
  231. $discount = $findLevel->discount / 10;
  232. $member1 = $totalPrice * $discount;
  233. }
  234. }
  235. }
  236. $new_item = (object)[
  237. 'cart_id' => $item->id,
  238. 'goods' => $goods,
  239. 'goods_id' => $goods->id,
  240. 'goods_name' => $goods->name,
  241. 'goods_pic' => $goods_pic,
  242. 'num' => $item->num,
  243. 'attr_list' => $attr_list,
  244. 'original_price' => doubleval($goods->original_price * $item->num),
  245. 'price' => floor_num($price, 2),
  246. '$goods_attr_info' => $goods_attr_info,
  247. 'unitPrice' => $price ?: doubleval($goods_attr_info['price']),
  248. 'max_num' => $attr_num,
  249. 'disabled' => ($item->num > $attr_num) ? true : false,
  250. 'status' => $status,
  251. 'seckill_activity_goods' => null, //$seckill_activity_goods ?: null, //秒杀逻辑,商品不可加购物车
  252. 'delivery_rules' => $delivery_rules ?: null,
  253. 'cost_price' => $goods->cost_price,
  254. 'user_id' => get_user_id(),
  255. // 'mch_id' => $md_id,
  256. 'rate' => $goods->rate,
  257. 'rate_type' => $goods->rate_type,
  258. 'balance' => $goods->balance,
  259. 'single_price' => $goods->price,
  260. 'weight' => $goods->weight,
  261. 'integral_price' => $goods->integral_price,
  262. 'freight' => $goods->freight,
  263. 'full_cut' => $goods->full_cut,
  264. 'goods_cat_id' => $goods->cat_id,
  265. 'id' => $goods->id,
  266. 'verify_card_id' => [],
  267. 'type' => $goods->type,
  268. 'delivery_type' => $goods->delivery_type,
  269. 'pieces' => $goods->pieces,
  270. 'forehead' => $goods->forehead,
  271. 'level_price' => $member1 ?? 0,
  272. 'user_is_level' => get_user()->level > 0 ? true : false,
  273. 'level_price_arr' => $firstAttrItem,
  274. 'original_price' => $firstAttrItem['original_price'],
  275. 'product_type' => $goods->product_type,
  276. ];
  277. if ($goods->mch_id != 0) {
  278. if (!is_array($mch_list['mch_id_' . $goods->mch_id])) {
  279. $mch_list['mch_id_' . $goods->mch_id] = [];
  280. }
  281. $new_item->mch_id = $goods->mch_id;
  282. $mch_list['mch_id_' . $goods->mch_id][] = $new_item;
  283. } else {
  284. $new_list[] = $new_item;
  285. }
  286. }
  287. $new_mch_list = [];
  288. foreach ($mch_list as $i => $item) {
  289. $mch = Mch::findOne([
  290. 'id' => $item[0]->mch_id,
  291. 'is_delete' => 0,
  292. 'is_open' => 1,
  293. 'is_lock' => 0,
  294. ]);
  295. if ($mch) {
  296. $new_mch_list[] = [
  297. 'id' => $mch->id,
  298. 'name' => $mch->name,
  299. 'list' => $item,
  300. ];
  301. }
  302. }
  303. // 获取平台可用优惠券
  304. $coupon_list = Coupon::getList(0, 0, 0, $goods_id_list);
  305. foreach ($new_mch_list as &$value) {
  306. $mch_goods_id_list = [];
  307. foreach ($value['list'] as $v) {
  308. $mch_goods_id_list[] = $v->goods_id;
  309. }
  310. $value['coupon_list'] = Coupon::getList($value['id'], 0, 0, $mch_goods_id_list);
  311. }
  312. $mch_data = [
  313. 'mch_id' => get_mch_id(),
  314. 'goods_list' => $new_list,
  315. 'name' => '平台自营',
  316. 'send_type' => ['express', 'shop'],
  317. 'is_shop' => null,
  318. 'shop_list' => [],
  319. 'plugin_type' => 0,
  320. 'total_price' => array_sum(array_column($new_list, 'price')),
  321. 'level_price' => array_sum(array_column($new_list, 'level_price')),
  322. 'level_price_arr' => [
  323. 'member1' => array_sum(array_column($new_list, 'level_price')),
  324. 'member2' => array_sum(array_column($new_list, 'next_level_price')),
  325. 'member6' => array_sum(array_column($new_list, 'next_level_price')),
  326. ],
  327. 'payment_type' => 0,
  328. 'diy_send_type' => [
  329. ['key' => 'express', 'name' => '快递配送'],
  330. ['key' => 'shop', 'name' => '自提配送'],
  331. ['key' => 'delivery', 'name' => '同城配送'],
  332. ],
  333. 'next_level_price' => '',
  334. 'next_level' => null,
  335. 'integral' => ['forehead' => 0, 'forehead_integral' => 0],
  336. 'coupon_list' => $new_mch_list['coupon_list'],
  337. ];
  338. $shipping_fee = new OrderForm();
  339. $calculations_shipping = $shipping_fee->getExpressPrice($mch_data);
  340. return [
  341. 'code' => 0,
  342. 'msg' => 'success',
  343. 'data' => [
  344. 'row_count' => $count,
  345. 'page_count' => $pagination->pageCount,
  346. 'list' => $new_list,
  347. 'mch_list' => $new_mch_list,
  348. 'coupon_list' => $coupon_list,
  349. 'shipping_fee' => $calculations_shipping,
  350. ],
  351. ];
  352. }
  353. public function save($params = [])
  354. {
  355. $type = (int)$params['type'];
  356. if ($this->list) {
  357. $cart_list = json_decode($this->list, true);
  358. foreach ($cart_list as $v) {
  359. $form = Cart::find()->where(['type'=>$type,'store_id' => $this->store_id, 'is_delete' => 0])->andWhere('id=:id', [':id' => $v['cart_id']])->one();
  360. $form->num = $v['num'];
  361. $form->save();
  362. }
  363. };
  364. if ($this->mch_list) {
  365. $mch_list = json_decode($this->mch_list, true);
  366. if (is_array($mch_list)) {
  367. foreach ($mch_list as $i => $mch) {
  368. if (is_array($mch['list'])) {
  369. foreach ($mch['list'] as $j => $item) {
  370. $cart = Cart::findOne([
  371. 'type'=>$type,
  372. 'id' => $item['cart_id'],
  373. 'user_id' => $this->user_id,
  374. ]);
  375. if (!$cart) {
  376. continue;
  377. }
  378. $cart->num = intval($item['num']);
  379. $cart->save();
  380. }
  381. }
  382. }
  383. }
  384. }
  385. return [
  386. 'code' => 0,
  387. 'msg' => 'success',
  388. ];
  389. }
  390. }