CartCalculate.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace app\model\cart;
  11. use addon\coupon\model\Coupon;
  12. use addon\manjian\model\Manjian;
  13. use app\model\goods\Goods;
  14. use app\model\BaseModel;
  15. /**
  16. * 购物车计算
  17. *
  18. * @author Administrator
  19. *
  20. */
  21. class CartCalculate extends BaseModel
  22. {
  23. private $error = 0; //是否有错误
  24. private $error_msg = ''; //错误描述
  25. /**
  26. * 订单计算
  27. * @param unknown $data
  28. */
  29. public function calculate($data)
  30. {
  31. $data = $this->getGoodsList($data);
  32. $data = $this->manjianPromotion($data);
  33. $promotion_money = $data[ 'promotion_money' ] ?? 0;
  34. $order_money = $data[ 'goods_money' ] - $promotion_money;
  35. $data[ 'order_money' ] = $order_money;
  36. $data = $this->couponCalculate($data);
  37. return $data;
  38. }
  39. /**
  40. * 获取购物车商品列表信息
  41. * @param unknown $cart_ids
  42. */
  43. public function getGoodsList($data)
  44. {
  45. $site_id = $data[ 'site_id' ];
  46. $sku_ids = $data[ 'sku_ids' ] ?? [];
  47. $sku_id_list = array_column($sku_ids, 'sku_id');
  48. $member_id = $data[ 'member_id' ];
  49. $sku_num_list = array_column($sku_ids, 'num', 'sku_id');
  50. $goods_model = new Goods();
  51. //组装商品列表
  52. $field = 'ngs.sku_id, ngs.sku_name, ngs.sku_no, ngs.price, ngs.discount_price, ngs.cost_price, ngs.stock, ngs.sku_image,
  53. ngs.site_id, ngs.goods_id,ns.site_name,ngs.goods_name';
  54. $alias = 'ngs';
  55. $join = [
  56. [
  57. 'site ns',
  58. 'ngs.site_id = ns.site_id',
  59. 'inner'
  60. ]
  61. ];
  62. $condition = [
  63. [ 'ngs.sku_id', 'in', $sku_id_list ],
  64. [ 'ngs.site_id', '=', $site_id ]
  65. ];
  66. $goods_list = model('goods_sku')->getList($condition, $field, '', $alias, $join);
  67. if (!empty($goods_list)) {
  68. foreach ($goods_list as $k => $v) {
  69. $item_num = $sku_num_list[ $v[ 'sku_id' ] ];
  70. $price_result = $goods_model->getGoodsPrice($v[ 'sku_id' ], $member_id);
  71. $price_info = $price_result[ 'data' ];
  72. $price = $price_info[ 'price' ];
  73. $v[ 'price' ] = $price;
  74. $v[ 'goods_money' ] = $price * $item_num;//todo 这儿要改
  75. $v[ 'real_goods_money' ] = $v[ 'goods_money' ];
  76. $v[ 'coupon_money' ] = 0; //优惠券金额
  77. $v[ 'promotion_money' ] = 0; //优惠金额
  78. $v[ 'stock' ] = numberFormat($v[ 'stock' ]);
  79. if (!empty($data[ 'goods_list' ])) {
  80. $data[ 'goods_list' ][] = $v;
  81. $data[ 'goods_num' ] += $item_num;
  82. $data[ 'goods_money' ] += $v[ 'goods_money' ];
  83. } else {
  84. $data[ 'site_id' ] = $site_id;
  85. $data[ 'site_name' ] = $v[ 'site_name' ];
  86. $data[ 'goods_money' ] = $v[ 'goods_money' ];
  87. $data[ 'goods_num' ] = $item_num;
  88. $data[ 'goods_list' ][] = $v;
  89. }
  90. }
  91. }
  92. return $data;
  93. }
  94. /****************************************************************************** 满减 start *****************************************************************************/
  95. /**
  96. * 满减优惠
  97. * @param $data
  98. */
  99. public function manjianPromotion($data)
  100. {
  101. $site_id = $data[ 'site_id' ];
  102. $promotion_money = $data[ 'promotion_money' ] ?? 0;
  103. //先查询全部商品的满减套餐 进行中
  104. $manjian_model = new Manjian();
  105. $all_info = $manjian_model->getManjianInfo([ [ 'manjian_type', '=', 1 ], [ 'site_id', '=', $site_id ], [ 'status', '=', 1 ] ], 'manjian_name,type,goods_ids,rule_json,manjian_id')[ 'data' ] ?? [];
  106. $goods_list = $data[ 'goods_list' ];
  107. //存在全场满减(不考虑部分满减情况)
  108. if (!empty($all_info)) {
  109. $discount_array = $this->getManjianDiscountMoney($all_info, $data);
  110. $all_info[ 'discount_array' ] = $discount_array;
  111. $discount_money = $discount_array[ 'real_discount_money' ];
  112. $promotion_money += $discount_money;
  113. if (!empty($discount_array[ 'rule' ])) {
  114. $goods_list = array_map(function($item) use ($all_info) {
  115. $item[ 'promotion' ][ 'manjian' ] = $all_info;
  116. return $item;
  117. }, $goods_list);
  118. }
  119. } else {
  120. $goods_ids = array_unique(array_column($data[ 'goods_list' ], 'goods_id'));
  121. $manjian_condition = array (
  122. [ 'goods_id', 'in', $goods_ids ],
  123. [ 'status', '=', 1 ]
  124. );
  125. $manjian_goods_list_result = $manjian_model->getManjianGoodsList($manjian_condition, 'manjian_id');
  126. $manjian_goods_list = $manjian_goods_list_result[ 'data' ];
  127. if (!empty($manjian_goods_list)) {
  128. $discount_money = 0;
  129. $manjian_goods_list = array_column($manjian_goods_list, 'manjian_id');
  130. $manjian_goods_list = array_unique($manjian_goods_list); //去重
  131. sort($manjian_goods_list);
  132. $manjian_list_result = $manjian_model->getManjianList([ [ 'manjian_id', 'in', $manjian_goods_list ], [ 'status', '=', 1 ] ]);
  133. $manjian_list = $manjian_list_result[ 'data' ];
  134. foreach ($manjian_list as $k => $v) {
  135. $manjian_goods_ids = explode(',', $v[ 'goods_ids' ]);
  136. $item_goods_data = [
  137. 'goods_money' => 0,
  138. 'goods_num' => 0
  139. ];
  140. $item_goods_list = [];
  141. $sku_ids = [];
  142. foreach ($goods_list as $goods_k => $goods_item) {
  143. if (in_array($goods_item[ 'goods_id' ], $manjian_goods_ids)) {
  144. $item_goods_data[ 'goods_money' ] += $goods_item[ 'goods_money' ];
  145. $item_goods_data[ 'goods_num' ] += $goods_item[ 'num' ];
  146. $item_goods_list[] = $goods_item;
  147. array_push($sku_ids, $goods_item[ 'sku_id' ]);
  148. $goods_list[ $goods_k ] = $v;
  149. }
  150. }
  151. $discount_array = $this->getManjianDiscountMoney($v, $item_goods_data);
  152. $manjian_list[ $k ][ 'discount_array' ] = $discount_array;
  153. $discount_money += $discount_array[ 'real_discount_money' ];
  154. if (!empty($discount_array[ 'rule' ])) {
  155. $goods_list = array_map(function($item) use ($sku_ids, $v) {
  156. if (in_array($item[ 'sku_id' ], $sku_ids)) {
  157. $item[ 'promotion' ][ 'manjian' ] = $v;
  158. return $item;
  159. }
  160. }, $goods_list);
  161. }
  162. }
  163. $promotion_money += $discount_money;
  164. }
  165. }
  166. $data[ 'goods_list' ] = $goods_list;
  167. $data[ 'promotion_money' ] = $promotion_money;
  168. return $data;
  169. }
  170. /**
  171. * 满减优惠金额
  172. * @param $rule_list
  173. * @param $goods_money
  174. */
  175. public function getManjianDiscountMoney($manjian_info, $data)
  176. {
  177. $goods_money = $data[ 'goods_money' ];
  178. $value = $manjian_info[ 'type' ] == 0 ? $data[ 'goods_money' ] : $data[ 'goods_num' ];
  179. //阶梯计算优惠
  180. $rule_item = json_decode($manjian_info[ 'rule_json' ], true);
  181. $discount_money = 0;
  182. $money = 0;
  183. $rule = []; // 符合条件的优惠规则
  184. array_multisort(array_column($rule_item, 'limit'), SORT_ASC, $rule_item); //排序,根据num 排序
  185. foreach ($rule_item as $k => $v) {
  186. if ($value >= $v[ 'limit' ]) {
  187. $rule = $v;
  188. if (isset($v[ 'discount_money' ])) {
  189. $discount_money = $v[ 'discount_money' ];
  190. $money = $v[ 'limit' ];
  191. }
  192. }
  193. }
  194. $real_discount_money = $discount_money > $goods_money ? $goods_money : $discount_money;
  195. return [ 'discount_money' => $discount_money, 'money' => $money, 'real_discount_money' => $real_discount_money, 'rule' => $rule ];
  196. }
  197. /**
  198. * 处理商品满减
  199. */
  200. public function distributionGoodsDemiscount($goods_list, $goods_money, $discount_money, $is_free_shipping = false, $sku_ids = [])
  201. {
  202. $temp_discount_money = $discount_money;
  203. $last_key = count($goods_list) - 1;
  204. foreach ($goods_list as $k => $v) {
  205. if ($last_key != $k) {
  206. $item_discount_money = round(floor($v[ 'goods_money' ] / $goods_money * $discount_money * 100) / 100, 2);
  207. } else {
  208. $item_discount_money = $temp_discount_money;
  209. }
  210. $temp_discount_money -= $item_discount_money;
  211. $goods_list[ $k ][ 'promotion_money' ] = $item_discount_money;
  212. $real_goods_money = $v[ 'real_goods_money' ] - $item_discount_money;
  213. $real_goods_money = $real_goods_money < 0 ? 0 : $real_goods_money;
  214. $goods_list[ $k ][ 'real_goods_money' ] = $real_goods_money; //真实订单项金额
  215. // 满减送包邮
  216. if ($is_free_shipping) {
  217. if (empty($sku_ids) || in_array($v[ 'sku_id' ], $sku_ids)) {
  218. $goods_list[ $k ][ 'is_free_shipping' ] = 1;
  219. }
  220. }
  221. }
  222. return $goods_list;
  223. }
  224. /****************************************************************************** 满减 end *****************************************************************************/
  225. /****************************************************************************** 订单优惠券 start *****************************************************************************/
  226. /**
  227. * 查询可用优惠券
  228. * @param $data
  229. */
  230. public function couponCalculate($data)
  231. {
  232. $site_id = $data[ 'site_id' ];
  233. $member_id = $data[ 'member_id' ];
  234. $goods_money = $data[ 'goods_money' ];//商品总额
  235. $coupon_list = [];
  236. $goods_list = $data[ 'goods_list' ];
  237. //先查询全场通用的优惠券
  238. $member_coupon_model = new Coupon();
  239. $all_condition = array (
  240. [ 'member_id', '=', $member_id ],
  241. [ 'state', '=', 1 ],
  242. [ 'site_id', '=', $site_id ],
  243. [ 'goods_type', '=', 1 ],
  244. [ 'at_least', '<=', $goods_money ]
  245. );
  246. $all_coupon_list = $member_coupon_model->getCouponList($all_condition)[ 'data' ] ?? [];
  247. foreach ($all_coupon_list as $k => $v) {
  248. $v[ 'coupon_goods_money' ] = $goods_money;
  249. $all_coupon_list[ $k ] = $this->getCouponPromotionMoney($v);
  250. }
  251. $coupon_list = array_merge($coupon_list, $all_coupon_list);
  252. $goods_ids = array_column($goods_list, 'goods_id');
  253. $item_condition = array (
  254. [ 'member_id', '=', $member_id ],
  255. [ 'state', '=', 1 ],
  256. [ 'site_id', '=', $site_id ],
  257. [ 'goods_type', '=', 2 ],
  258. );
  259. $item_like_array = [];
  260. foreach ($goods_ids as $k => $v) {
  261. $item_like_array[] = '%,' . $v . ',%';
  262. }
  263. $item_condition[] = [ 'goods_ids', 'like', $item_like_array, 'OR' ];
  264. $item_coupon_list = $member_coupon_model->getCouponList($item_condition)[ 'data' ] ?? [];
  265. //已领取的优惠券id
  266. $ed_coupon_ids = array_column(array_merge($item_coupon_list, $all_coupon_list), 'coupon_type_id');
  267. if (!empty($item_coupon_list)) {
  268. foreach ($item_coupon_list as $item_k => $item_v) {
  269. $item_goods_ids = explode(',', $item_v[ 'goods_ids' ]);
  270. $item_goods_money = 0;
  271. foreach ($goods_list as $goods_k => $goods_v) {
  272. if (in_array($goods_v[ 'goods_id' ], $item_goods_ids)) {
  273. $item_goods_money += $goods_v[ 'goods_money' ];
  274. }
  275. }
  276. if ($item_goods_money >= $item_v[ 'at_least' ]) {
  277. $item_v[ 'coupon_goods_money' ] = $item_goods_money;
  278. $coupon_list[] = $this->getCouponPromotionMoney($item_v);
  279. }
  280. }
  281. }
  282. $ing_coupon_condition = array (
  283. [ 'site_id', '=', $site_id ],
  284. [ 'status', '=', 1 ],
  285. [ 'is_show', '=', 1 ]
  286. );
  287. if (!empty($ed_coupon_ids)) {
  288. $ing_coupon_condition[] = [ 'coupon_type_id', 'not in', $ed_coupon_ids ];
  289. }
  290. $ing_coupon_list = $member_coupon_model->getCouponTypeList($ing_coupon_condition)[ 'data' ] ?? [];
  291. if (!empty($ing_coupon_list)) {
  292. foreach ($ing_coupon_list as $item_k => $item_v) {
  293. $goods_type = $item_v[ 'goods_type' ];
  294. if ($goods_type == 1) {//全局支持优惠券
  295. $item_goods_money = $goods_money;
  296. } else {
  297. $item_goods_ids = explode(',', $item_v[ 'goods_ids' ]);
  298. $item_goods_money = 0;
  299. foreach ($goods_list as $goods_k => $goods_v) {
  300. if (in_array($goods_v[ 'goods_id' ], $item_goods_ids)) {
  301. $item_goods_money += $goods_v[ 'goods_money' ];
  302. }
  303. }
  304. }
  305. if ($item_goods_money >= $item_v[ 'at_least' ]) {
  306. $check_result = $member_coupon_model->checkMemberReceiveCoupon([ 'site_id' => $site_id, 'member_id' => $member_id, 'coupon_type_info' => $item_v ]);
  307. if ($check_result[ 'code' ] >= 0) {//只有还可领取的优惠券才可以
  308. //核验会员是否还可以领取某张优惠券
  309. $item_v[ 'receive_type' ] = 'wait';
  310. $item_v[ 'coupon_goods_money' ] = $item_goods_money;
  311. $coupon_list[] = $this->getCouponPromotionMoney($item_v);
  312. }
  313. }
  314. }
  315. }
  316. //增加查询可以领取的优惠券
  317. $max_coupon_money = 0;
  318. foreach ($coupon_list as $k => $v) {
  319. $item_coupon_money = $v[ 'coupon_money' ] ?? 0;//需修改
  320. if ($item_coupon_money > $max_coupon_money) {
  321. $max_coupon_money = $v[ 'coupon_money' ];
  322. $coupon_info = $v;
  323. }
  324. }
  325. $coupon_money = $coupon_info[ 'coupon_money' ] ?? 0;
  326. if ($coupon_money > 0) {
  327. $data[ 'coupon_info' ] = $coupon_info;
  328. if ($coupon_money > $data[ 'order_money' ]) {
  329. $coupon_money = $data[ 'order_money' ];
  330. }
  331. $data[ 'order_money' ] -= $coupon_money;
  332. $data[ 'coupon_money' ] = $coupon_money;
  333. }
  334. return $data;
  335. }
  336. /**
  337. * 优惠券优惠金额
  338. * @param $coupon_info
  339. * @return mixed
  340. */
  341. public function getCouponPromotionMoney($coupon_info)
  342. {
  343. $coupon_goods_money = $coupon_info[ 'coupon_goods_money' ];//优惠券支持当前商品的总金额
  344. $coupon_money = 0;
  345. if ($coupon_info[ 'type' ] == 'reward') { //满减优惠券
  346. $coupon_money = $coupon_info[ 'money' ] > $coupon_goods_money ? $coupon_goods_money : $coupon_info[ 'money' ];
  347. } else if ($coupon_info[ 'type' ] == 'divideticket') { //瓜分优惠券
  348. $coupon_money = $coupon_info[ 'money' ] > $coupon_goods_money ? $coupon_goods_money : $coupon_info[ 'money' ];
  349. } else if ($coupon_info[ 'type' ] == 'discount') { //折扣优惠券
  350. //计算折扣优惠金额
  351. $coupon_money = $coupon_goods_money * ( 10 - $coupon_info[ 'discount' ] ) / 10;
  352. $coupon_money = $coupon_money > $coupon_info[ 'discount_limit' ] && $coupon_info[ 'discount_limit' ] != 0 ? $coupon_info[ 'discount_limit' ] : $coupon_money;
  353. $coupon_money = $coupon_money > $coupon_goods_money ? $coupon_goods_money : $coupon_money;
  354. $coupon_money = round(floor($coupon_money * 100) / 100, 2);
  355. }
  356. $coupon_info[ 'coupon_money' ] = $coupon_money;
  357. return $coupon_info;
  358. }
  359. /****************************************************************************** 订单优惠券 end *****************************************************************************/
  360. }