MCashierCart.Class.php 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  1. <?php
  2. namespace JinDouYun\Model\Cashier;
  3. use JinDouYun\Cache\ActivityLimitCache;
  4. use JinDouYun\Cache\GoodsBasicRelevant;
  5. use JinDouYun\Controller\Common\Logger;
  6. use JinDouYun\Dao\Cashier\DCashierCart;
  7. use JinDouYun\Dao\Cashier\DCashierCustomerPrice;
  8. use JinDouYun\Model\Customer\MCustomer;
  9. use JinDouYun\Model\Goods\MGoods;
  10. use JinDouYun\Model\GoodsManage\MSku;
  11. use JinDouYun\Model\Market\MActivity;
  12. use JinDouYun\Model\Market\MUserCoupon;
  13. use JinDouYun\Model\Price\MPrice;
  14. use JinDouYun\Model\Shop\MShop;
  15. use JinDouYun\Model\Stock\MInventory;
  16. use Mall\Framework\Core\ErrorCode;
  17. use Mall\Framework\Core\ResultWrapper;
  18. use Mall\Framework\Core\StatusCode;
  19. class MCashierCart
  20. {
  21. /**
  22. * @var int
  23. */
  24. private $onlineUserId;
  25. /**
  26. * @var int
  27. */
  28. private $onlineEnterpriseId;
  29. /**
  30. * @var int
  31. */
  32. private $cashierUid;
  33. /**
  34. * @var MGoods
  35. */
  36. private $objMGoods;
  37. /**
  38. * @var DCashierCart
  39. */
  40. private $objDCashierCart;
  41. /**
  42. * @var ActivityLimitCache
  43. */
  44. private $objActivityLimitCache;
  45. /**
  46. * @var MSku
  47. */
  48. private $objMSku;
  49. /**
  50. * @var int
  51. */
  52. private $customerId;
  53. /**
  54. * @var MCustomer
  55. */
  56. private $objMCustomer;
  57. /**
  58. * @var DCashierCustomerPrice
  59. */
  60. private $objDCashierCustomerPrice;
  61. /**
  62. * @var array 失效商品集合
  63. */
  64. private $invalidData = [];
  65. /**
  66. * @var array 操作类型
  67. */
  68. private static $type = [
  69. 'single' => 1,//单个商品
  70. 'shop' => 2,//按店铺
  71. 'all' => 3,//全选
  72. ];
  73. /**
  74. * @var array 阶梯价
  75. */
  76. private static $enabledLadder = [
  77. 'open' => 1,//启用阶梯价
  78. 'close' => 0,//未启用阶梯价
  79. ];
  80. /**
  81. * @var MCashierSettings
  82. */
  83. private $objMCashierSettings;
  84. /**
  85. * MCashierCart constructor.
  86. * @param $onlineUserId
  87. * @param $onlineEnterpriseId
  88. * @param $cashierUid
  89. * @throws \Exception
  90. */
  91. public function __construct($onlineUserId, $onlineEnterpriseId,$cashierUid)
  92. {
  93. $this->onlineUserId = $onlineUserId;
  94. $this->onlineEnterpriseId = $onlineEnterpriseId;
  95. $this->cashierUid = $cashierUid;
  96. $this->objMGoods = new MGoods($this->onlineEnterpriseId,true,$this->onlineUserId);
  97. $this->objDCashierCart = new DCashierCart();
  98. $this->objDCashierCart->setTable('qianniao_cashier_cart_'.$this->onlineEnterpriseId);
  99. $this->objActivityLimitCache = new ActivityLimitCache($this->onlineEnterpriseId);
  100. $this->objMSku = new MSku($this->onlineUserId, $this->onlineEnterpriseId);
  101. $this->objMCustomer = new MCustomer($this->onlineEnterpriseId,$this->onlineUserId);
  102. $this->objDCashierCustomerPrice = new DCashierCustomerPrice();
  103. $this->objDCashierCustomerPrice->setTable('qianniao_cashier_customer_price_'.$this->onlineEnterpriseId);
  104. $this->objMCashierSettings = new MCashierSettings($this->onlineUserId,$this->onlineEnterpriseId);
  105. }
  106. /**
  107. * 获取客户id,匿名用户使用匿名客户id
  108. */
  109. private function getCustomerInfo()
  110. {
  111. if ($this->onlineUserId == StatusCode::$noneUserCenter){
  112. $this->customerId = StatusCode::$noneCustomer;
  113. }else{
  114. $this->customerId = $this->objMCustomer->getCustomerIdByUserCenterId($this->onlineUserId);
  115. }
  116. }
  117. /**
  118. * Doc: (des="收银台加入购物车")
  119. * User: XMing
  120. * Date: 2020/9/17
  121. * Time: 2:24 下午
  122. * @param array $params
  123. * @return ResultWrapper
  124. * @throws \Exception
  125. */
  126. public function addCartApi($params)
  127. {
  128. $data = $params['goodsData'];
  129. if (empty($data)){
  130. return ResultWrapper::fail('加入购物车数据为空',ErrorCode::$paramError);
  131. }
  132. $data = array_shift($data);//小程序端加入购物车都是单个
  133. //验证此商品是否有效
  134. $goodsInfoResult = $this->objMGoods->getGoodsInfo($data['goodsId']);
  135. if (!$goodsInfoResult->isSuccess()){
  136. return ResultWrapper::fail($goodsInfoResult->getData(),$goodsInfoResult->getErrorCode());
  137. }
  138. $goodsInfo = $goodsInfoResult->getData();
  139. $checkResult = self::checkGoods($goodsInfo,$data);
  140. unset($data);
  141. if (!$checkResult->isSuccess()){
  142. return ResultWrapper::fail($checkResult->getData(),$checkResult->getErrorCode());
  143. }
  144. $data = $checkResult->getData();
  145. $addMap = [
  146. 'cashierUid' => $this->cashierUid,
  147. 'goodsBasicId' => $data['goodsBasicId'],
  148. 'goodsId' => $data['goodsId'],
  149. 'skuId' => $data['skuId'],
  150. 'buyNum' => $data['buyNum'],
  151. 'shopId' => $data['shopId'],
  152. 'source' => $data['source'],
  153. 'setNum' => $data['setNum'],
  154. 'activityId' => 0,
  155. 'goodsCode' => $data['goodsCode'],
  156. 'warehouseId' => $data['warehouseId']
  157. ];
  158. $groupResult = self::existCartAndGroup([$addMap]);
  159. if (!$groupResult->isSuccess()){
  160. return ResultWrapper::fail($groupResult->getData(),$groupResult->getErrorCode());
  161. }
  162. $groupData = $groupResult->getData();
  163. if (empty($groupData)){
  164. return ResultWrapper::fail('数组分组失败',ErrorCode::$paramError);
  165. }
  166. Logger::logs(E_USER_ERROR,'收银台加入购物车数据',__CLASS__,__LINE__,$groupData);
  167. $updates = isset($groupData['old']) ? $groupData['old'] : [];
  168. $inserts = isset($groupData['now']) ? $groupData['now'] : [];
  169. //操作数据库
  170. $this->objDCashierCart->beginTransaction();
  171. //需要更新的数据
  172. if (!empty($updates)){
  173. $update = array_shift($updates);
  174. $tableName = 'qianniao_cashier_cart_'.$this->onlineEnterpriseId;
  175. $sql = 'UPDATE '.$tableName.' SET buyNum = buyNum+'.$update['buyNum'].'
  176. WHERE goodsId = '.$update['goodsId'].' AND
  177. skuId = '.$update['skuId'].' AND
  178. activityId = '.$update['activityId'] .' AND
  179. cashierUid = '.$update['cashierUid'];
  180. $updateRes = $this->objDCashierCart->query($sql);
  181. if ($updateRes === false){
  182. $this->objDCashierCart->rollBack();
  183. return ResultWrapper::fail($this->objDCashierCart->error(),ErrorCode::$dberror);
  184. }
  185. }
  186. //需要插入的数据
  187. if (!empty($inserts)){
  188. $insert = array_shift($inserts);
  189. $insertMap = [
  190. 'cashierUid' => $this->cashierUid,
  191. 'selection' => StatusCode::$standard,
  192. 'goodsBasicId' => $insert['goodsBasicId'],
  193. 'goodsId' => $insert['goodsId'],
  194. 'skuId' => $insert['skuId'],
  195. 'buyNum' => $insert['buyNum'],
  196. 'shopId' => $insert['shopId'],
  197. 'source' => $insert['source'],
  198. 'activityId' => $insert['activityId'],
  199. 'goodsCode' => $insert['goodsCode'],
  200. 'warehouseId' => $insert['warehouseId']
  201. ];//要插入的数据
  202. $insertRes = $this->objDCashierCart->insert($insertMap);
  203. if ($insertRes === false){
  204. $this->objDCashierCart->rollBack();
  205. return ResultWrapper::fail($this->objDCashierCart->error(),ErrorCode::$dberror);
  206. }
  207. }
  208. $this->objDCashierCart->commit();
  209. return ResultWrapper::success('加入成功');
  210. }
  211. /**
  212. * Doc: (des="更新购车商品数量")
  213. * User: XMing
  214. * Date: 2020/8/6
  215. * Time: 9:43 上午
  216. * @param array $params
  217. * @return ResultWrapper
  218. * @throws \Exception
  219. */
  220. public function updateBuyNumApi($params)
  221. {
  222. if ($params['buyNum'] == 0){
  223. $dbResult = $this->objDCashierCart->delete(['id' => $params['cartId']]);
  224. if ($dbResult === false) {
  225. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  226. }
  227. return ResultWrapper::success('操作成功');
  228. }
  229. $dbResult = $this->objDCashierCart->update(['buyNum' => $params['buyNum']], $params['cartId']);
  230. if ($dbResult === false) {
  231. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  232. }
  233. return ResultWrapper::success('操作成功');
  234. }
  235. /**
  236. * 删除购物车中商品(可批量)
  237. * @param $ids
  238. * @param boolean $order 是否是来自订单
  239. * @return ResultWrapper
  240. */
  241. public function delCart($ids, $order = false)
  242. {
  243. $dbResult = $this->objDCashierCart->select($ids, 'id,goodsId,buyNum,skuId,activityId');
  244. if ($dbResult === false) {
  245. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  246. }
  247. //限购减对应数据
  248. if ($order === true) {
  249. foreach ($dbResult as $goods) {
  250. if ($goods['activityId'] != 0) {
  251. $userSurplusNum = $this->objActivityLimitCache->getLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId);
  252. $mapping[] = [
  253. 'activityId' => $goods['activityId'],
  254. 'goodsId' => $goods['goodsId'],
  255. 'skuId' => $goods['skuId'],
  256. 'buyNum' => $userSurplusNum + $goods['buyNum'],
  257. ];
  258. self::userLimit($mapping);
  259. }
  260. }
  261. }
  262. $dbResult = $this->objDCashierCart->delete($ids);
  263. if ($dbResult === false) {
  264. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  265. }
  266. return ResultWrapper::success($dbResult);
  267. }
  268. /**
  269. * Doc: (des="收银台购物车数据")
  270. * User: XMing
  271. * Date: 2020/9/16
  272. * Time: 4:02 下午
  273. * @param int $isZero
  274. * @param string $userCouponId
  275. * @return ResultWrapper
  276. * @throws \Exception
  277. */
  278. public function getCashierCartByUserCenterIdApi($isZero = 4,$userCouponId = '')
  279. {
  280. $cartList = $this->objDCashierCart->select(['cashierUid' => $this->cashierUid], 'id,goodsId,goodsCode,buyNum,shopId,source,goodsBasicId,selection,skuId,warehouseId,activityId,cashierUid', 'createTime DESC');
  281. if ($cartList === false) {
  282. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  283. }
  284. if(empty($cartList)){
  285. return ResultWrapper::success(['data' => [],'total' => 0]);
  286. }
  287. $data = self::formatGoodsAndShop($cartList,$userCouponId);
  288. //是否有改价操作,收银台,操作
  289. $formatResult = self::buildSetPriceCart($data);
  290. if (!$formatResult->isSuccess()){
  291. return ResultWrapper::fail($formatResult->getData(),$formatResult->getErrorCode());
  292. }
  293. $data = $formatResult->getData();//最终数据
  294. $zeroResult = $this->buildZero($data,$isZero);
  295. if (!$zeroResult->isSuccess()){
  296. return ResultWrapper::fail($zeroResult->getData(),$zeroResult->getErrorCode());
  297. }
  298. $data = $zeroResult->getData();//最终数据
  299. //订单使用的优惠券
  300. $userCouponInfo = [];
  301. if (!empty($userCouponId)) {
  302. $objMUserCoupon = new MUserCoupon($this->onlineUserId, $this->onlineEnterpriseId);
  303. $dbResult = $objMUserCoupon->getUserCoupon(['id' => $userCouponId]);
  304. if ($dbResult->isSuccess()) $userCouponInfo = $dbResult->getData();
  305. $userCouponInfo = isset($userCouponInfo[0]) ? $userCouponInfo[0] : [];
  306. }
  307. $data['useCoupon'] = $userCouponInfo;
  308. //优惠券数据
  309. $data = self::findCoupon($data);
  310. $return = [
  311. 'data' => $data,
  312. 'total' => empty($data) ? 0 : count($data),
  313. ];
  314. return ResultWrapper::success($return);
  315. }
  316. /**
  317. * Doc: (des="判断字符串是否是一个整数")
  318. * User: XMing
  319. * Date: 2020/10/12
  320. * Time: 10:29 上午
  321. * @param $num
  322. * @return bool
  323. */
  324. private static function isInteger($num)
  325. {
  326. if ($num - floor($num) != 0){
  327. return false;
  328. }
  329. return true;
  330. }
  331. /**
  332. * 后台--清空用户购物车
  333. */
  334. public function clearCart()
  335. {
  336. $where['cashierUid'] = $this->cashierUid;
  337. $dbResult = $this->objDCashierCart->delete($where);
  338. if ($dbResult === false) {
  339. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  340. }
  341. return ResultWrapper::success($dbResult);
  342. }
  343. /**
  344. * 判断在使用范围的店铺,指定商品是否满足最小金额
  345. * 查询可用的优惠券
  346. * @param $data
  347. * @return mixed
  348. * @throws \Exception
  349. */
  350. private function findCoupon($data)
  351. {
  352. $objMUserCoupon = new MUserCoupon($this->onlineUserId, $this->onlineEnterpriseId);
  353. $objGoodsBasicRelevant = new GoodsBasicRelevant($this->onlineEnterpriseId);
  354. $payAmount = $data['payMoney'];
  355. if ($data['activityMoney'] != 0) {
  356. $payAmount = bcsub($payAmount, $data['activityMoney'], 2);
  357. }
  358. $dbResult = $objMUserCoupon->availableCoupon([
  359. 'payAmount' => $payAmount
  360. ]);
  361. if (!$dbResult->isSuccess()) {
  362. return ResultWrapper::fail($dbResult->getData(), ErrorCode::$dberror);
  363. }
  364. $coupon = $dbResult->getData();
  365. foreach ($coupon as $key => $val) {
  366. $useShop = explode(',', $val['useShop']);//此优惠券可以使用的店铺
  367. $applyRange = $val['applyRange'];//优惠券使用范围
  368. $cart[$val['id']]['money'] = 0;
  369. foreach ($data['goodsData'] as $shopGoodsData) {
  370. foreach ($shopGoodsData['shopGoodsData'] as $goodsDetail) {
  371. $categoryId = $objGoodsBasicRelevant->getNameByBasicId($goodsDetail['goodsBasicId'], 'categoryId');
  372. $brandId = $objGoodsBasicRelevant->getNameByBasicId($goodsDetail['goodsBasicId'], 'brandId');
  373. if ( in_array($shopGoodsData['shopId'], $useShop) &&
  374. ($applyRange == StatusCode::$applyRange['allGoods'] ||
  375. in_array($categoryId, explode(',', $val['categoryCollect'])) ||
  376. in_array($goodsDetail['goodsId'],explode(',',$val['goodsCollect'])) )
  377. ) {
  378. $cart[$val['id']]['money'] = bcadd($cart[$val['id']]['money'], $goodsDetail['totalMoney']);//规定范围内的商品总金额
  379. }
  380. }
  381. }
  382. if ($val['minPrice'] != 0 && $cart[$val['id']]['money'] < $val['minPrice']) {
  383. unset($coupon[$key]);//不符合要求
  384. }
  385. }
  386. $data['coupon'] = array_values($coupon);
  387. return $data;
  388. }
  389. /**
  390. * Doc: (des="抹零操作")
  391. * User: XMing
  392. * Date: 2020/9/12
  393. * Time: 7:08 下午
  394. * @param array $data
  395. * @param int $isZero
  396. * @return ResultWrapper
  397. */
  398. private function buildZero($data,$isZero)
  399. {
  400. //是否开启抹零
  401. $data['rem_money'] = '0.00';
  402. $settingResult = $this->objMCashierSettings->get();
  403. if (!$settingResult->isSuccess()){
  404. return ResultWrapper::fail($settingResult->getData(),$settingResult->getErrorCode());
  405. }
  406. $setting = $settingResult->getData();
  407. if (!is_array($setting)){
  408. //不是数组时,说明未配置
  409. return ResultWrapper::success($data);
  410. }
  411. if (!isset($setting['add_form'])){
  412. return ResultWrapper::fail('收银台配置错误',ErrorCode::$paramError);
  413. }
  414. if (!isset($setting['add_form']['zero_set'])){
  415. return ResultWrapper::fail('收银台参数配置错误',ErrorCode::$paramError);
  416. }
  417. $zeroSet = $setting['add_form']['zero_set'];
  418. if ($zeroSet['status'] == StatusCode::$delete){
  419. //没有开启抹零,前台需要在抹零那判断是否开启
  420. return ResultWrapper::success($data);
  421. }
  422. $payMoney = $data['payMoney'];
  423. if ($zeroSet['auto_zero'] == StatusCode::$standard){
  424. //开启了自动抹零
  425. switch ($zeroSet['type']){
  426. case 1:
  427. //分
  428. $newPatMoney = bcadd($payMoney,0,1);
  429. break;
  430. case 2:
  431. //角
  432. $newPatMoney = bcadd($payMoney,0,0);
  433. break;
  434. case 3:
  435. //到角
  436. $newPatMoney = round($payMoney, 1);
  437. break;
  438. case 4:
  439. //到元
  440. $newPatMoney = round($payMoney, 0);
  441. break;
  442. default:
  443. $newPatMoney = 0;
  444. break;
  445. }
  446. $rem_money = bcsub($payMoney,$newPatMoney,2);
  447. $data['payMoney'] = $newPatMoney;
  448. $data['rem_money'] = $rem_money;
  449. }else{
  450. if ($isZero == StatusCode::$standard){
  451. //手动抹零
  452. switch ($zeroSet['type']){
  453. case 1:
  454. //分
  455. $newPatMoney = bcadd($payMoney,0,1);
  456. break;
  457. case 2:
  458. //角
  459. $newPatMoney = bcadd($payMoney,0,0);
  460. break;
  461. case 3:
  462. //到角
  463. $newPatMoney = round($payMoney, 1);
  464. break;
  465. case 4:
  466. //到元
  467. $newPatMoney = round($payMoney, 0);
  468. break;
  469. default:
  470. $newPatMoney = 0;
  471. break;
  472. }
  473. $rem_money = bcsub($payMoney,$newPatMoney,2);
  474. $data['payMoney'] = $newPatMoney;
  475. $data['rem_money'] = $rem_money;
  476. }
  477. }
  478. return ResultWrapper::success($data);
  479. }
  480. /**
  481. * Doc: (des="修改价格")
  482. * User: XMing
  483. * Date: 2020/9/12
  484. * Time: 2:48 下午
  485. * @param $data
  486. * @return ResultWrapper
  487. */
  488. private function buildSetPriceCart($data)
  489. {
  490. $allGoodsData = $data['goodsData'];
  491. $goodsData = array_shift($allGoodsData);
  492. $shopGoodsData = $goodsData['shopGoodsData'];
  493. $skuIds = [];
  494. foreach ($shopGoodsData as $item){
  495. $skuIds[] = $item['skuId'];
  496. }
  497. if (empty($skuIds)){
  498. return ResultWrapper::success($data);
  499. }
  500. //获取本收银员有没有对商品设置过价格
  501. $priceLists = $this->objDCashierCustomerPrice->select(
  502. [
  503. 'skuId' => $skuIds,
  504. 'cashierUid' => $this->cashierUid,
  505. 'customerUid' => $this->onlineUserId
  506. ],
  507. 'price,skuId'
  508. );
  509. if ($priceLists === false){
  510. return ResultWrapper::fail($this->objDCashierCustomerPrice->error(),ErrorCode::$dberror);
  511. }
  512. if (empty($priceLists)){
  513. return ResultWrapper::success($data);
  514. }
  515. $customerPriceMap = [];
  516. foreach ($priceLists as $val){
  517. $customerPriceMap[$val['skuId']] = $val['price'];
  518. }
  519. if (empty($customerPriceMap)){
  520. return ResultWrapper::success($data);
  521. }
  522. foreach ($shopGoodsData as $key => &$item){
  523. $item['subPrice'] = 0;
  524. if (!isset($customerPriceMap[$item['skuId']])){
  525. //没有修改价格
  526. continue;
  527. }
  528. $oldPrice = $item['price'];
  529. $changePrice = $customerPriceMap[$item['skuId']];
  530. $item['price'] = $changePrice;
  531. $item['subUnitPrice'] = bcsub($oldPrice,$changePrice,2);
  532. $item['subPrice'] = bcmul($item['subUnitPrice'],$item['buyNum'],2);
  533. $item['totalMoney'] = bcmul($item['price'],$item['buyNum'],2);
  534. }
  535. $totalMoney = array_sum(array_column($shopGoodsData,'totalMoney'));
  536. $setPriceSubMoney = bcadd(array_sum(array_column($shopGoodsData,'subPrice')),0,2);
  537. $goodsData['totalMoney'] = $totalMoney;
  538. $goodsData['subPrice'] = $setPriceSubMoney;
  539. $goodsData['payMoney'] = $totalMoney;
  540. $goodsData['shopGoodsData'] = array_values($shopGoodsData);
  541. $data['totalMoney'] = $totalMoney;
  542. $data['subPrice'] = $setPriceSubMoney;
  543. $data['payMoney'] = $totalMoney;
  544. $data['goodsData'] = [$goodsData];
  545. return ResultWrapper::success($data);
  546. }
  547. /**
  548. * 拼装购物车数据(商铺->商品->规格->库存->价格->分组)
  549. * 此方法正在修改,勿动
  550. * @param $data
  551. * @param $userCouponId
  552. * @param $vipCardId
  553. * @return array|mixed
  554. * @throws \Exception
  555. */
  556. private function formatGoodsAndShop($data, $userCouponId = null, $vipCardId = null)
  557. {
  558. foreach ($data as &$value){
  559. $value['buyNum'] = self::isInteger($value['buyNum']) ? (int)$value['buyNum'] : $value['buyNum'];
  560. }
  561. unset($value);
  562. $result = self::formatShop($data);//格式化店铺数据
  563. $result = self::formatGoods($result);//格式化商品数据
  564. /*if ($this->isFront === true){
  565. $result = self::calExpress($result);
  566. if(!$result->isSuccess()){
  567. return ResultWrapper::fail($result->getData(),$result->getErrorCode());
  568. }
  569. $result = $result->getData();
  570. }*/
  571. $result = self::formatPrice($result);//处理价格
  572. $result = self::formatSkuInventory($result);//处理库存
  573. $result = self::formatGroup($result, $userCouponId, $vipCardId);
  574. /**foreach ($result as &$row){
  575. * $row['basicGoodsId'] = $row['goodsBasicId'];
  576. * $row = $objMGoods->formatMultipleSkuMapping($row, StatusCode::$standard);//处理属性
  577. * $row['skuData'] = $row['specMultiple'];
  578. * //unset($row['specMultiple']);
  579. * }**/
  580. return $result;
  581. }
  582. /**
  583. * 数据分组
  584. *
  585. * @param $data
  586. * @param null $userCouponId
  587. * @param null $vipCardId
  588. * @return array
  589. * @throws \Exception
  590. */
  591. private function formatGroup($data, $userCouponId = null, $vipCardId = null)
  592. {
  593. static $checkNum = 0;//购物车中选中商品数量
  594. static $totalMoney = 0;//原总额
  595. static $payMoney = 0;//实际支付金额
  596. static $preferential = 0;//优惠券优惠
  597. static $cartNum = 0;
  598. static $goodsNum = 0;//购物车商品数量
  599. static $vipDiscount = 0;//会员卡优惠金额
  600. static $vipDoubleDiscount = 0;//会员卡折上折优惠金额
  601. static $activityMoney = 0;//互斥活动商品总金额
  602. static $expressMoney = 0;//运费
  603. $goodsData = [];
  604. foreach ($data as $key => $val) {
  605. if (!isset($val['expressMoney'])){
  606. $val['expressMoney'] = '0.00';
  607. }
  608. $shopGoodsData[$val['shopId']][] = $val;
  609. if (!isset($goodsData[$val['shopId']]['totalMoney'])) {
  610. $goodsData[$val['shopId']]['totalMoney'] = '0.00';
  611. }
  612. if (!isset($goodsData[$val['shopId']]['preferential'])) {
  613. $goodsData[$val['shopId']]['preferential'] = '0.00';
  614. }
  615. if (!isset($goodsData[$val['shopId']]['expressMoney'])){
  616. $goodsData[$val['shopId']]['expressMoney'] = '0.00';
  617. }
  618. $goodsData[$val['shopId']] = [
  619. 'shopId' => $val['shopId'],
  620. 'shopName' => $val['shopName'],
  621. 'shopLogo' => $val['shopLogo'],
  622. 'expressMoney' => bcadd($goodsData[$val['shopId']]['expressMoney'],$val['expressMoney'],2),
  623. 'totalMoney' => bcadd($goodsData[$val['shopId']]['totalMoney'], $val['totalMoney'], 2),//(购物车总金额)
  624. 'preferential' => bcadd($goodsData[$val['shopId']]['preferential'], bcmul($val['preferential'], $val['buyNum']), 2),//店铺总优惠金额
  625. 'payMoney' => bcsub(bcadd($goodsData[$val['shopId']]['totalMoney'], $val['totalMoney']), bcadd($goodsData[$val['shopId']]['preferential'], bcmul($val['preferential'], $val['buyNum'])), 2),//(购物实付金额)
  626. 'shopGoodsData' => $shopGoodsData[$val['shopId']],//商品数据
  627. ];
  628. //统计选中商品总数
  629. if ($val['selection'] == StatusCode::$standard) {
  630. $checkNum = bcadd($checkNum, 1);
  631. $totalMoney = bcadd($totalMoney, $val['totalMoney'], 2);
  632. $payMoney =bcadd(bcadd($expressMoney,$val['expressMoney'],2),bcadd($payMoney, bcsub($val['totalMoney'], bcmul($val['buyNum'], $val['preferential'])), 2),2);
  633. $preferential = bcadd($preferential, bcmul($val['buyNum'], $val['preferential']), 2);
  634. $activityMoney = bcadd($activityMoney, $val['activityMoney'], 2);//互斥商品总金额
  635. $expressMoney = bcadd($expressMoney,$val['expressMoney'],2);
  636. }
  637. $cartNum = bcadd($cartNum, 1);
  638. $goodsNum = bcadd($goodsNum, $val['buyNum']);
  639. }
  640. //处理运费
  641. if (!empty($this->startDeliveryPrice) && $expressMoney != 0 && $this->startDeliveryPrice <= $payMoney && $this->startDeliveryPrice > 0.01){
  642. $payMoney = bcsub($payMoney,$expressMoney,2);
  643. foreach($goodsData as &$datum){
  644. $datum['expressMoney'] = '0.00';
  645. $shopGoodsLists = $datum['shopGoodsData'];
  646. foreach ($shopGoodsLists as &$val){
  647. $val['expressMoney'] = '0.00';
  648. }
  649. $datum['shopGoodsData'] = $shopGoodsLists;
  650. }
  651. $expressMoney = '0.00';
  652. }
  653. unset($datum);
  654. unset($val);
  655. $result = [
  656. 'totalMoney' => $totalMoney,
  657. 'payMoney' => $payMoney,
  658. 'preferential' => $preferential,
  659. 'vipDiscount' => $vipDiscount,
  660. 'vipDoubleDiscount' => $vipDoubleDiscount,
  661. 'activityMoney' => $activityMoney,
  662. 'expressMoney' => $expressMoney,
  663. 'checkNum' => (int)$checkNum,
  664. 'cartNum' => (int)$cartNum,
  665. 'goodsNum' => (int)$goodsNum,
  666. 'goodsData' => array_values($goodsData),
  667. 'invalidData' => array_values($this->invalidData)
  668. ];
  669. //会员卡计算
  670. //if (!empty($vipCardId) && $vipCardId != 0) $result = self::vipCardRec($result, $vipCardId);
  671. //优惠券计算
  672. if (!empty($userCouponId) && $userCouponId != 0) $result = self::couponRec($result, $userCouponId);
  673. if (
  674. (!empty($vipCardId) && $vipCardId != 0)
  675. || (!empty($userCouponId) && $userCouponId != 0)
  676. ) {
  677. //优惠券优惠,会员卡优惠分摊到商品
  678. $result = self::calAvg($result);
  679. }
  680. return $result;
  681. }
  682. /**
  683. * 获取商品价格,及计算价格 ,(有促销活动的用促销价)
  684. * (原数据+price+originPrice+preferential+totalMoney)
  685. * @param $data
  686. * @return mixed
  687. * @throws \Exception
  688. */
  689. private function formatPrice($data)
  690. {
  691. if (empty($data)) return $data;
  692. $objMPrice = new MPrice($this->onlineUserId, $this->onlineEnterpriseId);
  693. $objMActivity = new MActivity($this->onlineUserId, $this->onlineEnterpriseId);
  694. $objMCustomer = new MCustomer($this->onlineEnterpriseId, $this->onlineUserId);
  695. $selectParam['material'] = [];
  696. $allGoodsId = [];
  697. foreach ($data as &$goods) {
  698. $allGoodsId[] = $goods['goodsId'];
  699. $selectParam['material'][$goods['shopId']][] = $goods['goodsId'];
  700. $goods['originPrice'] = 0;//原价
  701. $goods['price'] = 0;//单价
  702. $goods['preferential'] = 0;//优惠差价
  703. $goods['totalMoney'] = 0;//小计(unitPrice*buyNum)
  704. $goods['activityMoney'] = 0;//互斥活动商品总金额
  705. $goods['isMutex'] = StatusCode::$delete;//初始化互斥状态
  706. }
  707. unset($goods);
  708. $selectParam['customerId'] = $this->customerId;
  709. $dbResult = $objMPrice->getPrice($selectParam);
  710. if (!$dbResult->isSuccess()) {
  711. return $data;
  712. }
  713. $priceResult = $dbResult->getData();
  714. unset($dbResult);
  715. $customerResult = $objMCustomer->getCustomerInfoByUserCenterId($this->onlineUserId);
  716. $activityArr = [];
  717. if ($customerResult->isSuccess()) {
  718. $customer = $customerResult->getData();
  719. //获取促销活动价格
  720. $dbResult = $objMActivity->getActivity([
  721. 'goodsId' => implode(',', $allGoodsId),
  722. 'customerType' => isset($customer['type']) ? $customer['type'] : 0,
  723. ]);//TODO
  724. $activityResult = $dbResult->getData();
  725. unset($dbResult);
  726. foreach ($activityResult as $activity) {
  727. $activityArr[$activity['goodsId'] . $activity['skuId']] = $activity;
  728. }
  729. }
  730. //print_r($activityArr);
  731. //商品价格信息
  732. $goodsArr = [];
  733. foreach ($priceResult as $shopPriceArr) {
  734. foreach ($shopPriceArr as $goodsId => $goodsSkuArr) {
  735. $goodsArr[$goodsId] = $goodsSkuArr;
  736. }
  737. }
  738. //print_r($data);die;
  739. foreach ($data as &$goods) {
  740. //此商品存在促销价
  741. if (isset($activityArr[$goods['goodsId'] . $goods['skuId']])) {
  742. $price = $goodsArr[$goods['goodsId']][$goods['skuId']]['salePrice'];//商品正常销售价格
  743. //从缓存中获取活动详情
  744. if (isset($goods['activityId']) && !empty($goods['activityId'])) {
  745. $price = $activityArr[$goods['goodsId'] . $goods['skuId']]['price'];//商品活动价格
  746. $activityDetail = $this->objActivityLimitCache->getActivity($goods['activityId']);
  747. if (!empty($activityDetail) && $activityDetail['isMutex'] == StatusCode::$standard) {
  748. //开启互斥商品的总金额
  749. $goods['activityMoney'] = bcmul($price, $goods['buyNum'], 2);
  750. $goods['isMutex'] = StatusCode::$standard;
  751. }
  752. }
  753. } else {
  754. if (isset($goodsArr[$goods['goodsId']][$goods['skuId']])) {
  755. $priceInfo = $goodsArr[$goods['goodsId']][$goods['skuId']];//此商品规格的价格信息
  756. $price = isset($priceInfo['salePrice']) ? $priceInfo['salePrice'] : 0;
  757. // 开启阶梯价
  758. if ($priceInfo['enabledLadder']) {
  759. foreach ($priceInfo['ladderPrice'] as $ladder) {
  760. if ($goods['buyNum'] >= $ladder['from'] && $goods['buyNum'] <= $ladder['to']) {
  761. $price = isset($ladder['price']) ? $ladder['price'] : 0;
  762. }
  763. }
  764. }
  765. }
  766. }
  767. if (!isset($price)) $price = 0;
  768. $price = floatval($price);
  769. $goods['price'] = sprintf("%.2f", $price);
  770. $goods['originPrice'] = sprintf("%.2f", $price);//没有优惠活动暂时原价=销售价
  771. $goods['preferential'] = 0;//优惠券优惠金额
  772. $goods['totalMoney'] = bcmul($price, $goods['buyNum'], 2);//商品小计金额
  773. $goods['vipDiscount'] = 0;//会员卡优惠金额
  774. }
  775. return $data;
  776. }
  777. /**
  778. * 获取店铺信息
  779. * (原数据上+店铺名称+店铺logo)
  780. * @param $data
  781. * @return mixed
  782. * @throws \Exception
  783. */
  784. private function formatShop($data)
  785. {
  786. if (empty($data)) return $data;
  787. $objMGoods = new MShop($this->onlineEnterpriseId, $this->onlineUserId);
  788. $shopData = $objMGoods->getShopName(array_unique(array_column($data, 'shopId')));
  789. if (!empty($shopData)) {
  790. foreach ($data as &$shop) {
  791. $shop['shopName'] = isset($shopData[$shop['shopId']]['name']) ? $shopData[$shop['shopId']]['name'] : '';
  792. $shop['shopLogo'] = isset($shopData[$shop['shopId']]['logo']) ? $shopData[$shop['shopId']]['logo'] : '';
  793. $shop['cartId'] = $shop['id'];
  794. }
  795. }
  796. return $data;
  797. }
  798. /**
  799. * 商品信息
  800. * (原数据基础上+商品名称+商品图片)商品的状态 下架商品计入失效
  801. * @param $data
  802. * @return mixed
  803. * @throws \Exception
  804. */
  805. private function formatGoods($data)
  806. {
  807. if (empty($data)) return $data;
  808. $objGoodsBasicRelevantCache = new GoodsBasicRelevant($this->onlineEnterpriseId);
  809. $objMGoods = new MGoods($this->onlineEnterpriseId, false, $this->onlineUserId);
  810. $goodsData = $objMGoods->getGoodsNames(array_unique(array_column($data, 'goodsId')));
  811. if (!empty($goodsData)) {
  812. $dbResult = $objMGoods->getNameByGoodsIds(array_values(array_unique(array_column($goodsData, 'basicGoodsId'))));
  813. if ($dbResult->isSuccess()) {
  814. $basicData = $dbResult->getData();
  815. foreach ($goodsData as &$goods) {
  816. $goods['goodsName'] = isset($basicData[$goods['basicGoodsId']]['title']) ? $basicData[$goods['basicGoodsId']]['title'] : '';
  817. $goods['describe'] = isset($basicData[$goods['basicGoodsId']]['describe']) ? $basicData[$goods['basicGoodsId']]['describe'] : '';
  818. $goods['categoryId'] = isset($basicData[$goods['basicGoodsId']]['categoryId']) ? $basicData[$goods['basicGoodsId']]['categoryId'] : '';
  819. $goods['brandId'] = isset($basicData[$goods['basicGoodsId']]['brandId']) ? $basicData[$goods['basicGoodsId']]['brandId'] : '';
  820. $goods['categoryPath'] = isset($basicData[$goods['basicGoodsId']]['categoryPath']) ? $basicData[$goods['basicGoodsId']]['categoryPath'] : '';
  821. $goods['specType'] = isset($basicData[$goods['basicGoodsId']]['specType']) ? $basicData[$goods['basicGoodsId']]['specType'] : StatusCode::$specType['single'];
  822. $goods['storageCode'] = isset($basicData[$goods['basicGoodsId']]['storageCode']) ? $basicData[$goods['basicGoodsId']]['storageCode'] : '';
  823. $goods['categoryName'] = empty($goods['categoryId']) ? '' : $objGoodsBasicRelevantCache->getNameByCategoryId($goods['categoryId']);
  824. $goods['brandName'] = empty($goods['brandId']) ? '' : $objGoodsBasicRelevantCache->getNameByBrandId($goods['brandId']);
  825. }
  826. }
  827. }
  828. $objMSku = new MSku($this->onlineUserId, $this->onlineEnterpriseId);
  829. $specNameMapping = $objMSku->getSpecNameBySkuId(array_column($data, 'skuId'));
  830. if (!$specNameMapping->isSuccess()) {
  831. Logger::logs(E_USER_ERROR,'获取sku错误',__CLASS__,__LINE__,$specNameMapping->getData());
  832. $specNameMapping = [];
  833. } else {
  834. $specNameMapping = $specNameMapping->getData();
  835. }
  836. foreach ($data as $key => &$val) {
  837. $val['brandName'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['brandName'] : '';
  838. $val['categoryName'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['categoryName'] : '';
  839. $val['barCode'] = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['barCode'] : '';
  840. $val['storageCode'] = isset($goodsData[$val['goodsId']]['storageCode']) ? $goodsData[$val['goodsId']]['storageCode'] : '';
  841. $val['goodsName'] = isset($goodsData[$val['goodsId']]['goodsName']) ? $goodsData[$val['goodsId']]['goodsName'] : '';
  842. $images = isset($goodsData[$val['goodsId']]['images']) ? json_decode($goodsData[$val['goodsId']]['images'], true) : '';
  843. $val['goodsImages'] = empty($images) ? '' : $images[0];
  844. $val['isInvalid'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['enableStatus'] : StatusCode::$delete;//4=>失效商品
  845. $val['describe'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['describe'] : '';
  846. $val['categoryId'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['categoryId'] : '';
  847. $val['brandId'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['brandId'] : '';
  848. $val['categoryPath'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['categoryPath'] : '';
  849. $val['isActivity'] = empty($val['activityId']) ? StatusCode::$delete : StatusCode::$standard;//是否是活动商品
  850. $val['specType'] = isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['specType'] : StatusCode::$specType['single'];
  851. $val['unitName'] = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['unitName'] : '';
  852. $val['specGroup'] = isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['specGroup'] : [];
  853. $val['notExpress'] = StatusCode::$standard;
  854. $val['express'] = [
  855. 'weight' => isset($specNameMapping[$val['skuId']]) ? $specNameMapping[$val['skuId']]['weight'] : 0,
  856. 'expressType' => isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['expressType'] : 0,
  857. 'ruleId' => isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['ruleId'] : 0,
  858. 'expressFee' => isset($goodsData[$val['goodsId']]) ? $goodsData[$val['goodsId']]['expressFee'] : 0,
  859. ];
  860. if (isset($goodsData[$val['goodsId']]) && ($goodsData[$val['goodsId']]['enableStatus'] == StatusCode::$delete || $goodsData[$val['goodsId']]['deleteStatus'] == StatusCode::$delete)) {
  861. $val['invalidMsg'] = '此商品已下架';
  862. $this->invalidData[] = $val;//失效商品集合
  863. unset($data[$key]);
  864. }
  865. }
  866. return $data;
  867. }
  868. /**
  869. * 查询库存以及成本(*goodsBasicId *warehouseId) 库存不足的商品计入失效
  870. * (原数据+costPrice+inventoryNum)
  871. * @param $data
  872. * @return mixed
  873. * @throws \Exception
  874. */
  875. private function formatSkuInventory($data)
  876. {
  877. $inventorySelectParams = [];
  878. $skuIds = [];
  879. foreach ($data as &$goods) {
  880. $skuIds[] = $goods['skuId'];
  881. $goods['inventory'] = 0;
  882. $inventorySelectParams[$goods['shopId']][] = $goods['skuId'];
  883. }
  884. unset($goods);
  885. $objMInventory = new MInventory($this->onlineEnterpriseId, $this->onlineUserId);
  886. $inventoryMap = [];
  887. foreach ($inventorySelectParams as $shopId => $skuIds){
  888. $inventoryResult = $objMInventory->getInventoryByShopIdAndSkuIds($shopId,$skuIds);
  889. if (!$inventoryResult->isSuccess()) {
  890. return $data;
  891. }
  892. $inventoryMap[$shopId] = $inventoryResult->getData();
  893. }
  894. $objMSku = new MSku($this->onlineUserId, $this->onlineEnterpriseId);
  895. foreach ($data as $key => &$goods) {
  896. $h=['id'=>$goods['skuId']];
  897. $specNameMapping = $objMSku->getSpecNameBySkuId($h);
  898. $specNameMapping = $specNameMapping->getData();
  899. foreach ($specNameMapping as $v){
  900. $thisSku=$v;
  901. }
  902. //兼容带属性的
  903. $goods['costPrice'] = 0;
  904. $goods['inventoryNum'] = isset($inventoryMap[$goods['shopId']][$goods['skuId']]['num']) ? $inventoryMap[$goods['shopId']][$goods['skuId']]['num'] : 0;
  905. $goods['conversion'] = $thisSku['conversion'];//换算比例
  906. if ($goods['inventoryNum'] < $goods['buyNum']) {
  907. $goods['isInvalid'] = StatusCode::$delete;
  908. $goods['invalidMsg'] = '商品库存不足';
  909. $this->invalidData[] = $goods;
  910. unset($data[$key]);
  911. }
  912. }
  913. return $data;
  914. }
  915. /**
  916. * 缓存用户限购
  917. * @param $data
  918. * @return mixed
  919. */
  920. private function userLimit($data)
  921. {
  922. $result = false;
  923. foreach ($data as $goods) {
  924. $result = $this->objActivityLimitCache->writeLimit($goods['activityId'], $goods['goodsId'], $goods['skuId'], $this->onlineUserId, $goods['buyNum']);
  925. }
  926. return $result;
  927. }
  928. /**
  929. * Doc: (des="检测商品")
  930. * User: XMing
  931. * Date: 2020/8/4
  932. * Time: 3:21 下午
  933. * @param array $goodsData
  934. * @param array $addCart
  935. * @return ResultWrapper
  936. */
  937. private static function checkGoods(array $goodsData,array $addCart)
  938. {
  939. if (empty($goodsData)){
  940. return ResultWrapper::fail('商品信息为空',ErrorCode::$paramError);
  941. }
  942. //验证商品的状态以及库存
  943. if ($goodsData['enableStatus'] == StatusCode::$delete || $goodsData['deleteStatus'] == StatusCode::$delete){
  944. return ResultWrapper::fail('商品已下架',ErrorCode::$paramError);
  945. }
  946. $specMultiple = $goodsData['specMultiple'];//spec数据
  947. if (empty($specMultiple)){
  948. return ResultWrapper::fail('商品规格信息获取失败',ErrorCode::$paramError);
  949. }
  950. $specMultipleMap = [];//商品规格映射数据
  951. foreach ($specMultiple as $value){
  952. $specMultipleMap[$value['id']] = $value;
  953. }
  954. if (!isset($specMultipleMap[$addCart['skuId']])) {
  955. return ResultWrapper::fail('规格信息不存在', ErrorCode::$paramError);
  956. }
  957. if ($specMultipleMap[$addCart['skuId']]['inventory'] < $addCart['buyNum']) {
  958. return ResultWrapper::fail('商品库存不足', ErrorCode::$paramError);
  959. }
  960. $addCart['isActivity'] = $specMultipleMap[$addCart['skuId']]['isActivity'];//是否是活动商品
  961. $addCart['setNum'] = $specMultipleMap[$addCart['skuId']]['setNum'];//起订数量
  962. $addCart['warehouseId'] = $addCart['warehouseId'];
  963. switch ($specMultipleMap[$addCart['skuId']]['isActivity']){
  964. case StatusCode::$standard:
  965. $addCart['activityId'] = $specMultipleMap[$addCart['skuId']]['activity']['activityId'];
  966. $addCart['limitNum'] = $specMultipleMap[$addCart['skuId']]['activity']['limitNum'];//商品活动限购数量
  967. break;
  968. case StatusCode::$delete:
  969. $addCart['activityId'] = 0;
  970. break;
  971. }
  972. return ResultWrapper::success($addCart);
  973. }
  974. /**
  975. * 将加入购物车的数据进行分组[old=>在购物车中已存在,now=>新加入购物车商品]
  976. * @param $nowData [加入购物车的数据]
  977. * @return ResultWrapper
  978. */
  979. private function existCartAndGroup($nowData)
  980. {
  981. $dbResult = self::getCartByUid();
  982. if (!$dbResult->isSuccess()) {
  983. return ResultWrapper::fail('获取购物车数据失败', ErrorCode::$dberror);
  984. }
  985. $oldCartData = $dbResult->getData();
  986. $allHash = [];
  987. foreach ($oldCartData as $key => $val) {
  988. $allHash[] = md5($val['goodsId'] . $val['shopId'] . $val['skuId'] . $val['activityId']);
  989. }
  990. $old = [];//旧的数据
  991. $now = [];//新的数据
  992. foreach ($nowData as $key => &$val) {
  993. $md5 = md5($val['goodsId'] . $val['shopId'] . $val['skuId'] . $val['activityId']);
  994. if (in_array($md5, $allHash)) {
  995. $old[] = $val;
  996. } else {
  997. //之前购物车中没有此商品,检查起订量
  998. if ($val['setNum'] != 0) {
  999. //具有起订量
  1000. if ($val['buyNum'] < $val['setNum']){
  1001. $val['buyNum'] = $val['setNum'];
  1002. }
  1003. }
  1004. $now[] = $val;
  1005. }
  1006. }
  1007. $groupData = [
  1008. 'old' => $old,
  1009. 'now' => $now
  1010. ];
  1011. return ResultWrapper::success($groupData);
  1012. }
  1013. /**
  1014. * 获取当前用户的购物车数据
  1015. */
  1016. private function getCartByUid()
  1017. {
  1018. $result = $this->objDCashierCart->select(['cashierUid' => $this->cashierUid], 'id,goodsId,goodsCode,buyNum,shopId,goodsBasicId,selection,skuId,warehouseId,activityId,cashierUid', 'createTime DESC');
  1019. if ($result === false) {
  1020. return ResultWrapper::fail($this->objDCashierCart->error(), ErrorCode::$dberror);
  1021. }
  1022. return ResultWrapper::success($result);
  1023. }
  1024. /**
  1025. *
  1026. * 优惠计算分摊规则
  1027. * A商品 100元
  1028. * B商品 300元
  1029. * 商品总价 400元
  1030. *
  1031. * A商品享受的优惠 = 优惠券金额*(A商品原价/商品总价)
  1032. * B商品享受的优惠 = 优惠券金额*(B商品原价/商品总价)
  1033. *
  1034. * 5折会员卡 400*0.5=200元 -200
  1035. * 优惠券(满100减20) -20
  1036. * 共 -220
  1037. * 实际付款 180
  1038. * A总(220*(100/400)=55) 优惠券(20*(100/400)=5) 会员卡(200*(100/400)=50)
  1039. * B总(220*(300/400)=165) 优惠券(20*(300/400)=15) 会员卡(200*(300/400)=150)
  1040. * @param $data
  1041. * @return mixed
  1042. */
  1043. private function calAvg($data)
  1044. {
  1045. $account = 0;
  1046. $vipAccount = 0;
  1047. foreach ($data['goodsData'] as &$shops) {
  1048. $count = count($shops['shopGoodsData']);
  1049. foreach ($shops['shopGoodsData'] as $key => &$goods) {
  1050. if ($goods['isMutex'] == StatusCode::$delete) {
  1051. //活动商品不分摊
  1052. if ($data['preferential'] != 0) {
  1053. //有优惠券优惠,分摊金额
  1054. if ($key+1 != $count) {
  1055. $goods['preferential'] = bcmul($data['preferential'], bcdiv($goods['totalMoney'], $data['totalMoney'], 2), 2);
  1056. $account = bcadd($account,$goods['preferential'],2);
  1057. }else{
  1058. //最后一个商品分摊金额=总优惠-其他均摊
  1059. $goods['preferential'] = bcsub($data['preferential'],$account,2);
  1060. }
  1061. }
  1062. }
  1063. if ($data['vipDiscount'] != 0) {
  1064. //有会员卡折扣,分摊金额
  1065. if ($key+1 != $count){
  1066. $goods['vipDiscount'] = bcmul($data['vipDiscount'], bcdiv($goods['totalMoney'], $data['totalMoney'], 2), 2);
  1067. $vipAccount = bcadd($vipAccount,$goods['vipDiscount'],2);
  1068. }else{
  1069. $goods['vipDiscount'] = bcsub($data['vipDiscount'],$vipAccount,2);
  1070. }
  1071. }
  1072. }
  1073. }
  1074. return $data;
  1075. }
  1076. /**
  1077. * 优惠券优惠
  1078. * @param $data
  1079. * @param $userCouponId
  1080. * @return mixed
  1081. * @throws \Exception
  1082. */
  1083. private function couponRec($data, $userCouponId)
  1084. {
  1085. //优惠券
  1086. $userCouponInfo = [];
  1087. if (!empty($userCouponId)) {
  1088. $objMUserCoupon = new MUserCoupon($this->onlineUserId, $this->onlineEnterpriseId);
  1089. $dbResult = $objMUserCoupon->getUserCoupon(['id' => $userCouponId]);
  1090. if ($dbResult->isSuccess()) $userCouponInfo = $dbResult->getData();
  1091. $userCouponInfo = isset($userCouponInfo[0]) ? $userCouponInfo[0] : [];
  1092. $isMutex = $userCouponInfo['isMutex'];//是否与活动互斥
  1093. if ($userCouponInfo['applyRange'] == StatusCode::$applyRange['allGoods']) {
  1094. //优惠券的使用范围所有商品
  1095. if ($userCouponInfo['minPrice'] == 0 || $data['payMoney'] >= $userCouponInfo['minPrice']) {
  1096. //满足最低消费金额
  1097. $data['payMoney'] = bcsub($data['payMoney'], $userCouponInfo['reducePrice'], 2);
  1098. if ($data['payMoney'] < 0) {
  1099. $data['payMoney'] = 0;//优惠券面值不合理导致优惠后价格小于0
  1100. }
  1101. $data['preferential'] = bcadd($data['preferential'], $userCouponInfo['reducePrice'], 2);
  1102. }
  1103. } else if ($userCouponInfo['applyRange'] == StatusCode::$applyRange['appointCategory']) {
  1104. //优惠券使用范围指定分类
  1105. $couponCategory = $userCouponInfo['categoryCollect'];
  1106. if (!empty($couponCategory)) {
  1107. $goodsAmount = 0; //满足特定商品分类的(商品总额),初始化
  1108. $couponCategory = explode(',', $couponCategory);
  1109. //计算符合分类中商品价格总和
  1110. foreach (array_values($data['goodsData']) as $shop) {
  1111. foreach ($shop['shopGoodsData'] as $value) {
  1112. //$value['categoryId']
  1113. if (in_array($value['categoryId'], $couponCategory)) {
  1114. //满足特定商品分类的(商品总额)
  1115. $goodsAmount = bcadd($goodsAmount, $value['totalMoney']);
  1116. }
  1117. }
  1118. }
  1119. //商品总额是否满足最低金额
  1120. if ($userCouponInfo['minPrice'] == 0 || $goodsAmount >= $userCouponInfo['minPrice']) {
  1121. $data['payMoney'] = bcsub($data['payMoney'], $userCouponInfo['reducePrice'], 2);
  1122. if ($data['payMoney'] < 0) {
  1123. $data['payMoney'] = 0;//优惠券面值不合理导致优惠后价格小于0
  1124. }
  1125. $data['preferential'] = bcadd($data['preferential'], $userCouponInfo['reducePrice'], 2);
  1126. }
  1127. }
  1128. } else if ($userCouponInfo['applyRange'] == StatusCode::$applyRange['appointBrand']) {
  1129. //优惠券使用范围指定品牌
  1130. $couponBrand = $userCouponInfo['brandCollect'];
  1131. if (!empty($couponBrand)) {
  1132. $goodsAmount = 0; //满足特定商品品牌的(商品总额),初始化
  1133. $couponBrand = explode(',', $couponBrand);
  1134. //计算符合品牌中商品价格总和
  1135. foreach (array_values($data['goodsData']) as $shop) {
  1136. foreach ($shop['shopGoodsData'] as $value) {
  1137. //$value['categoryId']
  1138. if (in_array($value['brandId'], $couponBrand)) {
  1139. //满足特定商品品牌的(商品总额)
  1140. $goodsAmount = bcadd($goodsAmount, $value['totalMoney']);
  1141. }
  1142. }
  1143. }
  1144. //商品总额是否满足最低金额
  1145. if ($userCouponInfo['minPrice'] == 0 || $goodsAmount >= $userCouponInfo['minPrice']) {
  1146. $data['payMoney'] = bcsub($data['payMoney'], $userCouponInfo['reducePrice'], 2);
  1147. if ($data['payMoney'] < 0) {
  1148. $data['payMoney'] = 0;//优惠券面值不合理导致优惠后价格小于0
  1149. }
  1150. $data['preferential'] = bcadd($data['preferential'], $userCouponInfo['reducePrice'], 2);
  1151. }
  1152. }
  1153. }
  1154. unset($dbResult);
  1155. }
  1156. return $data;
  1157. }
  1158. }