StoreOrderSplitServices.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  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\jobs\order\SpliteOrderAfterJob;
  13. use app\services\BaseServices;
  14. use app\dao\order\StoreOrderDao;
  15. use app\services\store\SystemStoreServices;
  16. use think\exception\ValidateException;
  17. /**
  18. * 订单拆分
  19. * Class StoreOrderSplitServices
  20. * @package app\services\order
  21. * @mixin StoreOrderDao
  22. */
  23. class StoreOrderSplitServices extends BaseServices
  24. {
  25. /**
  26. * 需要清空恢复默认数据字段
  27. * @var string[]
  28. */
  29. protected $order_data = ['id', 'refund_status', 'refund_type', 'refund_express', 'refund_reason_wap_img', 'refund_reason_wap_explain', 'refund_reason_time', 'refund_reason_wap', 'refund_reason', 'refund_price'];
  30. /**
  31. * 构造方法
  32. * StoreOrderRefundServices constructor.
  33. * @param StoreOrderDao $dao
  34. */
  35. public function __construct(StoreOrderDao $dao)
  36. {
  37. $this->dao = $dao;
  38. }
  39. /**
  40. * 检测要拆分数组
  41. * @param int $id
  42. * @param array $cart_ids
  43. * @param array $orderInfo
  44. * @return bool
  45. * @throws \think\db\exception\DataNotFoundException
  46. * @throws \think\db\exception\DbException
  47. * @throws \think\db\exception\ModelNotFoundException
  48. */
  49. public function checkCartNum(int $id, array $cart_ids, $orderInfo = [])
  50. {
  51. if (!$cart_ids) {
  52. return false;
  53. }
  54. if (!$orderInfo) {
  55. $orderInfo = $this->dao->get($id, ['*']);
  56. }
  57. $total_num = array_sum(array_column($cart_ids, 'cart_num'));
  58. //商品和原订单一致,不拆分
  59. if ($total_num >= $orderInfo['total_num']) {
  60. return false;
  61. }
  62. return true;
  63. }
  64. /**
  65. * 平行拆分订单
  66. * @param int $id
  67. * @param array $cart_ids
  68. * @param array $orderInfo
  69. * @param int $store_id
  70. * @param bool $is_refund
  71. * @param int $erp_id
  72. * @return false
  73. * @throws \think\db\exception\DataNotFoundException
  74. * @throws \think\db\exception\DbException
  75. * @throws \think\db\exception\ModelNotFoundException
  76. */
  77. public function equalSplit(int $id, array $cart_ids, $orderInfo = [], int $store_id = 0, bool $is_refund = false, int $erp_id = 0)
  78. {
  79. if (!$cart_ids) {
  80. return false;
  81. }
  82. if (!$orderInfo) {
  83. $orderInfo = $this->dao->get($id, ['*']);
  84. }
  85. if (!$orderInfo) {
  86. throw new ValidateException('订单未能查到,不能拆分订单!');
  87. }
  88. if ($orderInfo['pid'] == -1) {
  89. throw new ValidateException('已拆分完毕,请返回列表重新操作');
  90. }
  91. if (!$this->checkCartNum($id, $cart_ids, $orderInfo)) {
  92. return false;
  93. }
  94. $orderInfo = is_object($orderInfo) ? $orderInfo->toArray() : $orderInfo;
  95. /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
  96. $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
  97. //订单下原商品信息
  98. $cartInfo = $storeOrderCartInfoServices->getCartColunm(['oid' => $id, 'split_status' => [0, 1]], 'is_gift,cart_num,split_surplus_num', 'cart_id');
  99. $new_cart_ids = array_combine(array_column($cart_ids, 'cart_id'), $cart_ids);
  100. $other_cart_ids = $other = [];
  101. foreach ($cartInfo as $cart_id => $cart) {
  102. if (!isset($new_cart_ids[$cart_id]) && $cart['split_surplus_num']) {//无拆分
  103. $other = ['cart_id' => $cart_id, 'cart_num' => $cart['split_surplus_num']];
  104. } else if ($new_cart_ids[$cart_id]['cart_num'] < $cart['split_surplus_num']) {
  105. $other = ['cart_id' => $cart_id, 'cart_num' => bcsub((string)$cart['split_surplus_num'], (string)$new_cart_ids[$cart_id]['cart_num'], 0)];
  106. } else {
  107. continue;
  108. }
  109. $other_cart_ids[] = $other;
  110. }
  111. $data = [$cart_ids, $other_cart_ids];
  112. $split_cart_ids = $cart_ids;
  113. if ($other_cart_ids && $orderInfo['status'] == 0 && $is_refund) {
  114. //拆分剩余 都是赠品
  115. $is_gift = true;
  116. foreach ($other_cart_ids as $cart) {
  117. if (!isset($cartInfo[$cart['cart_id']]) || !$cartInfo[$cart['cart_id']]['is_gift']) {
  118. $is_gift = false;
  119. break;
  120. }
  121. }
  122. if ($is_gift) {//未发货 申请退款 整单退
  123. return [];
  124. }
  125. }
  126. /** @var StoreOrderServices $storeOrderServices */
  127. $storeOrderServices = app()->make(StoreOrderServices::class);
  128. $orderInfo = $storeOrderServices->tidyOrder($orderInfo, true, true);
  129. //核算优惠金额
  130. $vipTruePrice = 0;
  131. $refund_num = 0;
  132. $all_true_price = 0;
  133. foreach ($orderInfo['cartInfo'] ?? [] as $key => &$cart) {
  134. $vipTruePrice = bcadd((string)$vipTruePrice, (string)$cart['vip_sum_truePrice'], 2);
  135. $refund_num = bcadd((string)$refund_num, (string)$cart['refund_num'], 0);
  136. $all_true_price = bcadd((string)$all_true_price, bcmul((string)($cart['truePrice'] ?? 0), (string)$cart['cart_num'], 4), 2);
  137. }
  138. $orderInfo['vip_true_price'] = $vipTruePrice;
  139. $orderInfo['total_price'] = floatval(bcsub((string)$orderInfo['total_price'], (string)$vipTruePrice, 2));
  140. //订单实际支付金额
  141. $order_pay_price = bcadd((string)$all_true_price, (string)$orderInfo['pay_postage'], 2);
  142. //有改价
  143. $change_price = $order_pay_price != $orderInfo['pay_price'];
  144. $order = $this->transaction(function () use ($id, $data, $orderInfo, $store_id, $storeOrderCartInfoServices, $split_cart_ids, $is_refund, $change_price, $order_pay_price, $erp_id) {
  145. $order = [];
  146. $i = 0;
  147. foreach ($data as $key => $cart_ids) {
  148. if ($key == 0 && $erp_id > 0) {
  149. $orderInfo['erpId'] = $erp_id;
  150. }
  151. //生成新订单、处理cart_info
  152. [$new_id, $cart_data] = $this->splitV2($id, $cart_ids, $orderInfo, $i, $store_id, $is_refund, $split_cart_ids);
  153. //处理订单
  154. $this->splitComputeOrder((int)$new_id, $cart_data, $orderInfo, (float)($change_price ? $order_pay_price : 0), (float)$orderInfo['pay_price'], (float)($order[0]['pay_price'] ?? 0));
  155. $order[] = $this->dao->get($new_id);
  156. $i++;
  157. }
  158. //标记主订单拆分完成
  159. if (!$orderInfo['pid']) $this->dao->update($id, ['pid' => -1]);
  160. //处理申请开票记录
  161. /** @var StoreOrderInvoiceServices $storeOrderInvoiceServics */
  162. $storeOrderInvoiceServics = app()->make(StoreOrderInvoiceServices::class);
  163. $storeOrderInvoiceServics->splitOrderInvoice((int)$id);
  164. //处理订单优惠活动记录
  165. /** @var StoreOrderPromotionsServices $storeOrderPromotionsServics */
  166. $storeOrderPromotionsServics = app()->make(StoreOrderPromotionsServices::class);
  167. $storeOrderPromotionsServics->splitOrderPromotions((int)$id);
  168. return $order;
  169. });
  170. //拆分完成后置队列 处理订单状态记录
  171. SpliteOrderAfterJob::dispatch([$id, $order]);
  172. return $order;
  173. }
  174. /**
  175. * 订单拆分
  176. * @param int $id
  177. * @param array $cart_ids
  178. * @param array $orderInfo
  179. * @param int $i
  180. * @param int $store_id
  181. * @param bool $is_refund
  182. * @param array $append
  183. * @return array|false
  184. * @throws \Psr\SimpleCache\InvalidArgumentException
  185. * @throws \think\db\exception\DataNotFoundException
  186. * @throws \think\db\exception\DbException
  187. * @throws \think\db\exception\ModelNotFoundException
  188. */
  189. public function splitV2(int $id, array $cart_ids, $orderInfo = [], int $i = 0, int $store_id = 0, bool $is_refund = false, array $append = [])
  190. {
  191. $ids = array_unique(array_column($cart_ids, 'cart_id'));
  192. if (!$cart_ids || !$ids) {
  193. return false;
  194. }
  195. if (!$orderInfo) {
  196. $orderInfo = $this->dao->get($id, ['*']);
  197. }
  198. if (!$orderInfo) {
  199. throw new ValidateException('订单未能查到,不能拆分订单!');
  200. }
  201. /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
  202. $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
  203. //订单下原商品信息
  204. $cartInfo = $storeOrderCartInfoServices->getCartColunm(['oid' => $id, 'cart_id' => $ids], '*', 'cart_id');
  205. if (!$cartInfo || count($cartInfo) != count($ids)) {
  206. return false;
  207. }
  208. if ($append) $append = array_combine(array_column($append, 'cart_id'), $append);
  209. $is_not_split = $i && $orderInfo['pid'];
  210. if ($is_not_split) {//保留原订单 不重新生成(只修改订单信息、订单商品信息)
  211. $new_id = $id;
  212. //删除原订单下商品信息
  213. $storeOrderCartInfoServices->delete(['oid' => $id]);
  214. //删除缓存
  215. $storeOrderCartInfoServices->clearOrderCartInfo($id);
  216. } else {
  217. /** @var StoreOrderCreateServices $storeOrderCreateServices */
  218. $storeOrderCreateServices = app()->make(StoreOrderCreateServices::class);
  219. $orderInfo = is_object($orderInfo) ? $orderInfo->toArray() : $orderInfo;
  220. $pid = $orderInfo['pid'] ?: $orderInfo['id'];
  221. foreach ($this->order_data as $field) {
  222. unset($orderInfo[$field]);
  223. }
  224. //核销码重新生成
  225. if ($orderInfo['verify_code']) {
  226. $orderInfo['verify_code'] = $storeOrderCreateServices->getStoreCode();
  227. }
  228. $order_data = $orderInfo;
  229. $order_data['promotions_give'] = is_array($order_data['promotions_give']) ? json_encode($order_data['promotions_give']) : $order_data['promotions_give'];
  230. $order_data['give_coupon'] = is_array($order_data['give_coupon']) ? implode(',', $order_data['give_coupon']) : $order_data['give_coupon'];
  231. //$pid 平行拆分 0:子订单拆分
  232. $order_data['pid'] = $pid ?: $id;
  233. $parentOrder = $this->dao->get($order_data['pid']);
  234. $oldOrderId = $parentOrder['order_id'];
  235. $childCont = $this->dao->count(['pid' => $parentOrder['id']]);
  236. if ($store_id) {//门店分配拆分
  237. /** @var SystemStoreServices $storeServices */
  238. $storeServices = app()->make(SystemStoreServices::class);
  239. if (!$storeInfo = $storeServices->getStoreInfo($store_id)) {
  240. throw new ValidateException('门店不存在');
  241. }
  242. $order_data['store_id'] = $store_id;
  243. $order_data['order_id'] = $storeOrderCreateServices->getNewOrderId();
  244. if ($order_data['shipping_type'] == 1) {
  245. $order_data['shipping_type'] = 3;
  246. } else {//自提订单
  247. $order_data['order_id'] = $storeOrderCreateServices->getNewOrderId();
  248. // $order_data['verify_code'] = $storeOrderCreateServices->getStoreCode();
  249. }
  250. $status_data = [
  251. 'change_type' => 'store_split_create_order',
  252. 'change_message' => '门店分配拆分生成订单',
  253. 'change_time' => time()
  254. ];
  255. } else {//发货拆分
  256. // $order_data['order_id'] = $storeOrderCreateServices->getNewOrderId();
  257. $order_data['order_id'] = $oldOrderId . '_' . ($childCont + 1);
  258. $status_data = [
  259. 'change_type' => 'split_create_order',
  260. 'change_message' => $is_refund ? '售后退款拆分生成订单' : '发货拆分生成订单',
  261. 'change_time' => time()
  262. ];
  263. }
  264. $order_data['cart_id'] = [];
  265. $order_data['unique'] = $storeOrderCreateServices->getNewOrderId('');
  266. $new_order = $this->dao->save($order_data);
  267. if (!$new_order) {
  268. throw new ValidateException('生成新订单失败');
  269. }
  270. $new_id = (int)$new_order->id;
  271. /** @var StoreOrderStatusServices $statusService */
  272. $statusService = app()->make(StoreOrderStatusServices::class);
  273. $status_data['oid'] = $new_id;
  274. $statusService->save($status_data);
  275. }
  276. //生成订单商品信息 保存
  277. $cart_data = $cart_data_all = $update_data = [];
  278. foreach ($cart_ids as $cart) {
  279. $split_surplus_num = $cartInfo[$cart['cart_id']]['split_surplus_num'] ?? 0;
  280. if (!isset($cartInfo[$cart['cart_id']]) || (!$is_not_split && !$split_surplus_num)) continue;
  281. $_info = is_string($cartInfo[$cart['cart_id']]['cart_info']) ? json_decode($cartInfo[$cart['cart_id']]['cart_info'], true) : $cartInfo[$cart['cart_id']]['cart_info'];
  282. $cart_data = $cartInfo[$cart['cart_id']];
  283. $cart_data['oid'] = $new_id;
  284. unset($cart_data['id']);
  285. $cart_data['split_surplus_num'] = $cart['cart_num'];
  286. $unit_write_times = max($_info['productInfo']['attrInfo']['write_times'] ?? 1, 1);
  287. $cart_data['write_times'] = bcmul((string)$cart['cart_num'], (string)$unit_write_times, 0);
  288. $split_refund_num = $append[$cart['cart_id']]['cart_num'] ?? 0;
  289. if (!$is_not_split) {//新增cart_info
  290. $cart_data['cart_id'] = $storeOrderCreateServices->getNewOrderId('');
  291. $cart_data['product_id'] = $_info['product_id'];
  292. $cart_data['old_cart_id'] = $cart['cart_id'];
  293. $cart_data['unique'] = md5($cart_data['cart_id'] . '_' . $cart_data['oid']);
  294. $cart_data['surplus_num'] = $cart['cart_num'];
  295. } else {//保留
  296. }
  297. $refund_num = 0;
  298. //拆出订单
  299. if (!$i) {
  300. //无核销 || 核销数量大于拆分数量
  301. if (!$cart_data['writeoff_time']) {
  302. $surplus_num = min($cart_data['write_surplus_times'], $cart_data['write_times']);
  303. } else {
  304. $writoff_numm = bcsub((string)$cart_data['write_times'], (string)$cart_data['write_surplus_times'], 0);
  305. $surplus_num = $writoff_numm >= $cart_data['write_times'] ? 0 : bcsub((string)$cart_data['write_times'], (string)$writoff_numm, 0);
  306. }
  307. if ($is_refund) $refund_num = $cart['cart_num'];
  308. } else {//修改原订单
  309. //无核销 || 核销数量大于拆分数量
  310. if (!$cart_data['writeoff_time']) {
  311. $surplus_num = $cart_data['write_times'];
  312. } else {
  313. $cart_num_times = bcmul((string)$cart['cart_num'], (string)$unit_write_times, 0);
  314. $surplus_num = $cart_data['write_surplus_times'] <= $cart_num_times ? 0 : bcsub((string)$cart_data['write_surplus_times'], (string)$cart_num_times, 0);
  315. }
  316. if ($is_refund) $refund_num = $split_refund_num >= $cart_data['refund_num'] ? 0 : bcsub((string)$cart_data['refund_num'], (string)$split_refund_num, 0);
  317. }
  318. $cart_data['cart_num'] = $cart['cart_num'];
  319. $cart_data['refund_num'] = max($refund_num, 0);
  320. $cart_data['write_surplus_times'] = max($surplus_num, 0);
  321. if (!$cart_data['write_surplus_times']) {//核销完毕
  322. $cart_data['is_writeoff'] = 1;
  323. } elseif ($cart_data['write_surplus_times'] == $cart_data['write_times']) {//未核销
  324. $cart_data['is_writeoff'] = 0;
  325. $cart_data['writeoff_time'] = 0;
  326. }
  327. if ($cart['cart_num'] >= $split_surplus_num) {//拆分完成
  328. $cart_data['cart_num'] = $split_surplus_num;
  329. $update_data['split_status'] = 2;
  330. $update_data['split_surplus_num'] = 0;
  331. } else {//拆分部分数量
  332. $update_data['split_surplus_num'] = bcsub((string)$split_surplus_num, $cart['cart_num'], 0);
  333. $update_data['split_status'] = $update_data['split_surplus_num'] > 0 ? 1 : 2;
  334. }
  335. $_info = $this->slpitComputeOrderCart($cart_data['cart_num'], $_info, $i, !!($cart_data['is_gift'] ?? 0));
  336. $_info['id'] = $cart_data['cart_id'];
  337. $cart_data['cart_info'] = json_encode($_info);
  338. //修改原来订单商品信息
  339. if (!$is_not_split && false === $storeOrderCartInfoServices->update(['oid' => $id, 'cart_id' => $cart['cart_id']], $update_data)) {
  340. throw new ValidateException('修改原来订单商品拆分状态失败,请稍候重试');
  341. }
  342. $cart_data_all[] = $cart_data;
  343. unset($cartInfo[$cart['cart_id']]);
  344. }
  345. if (!$storeOrderCartInfoServices->saveAll($cart_data_all)) {
  346. throw new ValidateException('新增拆分订单商品信息失败');
  347. }
  348. return [$new_id, $cart_data_all];
  349. // $split_order_info = $this->dao->get($new_id);
  350. // $this->splitComputeOrder($new_id, $cart_data_all, $split_order_info);
  351. // return $split_order_info;
  352. }
  353. /**
  354. * 获取整理后的订单商品信息
  355. * @param int $id
  356. * @param array $cart_ids
  357. * @param array $orderInfo
  358. * @return array|false
  359. * @throws \think\db\exception\DataNotFoundException
  360. * @throws \think\db\exception\DbException
  361. * @throws \think\db\exception\ModelNotFoundException
  362. */
  363. public function getSplitOrderCartInfo(int $id, array $cart_ids, $orderInfo = [])
  364. {
  365. $ids = array_unique(array_column($cart_ids, 'cart_id'));
  366. if (!$cart_ids || !$ids) {
  367. return false;
  368. }
  369. if (!$orderInfo) {
  370. $orderInfo = $this->dao->get($id, ['*']);
  371. }
  372. if (!$orderInfo) {
  373. throw new ValidateException('订单未能查到,不能拆分订单!');
  374. }
  375. /** @var StoreOrderCartInfoServices $storeOrderCartInfoServices */
  376. $storeOrderCartInfoServices = app()->make(StoreOrderCartInfoServices::class);
  377. $cartInfo = $storeOrderCartInfoServices->getCartColunm(['oid' => $id, 'cart_id' => $ids], '*', 'cart_id');
  378. $cart_data_all = [];
  379. foreach ($cart_ids as $cart) {
  380. $split_surplus_num = $cartInfo[$cart['cart_id']]['split_surplus_num'] ?? 0;
  381. if (!isset($cartInfo[$cart['cart_id']]) || !$split_surplus_num) continue;
  382. $_info = is_string($cartInfo[$cart['cart_id']]['cart_info']) ? json_decode($cartInfo[$cart['cart_id']]['cart_info'], true) : $cartInfo[$cart['cart_id']]['cart_info'];
  383. $cart_data = $cartInfo[$cart['cart_id']];
  384. $cart_data['oid'] = $id;
  385. $cart_data['product_id'] = $_info['product_id'];
  386. $cart_data['old_cart_id'] = $cart['cart_id'];
  387. $cart_data['cart_num'] = $cart['cart_num'];
  388. $cart_data['surplus_num'] = $cart['cart_num'];
  389. $cart_data['split_surplus_num'] = $cart['cart_num'];
  390. $_info = $this->slpitComputeOrderCart($cart_data['cart_num'], $_info);
  391. $_info['id'] = $cart_data['cart_id'];
  392. $cart_data['cart_info'] = $_info;
  393. $cart_data_all[] = $cart_data;
  394. unset($cartInfo[$cart['cart_id']]);
  395. }
  396. return $cart_data_all;
  397. }
  398. /**
  399. * 重新计算新订单中价格等信息
  400. * @param int $id 订单号
  401. * @param array $cart_info_data 重新计算过订单商品信息
  402. * @param array $orderInfo 订单信息
  403. * @param float $order_pay_price 订单原来支付金额 0:没改价继续计算 >0 存在改价 需要计算新订单实际支付金额
  404. * @param float $pay_price 订单实际支付金额
  405. * @param float $pre_pay_price 上一个订单实际支付金额
  406. * @return bool
  407. */
  408. public function splitComputeOrder(int $id, array $cart_info_data, $orderInfo = [], float $order_pay_price = 0.00, float $pay_price = 0.00, float $pre_pay_price = 0.00)
  409. {
  410. $order_update['cart_id'] = array_column($cart_info_data, 'cart_id');
  411. $order_update['total_num'] = array_sum(array_column($cart_info_data, 'cart_num'));
  412. $cost = $total_price = $true_total_price = $coupon_price = $deduction_price = $use_integral = $pay_postage = $gainIntegral = $one_brokerage = $two_brokerage = $promotions_price = $first_order_price = 0;
  413. $wrrteoffed = 0;
  414. foreach ($cart_info_data as $cart) {
  415. $_info = json_decode($cart['cart_info'], true);
  416. if (isset($cart['is_writeoff']) && $cart['is_writeoff']) {
  417. $wrrteoffed++;
  418. }
  419. //赠品跳过
  420. if (isset($cart['is_gift']) && $cart['is_gift']) {
  421. continue;
  422. }
  423. $true_total_price = bcadd((string)$true_total_price, (string)($_info['sum_true_price'] ?? '0'), 2);
  424. $total_price = bcadd((string)$total_price, (string)bcmul((string)($cart['cart_num'] ?? '1'), (string)($_info['sum_price'] ?? '0'), 2), 2);
  425. $deduction_price = bcadd((string)$deduction_price, (string)($_info['integral_price'] ?? '0'), 2);
  426. $coupon_price = bcadd((string)$coupon_price, (string)($_info['coupon_price'] ?? '0'), 2);
  427. $use_integral = bcadd((string)$use_integral, (string)($_info['use_integral'] ?? '0'), 0);
  428. if (!in_array($orderInfo['shipping_type'], [2, 4])) {
  429. $pay_postage = bcadd((string)$pay_postage, (string)($_info['postage_price'] ?? '0'), 2);
  430. }
  431. $cartInfoGainIntegral = bcmul((string)$cart['cart_num'], (string)($_info['productInfo']['give_integral'] ?? '0'), 0);
  432. $gainIntegral = bcadd((string)$gainIntegral, (string)$cartInfoGainIntegral, 0);
  433. $one_brokerage = bcadd((string)$one_brokerage, (string)($_info['one_brokerage'] ?? '0'), 2);
  434. $two_brokerage = bcadd((string)$two_brokerage, (string)($_info['two_brokerage'] ?? '0'), 2);
  435. $cost = bcadd((string)$cost, (string)bcmul((string)$cart['cart_num'], (string)($_info['costPrice'] ?? '0'), 2), 2);
  436. $promotions_price = bcadd((string)$promotions_price, (string)bcmul((string)$cart['cart_num'], (string)($_info['promotions_true_price'] ?? '0'), 2), 2);
  437. $first_order_price = bcadd((string)$first_order_price, (string)($_info['first_order_price'] ?? '0'), 2);
  438. }
  439. $order_update['coupon_id'] = array_unique(array_column($cart_info_data, 'coupon_id'));
  440. $order_update['pay_price'] = bcadd((string)$true_total_price, (string)$pay_postage, 2);
  441. //有订单原来支付金额 改价订单
  442. if ($order_pay_price) {
  443. if ($pre_pay_price) {//上一个已经计算 这里减法
  444. $order_update['pay_price'] = bcsub((string)$pay_price, (string)$pre_pay_price, 2);
  445. } else {//按比例计算实际支付金额
  446. $order_update['pay_price'] = bcmul((string)bcdiv((string)$pay_price, (string)$order_pay_price, 4), (string)$order_update['pay_price'], 2);
  447. }
  448. }
  449. if (!$pre_pay_price) {//最后一个订单保留赠送 积分 优惠券信息
  450. $order_update['give_integral'] = 0;
  451. $order_update['give_coupon'] = '';
  452. }
  453. $order_update['pay_price'] = $order_update['pay_price'] < 0 ? 0 : $order_update['pay_price'];
  454. $order_update['total_price'] = $total_price;
  455. $order_update['deduction_price'] = $deduction_price;
  456. $order_update['coupon_price'] = $coupon_price;
  457. $order_update['use_integral'] = $use_integral;
  458. $order_update['gain_integral'] = $gainIntegral;
  459. $order_update['pay_postage'] = $pay_postage;
  460. $order_update['one_brokerage'] = $one_brokerage;
  461. $order_update['two_brokerage'] = $two_brokerage;
  462. $order_update['cost'] = $cost;
  463. $order_update['promotions_price'] = $promotions_price;
  464. $order_update['first_order_price'] = $first_order_price;
  465. if ($orderInfo['status'] == 5) {//部分核销拆单
  466. if (count($cart_info_data) == $wrrteoffed) {//全部核销
  467. $order_update['status'] = 2;
  468. } else {
  469. $order_update['status'] = 0;
  470. }
  471. }
  472. if (false === $this->dao->update($id, $order_update, 'id')) {
  473. throw new ValidateException('保存新订单商品信息失败');
  474. }
  475. return true;
  476. }
  477. /**
  478. * 部分发货重新计算订单商品:实际金额、优惠、积分等金额
  479. * @param int $cart_num
  480. * @param array $cart_info
  481. * @param int $i
  482. * @param bool $is_gift
  483. * @return array
  484. */
  485. public function slpitComputeOrderCart(int $cart_num, array $cart_info, int $i = 0, bool $is_gift = false)
  486. {
  487. if (!$cart_num || !$cart_info) return [];
  488. $new_cart_info = $cart_info;
  489. if ($cart_num < $cart_info['cart_num']) {
  490. $compute_arr = ['coupon_price', 'integral_price', 'postage_price', 'use_integral', 'one_brokerage', 'two_brokerage', 'sum_true_price', 'first_order_price'];
  491. foreach ($compute_arr as $field) {
  492. if (!isset($cart_info[$field]) || !$cart_info[$field] || $is_gift) {
  493. $new_cart_info[$field] = 0;
  494. continue;
  495. }
  496. $scale = 2;
  497. if ($field == 'use_integral') $scale = 0;
  498. if (!$i) {//拆出
  499. $new_cart_info[$field] = bcmul((string)$cart_num, bcdiv((string)$cart_info[$field], (string)$cart_info['cart_num'], 4), $scale);
  500. } else {
  501. $field_number = bcmul((string)bcsub((string)$cart_info['cart_num'], (string)$cart_num, 0), bcdiv((string)$cart_info[$field], (string)$cart_info['cart_num'], 4), $scale);
  502. $new_cart_info[$field] = bcsub((string)$cart_info[$field], (string)$field_number, $scale);
  503. }
  504. }
  505. }
  506. $new_cart_info['cart_num'] = $cart_num;
  507. return $new_cart_info;
  508. }
  509. }