where(['mall_id' => $this->mall_id]); $model->with([ 'goods' => function ($query) { $query->select('id, name, spu_id, carousel_img_list, status'); }, 'detail' => function ($query) { $query->select('id, order_id, goods_attr_name, price, goods_price'); }, 'order' => function ($query) { $query->select('id, region_name, address, receiver_name, shipping_money, goods_price, mobile'); }, 'refund' => function ($query) { $query->select('id, order_no, reason, refund_price, pic_list, type, remark'); }, ]); // 查询 if (!empty($params['name'])) { $model->andWhere([ 'spu_id' => Goods::find()->where(['like', 'name', $params['name']])->select('spu_id'), ]); } if (!empty($params['order_no'])) { $model->andWhere([ 'order_refund_id' => MallOrderRefund::find()->where(['like', 'order_no', $params['order_no']])->select('id')->column(), ]); } if (!empty($params['data'])) { list($start, $end) = $params['data']; $start = strtotime($start); $end = strtotime($end); $model->andFilterWhere(['between', 'created_at', $start, $end]); } $pagination = new Pagination(['totalCount' => $model->count(), 'pageSize' => $limit]); $model->limit($pagination->limit)->offset($pagination->offset); $list = $model->orderBy('id desc') ->asArray() ->all(); foreach ($list as $k => $v) { $list[$k]['goods']['carousel_img_list'] = Json::decode($v['goods']['carousel_img_list']); $list[$k]['data'] = Json::decode($v['data']); $list[$k]['refund']['pic_list'] = Json::decode($v['refund']['pic_list']); $list[$k]['refund']['type_text'] = RefundTypeEnum::getValue($v['refund']['type']); $list[$k]['refund_status_text'] = RefundStatusEnum::getValue($v['refund_status']); $list[$k]['status_text'] = OrderRefundEnum::getValue($v['status']); } $data['list'] = $list; $data['status_arr'] = OrderRefundEnum::getMap(); $data['refund_status_arr'] = RefundStatusEnum::getMap(); $data['page_count'] = $pagination->pageCount; return $data; } /** * 添加售后 * * @param array $params * @return MallOrderRefund */ public function doRefund($params) { $params2 = $params; $db = Yii::$app->db->beginTransaction(); try { //订单详情表 $order_detail = OrderDetail::findOne(['id' => $params['order_detail_id'], 'user_id' => $params['user_id']]); if (empty($order_detail)) throw new Exception('订单不存在'); if ($order_detail->order_status == OrderStatusEnum::ACCOMPLISH) throw new Exception('订单已过售后时间,无法申请售后'); if (!in_array($order_detail->order_status, [OrderStatusEnum::PAY, OrderStatusEnum::SHIPMENTS, OrderStatusEnum::SING])) { throw new Exception('该订单状态下,无法申请售后'); } // 订单是否聚合 $order = MallOrder::find()->where(['id' => $order_detail['order_id']])->select('id, order_no, mall_id, shipping_money, order_source')->one(); if ($order->order_source != StarChainEnum::PLUGIN_SIGN) throw new Exception('该订单不是聚合供应链订单'); // 供应链订单信息 $chain_order = OrderItem::find()->where(['mall_order_id' => $order_detail['order_id']])->select('sku_id, spu_id, num')->one(); if (empty($chain_order)) throw new Exception('该订单不是聚合供应链订单'); // 公共调用 $order_detail = GlobalInvoke::exec(GlobalInvoke::ORDER_REFUND_SUBMIT, $this->mall_id, [ 'order_detail' => $order_detail, 'mall_id' => $this->mall_id, ]) ?: $order_detail; // 一共可以退款 $refund_total_money = bcadd($order_detail->goods_price, $order_detail->adjust_money, 2); // 未发货添加邮费 if ($order_detail['shipping_status'] == ShippingStatusEnum::UN_SHIPPED) { $refund_total_money = bcadd($refund_total_money, $order->shipping_money, 2); } if ($params['refund_price'] > $refund_total_money) { throw new Exception('最多可退款金额¥' . $refund_total_money); } // 替换成商城状态 $params['type'] = RefundTypeEnum::typeChange($params['type']); if (empty($params['type'])) { throw new Exception('选择退款状态有误'); } $order_detail->is_feedback = OrderStatusEnum::FEEDBACKING; if(!$order_detail->save()) throw new Exception(OrderDetail::getStaticError()); // 处理售后步骤 !empty($params['pic_list']) && $params['pic_list'] = Json::decode($params['pic_list']); MallOrderRefund::stepHandle($params); // 退款主表 $params2['is_feedback'] = $params['is_feedback'] = OrderStatusEnum::FEEDBACKING; $params2['order_id'] = $params['order_id'] = $order_detail->order_id; $params2['order_no'] = $params['order_no'] = MallOrder::generateOrderNo('r'); $order_refund_model = MallOrderRefund::setData($params); if(!$order_refund_model) throw new Exception(MallOrderRefund::getStaticError()); $params2['order_refund_id'] = $params['order_refund_id'] = $order_refund_model->id; $res = OrderRefundStep::setData($params); if(!$res) throw new Exception(OrderRefundStep::getStaticError()); //自动维护订单主表 $order = MallOrder::findOne($params['order_id']); $res = MallOrder::autoUpdateStatus($order); // 供应链订单详情 $order_item = OrderItem::getOrderItemByDetailId($order_detail->id); if (empty($order_item)) throw new Exception('售后订单详情不存在'); // 添加聚合售后 $refund = OrderRefund::add([ 'user_id' => $params['user_id'], 'mall_id' => $order->mall_id, 'order_id' => $order_detail['order_id'], 'order_detail_id' => $order_detail['id'], 'order_refund_id' => $order_refund_model->id, 'spu_id' => $order_item->spu_id, 'sku_id' => $order_item->sku_id, 'num' => $order_item->num, 'data' => $params2, ]); $db->commit(); // 触发售后统计 $refund_event = ['id' => $order_refund_model->id, 'type' => EnumsRefundTypeEnum::EVENT_APPLY]; Yii::$app->services->rabbitMq->push( RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, [ 'type' => EventNameEnum::ORDER_REFUND, 'params' => $refund_event, ], StatisticsHandle::class, 'handleSync' ); // 自动推送售后 Yii::$app->services->rabbitMq->push( RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, [ 'mall_id' => $refund->mall_id, 'id' => $refund->id, ], self::class, 'autoPush' ); return $order_refund_model; } catch (Exception $e) { $db->rollback(); return $this->error($e->getMessage()); } } /** * 驳回申请 * * @param array $ids * @return integer */ public function reject($ids) { $list = OrderRefund::find()->where(['id' => $ids, 'status' => OrderRefundEnum::NOT_PUSHED])->all(); $num = 0; foreach ($list as $v) { $db = Yii::$app->db->beginTransaction(); try { self::refuse($v); $db->commit(); $num++; } catch (Exception $e) { $db->rollback(); $v->error_msg = $e->getMessage(); $v->save(); } } return $num; } /** * 同意申请 * * @param array $ids [1,2,3] * @return void */ public function agree($ids) { $list = OrderRefund::find()->where(['id' => $ids, 'status' => OrderRefundEnum::NOT_PUSHED])->all(); $num = 0; /** * @var OrderRefund */ foreach ($list as $v) { $db = Yii::$app->db->beginTransaction(); try { $res = $this->push($v); $v->pushOk($res); $num++; $db->commit(); } catch (Exception $e) { $db->rollback(); $v->error_msg = $e->getMessage(); $v->save(); } } return $num; } /** * 推送申请 * * @param OrderRefund $model * @return void */ public function push(OrderRefund $model) { // 聚合订单 $chain_order = OrderItem::find() ->where(['mall_order_id' => $model->order_id, 'sku_id' => $model->sku_id]) ->one(); // 商城退款订单 $mall_refund_order = MallOrderRefund::find()->where(['id' => $model->order_refund_id])->one(); // 提交到聚合供应链 $params = $this->getParams($model, $chain_order, $mall_refund_order); \Yii::error('-------- 推送售后订单 --------'); \Yii::error(Json::encode($params)); return $this->api->applyRefund($params); } /** * 获取供应链售后参数 * * @param OrderRefund $model * @param OrderItem $chain_order * @param MallOrderRefund $mall_refund_order * @return array */ private function getParams($model, $chain_order, $mall_refund_order) { $data = Json::decode($model->data); $params = [ 'reason' => $mall_refund_order->reason, 'orderSn' => $chain_order->chain_order_sn, 'refundReasonId' => $data['reason_id'], 'goodsList' => [ [ 'goodsQuantity' => $model->num, 'goodsSpecId' => $model->sku_id, ] ], 'returnType' => /* RefundTypeEnum::typeChange */($data['type']), ]; $mall_refund_order->remark && $params['memo'] = $mall_refund_order->remark; Json::decode($mall_refund_order->pic_list) && $params['pictureurlList'] = Json::decode($mall_refund_order->pic_list); return $params; } /** * 驳回 * * @param OrderRefund $model * @return void */ public static function refuse(OrderRefund $model) { $model->status = OrderRefundEnum::REFUSE; $res = $model->save(); if ($res === false) throw new Exception($model->getError()); $res = OrderRefundLogic::refuseRefundForChain($model->mall_id, $model->order_refund_id); if ($res === false) throw new Exception(MallOrderRefund::$static_error); } /** * 售后状态变更 * * @param string $return_sn * @param integer $status * @return boolean */ public function statusChange($return_sn, $status) { try { /** * @var OrderRefund|null */ $refund_order = OrderRefund::getOrderByReturnSn($this->mall_id, $return_sn); if (empty($refund_order)) { throw new Exception("售后订单{$return_sn}不存在"); } switch ($status) { // 审核中 case '1': $refund_order->review(); break; // 卖家拒绝退款 case '2': $refund_order->refuseMoney(); break; // 退款成功 case '3': $refund_order->success(); break; // 卖家拒绝退货退款 case '4': $refund_order->refuseMoneyAndProduct(); break; // 待买家退货 case '5': $refund_detail = $this->api->orderReturnGoodsDetail($return_sn); $refund_order->waitBuyerSend($refund_detail); break; // 买家已退货,待卖家收货 case '6': $refund_order->waitSellerReceive(); break; // 买家已退货,卖家拒绝收货 case '7': $refund_order->sellerRefuseReceive(); break; // 卖家已收货,待确认退款 case '8': $refund_order->sellerReceiveOfWait(); break; // 退货退款成功 case '9': $refund_order->successMoneyAndProduct(); break; // 卖家拒绝换货 case '10': $refund_order->refuseExchange(); break; // 买家已退货,待卖家换货 case '11': $refund_order->waitSellerSend(); break; // 卖家已换货,待买家收货 case '12': $refund_detail = $this->api->orderReturnGoodsDetail($return_sn); $refund_order->waitBuyerReceive($refund_detail); break; // 换货成功 case '13': $refund_order->successExchange(); break; // 已关闭 case '14': $refund_order->close(); break; // 卖家同意退款 case '15': $refund_order->adoptMoney(); break; // 卖家同意仅退款 case '16': $refund_order->adoptOnlyMoney(); break; // 卖家拒绝仅退款 case '17': $refund_order->refuseOnlyMoney(); break; // 仅退款成功 case '18': $refund_order->successOnlyMoney(); break; default: break; } } catch (Exception $e) { return $this->error("售后订单{$return_sn}, 售后失败, 状态为{$status}, 失败原因:" . $e->getMessage()); } return true; } /** * 售后处理 * * @param integer $refund_id * @return void */ public function buyerDelivery($refund_id) { $chain_refund_sn = OrderRefund::find()->where(['order_refund_id' => $refund_id])->select('chain_refund_sn')->scalar(); if ($chain_refund_sn) { $refund_order = MallOrderRefund::find()->where(['id' => $refund_id])->select('id, express, express_no')->one(); try { // 都不为空的时候调用 !empty($refund_order) && $refund_order->express_no && $refund_order->express && $this->api->sendReturnGoods( $chain_refund_sn, $refund_order->express_no, $refund_order->express ); } catch (Exception $e) { Yii::error(""); } } } /** * 取消订单 * * @param integer $id * @return boolean */ public function cancel($id) { $model = OrderRefund::find()->where(['order_refund_id' => $id, 'status' => OrderRefundEnum::NOT_PUSHED])->one(); return self::refuse($model); } /** * 售后订单收货完成 * * @param integer $id * @return boolean */ public function finish($id) { $model = OrderRefund::find()->where(['order_refund_id' => $id])->one(); if (empty($model)) return false; $this->api->receiptRefund($model->chain_refund_sn); } /** * 自动推送售后 * * @param array $params * @return boolean */ public static function autoPush($params = []) { if (empty($mall_id = $params['mall_id']) || empty($id = $params['id'])) return true; // 获取设置 $setting = Setting::getSetting($mall_id); if (empty($setting) || empty($setting['refund_auto_push'])) return true; try { /** * @var OrderRefund */ $model = OrderRefund::find()->where(['id' => $id])->one(); $res = (new static(['mall_id' => $mall_id]))->push($model); $model->pushOk($res); } catch (Exception $e) { echo '文件: ' . $e->getFile() . ', 错误行数: ' . $e->getLine() . ', 错误信息: ' . $e->getMessage(); } return true; } }