StoreOrderCartInfoServices.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\services\order;
  12. use app\dao\order\StoreOrderCartInfoDao;
  13. use app\services\BaseServices;
  14. use crmeb\services\CacheService;
  15. use crmeb\services\SystemConfigService;
  16. use crmeb\traits\OptionTrait;
  17. use crmeb\traits\ServicesTrait;
  18. use crmeb\utils\Arr;
  19. use think\exception\ValidateException;
  20. /**
  21. * Class StoreOrderCartInfoServices
  22. * @package app\services\order
  23. * @mixin StoreOrderCartInfoDao
  24. */
  25. class StoreOrderCartInfoServices extends BaseServices
  26. {
  27. use OptionTrait;
  28. use ServicesTrait;
  29. /**
  30. * StorePinkServices constructor.
  31. * @param StoreOrderCartInfoDao $dao
  32. */
  33. public function __construct(StoreOrderCartInfoDao $dao)
  34. {
  35. $this->dao = $dao;
  36. }
  37. /**
  38. * 清空订单商品缓存
  39. * @param int $oid
  40. * @return bool
  41. * @throws \Psr\SimpleCache\InvalidArgumentException
  42. */
  43. public function clearOrderCartInfo(int $oid)
  44. {
  45. return CacheService::delete(md5('store_order_cart_info_' . $oid));
  46. }
  47. /**
  48. * 获取指定订单下的商品详情
  49. * @param int $oid
  50. * @return array|mixed
  51. */
  52. public function getOrderCartInfo(int $oid)
  53. {
  54. $cartInfo = CacheService::get(md5('store_order_cart_info_' . $oid));
  55. if ($cartInfo) return $cartInfo;
  56. $cart_info = $this->dao->getCartColunm(['oid' => $oid], 'cart_info', 'cart_id');
  57. $info = [];
  58. foreach ($cart_info as $k => $v) {
  59. $_info = is_string($v) ? json_decode($v, true) : $v;
  60. if (!isset($_info['productInfo'])) $_info['productInfo'] = [];
  61. //缩略图处理
  62. if (isset($_info['productInfo']['attrInfo'])) {
  63. $_info['productInfo']['attrInfo'] = get_thumb_water($_info['productInfo']['attrInfo']);
  64. }
  65. $_info['product_type'] = $_info['productInfo']['product_type'] ?? 0;
  66. $_info['supplier_id'] = $_info['productInfo']['supplier_id'] ?? 0;
  67. $_info['is_support_refund'] = $_info['productInfo']['is_support_refund'] ?? 1;
  68. $_info['productInfo'] = get_thumb_water($_info['productInfo']);
  69. $_info['refund_num'] = $this->dao->sum(['cart_id' => $_info['id']], 'refund_num');
  70. $info[$k]['cart_info'] = $_info;
  71. unset($_info);
  72. }
  73. CacheService::set(md5('store_order_cart_info_' . $oid), $info);
  74. return $info;
  75. }
  76. /** 获取指定订单下的商品详情 供应商
  77. * @param int $oid
  78. * @return array
  79. */
  80. public function getOrderCartInfoSettlePrice(int $oid)
  81. {
  82. $cart_info = $this->dao->getCartColunm(['oid' => $oid], 'cart_num,refund_num,cart_info', 'id');
  83. $settlePrice = 0;
  84. $refundSettlePrice = 0;
  85. foreach ($cart_info as $k => &$v) {
  86. $_info = is_string($v['cart_info']) ? json_decode($v['cart_info'], true) : $v['cart_info'];
  87. $v['cart_info'] = $_info;
  88. if (!isset($_info['productInfo'])) $_info['productInfo'] = [];
  89. $settle_price = $_info['productInfo']['attrInfo']['settle_price'] ?? 0;
  90. $_info['settlePrice'] = bcmul((string)$settle_price, (string)$v['cart_num'], 2); //购买结算价格
  91. $settlePrice = bcadd($_info['settlePrice'], $settlePrice, 2);
  92. $_info['refundSettlePrice'] = bcmul((string)$settle_price, (string)$v['refund_num'], 2);//退款结算价格
  93. $refundSettlePrice = bcadd($_info['refundSettlePrice'], $refundSettlePrice, 2);
  94. }
  95. return ['settlePrice' => $settlePrice, 'refundSettlePrice' => $refundSettlePrice, 'info'=> $cart_info];
  96. }
  97. /**
  98. * 查找购物车里的所有商品标题
  99. * @param int $oid
  100. * @param false $goodsNum
  101. * @return bool|mixed|string
  102. * @throws \think\db\exception\DataNotFoundException
  103. * @throws \think\db\exception\DbException
  104. * @throws \think\db\exception\ModelNotFoundException
  105. */
  106. public function getCarIdByProductTitle(int $oid, bool $goodsNum = false)
  107. {
  108. $key = md5('store_order_cart_product_title_' . $oid);
  109. $title = CacheService::get($key);
  110. if (!$title) {
  111. $orderCart = $this->dao->getCartInfoList(['oid' => $oid], ['cart_info']);
  112. foreach ($orderCart as $item) {
  113. if (isset($item['cart_info']['productInfo']['store_name'])) {
  114. if ($goodsNum && isset($item['cart_info']['cart_num'])) {
  115. $title .= $item['cart_info']['productInfo']['store_name'] . ' * ' . $item['cart_info']['cart_num'] . ' | ';
  116. } else {
  117. $title .= $item['cart_info']['productInfo']['store_name'] . '|';
  118. }
  119. }
  120. }
  121. if ($title) {
  122. $title = substr($title, 0, strlen($title) - 1);
  123. }
  124. CacheService::set($key, $title);
  125. }
  126. return $title ? $title : '';
  127. }
  128. /**
  129. * 获取打印订单的商品信息
  130. * @param int $oid
  131. * @return array
  132. * @throws \think\db\exception\DataNotFoundException
  133. * @throws \think\db\exception\DbException
  134. * @throws \think\db\exception\ModelNotFoundException
  135. */
  136. public function getCartInfoPrintProduct(int $oid)
  137. {
  138. $cartInfo = $this->dao->getCartInfoList(['oid' => $oid], ['is_gift', 'cart_info']);
  139. $product = [];
  140. foreach ($cartInfo as $item) {
  141. $value = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
  142. $value['productInfo']['store_name'] = $value['productInfo']['store_name'] ?? "";
  143. $value['productInfo']['store_name'] = substrUTf8($value['productInfo']['store_name'], 10, 'UTF-8', '');
  144. $value['is_gift'] = $item['is_gift'];
  145. $product[] = $value;
  146. }
  147. return $product;
  148. }
  149. /**
  150. * 保存购物车info
  151. * @param $oid
  152. * @param array $cartInfo
  153. * @param $uid
  154. * @param array $promotions
  155. * @return int
  156. */
  157. public function setCartInfo($oid, array $cartInfo, $uid, array $promotions = [])
  158. {
  159. $group = [];
  160. foreach ($cartInfo as $cart) {
  161. $group[] = [
  162. 'oid' => $oid,
  163. 'uid' => $uid,
  164. 'cart_id' => $cart['id'],
  165. 'type' => $cart['productInfo']['type'] ?? 0,
  166. 'relation_id' => $cart['productInfo']['relation_id'] ?? 0,
  167. 'product_id' => $cart['product_id'] ?? $cart['productInfo']['id'],//原商品ID
  168. 'product_type' => $cart['productInfo']['product_type'] ?? 0,
  169. 'sku_unique' => $cart['product_attr_unique'] ?? '',
  170. 'promotions_id' => implode(',', $cart['promotions_id'] ?? []),
  171. 'is_gift' => isset($cart['is_gift']) && $cart['is_gift'] ? 1 : 0,
  172. 'is_support_refund' => isset($cart['is_gift']) && $cart['is_gift'] ? 0 : ($cart['productInfo']['is_support_refund'] ?? 1),
  173. 'cart_info' => json_encode($cart),
  174. 'cart_num' => $cart['cart_num'],
  175. 'surplus_num' => $cart['cart_num'],
  176. 'split_surplus_num' => $cart['cart_num'],
  177. 'write_times' => bcmul((string)$cart['cart_num'], (string)(max($cart['productInfo']['attrInfo']['write_times'] ?? 1, 1)), 0),
  178. 'write_surplus_times' => bcmul((string)$cart['cart_num'], (string)(max($cart['productInfo']['attrInfo']['write_times'] ?? 1, 1)), 0),
  179. 'unique' => md5($cart['id'] . '' . $oid)
  180. ];
  181. }
  182. if ($promotions) {
  183. /** @var StoreOrderPromotionsServices $services */
  184. $services = app()->make(StoreOrderPromotionsServices::class);
  185. $services->setPromotionsDetail((int)$uid, (int)$oid, $cartInfo, $promotions);
  186. }
  187. return $this->dao->saveAll($group);
  188. }
  189. /**
  190. * 订单创建成功之后计算订单(实际优惠、积分、佣金、上级、上上级)
  191. * @param $oid
  192. * @param array $cartInfo
  193. * @return bool
  194. */
  195. public function updateCartInfo($oid, array $cartInfo)
  196. {
  197. foreach ($cartInfo as $cart) {
  198. $group = [
  199. 'cart_info' => json_encode($cart)
  200. ];
  201. $this->dao->update(['oid' => $oid, 'cart_id' => $cart['id']], $group);
  202. }
  203. return true;
  204. }
  205. /**
  206. * 商品编号
  207. * @param int $oid
  208. * @return array
  209. */
  210. public function getCartIdsProduct(int $oid)
  211. {
  212. $where = [
  213. 'oid' => $oid
  214. ];
  215. return $this->dao->getColumn($where, 'product_id', 'oid', true);
  216. }
  217. /**
  218. * 检测这些商品是否还可以拆分
  219. * @param int $oid
  220. * @param array $cart_data
  221. * @return bool
  222. * @throws \think\db\exception\DataNotFoundException
  223. * @throws \think\db\exception\DbException
  224. * @throws \think\db\exception\ModelNotFoundException
  225. */
  226. public function checkCartIdsIsSplit(int $oid, array $cart_data)
  227. {
  228. if (!$cart_data) return false;
  229. $ids = array_unique(array_column($cart_data, 'cart_id'));
  230. if ($this->dao->getCartInfoList(['oid' => $oid, 'cart_id' => $ids, 'split_status' => 2], ['cart_id'])) {
  231. throw new ValidateException('您选择的商品已经拆分完成,请刷新或稍后重新选择');
  232. }
  233. $cartInfo = $this->getSplitCartList($oid, 'surplus_num,split_surplus_num,cart_info,cart_num', 'cart_id');
  234. if (!$cartInfo) {
  235. throw new ValidateException('该订单已发货完成');
  236. }
  237. foreach ($cart_data as $cart) {
  238. $surplus_num = $cartInfo[$cart['cart_id']]['surplus_num'] ?? 0;
  239. if (!$surplus_num) {//兼容之前老数据
  240. $_info = $cartInfo[$cart['cart_id']]['cart_info'] ?? [];
  241. $surplus_num = $_info['cart_num'] ?? 0;
  242. }
  243. if ($cart['cart_num'] > $surplus_num) {
  244. throw new ValidateException('您选择商品拆分数量大于购买数量');
  245. }
  246. }
  247. return true;
  248. }
  249. /**
  250. * 获取可退款商品
  251. * @param int $oid
  252. * @param string $field
  253. * @param string $key
  254. * @return array
  255. */
  256. public function getRefundCartList(int $oid, string $field = '*', string $key = '')
  257. {
  258. $cartInfo = $this->dao->getColumn([['oid', '=', $oid]], $field, $key);
  259. foreach ($cartInfo as $key => &$item) {
  260. if ($field == 'cart_info') {
  261. $item = is_string($item) ? json_decode($item, true) : $item;
  262. } else {
  263. if (isset($item['cart_info'])) $item['cart_info'] = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
  264. if (isset($item['cart_num']) && !$item['cart_num']) {//兼容之前老数据
  265. $item['cart_num'] = $item['cart_info']['cart_num'] ?? 0;
  266. }
  267. }
  268. $surplus = (int)bcsub((string)$item['cart_num'], (string)$item['refund_num'], 0);
  269. if ($surplus > 0) {
  270. $item['surplus_num'] = $surplus;
  271. } else {
  272. unset($cartInfo[$key]);
  273. }
  274. }
  275. return array_merge($cartInfo);
  276. }
  277. /**
  278. * 获取某个订单还可以拆分商品 split_status 0:未拆分1:部分拆分2:拆分完成
  279. * @param int $oid
  280. * @param string $field
  281. * @param string $key
  282. * @return array
  283. */
  284. public function getSplitCartList(int $oid, string $field = '*', string $key = '')
  285. {
  286. /** @var StoreOrderServices $orderServices */
  287. $orderServices = app()->make(StoreOrderServices::class);
  288. $order = $orderServices->get($oid);
  289. if (!$order) {
  290. throw new ValidateException('订单不存在');
  291. }
  292. $store_id = $this->getItem('store_id', 0);
  293. $supplier_id = $this->getItem('supplier_id', 0);
  294. //拆分完整主订单查询未发货子订单
  295. if ($order['pid'] == -1) {
  296. $oid = $orderServices->value(['pid' => $oid, 'status' => 0, 'supplier_id' => $supplier_id, 'store_id' => $store_id, 'refund_type' => [0, 3]], 'id');
  297. }
  298. $cartInfo = $this->dao->getColumn([['oid', '=', $oid], ['split_status', 'IN', [0, 1]]], $field, $key);
  299. foreach ($cartInfo as &$item) {
  300. if ($field == 'cart_info') {
  301. $item = is_string($item) ? json_decode($item, true) : $item;
  302. } else {
  303. if (isset($item['cart_info'])) $item['cart_info'] = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
  304. if (isset($item['cart_num']) && !$item['cart_num']) {//兼容之前老数据
  305. $item['cart_num'] = $item['cart_info']['cart_num'] ?? 0;
  306. }
  307. $item['surplus_num'] = $item['split_surplus_num'];
  308. }
  309. }
  310. return $cartInfo;
  311. }
  312. /** 次卡商品未核销短信提醒
  313. * @return bool
  314. */
  315. public function reminderUnverifiedRemind()
  316. {
  317. /** @var StoreOrderServices $orderServices */
  318. $orderServices = app()->make(StoreOrderServices::class);
  319. // 临期
  320. //系统预设取消订单时间段
  321. $keyValue = ['reminder_deadline_second_card_time'];
  322. //获取配置
  323. $systemValue = SystemConfigService::more($keyValue);
  324. //格式化数据
  325. $systemValue = Arr::setValeTime($keyValue, is_array($systemValue) ? $systemValue : []);
  326. $reminder_deadline_second_card_time = $systemValue['reminder_deadline_second_card_time'];
  327. $reminder_deadline_second_card_time = (int)bcmul((string)$reminder_deadline_second_card_time, '3600', 0);
  328. $writeTime = time() + $reminder_deadline_second_card_time;
  329. $adventList = $this->dao->getAdventCartInfoList(time(), $writeTime);
  330. if ($adventList) {
  331. foreach ($adventList as $key => $item) {
  332. $cart_info = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
  333. $store_name = substrUTf8($cart_info['productInfo']['store_name'], 10, 'UTF-8', '');
  334. $data['store_name'] = $store_name;
  335. $order = $orderServices->get($item['oid'], ['id', 'uid', 'pay_time', 'user_phone']);
  336. if (!$order) {
  337. continue;
  338. }
  339. $data['uid'] = $order['uid'];
  340. $data['end_time'] = date('Y-m-d H:i', $item['write_end']);
  341. $data['pay_time'] = date('Y-m-d H:i', $order['pay_time']);
  342. $data['phone'] = $order['user_phone'];
  343. event('notice.notice', [$data, 'reminder_brink_death']);
  344. $this->dao->update($item['id'], ['is_advent_sms' => 1]);
  345. }
  346. }
  347. // 过期
  348. $expireList = $this->dao->getExpireCartInfoList(time());
  349. if ($expireList) {
  350. foreach ($expireList as $key => $item) {
  351. $cart_info = is_string($item['cart_info']) ? json_decode($item['cart_info'], true) : $item['cart_info'];
  352. $store_name = substrUTf8($cart_info['productInfo']['store_name'], 10, 'UTF-8', '');
  353. $data['store_name'] = $store_name;
  354. $data['end_time'] = date('Y-m-d H:i', $item['write_end']);
  355. $order = $orderServices->get($item['oid'], ['id', 'uid', 'pay_time', 'user_phone']);
  356. if (!$order) {
  357. continue;
  358. }
  359. $data['uid'] = $order['uid'];
  360. $data['phone'] = $order['user_phone'];
  361. event('notice.notice', [$data, 'expiration_reminder']);
  362. $this->dao->update($item['id'], ['is_expire_sms' => 1]);
  363. }
  364. }
  365. return true;
  366. }
  367. }