OrderService.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. <?php
  2. namespace addons\Community\common\service;
  3. use addons\Community\common\enums\CommunityEnum;
  4. use addons\Community\common\helper\CommunityHelper;
  5. use addons\Community\common\models\CommunityGoodsSetting;
  6. use addons\Community\common\models\CommunityHead;
  7. use addons\Community\common\models\CommunityHeadCommission;
  8. use addons\Community\common\models\CommunityHeadOrder;
  9. use addons\SmartForm\common\service\SmsNoticeService;
  10. use common\enums\AddonsEnum;
  11. use common\enums\ClerkEnum;
  12. use common\enums\GlobalFuncEnum;
  13. use common\enums\MarketingTypeEnum;
  14. use common\enums\OrderSourceEnum;
  15. use common\enums\OrderStatusEnum;
  16. use common\enums\PayTypeEnum;
  17. use common\enums\ShippingTypeEnum;
  18. use common\enums\StatusEnum;
  19. use common\globals\GlobalInvoke;
  20. use common\models\goods\Goods;
  21. use common\models\goods\GoodsAttr;
  22. use common\models\mall\MallAddons;
  23. use common\models\order\Order;
  24. use common\models\order\OrderDetail;
  25. use common\models\order\OrderMarketing;
  26. use common\models\user\User;
  27. use Yii;
  28. use yii\helpers\Json;
  29. class OrderService
  30. {
  31. /**
  32. * 订单列表 - 后台
  33. * @param int $mall_id
  34. * @param array $params
  35. * @return array|false|mixed|string|null
  36. */
  37. public function page(int $mall_id, array $params)
  38. {
  39. // 组织条件
  40. $user_ids = [];
  41. if (!empty($params["user_id"])) {
  42. $user_ids[] = $params["user_id"];
  43. }
  44. if (!empty($params["member"])) {
  45. $user_or[] = 'or';
  46. $user_or[] = ['like', 'mobile', $params['member']];
  47. $user_or[] = ['like', 'nickname', $params['member']];
  48. $u_ids = User::find()->where(['mall_id' => $mall_id])->andWhere($user_or)->column();
  49. if (!empty($u_ids)) {
  50. $user_ids = array_merge($user_ids, $u_ids);
  51. }
  52. }
  53. $where = [
  54. ['mall_id' => $mall_id]
  55. ];
  56. // 卖家查询
  57. if (!empty($params['head_member'])) {
  58. $head_member_or[] = 'or';
  59. $head_member_or[] = ['like', 'mobile', $params['head_member']];
  60. $head_member_or[] = ['like', 'nickname', $params['head_member']];
  61. $u_ids = User::find()->where(['mall_id' => $mall_id])->andWhere($head_member_or)->column();
  62. if (!empty($u_ids)) {
  63. $where[] = ['in', 'user_id', $u_ids];
  64. }
  65. }
  66. if (!empty($params['status'])) {
  67. $where[] = ['apply_status' => $params['status']];
  68. }
  69. // 团长检索
  70. if (!empty($params['name'])) {
  71. $h_ids = CommunityHead::find()->where(['mall_id' => $mall_id])->andWhere(['status' => StatusEnum::ENABLED])
  72. ->andWhere(['like', 'name', trim($params['name'])])->select('id')->column();
  73. if (!empty($h_ids)) $where[] = ['in', 'head_id', $h_ids];
  74. }
  75. if (!empty($params['date_start']) && !empty($params['date_end'])) {
  76. $s = strtotime($params['date_start']);
  77. $e = strtotime($params['date_end']);
  78. $where[] = ['between', 'created_at', $s, $e];
  79. } elseif (!empty($params['date_start'])) {
  80. $s = strtotime($params['date_start']);
  81. $where[] = ['<=', 'created_at', $s];
  82. } elseif (!empty($params['date_end'])) {
  83. $e = strtotime($params['date_end']);
  84. $where[] = ['>=', 'created_at', $e];
  85. }
  86. // 买家查询
  87. if (!empty($user_ids)) $where[] = ['in', 'buyer_user_id', $user_ids];
  88. if (isset($params['order_status']) && is_numeric($params['order_status'])) {
  89. $where[] = [
  90. 'order_id' => Order::find()
  91. ->where([
  92. 'id' => CommunityHeadOrder::find()
  93. ->where([
  94. 'status' => StatusEnum::ENABLED,
  95. 'mall_id' => $mall_id
  96. ])
  97. ->select('order_id')
  98. ->column(),
  99. 'order_status' => $params['order_status'],
  100. 'mall_id' => $mall_id,
  101. 'status' => StatusEnum::ENABLED
  102. ])
  103. ->select('id')
  104. ->column()
  105. ];
  106. }
  107. $map['where'] = $where;
  108. $map['with'] = [
  109. 'head' => function($query) {
  110. $query->select('id, name, logo, contacts, mobile');
  111. },
  112. 'order'=> function($query) {
  113. $query->with('detail');
  114. },
  115. 'headUser', 'buyer'
  116. ];
  117. $map['order'] = 'id desc';
  118. $map["limit"] = $params["limit"];
  119. $map["page"] = $params["page"];
  120. $ret = CommunityHeadOrder::listPage($map);
  121. if (!empty(CommunityHeadOrder::$static_error)) return CommunityHeadOrder::$static_error;
  122. if (!empty($ret['list'])) {
  123. foreach ($ret['list'] as &$item) {
  124. if ($item['order']['consign_time'] > 0) { // 只有已经发货的才有预计提货时间
  125. $item['expected_receive_at'] = CommunityHelper::getPickUpAt($item['mall_id'], $item['order']['consign_time']);
  126. } else {
  127. $item['expected_receive_at'] = '-';
  128. }
  129. }
  130. }
  131. return $ret;
  132. }
  133. /**
  134. * 创建订单
  135. * @param Order $order
  136. * @param int $head_id
  137. * @return bool
  138. */
  139. public function create(Order $order, int $head_id)
  140. {
  141. $head_user_id = CommunityHead::find()->where(['mall_id' => $order->mall_id])
  142. ->andWhere(['id' => $head_id])->select('user_id')->scalar();
  143. if (!$head_user_id) {
  144. \Yii::error("同步订单 {$order->id} 至自提点 {$head_id} 获取不到团长ID");
  145. return false;
  146. }
  147. $model = new CommunityHeadOrder();
  148. $model->mall_id = $order->mall_id;
  149. $model->buyer_user_id = $order->user_id;
  150. $model->head_id = $head_id;
  151. $model->user_id = $head_user_id;
  152. $model->order_id = $order->id;
  153. $model->order_no = $order->order_no;
  154. $model->order_status = OrderStatusEnum::NOT_PAY;
  155. if (!$model->save()) {
  156. \Yii::error("同步订单 {$order->id} 至自提点 {$head_id} 失败 {$model->getErrorMessage()}");
  157. return false;
  158. }
  159. return true;
  160. }
  161. /**
  162. * @param Order $order
  163. * @param int $status
  164. * @param \Closure|null $callback
  165. * @return bool
  166. */
  167. public function changeStatus(Order $order, int $status, \Closure $callback = null)
  168. {
  169. $t = \Yii::$app->db->beginTransaction();
  170. try {
  171. $data = CommunityHeadOrder::getOne([
  172. ['order_id' => $order->id],
  173. ['mall_id' => $order->mall_id]
  174. ]);
  175. if (empty($data)) {
  176. return false;
  177. }
  178. // $status = $status == OrderStatusEnum::SHIPMENTS ? OrderStatusEnum::TAKE : $status;
  179. $data->order_status = $status;
  180. if (!$data->save()) {
  181. \Yii::error("同步订单 {$order->id} 状态 {$status} 至自提点 {$data->head_id} 失败 {$data->getErrorMessage()}");
  182. throw new \Exception($data->getErrorMessage());
  183. }
  184. if ($status == OrderStatusEnum::TAKE) {
  185. // 更新订单状态 - 需要将平台订单状态修改为 6 ?等待用户自提 - 如果长时间没消费怎么办?
  186. $order->order_status = $status;
  187. if (!$order->save()) {
  188. \Yii::error("同步订单 更新订单 {$order->id} 状态 {$status} 至自提点 {$data->head_id} 失败 {$data->getErrorMessage()}");
  189. throw new \Exception($order->getErrorMessage());
  190. }
  191. // 订单详情
  192. if (!OrderDetail::updateAll(['order_status' => $status], ['order_status' => OrderStatusEnum::SHIPMENTS, 'order_id' => $order->id])) {
  193. \Yii::error("同步订单 更新 orderDetail {$order->id} 状态 {$status} 至自提点 {$data->head_id} 失败 {$data->getErrorMessage()}");
  194. throw new \Exception(OrderDetail::getStaticError());
  195. }
  196. }
  197. // 闭包处理
  198. if (!empty($callback)) {
  199. $callback->call($this);
  200. }
  201. $t->commit();
  202. return true;
  203. } catch (\Exception $e) {
  204. $t->rollBack();
  205. \Yii::error(Json::encode([
  206. 'file' => $e->getFile(),
  207. 'line' => $e->getLine(),
  208. 'msg' => $e->getMessage()
  209. ]));
  210. return false;
  211. }
  212. }
  213. public function frontPage(int $mall_id, array $params, array $mall, string $platform, int $user_id)
  214. {
  215. // 通过用户ID去取数据
  216. $head_where = [
  217. ['mall_id' => $mall_id],
  218. ['user_id' => $user_id],
  219. ['status' => StatusEnum::ENABLED]
  220. ];
  221. if (isset($params['order_status']) && $params['order_status'] != 999) {
  222. if ($params['order_status'] == OrderStatusEnum::SING) { // 如果筛选的是已收货的订单那么就将已提货的订单一起取出来
  223. $params['order_status'] = [OrderStatusEnum::SING, OrderStatusEnum::TAKE_FINISH];
  224. }
  225. $head_where[] = ['order_status' => $params['order_status']];
  226. } else {
  227. if (!empty($params['wait_pending'])) {
  228. $head_where[] = ['not in', 'order_status', [OrderStatusEnum::ACCOMPLISH, OrderStatusEnum::REPEAL,
  229. OrderStatusEnum::TAKE_FINISH, OrderStatusEnum::SING]]; // 排除 已完成, 已关闭, 已自提, 已签收
  230. }
  231. }
  232. if (!empty($params['keyword'])) {
  233. $u_ids = User::find()->where(['mall_id' => $mall_id])
  234. ->andWhere(['or', ['like', 'mobile', $params['keyword']], ['like', 'nickname', $params['keyword']]])
  235. ->select('id')
  236. ->column();
  237. if (!empty($u_ids)) {
  238. $head_where[] = ['buyer_user_id' => $u_ids];
  239. } else {
  240. $head_where[] = ['buyer_user_id' => 0];
  241. }
  242. }
  243. $map['where'] = $head_where;
  244. $map['select'] = 'order_id';
  245. $map['limit'] = $params['limit'] ?? 5;
  246. $map['page'] = $params['page'] ?? 1;
  247. $map['order'] = 'id desc';
  248. $ret = CommunityHeadOrder::listPage($map);
  249. if (!empty($ret['list'])) {
  250. $order_ids = array_column($ret['list'], 'order_id');
  251. $where[] = ['in', 'id', $order_ids];
  252. $where[] = ['is_feedback' => OrderStatusEnum::NOT_FEEDBACK];
  253. $where[] = ['!=', 'order_source', OrderSourceEnum::SOURCE_SELF_MALL];
  254. if ($params['shipping_type']) {// 判断订单配送类型
  255. $where[] = ['shipping_type' => $params['shipping_type']];
  256. }
  257. // $select = 'id,pay_money,order_status,shipping_type,is_recycle,marketing_type,extra_info,order_source, consign_time';
  258. // $params['order'] = 'id desc';
  259. // if(!empty($params['keyword'])){
  260. // $goods_list = Goods::lists(['where'=>[
  261. // ['mall_id'=>$mall_id],
  262. // ['like','goods_name',trim($params['keyword']).'%',false]
  263. // ],'select'=>'id']);
  264. //
  265. // $goods_ids = array_column($goods_list,'id');
  266. // $order_detail_list = OrderDetail::lists(['where'=>[
  267. // ['mall_id'=>$mall_id],
  268. // ['in','goods_id',$goods_ids]
  269. // ],'select'=>'order_id']);
  270. // $order_ids = array_column($order_detail_list,'order_id');
  271. // $where[]=[
  272. // 'or',
  273. // ['id'=>$order_ids],
  274. // ['like','order_no',trim($params['keyword']).'%',false]
  275. // ];
  276. // }
  277. $select = 'id,pay_money,order_status,shipping_type,is_recycle,marketing_type,extra_info,order_source,store_id,mch_id,receiver_name,mobile, consign_time, mall_id';
  278. $params['order'] = 'pay_time desc';
  279. $params['select'] = $select;
  280. $params['where'] = $where;
  281. $params['with'] = ['detail' => function ($query) {
  282. $query->select('id,order_id,goods_id,goods_name,pic_url,goods_attr_id,num,price,is_feedback,sign_id,goods_attr_name,extra_info,adjust_money');
  283. }];
  284. $params['limit'] = 0;
  285. // $params['page'] = 0;
  286. $order_list = Order::lists($params);
  287. $ret['mall_name'] = $mall['name'];
  288. $ret['mall_logo'] = Yii::$app->services->setting->mall->get($mall_id, 'basic.logo');
  289. if (!empty($order_list)) {
  290. foreach ($order_list as $key => $val) {
  291. array_map(function ($arg) use (&$val) {
  292. if (!isset($val['num'])) $val['num'] = 0;
  293. $val['num'] += $arg['num'];
  294. }, $val['detail']);
  295. // 剩余库存
  296. $stock = [];
  297. if($val['detail']){
  298. foreach ($val['detail'] as $k => $v){
  299. $order_list[$key]['detail'][$k]['price'] = $order_list[$key]['detail'][$k]['price'] + $order_list[$key]['detail'][$k]['adjust_money'];
  300. $order_list[$key]['detail'][$k]['price'] = round($order_list[$key]['detail'][$k]['price'],2);
  301. $goods_unit = Goods::getOne([['=','id',$v['goods_id']]],false,'','','unit')['unit'];
  302. $val['detail'][$k]['unit'] = $goods_unit;
  303. // 当订单关闭时可以直接再次购买
  304. if ($val['order_status'] == OrderStatusEnum::REPEAL) {
  305. // 查询商品是否有货
  306. $stock[] = [
  307. 'num' => $v['num'],
  308. 'store_id' => $v['store_id']??0,
  309. 'goods_id' => $v['goods_id'],
  310. 'attr_id' => $v['goods_attr_id'],
  311. 'stock' => GoodsAttr::find()->where(['id' => $v['goods_attr_id']])->select('stock')->scalar(),
  312. ];
  313. }
  314. }
  315. }
  316. // 获取支付金额
  317. $order_list[$key] = GlobalInvoke::exec(GlobalInvoke::ORDER_DETAIL, $mall_id, [
  318. 'order' => $val,
  319. 'mall_id' => $mall_id,
  320. ]) ?: $val;
  321. $order_list[$key]['mall_name'] = $mall['name'];
  322. $order_list[$key]['mall_logo'] = Yii::$app->services->setting->mall->get($mall_id, 'basic.logo');
  323. // 判断是否可以再次购买
  324. $is_agent = empty($stock) ? 0 : 1;
  325. foreach ($stock as $v) {
  326. // 当库存小于购买数量 不可再次购买
  327. if ($v['stock'] < $v['num']) {
  328. $is_agent = 0;
  329. }
  330. }
  331. $order_list[$key]['is_agent'] = $is_agent;
  332. $order_list[$key]['is_agent_data'] = $is_agent ? $stock : [];
  333. // 计算预计取货时间
  334. $order_list[$key]['expected_receive_at'] = "";
  335. if (!empty($val['consign_time']) && $val['order_status'] == OrderStatusEnum::SHIPMENTS) {
  336. $order_list[$key]['expected_receive_at'] = CommunityHelper::getPickUpAt($mall_id, $val['consign_time']);
  337. }
  338. }
  339. $order_list = GlobalInvoke::exec(GlobalFuncEnum::ORDER_LIST, $mall_id, [
  340. 'order' => $order_list, 'mall_id' => $mall_id
  341. ]) ?: $order_list;
  342. $ret['shipping_type_text'] = ShippingTypeEnum::getMap();
  343. $ret['order_status_text'] = OrderStatusEnum::getMap();
  344. $ret['order_status_text'][OrderStatusEnum::SHIPMENTS] = '待取货';
  345. $ret['is_feedback_text'] = OrderStatusEnum::getFeedbackMap();
  346. }
  347. $ret['pay_type_list'] = \Yii::$app->services->pay->getEnablePayment($mall_id, $platform);
  348. $ret['marketing_type_map'] = MarketingTypeEnum::getMap();
  349. $ret['list'] = $order_list;
  350. }
  351. return $ret;
  352. }
  353. /**
  354. * 订单详情
  355. * @param int $mall_id
  356. * @param int|string $order_id
  357. * @param string $filed_key order_id | order_no
  358. * @param int $user_id
  359. * @param string $platform
  360. * @return array|mixed
  361. */
  362. public function detail(int $mall_id, $order_id, string $filed_key, int $user_id, string $platform)
  363. {
  364. $order_id = CommunityHeadOrder::find()
  365. ->where(['mall_id' => $mall_id])
  366. ->andWhere(['user_id' => $user_id])
  367. ->andWhere(['status' => StatusEnum::ENABLED])
  368. ->andWhere([$filed_key => $order_id])
  369. ->select('order_id')->scalar();
  370. if (empty($order_id)) return '订单不存在.';
  371. $select = 'id,mall_id,user_id,store_id,order_no,receiver_name,mobile,pay_money,shipping_money,original_goods_price,coupon_money,goods_price,order_status,pay_status,
  372. shipping_status,review_status,is_feedback,address,created_at,pay_time,region_name,remark,consign_time,finish_time,sign_time,shipping_type,payment_type,score,score_money,marketing_id,marketing_type,extra_info,order_source';
  373. $where = [];
  374. $where[] = ['mall_id' => $mall_id];
  375. $where[] = ['id' => $order_id];
  376. $order = Order::getOne($where, true, ['detail' => function ($query) {
  377. $query->select('id,order_id,goods_id,goods_name,pic_url,num,price,is_feedback,sign_id,goods_attr_name,order_status,adjust_money,extra_info');
  378. }], false, $select);
  379. if (empty($order)) return '该订单不存在';
  380. $marketing = OrderMarketing::getMarketingInfo($order);
  381. $order['order_status_text'] = OrderStatusEnum::getMap();
  382. $order['order_status_text'][OrderStatusEnum::SHIPMENTS] = $order['shipping_type'] == ShippingTypeEnum::MERCHANT_DISTRIBUTION ? '待配送' : '待取货';
  383. $order['is_feedback_text'] = OrderStatusEnum::getFeedbackMap();
  384. $order['shipping_type_text'] = ShippingTypeEnum::getMap();
  385. $order['payment_type_text'] = PayTypeEnum::getMap();
  386. $order['pay_type_list'] = \Yii::$app->services->pay->getEnablePayment($mall_id, $platform);
  387. $order['change_price'] = array_sum(array_column($order['detail'],'adjust_money'));//预留字段
  388. $order['marketing'] = $marketing;
  389. $order['marketing_type_map'] =MarketingTypeEnum::getMap();
  390. $order_setting = Yii::$app->services->setting->mall->get($mall_id, 'order');
  391. $order['payment_expire_time'] = $order_setting['payment_expire_time']??30;
  392. $order['auto_receiving_time'] = $order_setting['auto_receiving_time']??14;
  393. //查询商品单位
  394. $goods_ids = [];
  395. if(!empty($order['detail'])){
  396. foreach ($order['detail'] as $k => $v){
  397. $goods_ids[] = $v['goods_id'];
  398. $goods_unit = Goods::getOne([['=','id',$v['goods_id']]],false,'','','unit')['unit'];
  399. $order['detail'][$k]['unit'] = $goods_unit;
  400. }
  401. }
  402. // 获取订单详情的状态文字描述
  403. $order['status_text'] = OrderStatusEnum::getApiStatus($order['status'], $order['shipping_type']);
  404. $order['status'] == OrderStatusEnum::NOT_PAY && $order['status_text']['desc'] = $order['payment_expire_time'] . $order['status_text']['desc'];
  405. $order['status'] == OrderStatusEnum::SHIPMENTS && $order['status_text']['desc'] = $order['auto_receiving_time'] . $order['status_text']['desc'];
  406. $order['expected_receive_at'] = ""; // 预计取货时间
  407. $order['is_show_receipt_btn'] = StatusEnum::ENABLED; // 是否显示收货按钮
  408. $order['shipping_money'] = $order['shipping_money'] ?? 0;
  409. $config = Yii::$app->services->setting->addons->get($mall_id, CommunityEnum::ADDONS_NAME, 'basic');
  410. $is_enable_write_off = !empty($config['is_enable_write_off']) ? StatusEnum::ENABLED : StatusEnum::DISABLED; // 是否有开启核销
  411. if (!empty($is_enable_write_off) || $order['order_status'] != OrderStatusEnum::SHIPMENTS) { // 开启了核销
  412. $order['is_show_receipt_btn'] = StatusEnum::DISABLED;
  413. }
  414. if (!empty($order['consign_time']) && $order['order_status'] == OrderStatusEnum::SHIPMENTS) {
  415. $order['expected_receive_at'] = CommunityHelper::getPickUpAt($mall_id, $order['consign_time']);
  416. }
  417. // 判断是否有智能表单
  418. if (!empty($goods_ids) && MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_SMART_FORM)) {
  419. // 如果有安装
  420. $goods_ids = array_unique($goods_ids);
  421. $order['smart_form'] = SmsNoticeService::findByUserIdAndGoodsIds($order['user_id'], $goods_ids, $order['id']);
  422. }
  423. // 公共调用
  424. return GlobalInvoke::exec(GlobalInvoke::ORDER_DETAIL, $mall_id, [
  425. 'order' => $order,
  426. 'mall_id' => $mall_id,
  427. ]) ?: $order;
  428. }
  429. /**
  430. * 公共调用订单详情
  431. * @param $params
  432. * @return mixed
  433. */
  434. public function globalDetail($params)
  435. {
  436. // $params['order'] // 订单主体信息
  437. // 如果是站点自提
  438. if (in_array($params['order']['shipping_type'], [ShippingTypeEnum::PICKUP, ShippingTypeEnum::MERCHANT_DISTRIBUTION]) && !empty($params['order']['extra_info'])) {
  439. try {
  440. $ext = Json::decode($params['order']['extra_info']);
  441. } catch (\Exception $exception) {
  442. return $params['order'];
  443. }
  444. if (!empty($ext['head_id']) && !empty($params['order']['mall_id'])) { // 确定为站点自提
  445. // 返回 是否是社区团购自提订单
  446. if (!empty($params['order']['id'])) {
  447. $params['order']['is_community_order'] = (bool)CommunityHeadOrder::find()
  448. ->where(['order_id' => $params['order']['id']])
  449. ->count();
  450. }
  451. // 返回自提订单是否允许退款,如果不是社区团购自提订单也没必要返回是否允许退款的配置了
  452. if (!empty($params['order']['detail']) && !empty($params['order']['is_community_order'])) {
  453. $goodsIds = array_column($params['order']['detail'], 'goods_id');
  454. $where = ['goods_id' => $goodsIds, 'status' => StatusEnum::ENABLED, 'enable' => StatusEnum::ENABLED];
  455. $goodsSettingList = CommunityGoodsSetting::find()
  456. ->where($where)
  457. ->select('goods_id, enable_refund')
  458. ->asArray()
  459. ->indexBy('goods_id')
  460. ->all();
  461. array_walk($params['order']['detail'], function (&$item) use ($goodsSettingList) {
  462. $item['community_goods_setting'] = $goodsSettingList[$item['goods_id']] ?? [];
  463. if (isset($item['community_goods_setting']['enable_refund'])) {
  464. // 返回前端是否要显示售后按钮,前端状态 1待发货 2已发货 才能申请
  465. $item['community_goods_setting']['enable_refund_1'] = $item['community_goods_setting']['enable_refund'] &&
  466. in_array($item['order_status'], [OrderStatusEnum::PAY, OrderStatusEnum::SHIPMENTS]);
  467. }
  468. });
  469. }
  470. $head_info = (new HeadService())->pickupInfoOrder($params['order']['mall_id'], $ext['head_id']);
  471. if (empty($head_info)) {
  472. Yii::error("获取团长信息失败: {$params['order']['id']}, {$params['order']['extra_info']}");
  473. return $params['order'];
  474. }
  475. $config = Yii::$app->services->setting->addons->get($params['order']['mall_id'], CommunityEnum::ADDONS_NAME, 'basic');
  476. $head_info['tips'] = '具体取货时间可联系自提点';
  477. if ($config['pick_up_time_range_type'] == StatusEnum::DISABLED) {
  478. $head_info['business_hours'] = '全天';
  479. } else {
  480. $head_info['business_hours'] = implode(' - ', Json::decode($config['pick_up_time_range_custom_at']));
  481. }
  482. $head_info['pickup_at'] = '';
  483. if (!empty($params['order']['consign_time']) && !empty($params['order']['mall_id'])) {
  484. $head_info['pickup_at'] = CommunityHelper::getPickUpAt($params['order']['mall_id'], $params['order']['consign_time']);
  485. }
  486. $is_enable_write_off = $config['is_enable_write_off'] ?? StatusEnum::DISABLED;
  487. // 如果订单不为用户自提那么就不能走核销码,如果订单为用户自提那么只能在已支付、已发货情况下进行核销
  488. // 如果是自提,那么就有核销码,如果是送货上门,那么就没有核销码
  489. if (!in_array($params['order']['order_status'], [OrderStatusEnum::PAY, OrderStatusEnum::SHIPMENTS]) ||
  490. $params['order']['shipping_type'] != ShippingTypeEnum::PICKUP) {
  491. $is_enable_write_off = StatusEnum::DISABLED;
  492. }
  493. $params['order']['pickup_info'] = [
  494. 'is_enable_write_off' => $is_enable_write_off,
  495. 'head_info' => $head_info,
  496. 'pickup_person' => [ // 提货人
  497. 'contact_name' => !empty($ext['contact_name']) ? $ext['contact_name'] : $params['order']['receiver_name'],
  498. 'contact_phone' => !empty($ext['contact_phone']) ? $ext['contact_phone'] : $params['order']['mobile']
  499. ],
  500. ];
  501. }
  502. $params['order']['is_community_pickup'] = StatusEnum::ENABLED; // 是否为社区自提
  503. } else {
  504. $params['order']['is_community_pickup'] = StatusEnum::DISABLED;
  505. }
  506. return $params['order'];
  507. }
  508. /**
  509. * 公共调用 - 订单列表
  510. * @param $params
  511. * @return mixed
  512. */
  513. public function globalList($params)
  514. {
  515. if (!empty($params['order'])) {
  516. $config = Yii::$app->services->setting->addons->get($params['mall_id'], CommunityEnum::ADDONS_NAME, 'basic');
  517. foreach ($params['order'] as &$item) {
  518. $item['order_status_txt'] = OrderStatusEnum::getValue($item['order_status']);
  519. $item['community_addons_data'] = [
  520. 'is_community_pickup' => StatusEnum::DISABLED,
  521. 'pickup_tips' => '',
  522. 'pickup_at' => '',
  523. 'is_enable_write_off' => StatusEnum::DISABLED,
  524. ];
  525. if (in_array($item['shipping_type'], [ShippingTypeEnum::PICKUP, ShippingTypeEnum::MERCHANT_DISTRIBUTION]) && !empty($item['extra_info'])) {
  526. try {
  527. $ext = Json::decode($item['extra_info']);
  528. } catch (\Exception $e) {
  529. return $params['order'];
  530. }
  531. if (!empty($ext['head_id'])) {
  532. // 这个是用来自提的
  533. $is_enable_write_off = $config['is_enable_write_off'] ?? StatusEnum::DISABLED;
  534. // 如果订单不为用户自提那么就不能走核销码,如果订单为用户自提那么只能在已支付、已发货情况下进行核销
  535. if (!in_array($item['order_status'], [OrderStatusEnum::PAY, OrderStatusEnum::SHIPMENTS]) ||
  536. $item['shipping_type'] != ShippingTypeEnum::PICKUP) {
  537. $is_enable_write_off = StatusEnum::DISABLED;
  538. }
  539. $item['community_addons_data']['is_community_pickup'] = StatusEnum::ENABLED;
  540. $item['community_addons_data']['pickup_tips'] = '站点自提';
  541. $item['community_addons_data']['is_enable_write_off'] = $is_enable_write_off;
  542. if ($item['order_status'] == OrderStatusEnum::SHIPMENTS) {
  543. $item['order_status_txt'] = $item['shipping_type'] == ShippingTypeEnum::MERCHANT_DISTRIBUTION ? '待配送' : '待自提';
  544. }
  545. // 需要取出信息
  546. if (!empty($item['consign_time']) && !empty($item['mall_id'])) {
  547. $item['community_addons_data']['pickup_at'] = CommunityHelper::getPickUpAt($item['mall_id'], $item['consign_time']);
  548. }
  549. }
  550. }
  551. }
  552. }
  553. return $params['order'];
  554. }
  555. /**
  556. * 公共调用 - 总后台订单列表
  557. * @param $params
  558. * @return mixed
  559. */
  560. public function globalBackendLists($params)
  561. {
  562. foreach ($params['order'] as &$order) {
  563. // 送货上门
  564. // 物流配送
  565. // 自提点自提
  566. $txt = "";
  567. $type = "";
  568. switch ($order['shipping_type']) {
  569. case '1': // 物流
  570. $txt = '快递配送';
  571. $type = "primary";
  572. break;
  573. case '2': // 自提点自提
  574. $txt = '自提点自提';
  575. $type = "success";
  576. break;
  577. case '3': // 送货上门
  578. $txt = '送货上门';
  579. $type = "danger";
  580. break;
  581. }
  582. $order['community_shipping_type'] = [
  583. 'title' => $txt,
  584. 'type' => $type
  585. ];
  586. if (!empty($order['mall_id']) && !empty($order['extra_info'])) {
  587. try {
  588. $ext = Json::decode($order['extra_info']);
  589. } catch (\Exception $e) {
  590. return $params['order'];
  591. }
  592. if (!empty($ext['head_id'])) {
  593. $order['community_addons_data']['is_community_pickup'] = StatusEnum::ENABLED;
  594. $order['community_addons_data']['head_info'] = (new HeadService())->pickupInfo($order['mall_id'], $ext['head_id']);
  595. }
  596. }
  597. }
  598. return $params['order'];
  599. }
  600. public function getClerkCode($mall_id)
  601. {
  602. while (true) {
  603. $clerk_code = ClerkEnum::getCode(ClerkEnum::COMMUNITY_CLERK_CODE_PRE);
  604. $res = Order::findOne(['clerk_code' => $clerk_code]);
  605. if (empty($res)) break;
  606. }
  607. if (empty($clerk_code)) throw new \Exception('核销码生成失败');
  608. return $clerk_code;
  609. }
  610. public function updateCode()
  611. {
  612. $i = 1;
  613. $page_size = 1000;
  614. while ($list = CommunityHeadOrder::find()
  615. ->andWhere(['>', 'id', 0])
  616. ->offset(($i - 1) * $page_size)->limit($page_size)->all()) {
  617. foreach ($list as $item) {
  618. $code = $this->getClerkCode($item['mall_id']);
  619. $order = Order::find()->where(['order_no'=>$item['order_no'],'sign_time'=>0,'shipping_type'=>2,'store_id'=>0,'mch_id'=>0])->one();
  620. if($order){
  621. $order_no = $order['order_no'];
  622. $sql = "UPDATE `qimall_order` SET `clerk_code`='{$code}' WHERE `order_no`='{$order_no}'";
  623. $res = Yii::$app->db->createCommand($sql)->execute();
  624. var_dump($res);
  625. }
  626. }
  627. $i++;
  628. }
  629. }
  630. /**
  631. * 公共调用 - 订单详情设置是否是自提订单 并且该商品是否允许退款字段
  632. * @param $params
  633. * @return mixed
  634. */
  635. public function globalOrderDetailsItem($params)
  636. {
  637. if (empty($params['order_detail']['order_id'])) {
  638. return $params['order_detail'];
  639. }
  640. // 是否是自提订单
  641. $params['order_detail']['is_community_order'] = (bool)CommunityHeadOrder::find()
  642. ->where(['order_id' => $params['order_detail']['order_id']])
  643. ->count();
  644. if ($params['order_detail']['is_community_order'] && !empty($params['order_detail']['goods_id'])) {
  645. $params['order_detail']['community_goods_setting'] = CommunityGoodsSetting::getOne([
  646. ['mall_id' => $params['mall_id']],
  647. ['goods_id' => $params['order_detail']['goods_id']],
  648. ['status' => StatusEnum::ENABLED],
  649. ['enable' => StatusEnum::ENABLED]
  650. ], true, [], false, 'enable_refund');
  651. if (isset($params['order_detail']['community_goods_setting']['enable_refund'])) {
  652. // 返回前端是否要显示售后按钮,前端状态 1待发货 2已发货 才能申请
  653. $params['order_detail']['community_goods_setting']['enable_refund_1'] = $params['order_detail']['community_goods_setting']['enable_refund'] &&
  654. in_array($params['order_detail']['order_status'], [OrderStatusEnum::PAY, OrderStatusEnum::SHIPMENTS]);
  655. }
  656. }
  657. return $params['order_detail'];
  658. }
  659. /**
  660. * 我的订单页面所需数据
  661. *
  662. * @param string $mall_id
  663. * @param string $user_id
  664. *
  665. * @return array
  666. */
  667. public function myOrder(string $mall_id, string $user_id): array
  668. {
  669. // 通过用户ID去取数据
  670. $head_where = [
  671. ['mall_id' => $mall_id],
  672. ['user_id' => $user_id],
  673. ['status' => StatusEnum::ENABLED]
  674. ];
  675. $order_status = [
  676. 'pending_shipment' => [
  677. 'order_status' => 1,
  678. ],
  679. 'pending_pickup' => [
  680. 'order_status' => 2,
  681. 'shipping_type' => 2,
  682. ],
  683. 'pending_delivery' => [
  684. 'order_status' => 2,
  685. 'shipping_type' => 3,
  686. ],
  687. ];
  688. $tabCount = [
  689. 'pending_shipment' => 0,
  690. 'pending_pickup' => 0,
  691. 'pending_delivery' => 0,
  692. ];
  693. foreach ($order_status as $k => $item) {
  694. $ret = CommunityHeadOrder::lists([
  695. 'where' => array_merge($head_where, [['order_status' => $item['order_status']]]),
  696. 'select' => 'order_id'
  697. ]);
  698. if (!empty($ret)) {
  699. $order_ids = array_column($ret, 'order_id');
  700. $where = [
  701. ['in', 'id', $order_ids],
  702. ['is_feedback' => OrderStatusEnum::NOT_FEEDBACK],
  703. ['!=', 'order_source', OrderSourceEnum::SOURCE_SELF_MALL]
  704. ];
  705. if (isset($item['shipping_type'])) {// 判断订单配送类型
  706. $where[] = ['shipping_type' => $item['shipping_type']];
  707. }
  708. $orderFind = Order::find();
  709. Order::paramPack([
  710. 'where' => $where
  711. ], $orderFind);
  712. $tabCount[$k] = $orderFind->count();
  713. }
  714. }
  715. // 返回待发货、待自提、待配送数量
  716. return ['tab_counts' => $tabCount];
  717. }
  718. }