OrderService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. namespace api\services;
  3. use common\models\order\Order;
  4. use common\enums\AppEnum;
  5. use common\enums\GoodsTypeEnum;
  6. use common\enums\OrderStatusEnum;
  7. use common\enums\PreviewTypeEnum;
  8. use common\enums\ShippingTypeEnum;
  9. use common\enums\StatusEnum;
  10. use common\events\order\OrderChangeAddressEvent;
  11. use common\logic\order\OrderFormLogic;
  12. use common\logic\order\OrderInitDataLogic;
  13. use common\logic\order\OrderMarketingLogic;
  14. use common\models\order\OrderExtra;
  15. use common\models\order\OrderModifyShippingAddressLog;
  16. use common\models\user\UserAddress;
  17. use Exception;
  18. use yii\helpers\Json;
  19. class OrderService
  20. {
  21. protected $order;
  22. # 订单留言模型
  23. protected $order_extra;
  24. public function __construct(Order $order, OrderExtra $order_extra)
  25. {
  26. $this->order = $order;
  27. $this->order_extra = $order_extra;
  28. }
  29. /**
  30. * 订单留言列表
  31. * @param $order_id
  32. * @param $mall_id
  33. * @return array|\yii\db\ActiveRecord[]
  34. * @throws \Exception
  35. */
  36. public function leave($order_id, $mall_id): array
  37. {
  38. $where = ['order_id' => $order_id, 'mall_id' => $mall_id];
  39. // 判断订单是否存在
  40. $exists = $this->order::find()->where(['=', 'id', $order_id])->where(['=', 'mall_id', $mall_id])->exists();
  41. if (!$exists) {
  42. throw new \Exception('订单不存在!');
  43. }
  44. return $this->order_extra::getInfo($where,"id,message,created_at");
  45. }
  46. /**
  47. * 修改地址
  48. *
  49. * @param int $userId
  50. * @param int $mallId
  51. * @param int $addressId
  52. * @param int $orderId
  53. *
  54. * @return void
  55. * @throws Exception
  56. */
  57. public function modifyAddress(int $userId, int $mallId, int $addressId, int $orderId)
  58. {
  59. $addressExist = UserAddress::find()
  60. ->where(['id' => $addressId, 'user_id' => $userId, 'status' => StatusEnum::ENABLED])
  61. ->count();
  62. if (!$addressExist) {
  63. throw new \RuntimeException('地址错误');
  64. }
  65. $order = \common\models\order\Order::find()
  66. ->where([
  67. 'id' => $orderId,
  68. 'mall_id' => $mallId,
  69. 'user_id' => $userId,
  70. 'status' => StatusEnum::ENABLED,
  71. ])
  72. ->with([
  73. 'detail' => function ($query) {
  74. $query->where(['status' => StatusEnum::ENABLED]);
  75. }
  76. ])
  77. ->asArray()
  78. ->one();
  79. if (empty($order) || empty($order['detail'])) {
  80. throw new \RuntimeException('订单不存在');
  81. }
  82. if (
  83. OrderModifyShippingAddressLog::find()
  84. ->where(['mall_id' => $mallId, 'order_id' => $orderId, 'status' => [StatusEnum::DISABLED, StatusEnum::ENABLED]])
  85. ->count()
  86. ) {
  87. throw new \RuntimeException('当前订单已修改过收货地址');
  88. }
  89. if (!in_array($order['order_status'], [OrderStatusEnum::NOT_PAY, OrderStatusEnum::PAY]) || $order['shipping_type'] == ShippingTypeEnum::PICKUP) {
  90. throw new \RuntimeException('当前订单不允许修改地址');
  91. }
  92. // 验证,只要有一件已经发货就不能修改地址了
  93. $isSend = false;
  94. foreach ($order['detail'] as $detailItem) {
  95. if ($detailItem['order_status'] >= OrderStatusEnum::SHIPMENTS && $detailItem['order_status'] <= OrderStatusEnum::ACCOMPLISH) {
  96. $isSend = true;
  97. break;
  98. }
  99. }
  100. if ($isSend) {
  101. throw new \RuntimeException('当前订单不允许修改地址');
  102. }
  103. // 排除售后成功的订单
  104. foreach ($order['detail'] as $key => $detailItem) {
  105. if ($detailItem['is_feedback'] == OrderStatusEnum::FEEDBACKED) {
  106. unset($order['detail'][$key]);
  107. }
  108. }
  109. if (empty($order['detail'])) {
  110. throw new \RuntimeException('当前订单不允许修改地址');
  111. }
  112. // 初始化订单
  113. $orderFormLogic = new OrderFormLogic();
  114. $form = $orderFormLogic->getDefaultform($mallId, $userId);
  115. $freightAttr = [];
  116. foreach ($order['detail'] as $detail) {
  117. $freightAttr[] = ['attr_id' => $detail['goods_attr_id'], 'num' => $detail['num']];
  118. }
  119. if (empty($freightAttr)) {
  120. throw new \RuntimeException('当前订单不允许修改地址');
  121. }
  122. $form->attributes = [
  123. 'type' => PreviewTypeEnum::FREIGHT,
  124. 'data' => [
  125. 'shipping_type' => $order['shipping_type'],
  126. 'freight_attr' => $freightAttr,
  127. 'address_id' => $addressId
  128. ]
  129. ];
  130. $form['action'] = AppEnum::ACTION_CREATE;
  131. // 初始化订单数据
  132. $orderInitDataLogic = new OrderInitDataLogic();
  133. $form = $orderInitDataLogic->execute($form, $form->type);
  134. if ($form === false) throw new \RuntimeException($orderInitDataLogic->getError());
  135. // 验证新的区域是否允许购买
  136. try {
  137. $this->compute($form);
  138. }catch (Exception $e) {
  139. throw new \RuntimeException($e->getMessage());
  140. }
  141. /* 验证邮费,如果新地址需要给的邮费比下单时候的邮费高则不允许修改 */
  142. // 营销减免活动
  143. $orderMarketingLogic = new OrderMarketingLogic();
  144. $form = $orderMarketingLogic->run($form, true);
  145. if ($form === false) throw new \RuntimeException($orderMarketingLogic->getError());
  146. if (empty($form['group_order_goods']) || !is_array($form['group_order_goods'])) {
  147. throw new \RuntimeException('订单错误,修改失败');
  148. }
  149. // 因为修改地址只有一个订单修改,不会返回多条数据,所以使用reset拿第一个
  150. $goodsOrderGoods = reset($form['group_order_goods']);
  151. if (empty($goodsOrderGoods['mch_order_info'])) {
  152. throw new \RuntimeException('订单错误,修改失败');
  153. }
  154. $mchOrderInfo = $goodsOrderGoods['mch_order_info'];
  155. if (
  156. !isset($form['marketing']['deduct']['shipping_fee']['money']) ||
  157. !is_numeric($form['marketing']['deduct']['shipping_fee']['money'])
  158. ) {
  159. throw new \RuntimeException('订单错误,修改失败');
  160. }
  161. // 新地址邮费大于原地址
  162. if (bccomp($form['marketing']['deduct']['shipping_fee']['money'], $order['shipping_money'], 2) > 0) {
  163. throw new \RuntimeException('当前地址运费超过原地址运费,不允许修改');
  164. }
  165. // 执行修改
  166. \common\models\order\Order::changeAddress([
  167. 'id' => $orderId,
  168. 'mall_id' => $mallId,
  169. 'province' => $mchOrderInfo['province'],
  170. 'city' => $mchOrderInfo['city'],
  171. 'area' => $mchOrderInfo['area'],
  172. 'town' => $mchOrderInfo['town'],
  173. 'community' => $mchOrderInfo['community'],
  174. 'region_name' => $mchOrderInfo['region_name'],
  175. 'address' => $mchOrderInfo['address'],
  176. 'receiver_name' => $mchOrderInfo['receiver_name'],
  177. 'mobile' => $mchOrderInfo['mobile'],
  178. 'updated_at' => time()
  179. ]);
  180. OrderModifyShippingAddressLog::setData([
  181. 'order_id' => $orderId,
  182. 'mall_id' => $mallId
  183. ]);
  184. }
  185. /**
  186. * 验证区域是否能购买
  187. *
  188. * @param $form
  189. *
  190. * @return mixed
  191. * @throws Exception
  192. */
  193. public function compute($form)
  194. {
  195. // 如果是预约类型的订单那么不做判断
  196. if ($form->type == PreviewTypeEnum::RESERVE_NOW) return $form;
  197. $district_id = 0;
  198. $town_id = 0;
  199. if ($form->address_id == 0) {
  200. $where[] = ['user_id' => $form['user_id'], 'status' => 1, 'is_default' => 1];
  201. /**
  202. * @var $user_address UserAddress
  203. */
  204. $user_address = UserAddress::getOne($where, false, [], false, 'district_id, town_id');
  205. if (empty($user_address)) {
  206. $where1[] = ['user_id' => $form['user_id'], 'status' => 1];
  207. $user_address = UserAddress::getOne($where1, false, [], false, 'district_id, town_id');
  208. }
  209. } else {
  210. $where2[] = ['id' => $form->address_id, 'status' => 1];
  211. $user_address = UserAddress::getOne($where2, false, [], false, 'district_id, town_id');
  212. }
  213. $is_area_limit_town = \Yii::$app->services->setting->mall->get($form['mall_id'], 'area.is_area_limit_town');
  214. foreach ($form->sku as $item) {
  215. if ($item['goods']['is_area_limit'] == 1) {
  216. $area_limit = Json::decode($item['goods']['area_limit']);
  217. $address_ids = [];
  218. if(!empty($area_limit)&&is_array($area_limit)){
  219. $address_ids = array_column($area_limit, 'id');
  220. }
  221. if (!empty($user_address)) {
  222. $district_id = $user_address->district_id;
  223. $town_id = $user_address->town_id;
  224. }
  225. // 如果区县/乡镇有其中一个满足条件的话那么就需要抛出异常
  226. if (empty($is_area_limit_town)) {
  227. if ((!empty($district_id) && !in_array($district_id, $address_ids))) {
  228. throw new Exception('当前收货地址不允许购买');
  229. }
  230. } else if (!empty($town_id) && !in_array("_$town_id", $address_ids)) {
  231. throw new Exception('当前收货地址不允许购买!');
  232. }
  233. }else{
  234. $is_area_limit = \Yii::$app->services->setting->mall->get($form['mall_id'], 'area.is_area_limit');
  235. //创建订单时在判断限购局域
  236. if($is_area_limit && $is_area_limit==1 && $item['goods']['goods_type'] != GoodsTypeEnum::GoodsTypeVirtual && $form->action == 'create_order'){ //虚拟商品部限制
  237. $config = \Yii::$app->services->setting->mall->get($form['mall_id'], 'area.area_limit');
  238. $common_address_ids = [];
  239. if ($config) {
  240. $config = \Qiniu\json_decode($config, true);
  241. $common_address_ids = array_column($config, 'id');
  242. }
  243. // var_dump($district_id,$form->address_id,$user_address->district_id,$common_address_ids);die;
  244. if (!empty($common_address_ids)) {
  245. // 是否仅限制第三级
  246. if (empty($is_area_limit_town)) {
  247. if ($district_id != 0) {
  248. if (!in_array($district_id, $common_address_ids)) {
  249. throw new Exception('全局配置设置,当前收货地址不允许购买,请把默认收货地址设置成允许收货地址的局域');
  250. }
  251. }else if($user_address->district_id){
  252. if (!in_array($user_address->district_id, $common_address_ids)) {
  253. throw new Exception('全局配置设置,当前收货地址不允许购买,请把默认收货地址设置成允许收货地址的局域');
  254. }
  255. }
  256. } else {
  257. if ($town_id != 0) {
  258. if (!in_array("_$town_id", $common_address_ids))
  259. throw new Exception('全局配置设置,当前收货地址不允许购买,请把默认收货地址设置成允许收货地址的局域!');
  260. } elseif (!empty($user_address->town_id)) {
  261. if (!in_array("_$user_address->town_id", $common_address_ids)) {
  262. throw new Exception('全局配置设置,当前收货地址不允许购买,请把默认收货地址设置成允许收货地址的局域!');
  263. }
  264. }
  265. }
  266. }
  267. }
  268. }
  269. }
  270. return $form;
  271. }
  272. /**
  273. * 获取订单的收货地址
  274. *
  275. * @param int $userId
  276. * @param int $mallId
  277. * @param int $orderId
  278. *
  279. * @return array
  280. */
  281. public function getOrderDeliveryAddress(int $userId, int $mallId, int $orderId): array
  282. {
  283. return \common\models\order\Order::find()
  284. ->where(['user_id' => $userId, 'mall_id' => $mallId, 'id' => $orderId])
  285. ->select('address, region_name, mobile, receiver_name')
  286. ->asArray()
  287. ->one();
  288. }
  289. }