CartItemService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. <?php
  2. namespace addons\TinyShop\services\member;
  3. use Yii;
  4. use yii\db\ActiveQuery;
  5. use yii\helpers\Json;
  6. use yii\web\NotFoundHttpException;
  7. use yii\web\UnprocessableEntityHttpException;
  8. use common\components\Service;
  9. use common\enums\StatusEnum;
  10. use common\helpers\ArrayHelper;
  11. use addons\TinyShop\common\forms\CartItemForm;
  12. use addons\TinyShop\common\models\member\CartItem;
  13. use addons\TinyShop\common\interfaces\CartItemInterface;
  14. use addons\TinyShop\common\enums\ProductTypeEnum;
  15. use addons\TinyShop\common\enums\MarketingEnum;
  16. /**
  17. * Class CartItemService
  18. * @package addons\TinyShop\services\member
  19. * @author jianyan74 <751393839@qq.com>
  20. */
  21. class CartItemService extends Service implements CartItemInterface
  22. {
  23. /**
  24. * 驱动
  25. *
  26. * 默认mysql
  27. *
  28. * @var string
  29. */
  30. public $drive;
  31. /**
  32. * @var CartItem
  33. */
  34. protected $modelClass;
  35. public function init()
  36. {
  37. if ($this->drive == 'mysql') {
  38. $this->modelClass = CartItem::class;
  39. }
  40. parent::init();
  41. }
  42. /**
  43. * @param $member_id
  44. * @return array|\yii\db\ActiveRecord[]
  45. */
  46. public function all($member_id)
  47. {
  48. $data = $this->modelClass::find()
  49. ->where(['member_id' => $member_id])
  50. ->andWhere(['>=', 'status', StatusEnum::DISABLED])
  51. ->andFilterWhere(['merchant_id' => $this->getMerchantId()])
  52. ->orderBy('marketing_id desc, created_at asc')
  53. ->with(['baseMerchant', 'product', 'sku'])
  54. ->asArray()
  55. ->all();
  56. $carts = [];
  57. $carts[0] = [
  58. 'merchant' => [],
  59. 'items' => [
  60. [
  61. 'marketing' => [],
  62. 'products' => [],
  63. 'updated_at' => '', // 排序时间
  64. ]
  65. ],
  66. ];
  67. $loseEfficacy = [];
  68. $deleteIds = [];
  69. foreach ($data as $key => &$datum) {
  70. $datum['original_price'] = $datum['price'];
  71. $datum['min_buy'] = 0;
  72. $datum['max_buy'] = 0;
  73. $datum['remark'] = '';
  74. $datum['price'] = floatval($datum['sku']['price'] ?? $datum['price']);
  75. $datum['marketing_price'] = $datum['price'];
  76. $datum['product_name'] = $datum['product']['name'];
  77. $datum['product_picture'] = $datum['sku']['picture'] ?? '';
  78. $datum['stock'] = $datum['sku']['stock'] ?? 0;
  79. empty($datum['product_picture']) && $datum['product_picture'] = $datum['product']['picture'];
  80. // 无效商品
  81. $datum['product']['stock'] <= 0 && $datum['remark'] = '库存不足';
  82. !isset($datum['sku']) && $datum['remark'] = '宝贝已不能购买';
  83. if ($datum['status'] == StatusEnum::DISABLED || !empty($datum['remark'])) {
  84. empty($datum['remark']) && $datum['remark'] = '宝贝已失效';
  85. unset(
  86. $datum['product'],
  87. $datum['sku'],
  88. $datum['baseMerchant'],
  89. $datum['created_at']
  90. );
  91. $loseEfficacy[] = $datum;
  92. unset($data[$key]);
  93. continue;
  94. }
  95. unset(
  96. $datum['product'],
  97. $datum['sku'],
  98. $datum['baseMerchant'],
  99. $datum['created_at']
  100. );
  101. }
  102. !empty($deleteIds) && $this->deleteIds($deleteIds, $member_id);
  103. // 重构营销
  104. $marketingData = [];
  105. foreach ($data as $value) {
  106. $marketingData[] = [
  107. 'marketing' => [],
  108. 'marketing_tag' => '',
  109. 'marketing_explain' => '',
  110. 'products' => [$value],
  111. 'updated_at' => $value['updated_at'],
  112. ];
  113. }
  114. // 写入购物车
  115. foreach ($marketingData as $marketingDatum) {
  116. $carts[0]['items'][] = $marketingDatum;
  117. }
  118. return [$carts, $loseEfficacy];
  119. }
  120. /**
  121. * 加入购物车
  122. *
  123. * @param CartItemForm $form
  124. * @return mixed|void
  125. */
  126. public function create(CartItemForm $form)
  127. {
  128. $sku = $form->getSku();
  129. $model = $this->findModel($sku['product_id'], $sku['id'], $form->member_id, $form->marketing_id, $form->marketing_type);
  130. $model->number += $form->number;
  131. $model->sku_id = $sku['id'];
  132. $model->sku_name = $sku['name'];
  133. $model->member_id = $form->member_id;
  134. $model->marketing_id = $form->marketing_id;
  135. $model->marketing_type = $form->marketing_type;
  136. $model->price = $sku['price'];
  137. $model->product_id = $sku['product']['id'];
  138. $model->product_picture = $sku['product']['picture'];
  139. $model->product_name = $sku['product']['name'];
  140. $model->merchant_id = $sku['merchant_id'];
  141. if (!in_array($sku['product']['type'], ProductTypeEnum::entity())) {
  142. throw new UnprocessableEntityHttpException('虚拟商品不可加入购物车');
  143. }
  144. if ($sku['stock'] < $model->number) {
  145. throw new UnprocessableEntityHttpException('购物车已有数量已超出库存');
  146. }
  147. if ($sku['product']['max_buy'] > 0) {
  148. // 当前购物车所有的数量
  149. $sum = Yii::$app->tinyShopService->memberCartItem->getSumByProductId($sku['product']['id'], $form->member_id) + $form->number;
  150. if ($sum > $sku['product']['max_buy']) {
  151. throw new UnprocessableEntityHttpException('购物车已存在该商品,每人最多购买数量为' . $sku['product']['max_buy']);
  152. }
  153. }
  154. if ($sku['product']['min_buy'] > $model->number) {
  155. throw new UnprocessableEntityHttpException('每人最少购买数量为' . $sku['product']['min_buy']);
  156. }
  157. if (!$model->save()) {
  158. throw new UnprocessableEntityHttpException($this->getError($model));
  159. }
  160. return $model;
  161. }
  162. /**
  163. * 修改购物车数量
  164. *
  165. * @param CartItemForm $form
  166. * @return mixed|void
  167. */
  168. public function updateNumber(CartItemForm $form)
  169. {
  170. $model = $this->findById($form->id, $form->member_id);
  171. if (!$model) {
  172. throw new UnprocessableEntityHttpException('购物车商品已被移除');
  173. }
  174. $sku = Yii::$app->tinyShopService->productSku->findById($model->sku_id);
  175. if ($sku['product']['max_buy'] > 0) {
  176. // 当前购物车所有的数量
  177. $sum = Yii::$app->tinyShopService->memberCartItem->findSumByProductId($sku['product']['id'], $form->member_id);
  178. $sum = ($sum - $model->number) + $form->number;
  179. if ($sum > $sku['product']['max_buy']) {
  180. throw new UnprocessableEntityHttpException('每人最多购买数量为' . $sku['product']['max_buy']);
  181. }
  182. }
  183. $model->number = $form->number;
  184. if ($sku['stock'] < $model->number) {
  185. throw new UnprocessableEntityHttpException('购物车已有数量已超出库存');
  186. }
  187. if ($sku['product']['min_buy'] > $model->number) {
  188. throw new UnprocessableEntityHttpException('每人最少购买数量为' . $sku['product']['min_buy']);
  189. }
  190. if (!$model->save()) {
  191. throw new UnprocessableEntityHttpException($this->getError($model));
  192. }
  193. return $model;
  194. }
  195. /**
  196. * 修改规格
  197. *
  198. * @param CartItemForm $form
  199. */
  200. public function updateSku(CartItemForm $form)
  201. {
  202. $sku = $form->getSku();
  203. /** @var CartItem $oldCartItem */
  204. $oldCartItem = Yii::$app->tinyShopService->memberCartItem->findById($form->id, $form->member_id);
  205. if (!$oldCartItem) {
  206. throw new UnprocessableEntityHttpException('购物车找不到该商品');
  207. }
  208. Yii::$app->tinyShopService->memberCartItem->deleteIds([$form->id], $form->member_id);
  209. $model = $this->findModel($sku['product_id'], $sku['id'], $form->member_id);
  210. $model->number = $oldCartItem->number;
  211. $model->member_id = $oldCartItem->member_id;
  212. $model->sku_id = $sku->id;
  213. $model->sku_name = $sku->name;
  214. $model->price = $sku->price;
  215. $model->merchant_id = $sku->merchant_id;
  216. $model->product_id = $sku->product_id;
  217. $model->product_name = $oldCartItem->product_name;
  218. $model->product_picture = $oldCartItem->product_picture;
  219. $form->verifyValid($model->number);
  220. if (!$model->save()) {
  221. throw new NotFoundHttpException($this->getError($model));
  222. }
  223. return $model;
  224. }
  225. /**
  226. * 删除一组
  227. *
  228. * @param array $sku_ids
  229. * @param $member_id
  230. * @return bool
  231. */
  232. public function deleteIds(array $ids, $member_id)
  233. {
  234. return $this->modelClass::deleteAll([
  235. 'and',
  236. ['in', 'id', $ids,],
  237. ['member_id' => $member_id]
  238. ]);
  239. }
  240. /**
  241. * 清空购物车
  242. *
  243. * @param $member_id
  244. * @param bool $lose_status 失效
  245. * @return bool
  246. */
  247. public function clear($member_id, $lose_status = false)
  248. {
  249. $where = [];
  250. $where['member_id'] = $member_id;
  251. if ($lose_status == StatusEnum::ENABLED) {
  252. $where['status'] = StatusEnum::DISABLED;
  253. }
  254. $this->modelClass::deleteAll($where);
  255. return true;
  256. }
  257. /**
  258. * 获取该产品总数量
  259. *
  260. * @return false|string|null
  261. */
  262. public function getSumByProductId($product_id, $member_id)
  263. {
  264. return $this->modelClass::find()
  265. ->select('sum(number)')
  266. ->where(['product_id' => $product_id])
  267. ->andWhere(['member_id' => $member_id])
  268. ->andWhere(['status' => StatusEnum::ENABLED])
  269. ->scalar() ?? 0;
  270. }
  271. /**
  272. * @param $member_id
  273. * @param $marketing_id
  274. * @return false|string|null
  275. */
  276. public function getCountByPlusBuyId($member_id, $marketing_id)
  277. {
  278. return $this->modelClass::find()
  279. ->where(['member_id' => $member_id, 'marketing_id' => $marketing_id, 'marketing_type' => MarketingEnum::PLUS_BUY, 'status' => StatusEnum::ENABLED])
  280. ->andFilterWhere(['merchant_id' => $this->getMerchantId()])
  281. ->sum('number');
  282. }
  283. /**
  284. * @param $ids
  285. * @param $all
  286. * @return void
  287. */
  288. public function loseByProductIds($ids, $all = false)
  289. {
  290. $this->modelClass::updateAll(['status' => StatusEnum::DISABLED], ['in', 'product_id', $ids]);
  291. }
  292. /**
  293. * @param $skuIds
  294. * @return mixed|void
  295. */
  296. public function loseBySkus($skuIds)
  297. {
  298. $this->modelClass::updateAll(['status' => StatusEnum::DISABLED], ['in', 'sku_id', $skuIds]);
  299. }
  300. /**
  301. * 获取总数量
  302. *
  303. * @param $member_id
  304. * @return int|string
  305. */
  306. public function findCountByMemberId($member_id)
  307. {
  308. return $this->modelClass::find()
  309. ->select('count(id)')
  310. ->where(['member_id' => $member_id, 'status' => StatusEnum::ENABLED])
  311. ->andFilterWhere(['merchant_id' => $this->getMerchantId()])
  312. ->scalar() ?? 0;
  313. }
  314. /**
  315. * @param $member_id
  316. * @param $marketing_id
  317. * @return false|string|null
  318. */
  319. public function findSumByPlusBuyId($member_id, $marketing_id)
  320. {
  321. return $this->modelClass::find()
  322. ->where([
  323. 'member_id' => $member_id,
  324. 'marketing_id' => $marketing_id,
  325. 'marketing_type' => MarketingEnum::PLUS_BUY,
  326. 'status' => StatusEnum::ENABLED]
  327. )
  328. ->sum('number') ?? 0;
  329. }
  330. /**
  331. * 获取该商品总数量
  332. *
  333. * @return false|string|null
  334. */
  335. public function findSumByProductId($product_id, $member_id)
  336. {
  337. return $this->modelClass::find()
  338. ->select('sum(number)')
  339. ->where(['member_id' => $member_id, 'product_id' => $product_id, 'status' => StatusEnum::ENABLED])
  340. ->scalar() ?? 0;
  341. }
  342. /**
  343. * @param $sku_id
  344. * @param $member_id
  345. * @return array|\yii\db\ActiveRecord|null|CartItem
  346. */
  347. public function findBySukId($sku_id, $member_id)
  348. {
  349. return $this->modelClass::find()
  350. ->where(['member_id' => $member_id, 'sku_id' => $sku_id, 'status' => StatusEnum::ENABLED])
  351. ->one();
  352. }
  353. /**
  354. * @param $id
  355. * @param $member_id
  356. * @return array|\yii\db\ActiveRecord|null|CartItem
  357. */
  358. public function findById($id, $member_id)
  359. {
  360. return $this->modelClass::find()
  361. ->where(['id' => $id, 'member_id' => $member_id, 'status' => StatusEnum::ENABLED])
  362. ->one();
  363. }
  364. /**
  365. * 查询
  366. *
  367. * @param $ids
  368. * @param $member_id
  369. * @param false $plus_buy
  370. * @return array|\yii\db\ActiveRecord[]
  371. */
  372. public function findByIds($ids, $member_id, $plus_buy = false)
  373. {
  374. $condition = $plus_buy == false ? ['marketing_id' => 0] : [];
  375. return $this->modelClass::find()
  376. ->where(['in', 'id', $ids])
  377. ->andWhere(['status' => StatusEnum::ENABLED, 'member_id' => $member_id])
  378. ->andFilterWhere($condition)
  379. ->with(['product.myGet' => function(ActiveQuery $query) use ($member_id) {
  380. return $query->andWhere(['buyer_id' => $member_id]);
  381. }, 'product.cateMap', 'sku', 'merchant'])
  382. ->asArray()
  383. ->all();
  384. }
  385. /**
  386. * @param $product_id
  387. * @param $sku_id
  388. * @param $member_id
  389. * @param $marketing_id
  390. * @param $marketing_type
  391. * @return CartItem|array|\yii\db\ActiveRecord
  392. */
  393. protected function findModel($product_id, $sku_id, $member_id, $marketing_id = 0, $marketing_type = '')
  394. {
  395. $model = $this->modelClass::find()
  396. ->where([
  397. 'product_id' => $product_id,
  398. 'member_id' => $member_id,
  399. 'marketing_id' => $marketing_id,
  400. 'status' => StatusEnum::ENABLED,
  401. ])
  402. ->andFilterWhere(['marketing_type' => $marketing_type])
  403. ->andFilterWhere(['merchant_id' => $this->getMerchantId()])
  404. ->andFilterWhere(['sku_id' => $sku_id])
  405. ->one();
  406. if (!$model) {
  407. /** @var CartItem $model */
  408. $model = new $this->modelClass();
  409. return $model->loadDefaultValues();
  410. }
  411. return $model;
  412. }
  413. }
粤ICP备19079148号