OrderClass.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. <?php
  2. /**
  3. * 商城订单核心类
  4. * 用途:mallApp 订单详情/列表组装;拼团单附带 groupBuyStatus 供前端结合 status/payStatus 展示
  5. */
  6. namespace bizMall\order\classes;
  7. use biz\stat\classes\StatOrderCountClass;
  8. use bizMall\merchant\classes\MerchantAssetClass;
  9. use bizMall\shop\classes\MainClass;
  10. use bizMall\shop\classes\ShopClass;
  11. use bizMall\stat\classes\StatOrderClass;
  12. use bizMall\user\classes\UserClass;
  13. use common\components\imgUtil;
  14. use common\components\mapUtil;
  15. use common\components\miniUtil;
  16. use common\components\dict;
  17. use common\components\orderSn;
  18. use bizHd\groupBuy\classes\GroupBuyClass;
  19. use bizMall\base\classes\BaseClass;
  20. use common\components\util;
  21. class OrderClass extends BaseClass
  22. {
  23. public static $baseFile = '\bizMall\order\models\Order';
  24. //完成
  25. const ORDER_STATUS_COMPLETE = 4;
  26. //已取消
  27. const ORDER_STATUS_CANCEL = 5;
  28. //配送中
  29. const ORDER_STATUS_SENDING = 3;
  30. //待配送
  31. const ORDER_STATUS_UN_SEND = 2;
  32. //待付款
  33. const ORDER_STATUS_UN_PAY = 1;
  34. //订单总流程数
  35. const ORDER_TOTAL_FLOW = 4;
  36. //未确认配送方式
  37. const SEND_TYPE_UNKNOWN = 0;
  38. //自取
  39. const SEND_TYPE_NO = 1;
  40. //自己送
  41. const SEND_TYPE_MYSELF = 2;
  42. //代送
  43. const SEND_TYPE_OTHER = 3;
  44. //送达时间段
  45. public static $reachPeriod = [0 => '上午', 1 => '下午', 2 => '晚上'];
  46. //优惠金额
  47. public static $randDiscount = [
  48. 50 => [1, 3],
  49. 100 => [5, 9],
  50. 300 => [10, 15],
  51. 500 => [16, 18],
  52. 1000 => [18, 30],
  53. 20000 => [90, 100],
  54. ];
  55. //所有的欠款采购单 ssh 2021.1.26
  56. public static function getDebtList($where)
  57. {
  58. $list = self::getAllList('*', $where, 'addTime DESC');
  59. if (!empty($list)) {
  60. foreach ($list as $key => $value) {
  61. $debtPrice = $value['debtPrice'] ?? 0;
  62. $remainDebtPrice = $value['remainDebtPrice'] ?? 0;
  63. $hasPayDebt = 0;
  64. if ($debtPrice > $remainDebtPrice) {
  65. $hasPayDebt = bcsub($debtPrice, $remainDebtPrice, 2);
  66. }
  67. $list[$key]['hasPayDebt'] = floatval($hasPayDebt);
  68. }
  69. }
  70. $count = self::getCount($where);
  71. return ['list' => $list, 'debtNum' => $count];
  72. }
  73. //计算运费,请搜索关键词calc_freight,二个方法要合一起 ssh 20221014
  74. public static function getDistanceFee($userLat, $userLong, $shopLat, $shopLong, $weight)
  75. {
  76. //基础配送费8元,0-5公里,每公里+1元,5-100公里,6元起,每公里+2元
  77. //5-10公斤,2元起,每公斤+2元,10-15公斤,+12元,超过15公斤,+20元
  78. //00:00 - 06:00 +6元,22:00-24:00 +4元
  79. //恶劣天气,下单高峰期会临时调整价格
  80. //起步价
  81. $baseFee = 10;
  82. $distance = mapUtil::calculateDistance($userLong, $userLat, $shopLong, $shopLat);
  83. //0-5公里,每公里+1元,5-100公里,6元起,每公里+2元
  84. $formatDistance = ceil($distance / 1000);
  85. $startKiloFee = 6;
  86. if ($formatDistance < 5) {
  87. $addDistanceFee = bcmul($formatDistance, 2);
  88. } elseif ($formatDistance == 5) {
  89. $addDistanceFee = $startKiloFee;
  90. } else {
  91. $overKilo = bcsub($formatDistance, 5);
  92. $overFee = bcmul($overKilo, 3);
  93. $addDistanceFee = bcadd($startKiloFee, $overFee);
  94. }
  95. //5-10公斤,2元起,每公斤+2元,10-15公斤,+12元,超过15公斤,+20元
  96. $formatWeight = ceil($weight);
  97. if ($formatWeight > 15) {
  98. $addWeightFee = 20;
  99. } elseif ($formatWeight >= 10 && $formatWeight <= 15) {
  100. $addWeightFee = 12;
  101. } elseif ($formatWeight >= 5 && $formatWeight < 10) {
  102. $overWeight = bcsub($formatWeight, 4);
  103. $addWeightFee = bcmul($overWeight, 2);
  104. } else {
  105. $addWeightFee = 0;
  106. }
  107. $addFee = bcadd($addDistanceFee, $addWeightFee, 2);
  108. $totalFee = bcadd($baseFee, $addFee, 2);
  109. //特殊时段费
  110. $timeFee = 0;
  111. $hour = date("G");
  112. //22:00 - 24:00 +4元
  113. if (in_array($hour, [22, 23])) {
  114. $timeFee = 4;
  115. }
  116. //00:00 - 06:00 +6元
  117. if (in_array($hour, [0, 1, 2, 3, 4, 5])) {
  118. $timeFee = 6;
  119. }
  120. $totalFee = bcadd($totalFee, $timeFee, 2);
  121. //恶劣天气和下单高峰费用
  122. $weatherFee = 0;
  123. $totalFee = bcadd($totalFee, $weatherFee, 2);
  124. $showDistance = sprintf("%.1f", ($distance / 1000));
  125. //noticeUtil::push("零售商城 距离:{$distance} {$showDistance} 重量:{$weight} 费用:{$totalFee}", '15280215347');
  126. //return ['distance' => 0, 'showDistance' => 0, 'fee' => 0];
  127. return ['distance' => $distance, 'showDistance' => $showDistance, 'fee' => $totalFee];
  128. }
  129. //添加订单 ssh 2019.12.5
  130. public static function addOrder($data)
  131. {
  132. $data['orderSn'] = isset($data['orderSn']) ? $data['orderSn'] : orderSn::getOrderSn();
  133. $data['payStatus'] = 0;
  134. $shopId = $data['shopId'] ?? 0;
  135. $shop = ShopClass::getLockById($shopId);
  136. if (empty($shop)) {
  137. util::fail('没有找到门店85');
  138. }
  139. $mainId = $shop->mainId ?? 0;
  140. $main = MainClass::getLockById($mainId);
  141. if (empty($main)) {
  142. util::fail('没有main信息呢!');
  143. }
  144. $riseNum = StatOrderCountClass::addOrder($shop, $main);
  145. $address = $data['address'] ?? '';
  146. $floor = $data['floor'] ?? '';
  147. $fullAddress = $address . $floor;
  148. $data['fullAddress'] = $fullAddress;
  149. //将花店每月的总订单数作为编号
  150. $data['sendNum'] = date('j') . $riseNum;
  151. $return = self::add($data, true);
  152. $main->unPayOrder += 1;
  153. $main->totalOrder += 1;
  154. $main->save();
  155. return $return;
  156. }
  157. public static function getByOrderSn($orderSn)
  158. {
  159. return self::getByCondition(['orderSn' => $orderSn]);
  160. }
  161. //评价 ssh 2019.12.16
  162. public static function comment($data)
  163. {
  164. $id = $data['id'];
  165. unset($data['id']);
  166. return self::updateById($id, $data);
  167. }
  168. //订单
  169. public static function getOrderById($id)
  170. {
  171. $order = self::getById($id);
  172. if (empty($order)) {
  173. return [];
  174. }
  175. $orderSn = $order['orderSn'] ?? '';
  176. if (empty($orderSn)) {
  177. return [];
  178. }
  179. $goodsList = OrderGoodsClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  180. if (!empty($goodsList)) {
  181. foreach ($goodsList as $key => $val) {
  182. $shortCover = $val['cover'] ?? '';
  183. $cover = imgUtil::groupImg($shortCover);
  184. $goodsList[$key]['cover'] = $cover;
  185. $goodsList[$key]['shortCover'] = $shortCover;
  186. }
  187. }
  188. $order['goodsInfoList'] = $goodsList;
  189. $itemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  190. if (!empty($itemList)) {
  191. foreach ($itemList as $key => $item) {
  192. $shortCover = $item['cover'] ?? '';
  193. $cover = imgUtil::groupImg($shortCover);
  194. $itemList[$key]['cover'] = $cover;
  195. $itemList[$key]['shortCover'] = $shortCover;
  196. }
  197. }
  198. $order['itemList'] = $itemList;
  199. return self::attachGroupBuyStatus($order);
  200. }
  201. //根据订单查询 ssh 2020.1.4
  202. public static function getOrderBySn($orderSn)
  203. {
  204. $order = self::getByCondition(['orderSn' => $orderSn]);
  205. if (empty($order)) {
  206. return [];
  207. }
  208. $goodsList = OrderGoodsClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  209. if (!empty($goodsList)) {
  210. foreach ($goodsList as $key => $val) {
  211. $shortCover = $val['cover'] ?? '';
  212. $cover = imgUtil::groupImg($shortCover);
  213. $goodsList[$key]['cover'] = $cover;
  214. }
  215. }
  216. $order['goodsInfoList'] = $goodsList;
  217. $itemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  218. if (!empty($itemList)) {
  219. foreach ($itemList as $key => $item) {
  220. $shortCover = $item['cover'] ?? '';
  221. $cover = imgUtil::groupImg($shortCover);
  222. $itemList[$key]['cover'] = $cover;
  223. }
  224. }
  225. $order['itemList'] = $itemList;
  226. return self::attachGroupBuyStatus($order);
  227. }
  228. /**
  229. * 给订单附带拼团状态,供商城详情展示与售后判断
  230. * 非拼团单 groupBuyStatus=0;拼团单为 1拼团中 2成功 3失败 4已取消
  231. * @param array $order 订单数组
  232. * @return array
  233. */
  234. public static function attachGroupBuyStatus($order)
  235. {
  236. if (empty($order) || !is_array($order)) {
  237. return $order;
  238. }
  239. $groupBuyId = intval($order['groupBuyId'] ?? 0);
  240. $order['groupBuyId'] = $groupBuyId;
  241. $order['groupBuyStatus'] = $groupBuyId > 0 ? GroupBuyClass::getStatusById($groupBuyId) : 0;
  242. return $order;
  243. }
  244. //返回随机优惠金额 ssh 2019.9.12
  245. public static function getRandDiscount($amount)
  246. {
  247. if ($amount <= 0) {
  248. return 0;
  249. }
  250. $randDiscount = self::$randDiscount;
  251. krsort($randDiscount);
  252. $rand = 0;
  253. foreach ($randDiscount as $currentAmount => $val) {
  254. if ($amount >= $currentAmount) {
  255. $rand = rand($val[0], $val[1]);
  256. break;
  257. }
  258. }
  259. return $rand / 10;
  260. }
  261. //订单完成 ssh 2020.3.12
  262. public static function complete($order, $currentFlow)
  263. {
  264. $id = $order['id'];
  265. self::updateById($id, ['status' => OrderClass::ORDER_STATUS_COMPLETE, 'currentFlow' => $currentFlow]);
  266. }
  267. //转化出送到时间 ssh 2020.3.15
  268. public static function getReachTime($order)
  269. {
  270. $reachTime = '';
  271. if (isset($order['reachDate']) && !empty($order['reachDate'])) {
  272. $prev = date("n-j", strtotime($order['reachDate']));
  273. $periodData = self::$reachPeriod;
  274. $periodKey = $order['reachPeriod'];
  275. $period = isset($periodData[$periodKey]) ? $periodData[$periodKey] : '上午';
  276. $reachTime = $prev . ' ' . $period;
  277. }
  278. return $reachTime;
  279. }
  280. //支付成功获取unionId ssh 2020.5.12
  281. public static function payToUpdateUnionId($merchant, $merchantExtend, $orderSn, $user)
  282. {
  283. $mcId = $merchantExtend['wxPayMerchantId'];
  284. $miniOpenId = isset($user['miniOpenId']) ? $user['miniOpenId'] : '';
  285. $unionId = isset($user['unionId']) ? $user['unionId'] : '';
  286. $userId = $user['id'];
  287. if (empty($unionId)) {
  288. $unionId = miniUtil::getPaidUnionId($merchant, $miniOpenId, $mcId, (string)$orderSn, 0);
  289. if (!empty($unionId)) {
  290. $findUser = UserClass::getByUnionId($unionId);
  291. if (empty($findUser)) {
  292. UserClass::updateByCondition(['id' => $userId], ['unionId' => $unionId]);
  293. } else {
  294. UserClass::mergeUser($findUser, $user);
  295. }
  296. }
  297. }
  298. }
  299. //订单到期未付款的订单置成取消状态 ssh 2020.5.25
  300. public static function setExpire($order)
  301. {
  302. $now = time();
  303. if (!empty($order['deadline']) && $now > $order['deadline']) {
  304. if ($order['status'] == 0) {
  305. $id = $order['id'];
  306. OrderClass::updateById($id, ['status' => 4]);
  307. }
  308. }
  309. }
  310. /**
  311. * 应付金额为0:走零售订单完整支付成功流程(状态、流水、库存标记、待付款计数等)
  312. */
  313. public static function completeZeroAmountPay($orderId)
  314. {
  315. $order = \bizHd\order\classes\OrderClass::getLockById($orderId);
  316. if (empty($order)) {
  317. util::fail('没有找到订单');
  318. }
  319. if ((int)$order->payStatus === 1) {
  320. return $order;
  321. }
  322. if ((int)$order->status !== self::ORDER_STATUS_UN_PAY) {
  323. util::fail('订单不是待付款状态');
  324. }
  325. $payWay = dict::getDict('payWay', 'wxPay');
  326. \bizHd\order\classes\OrderClass::payAfter($order, $payWay);
  327. return $order;
  328. }
  329. //支付成功需要处理的流程 ssh 2020.5.25
  330. public static function payAfter($order, $updateData)
  331. {
  332. $orderId = $order['id'];
  333. $orderSn = $order['orderSn'];
  334. $now = time();
  335. self::updateById($orderId, $updateData);
  336. //发货流程的完成下单
  337. OrderSendClass::placeOrder(['orderId' => $orderId, 'payTime' => $now, 'orderSn' => $orderSn]);
  338. $sjId = $order['sjId'];
  339. $asset = MerchantAssetClass::getBySjId($sjId);
  340. //增加订单数
  341. StatOrderClass::addOrder($sjId, $asset);
  342. //如果门店和朋友圈订单并且没有填写收花人的直接将订单置为自取并且是完成状态
  343. if (isset($order['fromType']) && in_array($order['fromType'], [0, 2])) {
  344. if (isset($order['receiveMobile']) && isset($order['address'])) {
  345. if (empty($order['receiveMobile']) && empty($order['address'])) {
  346. OrderSendClass::withoutSend($order);
  347. }
  348. }
  349. }
  350. }
  351. }