OrderService.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <?php
  2. namespace addons\Happiness\common\service;
  3. use addons\CloudStock\common\logic\order\RestrictPurchases;
  4. use addons\Community\common\models\CommunityGoods;
  5. use addons\Community\common\service\SettingService;
  6. use common\enums\ShippingTypeEnum;
  7. use common\globals\GlobalInvoke;
  8. use addons\Happiness\common\logic\order\OrderInitDataLogic;
  9. use addons\Happiness\common\logic\order\OrderMarketingLogic;
  10. use common\logic\order\OrderLimitLogic;
  11. use addons\Happiness\common\logic\order\OrderValidateLogic;
  12. use common\models\common\Region;
  13. use common\models\mall\MallAddons;
  14. use common\models\user\UserAddress;
  15. use common\models\user\UserPartitionRelationship;
  16. use common\enums\StatusEnum;
  17. use common\enums\AddonsEnum;
  18. use common\enums\AppEnum;
  19. use common\enums\ClerkEnum;
  20. use addons\Happiness\common\models\Order;
  21. use addons\Happiness\common\models\HappinessOrder;
  22. use addons\Happiness\common\models\HappinessStore;
  23. use yii\helpers\Json;
  24. use Exception;
  25. use Money\Exchange;
  26. use Swoole\Http\Status;
  27. use Yii;
  28. class OrderService extends BaseService
  29. {
  30. //生成核销码
  31. public function getClerkCode($mall_id)
  32. {
  33. while (true) {
  34. $clerk_code = ClerkEnum::getCode(ClerkEnum::HAPPINESS_CLERK_CODE_PRE);
  35. $res = Order::findOne(['clerk_code' => $clerk_code]);
  36. if (empty($res)) break;
  37. }
  38. if (empty($clerk_code)) throw new \Exception('核销码生成失败');
  39. return $clerk_code;
  40. }
  41. public function preview($form)
  42. {
  43. try {
  44. // 获取收货地址
  45. $address_info = UserAddress::getUserAddress($this->user_id, $form->data['address_id']);
  46. $form->address_id = $address_info['id']??0;
  47. $store_info = HappinessStore::getOne([['id'=>$form->data['store_id'],'mall_id'=>$this->mall_id]], true,
  48. [], 'id desc', "*");
  49. if (empty($store_info)) throw new Exception('门店不存在');
  50. //省市区
  51. $region=Region::find()->where(['id' => [$store_info['province_id'], $store_info['city_id'],
  52. $store_info['district_id']]])->select('id,name')->indexBy('id')->asArray()->all();
  53. $store_info['address']=$region[$store_info['province_id']]['name'].$region[$store_info['city_id']]['name']
  54. .$region[$store_info['district_id']]['name']
  55. .$store_info['address'];
  56. $store_info['intra_city_distribution'] = json_decode($store_info['intra_city_distribution'], true);
  57. $form->store_info = $store_info;
  58. $form->store_id = $store_info['id']??0;
  59. if (empty($address_info)) $address_info = null;
  60. $orderInitDataLogic = new OrderInitDataLogic();
  61. $form = $orderInitDataLogic->execute($form, $form->type);
  62. if ($form === false) throw new Exception($orderInitDataLogic->getError());
  63. $is_bind_popups = UserPartitionRelationship::getIsNeedPopups($this->mall_id, $this->user_id);
  64. if($is_bind_popups == 1) throw new Exception('请进入商品详情页,绑定邀请码!');
  65. // 购买限制验证
  66. $orderLimitLogic = new OrderLimitLogic();
  67. $form = $orderLimitLogic->run($form);
  68. if ($form === false) throw new Exception($orderLimitLogic->getError());
  69. // 强制免运费
  70. $form = $this->isForceFreeShipping($form);
  71. // 营销减免活动
  72. $orderMarketingLogic = new OrderMarketingLogic();
  73. $form = $orderMarketingLogic->run($form);
  74. if ($form === false) throw new Exception($orderMarketingLogic->getError());
  75. $group_order_goods = $form['group_order_goods'];
  76. $group_order_goods_list = [];
  77. $gIds = [];
  78. foreach ($group_order_goods as $val){
  79. $group_order_goods_list[]=$val;
  80. foreach ($val['goods'] as $gId => $item) {
  81. $gIds[] = $gId;
  82. }
  83. }
  84. $marketing = $form['marketing']??[];
  85. $pay_type_list = \Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform, 1, ['pay_money' => $form['total_pay_money'], 'user_id' => $this->user_id]);
  86. if($form['total_pay_money']<=0){
  87. $tmp = [];
  88. foreach ($pay_type_list as $item){
  89. if($item['trade_type']=='default'){
  90. $tmp[]=$item;
  91. break;
  92. }
  93. }
  94. $pay_type_list = $tmp;
  95. }
  96. $shipping_type_list = ShippingTypeEnum::getMap();
  97. $option_list = [];
  98. $group_order_goods = $group_order_goods_list;
  99. $extends_fields = [];
  100. $info = compact('group_order_goods', 'marketing', 'address_info', 'pay_type_list', 'shipping_type_list', 'option_list', 'extends_fields', 'store_info');
  101. if($form['total_pay_money'] < 0) $form['total_pay_money'] = 0;
  102. $info['total_pay_money'] = '¥' . $form['total_pay_money'];
  103. $info['total_pay_money_not_coupon'] = $form['total_pay_money_not_coupon'];
  104. $info['is_address'] = $form['is_address'] ?? 0;
  105. $info['is_virtual'] = $form['is_virtual'] ?? 0;
  106. $info['is_sign_agreement'] = $form['is_sign_agreement'] ?? 0;
  107. $info['shipping_type'] = $form->data['shipping_type'] ?? null;
  108. // 农业补贴 - 是否需要显示推荐人输入框
  109. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_AGRICULTURAL_SUBSIDIES)) {
  110. $aConfig = Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_AGRICULTURAL_SUBSIDIES, 'basic');
  111. if($aConfig && isset($aConfig['goods'])){
  112. $tGoods = json_decode($aConfig['goods'], true);
  113. $tGids = array_column($tGoods, 'goods_id');
  114. $info['show_invite_form'] = StatusEnum::DISABLED;
  115. if ($aConfig['enable_bind_master'] == StatusEnum::ENABLED && !empty(array_intersect($tGids, $gIds))) {
  116. $info['show_invite_form'] = StatusEnum::ENABLED;
  117. }
  118. }
  119. // 判断是否包含当前商品
  120. // $info['show_invite_form'] = Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_AGRICULTURAL_SUBSIDIES, 'basic.enable_bind_master');
  121. }
  122. $form->data['type'] = $form->type;
  123. //物流方式为快递配送,则调用公共调用
  124. if ($form->shipping_type == 1) {
  125. $invoke_res = GlobalInvoke::exec(GlobalInvoke::ORDER_PREVIEW_APPEND_FILEDS, $this->mall_id, ['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'data' => $info, 'params' => $form->data]);
  126. $info = !empty($invoke_res) ? $invoke_res : $info;
  127. }
  128. return $info;
  129. } catch (\Exception $e) {
  130. throw new Exception($e->getMessage());
  131. }
  132. }
  133. public function created($form)
  134. {
  135. try {
  136. // 获取收货地址
  137. $address_info = UserAddress::getUserAddress($this->user_id, $form->data['address_id']);
  138. //获取门店
  139. $store_info = HappinessStore::getOne([['id'=>$form->data['store_id'],'mall_id'=>$this->mall_id]], true,
  140. [], 'id desc', "*");
  141. if (empty($store_info)) throw new Exception('门店不存在');
  142. $store_info['intra_city_distribution'] = json_decode($store_info['intra_city_distribution'], true);
  143. $form->store_info = $store_info;
  144. $form->store_id = $store_info['id']??0;
  145. if (empty($address_info)) $address_info = null;
  146. $orderInitDataLogic = new OrderInitDataLogic();
  147. $form = $orderInitDataLogic->execute($form, $form->type);
  148. if ($form === false) throw new Exception($orderInitDataLogic->getError());
  149. $is_bind_popups = UserPartitionRelationship::getIsNeedPopups($this->mall_id, $this->user_id);
  150. if($is_bind_popups == 1) throw new Exception('请进入商品详情页,绑定邀请码!');
  151. // 购买限制验证
  152. $orderLimitLogic = new OrderLimitLogic();
  153. $form = $orderLimitLogic->run($form);
  154. if ($form === false) throw new Exception($orderLimitLogic->getError());
  155. // 强制免运费
  156. $form = $this->isForceFreeShipping($form);
  157. // 数据校验
  158. $flag = OrderValidateLogic::run($form);
  159. if (is_string($flag)) throw new Exception($flag);
  160. // 营销减免活动
  161. $orderMarketingLogic = new OrderMarketingLogic();
  162. $form = $orderMarketingLogic->run($form, true);
  163. if ($form === false) throw new Exception($orderMarketingLogic->getError());
  164. $goods_ids = array_column($form['order_goods'],'goods_id');
  165. if(MallAddons::isInstall($this->mall_id,'CloudStock')){
  166. (new RestrictPurchases())->orderCreate(['user_id' => $this->user_id,'mall_id' => $this->mall_id,'type' => 'order','goods_ids'=>$goods_ids]);
  167. }
  168. $need_auth = GlobalInvoke::exec(GlobalInvoke::REAL_AUTH, $this->mall_id, ['user_id' => $this->user_id,'mall_id' => $this->mall_id,'type' => 'order','goods_ids'=>$goods_ids]);
  169. if($need_auth === true){
  170. //需要先进行实名认证
  171. throw new Exception('请先进行实名认证');
  172. }
  173. foreach ($form['group_order_goods'] as $key => $value) {
  174. if ($value['mch_order_info']['num'] == 0) throw new Exception('无可购买商品');
  175. }
  176. $delivery_amount = 0;
  177. if ($form->data['shipping_type'] == 3) {
  178. if ($form->store_info['intra_city_distribution']['is_alone'] == 1) {
  179. $delivery_amount = $form->store_info['intra_city_distribution']['initial_delivery_amount'];
  180. } else if (['intra_city_distribution']['is_alone'] == 0){
  181. $delivery_amount = $form->store_info['setting']['delivery_amount'];
  182. }
  183. }
  184. if ($delivery_amount > $form->total_pay_money) {
  185. throw new Exception('订单未达起送价,还差'.bcsub($delivery_amount, $form->total_pay_money, 2).'元');
  186. // throw new Exception('起送金额是'.$delivery_amount.'元');
  187. }
  188. $res = Order::createOrder($form);
  189. if ($res === false) throw new Exception(Order::getStaticError());
  190. return $res;
  191. } catch (\Exception $e) {
  192. throw new Exception($e->getMessage());
  193. }
  194. }
  195. protected function isForceFreeShipping($form)
  196. {
  197. // 社区团购 是否强制免运费
  198. if (!$form->is_force_free_shipping && MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_COMMUNITY) &&
  199. (new SettingService())->isForceFreeShipping($this->mall_id)) { // 需要处理
  200. // 判断是否为社区团购订单
  201. // 这种判断仅限于定制创建的时候
  202. if ($form->action == AppEnum::ACTION_CREATE && in_array($form->shipping_type,
  203. [ShippingTypeEnum::PICKUP, ShippingTypeEnum::MERCHANT_DISTRIBUTION]) && !empty($form->extra_info)) {
  204. $ext = json_decode($form->extra_info, true);
  205. if (empty($ext['head_id'])) {
  206. return $form;
  207. }
  208. }
  209. // 如果有安装社区团购 并且
  210. $community_res = (new CommunityGoods())->orderPreviewAppendFields(['mall_id' => $this->mall_id, 'user_id' => $this->user_id,
  211. 'data' => [], 'params' => array_merge($form->data, ['type' => $form->type])]);
  212. $shipping_type = null;
  213. if (!empty($community_res['option_list']) && is_array($community_res['option_list'])) {
  214. $option_list = array_values(array_filter($community_res['option_list'], function ($val) {
  215. return $val['enable'] == StatusEnum::ENABLED;
  216. }));
  217. $shipping_type = $option_list[0]['key'] ?? null;
  218. }
  219. $shipping_type = $form->data['shipping_type'] ?? $shipping_type; // 如果前端没有传,那么就取默认第一个
  220. $form->is_force_free_shipping = in_array($shipping_type, [ShippingTypeEnum::PICKUP]);
  221. }
  222. return $form;
  223. }
  224. //订单详情公共调用
  225. public function globalOrderDetail($data) {
  226. try {
  227. //获取门店订单
  228. $store_order = HappinessOrder::getOne([
  229. ['mall_id' => $data['order']['mall_id']],
  230. ['order_id' => $data['order']['id']],
  231. ]);
  232. if (empty($store_order)) {
  233. $data['order']['is_happiness_order'] = 0;
  234. return $data['order'];
  235. }
  236. $data['order']['show_botton'] = false;
  237. //获取门店信息
  238. $store_info = HappinessStore::getOne([
  239. ['mall_id' => $data['order']['mall_id']],
  240. ['id' => $store_order->store_id],
  241. ], true);
  242. if (!empty($store_info)) $data['order']['store'] = $store_info;
  243. $data['order']['is_happiness_order'] = 1;
  244. $data['order']['store_name'] = $store_info['store_name'];
  245. $data['order']['shop_mobile'] = $store_info['shop_mobile'];
  246. $data['order']['latitude'] = $store_info['latitude'];
  247. $data['order']['longitude'] = $store_info['longitude'];
  248. //省市区
  249. $region=Region::find()->where(['id' => [$store_info['province_id'], $store_info['city_id'],
  250. $store_info['district_id']]])->select('id,name')->indexBy('id')->asArray()->all();
  251. $store_info['address']=$region[$store_info['province_id']]['name'].$region[$store_info['city_id']]['name']
  252. .$region[$store_info['district_id']]['name']
  253. .$store_info['address'];
  254. $data['order']['store_address'] = $store_info['address'];
  255. if ($data['order']['order_status'] == 3 && $data['order']['shipping_type'] == 3) {
  256. $data['order']['is_show_return_btn'] = 0;
  257. foreach ($data['order']['detail'] as $key => $value) {
  258. $data['order']['detail'][$key]['is_show_return_btn'] = 0;
  259. }
  260. }
  261. return $data['order'];
  262. } catch (\Exception $e) {
  263. throw new Exception($e->getMessage());
  264. }
  265. }
  266. public function globalBackendLists($data)
  267. {
  268. try {
  269. $order_ids = array_column($data['order'], 'id');
  270. //获取幸福小店订单
  271. $happiness_order = HappinessOrder::lists([
  272. 'where' => [
  273. ['order_id' => $order_ids],
  274. ],
  275. 'index' => 'order_id'
  276. ]);
  277. if (!empty($happiness_order)) {
  278. foreach ($data['order'] as &$item) {
  279. if (!empty($happiness_order[$item['id']])) {
  280. $item['show_botton'] = false;
  281. } else {
  282. $item['show_botton'] = true;
  283. }
  284. }
  285. }
  286. return $data['order'];
  287. } catch (\Exception $e) {
  288. throw new Exception($e->getMessage());
  289. }
  290. }
  291. }