'申请中', self::STATUS_PASS => '已通过', self::STATUS_REFUSE => '已拒绝', self::STATUS_PAY => '已打款', self::STATUS_PAY_FAIL => '打款失败', self::STATUS_CANCEL => '用户取消', ]; public static $status_desc = [ self::STATUS_APPLY => '退款申请中', self::STATUS_PASS => '已通过', self::STATUS_REFUSE => '已拒绝', self::STATUS_PAY => '退款已退回至原申请方', self::STATUS_PAY_FAIL => '退款失败 等待商户重试', self::STATUS_CANCEL => '用户取消', ]; public static function tableName() { return '{{%order_goods_cancel}}'; } public function beforeSave($insert) { $order_detail = OrderDetail::findOne($this->order_detail_id); if (!self::is_activity_goods($this->order_id, $order_detail->goods_id)) { $this->addError('goods', '营销活动产品不可单独退款'); return false; } return parent::beforeSave($insert); // TODO: Change the autogenerated stub } public function rules() { return [ [['id', 'order_id', 'order_detail_id', 'num', 'user_id', 'store_id', 'status'], 'integer'], [['refund_price', 'created_at', 'updated_at'], 'number'], [['refund_order_no'], 'string'] ]; } public function behaviors() { return [ [ 'class' => TimestampBehavior::class ] ]; } public function attributeLabels() { return [ 'id' => '', 'order_id' => '订单ID', 'order_detail_id' => '订单详情ID', 'num' => '退款订单数量', 'user_id' => '用户ID', 'store_id' => '商城ID', 'refund_order_no' => '取消订单商户号', 'refund_price' => '取消订单金额(单种商品退款总金额)', 'status' => '状态:0申请中 1已通过 2已拒绝 3打款完成 4打款失败 5用户取消', 'created_at' => '', 'updated_at' => '', ]; } public static function getOrderNo() { $refund_order_no = null; while (true) { $refund_order_no = date('YmdHis') . mt_rand(100000, 999999); $exist_order_refund_no = self::find()->where(['refund_order_no' => $refund_order_no])->exists(); if (!$exist_order_refund_no) { break; } } return 'OGC' . $refund_order_no; } public static function getCancelGoodsOrderQuery($order_id, $field = '', $group = '', $order_detail_id = 0) { $query = self::find()->where([ 'order_id' => $order_id, ]); if ($order_detail_id) { $query->andWhere(['order_detail_id' => $order_detail_id]); } $query->andWhere(['status' => [ self::STATUS_APPLY, self::STATUS_PASS, self::STATUS_PAY, self::STATUS_PAY_FAIL ]]); if ($group) { $query->groupBy($group); } if ($field) { $query->select($field); } return $query; } //判断是否是活动产品 public static function is_activity_goods($order_id, $goods_id) { //推N返1 $activityRebateOrderN = ActivityRebateOrderNLog::findOne(['is_delete' => 0, 'goods_id' => $goods_id]); if ($activityRebateOrderN) { return false; } //排队免单 $activityQueueLog = QueueLog::findOne(['order_id' => $order_id]); if ($activityQueueLog) { return false; } //消费全返 $activityRebateOrderSelf = ActivityOrderRebateSelfLog::findOne(['order_id' => $order_id, 'goods_id' => $goods_id]); if ($activityRebateOrderSelf) { return false; } //团队级差分红 $activityTeamBonus = TeamBonusOrderExt::findOne(['order_id' => $order_id]); if ($activityTeamBonus) { return false; } //团队业绩分红 $activityTeamGrades = TeamGradesPoolDetailExt::findOne(['order_id' => $order_id]); if ($activityTeamGrades) { return false; } //37拼购 $activityShareGroup = ShareGroupPurchaseParentLog::findOne(['order_id' => $order_id]); if ($activityShareGroup) { return false; } //超级卖货 $activitySuperSales = SuperSalesSub::findOne(['order_id' => $order_id]); if ($activitySuperSales) { return false; } //消费积分增值 $activityIntegralAppreciation = IntegralAppreciationPoolSub::findOne(['order_id' => $order_id]); if ($activityIntegralAppreciation) { return false; } //视频号 $activityVideoShopOrder = VideoShopOrderExt::findOne(['order_id' => $order_id]); if ($activityVideoShopOrder) { return false; } //股东/链动 $activityShareHolder = ShareDetail::find()->where(['type_id' => $order_id])->andWhere(['>', 'money', 0])->asArray()->one(); if ($activityShareHolder) { return false; } $activityShareHolderPool = BonusPoolDetail::find()->where(['order_id' => $order_id])->asArray()->one(); if ($activityShareHolderPool) { return false; } $order = Order::findOne($order_id); if ($order) { if ($order->activity_cut_price_order_id > 0 || $order->activity_wechat_room_id > 0 || $order->pt_order_id > 0 || $order->seckill_order_id > 0 || $order->mch_id > 0 || intval($order->order_type) === Order::ORDER_TYPE_GIVING_GIFTS ) { return false; } } $share_holder_level = ShareHolderLevel::find()->where(['is_delete' => 0, 'status' => 1, 'store_id' => $order->store_id])->orderBy('level desc')->all(); foreach ($share_holder_level as $value) { $condition = json_decode($value->condition, true); $goods = $condition['goods']; if ((bool)$goods['is_open'] && !empty($goods['value']['id'])) { $order_model = Order::find()->alias('o')->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id=o.id')->where(['o.id' => $order->id, 'o.is_delete' => 0, 'o.is_pay' => 1]) ->andWhere(['od.goods_id' => $goods['value']['id']])->select('o.id order_id')->asArray()->one(); if ($order_model) { return false; } } } $goods = Goods::findOne($goods_id); if (intval($goods->cloud_goods_id) > 0) { $cloud_url = "/goods/getGoodsInfo"; $cloud_data = []; $cloud_data['goods_id'] = $goods->cloud_goods_id; $domain = (new OptionSetting)->getCloudDomainName(); $cloud_info = cloud_post($domain . $cloud_url, $cloud_data); $cloud_info = json_decode($cloud_info, true); if ($cloud_info['code'] != 0) { return false; } else { $cloud_goods = $cloud_info['data']['goods']; //获取云仓产品 if (intval($cloud_goods['stbz_goods_id'])) { return false; } } } return true; } public static function orderGoodsCancelHandle($id, $status) { try { $order_goods_cancel = self::findOne($id); if (!$order_goods_cancel) { throw new \Exception('订单取消记录不存在'); } $status = intval($status); //如果当前状态不是未审核或者打款失败的状态 那么就不能操作 // if (!in_array($order_goods_cancel->status, [ // self::STATUS_APPLY, // self::STATUS_PAY_FAIL // ])) { // throw new \Exception('当前申请记录已打款/已取消'); // } if (!in_array($status, [ self::STATUS_PASS, self::STATUS_REFUSE, ])) { throw new \Exception('状态错误'); } $order_id = $order_goods_cancel->order_id; $order = \app\models\Order::findOne($order_id); // if (intval($order->trade_status) !== Order::ORDER_FLOW_NO_SEND) { // throw new \Exception('订单状态错误'); // } if (intval($order->is_sale) || ($order->future_sales_time > 0 && $order->future_sales_time <= time())) { throw new \Exception('订单已过售后期'); } $refund_price = $order_goods_cancel->refund_price; $order_detail_array = \app\models\OrderDetail::find()->where(['order_id' => $order_id]) ->select('id, num')->asArray()->all(); //判断如果订单详情的所有商品已经都取消 那就认为这就是最后一笔订单 那么就可以开始取消积分优惠券卡券等信息 $open = true; foreach ($order_detail_array as $order_detail_item) { $cancel_order_detail_num = self::find() ->where([ 'order_id' => $order_id, 'order_detail_id' => $order_detail_item['id'], 'status' => self::STATUS_PAY ])->sum('num') ?: 0; //再给当前的也计算上 if ($order_detail_item['id'] == $order_goods_cancel->order_detail_id) { $cancel_order_detail_num += $order_goods_cancel->num; } if ($cancel_order_detail_num < $order_detail_item['num']) { $open = false; break; } } //如果是全部订单都退款 那么退款金额还需要包含运费信息 if ($open) { $refund_price = bcadd($refund_price, $order->express_price, 2); } if ($status === self::STATUS_REFUSE) { $order_goods_cancel->status = $status; $order_goods_cancel->save(); return [ 'code' => 0, 'msg' => '处理完成' ]; } debug_log([ '开始退款'], 'orderDetail.log'); $orderRevoke = new OrderRevoke(); $orderRevoke->order = $order; $orderRevoke->type = 0; if (in_array($order_goods_cancel->status, [ self::STATUS_APPLY, self::STATUS_PAY_FAIL ])) { if ($order->pay_type == Order::PAY_TYPE_BALANCE_PAID) { if (!$orderRevoke->OrderRefund($refund_price)) { $order_goods_cancel->status = self::STATUS_PAY_FAIL; if (!$order_goods_cancel->save()) { //保存失败 throw new \Exception(implode(';', array_values($order_goods_cancel->firstErrors))); } throw new \Exception('退款失败,取消失败'); } $order_goods_cancel->status = self::STATUS_PAY; if (!$order_goods_cancel->save()) { //保存失败 throw new \Exception(implode(';', array_values($order_goods_cancel->firstErrors))); } } if (in_array($order->pay_type, [ Order::ORDER_TYPE_GIVING_GIFTS, Order::PAY_TYPE_YUNST_WECHAT_PAY, Order::PAY_TYPE_WECHAT, Order::PAY_TYPE_WX_B2B, Order::PAY_TYPE_ADAPAY_WX, Order::PAY_TYPE_ADAPAY_ALIPAY, Order::PAY_TYPE_ADAPAY_QUICKPAY_FRONTPAY, Order::PAY_TYPE_HUIFU_V2_JSPAY_WX, Order::PAY_TYPE_ALLINPAY_WX, Order::PAY_TYPE_ALI, Order::PAY_TYPE_MONTH ])) { $res = Refund::refund( $order, $order->order_union_id ? OrderNo::ORDER_UNION : '', $order_goods_cancel->refund_order_no, $refund_price ); debug_log(['Refund' => $res], 'orderDetail.log'); if ($res !== true) { $order_goods_cancel->status = self::STATUS_PAY_FAIL; if (!$order_goods_cancel->save()) { //保存失败 throw new \Exception(implode(';', array_values($order_goods_cancel->firstErrors))); } throw new \Exception($res['msg']); } $order_goods_cancel->status = self::STATUS_PAY; if (!$order_goods_cancel->save()) { //保存失败 throw new \Exception(implode(';', array_values($order_goods_cancel->firstErrors))); } } } // 恢复商品库存 $orderRevoke->backGoodsNum($order_goods_cancel->id); //查询当前订单中是否还存在未取消的订单 如果没有 那么就开始退款积分优惠券卡券等信息 if ($open) { $order->trade_status = Order::ORDER_FLOW_CANCEL; //开始取消积分优惠券卡券等信息 // 预约商品增加库存 BookOrderNum::bookNumAdd($order); // 取消下单时送的核销卡 VerifyCardSale::cancelCard($order); $order->save(); $goods = Goods::findOne(OrderDetail::findOne(['order_id' => $order->id])->goods_id); if ($order->order_type == Order::ORDER_TYPE_Adopt) { NoticeSend::OrderCancel($order->user_id, $order->mobile, $order->order_no, $order->pay_price, $goods->name, 1); }else{ NoticeSend::OrderCancel($order->user_id, $order->mobile, $order->order_no, $order->pay_price, $goods->name, 0); } // 订单打印 if ((int)$order->md_id === -1 || (int)$order->md_id === 0 || !isset($order->md_id)) { $order->md_id = 0; } $printer_order = new PrintOrder($order->store_id, $order->id, 'confirm', 0, $order->md_id, 0, $order['mch_id']); $printer_order->is_refund = true; $printer_order->print_order(); $check = SaaSLeaguePriceLog::findOne(['order_id' => $order->id, 'type' => 4]); if($order->take_price > 0){ $user = User::findOne($order->user_id); $saas_user = SaasUser::findOne(['mobile' => $user->binding]); if($saas_user){ $take_price = $order->take_price; $before = $saas_user->league_price; $saas_user->updateCounters(['league_price' => floatval($take_price)]); SaaSLeaguePriceLog::setLeaguePriceLog( $order->store_id, $saas_user->id, $take_price, $before, SaaSLeaguePriceLog::TYPE_CANCEL, SaaSLeaguePriceLog::SEND_TYPE, SaaSLeaguePriceLog::ROLE_USER, $order->id ); } } $balance = isset($order->balance) ? $order->balance : 0; if ($balance > 0) { AccountLog::saveLog( $order->user_id, $balance, AccountLog::TYPE_BALANCE, AccountLog::LOG_TYPE_INCOME, 0, $order->id, "商城订单取消,商品余额抵扣" ); } $integral = isset($order->integral) ? json_decode($order->integral)->forehead_integral : 0; if ($integral > 0) { AccountLog::saveLog( $order->user_id, $integral, AccountLog::TYPE_INTEGRAL, AccountLog::LOG_TYPE_INCOME, 0, $order->id, "商城订单取消,商品积分抵扣恢复" ); } //如果已经转单 就调用取消接口 $orderTransit = OrderTransit::findOne(['order_id' => $order->id, 'is_delete' => 0]); if ($orderTransit) { $merchant = new MerchantForm(); $merchant->order_id = $orderTransit->cloud_order_id; $result = $merchant->purchaseOrderCancel(); debug_log('云仓订单取消'); debug_log($result); } } //商品取消后通知云仓代码 $order_detail = OrderDetail::findOne($order_goods_cancel->order_detail_id); $order_transit = OrderTransit::find()->where(['order_id' => $order->id, 'is_delete' => 0]) ->asArray()->all(); if ($order_transit) { $goods = Goods::findOne($order_detail->goods_id); $attr = ''; $cloud_order_id = 0; $order_detail_attr = json_decode($order_detail->attr, true); $order_detail_attr_id = array_column($order_detail_attr, 'attr_id'); sort($order_detail_attr_id); $order_detail_goods_info = json_decode($order_detail->goods_info, true); if (is_string($order_detail_goods_info['attr'])) { $order_detail_goods_info['attr'] = json_decode($order_detail_goods_info['attr'], true); } $goods_attr_no = ''; foreach ($order_detail_goods_info['attr'] as $order_detail_goods_attr_item) { $goods_attr_id = array_column($order_detail_goods_attr_item['attr_list'], 'attr_id'); sort($goods_attr_id); if (!array_diff($goods_attr_id, $order_detail_attr_id)) { $goods_attr_no = $order_detail_goods_attr_item['no']; } } $cloud_order_id_array = array_column($order_transit, 'cloud_order_id'); $domain = (new OptionSetting)->getCloudDomainName(); $order_data_url = "/user/getPurchaseOrder"; $order_data['order_ids'] = implode(',', $cloud_order_id_array); $order_data_info = cloud_post($domain . $order_data_url, $order_data); $order_data_info = json_decode($order_data_info, true); if ($order_data_info['code'] || !isset($order_data_info['data']['list'])) { return; } foreach ($order_data_info['data']['list'] as $cloud_order_item) {//订单 foreach ($cloud_order_item['goods_list'] as $cloud_order_goods_item) {//商品 if ($goods_attr_no == $cloud_order_goods_item['attr']['no']) { $attr = $cloud_order_goods_item['attr']; $cloud_order_id = $cloud_order_item['id']; } } } $attr = json_encode($attr, JSON_UNESCAPED_UNICODE); $form = new MerchantForm(); $form->store_id = $order->store_id; $form->order_id = $cloud_order_id; $form->goods_id = $goods->cloud_goods_id; $form->attr = $attr; $form->mch_cancel_id = $order_goods_cancel->id; $form->goods_num = $order_goods_cancel->num; $form->md_id = $order->md_id; $result = $form->purchaseOrderCancelGoods(); if ($result['code']) { return $result; } } //如果只是部分退款 那么就走下面的计算逻辑 如果是全退 那么就直接会改变订单状态 重新计算没意义 if (!$open) { //重新计算分销门店佣金/分账金额 $form = new ShareMoneyForm(); $form->order = $order; $form->order_type = 0; $form->setData(); if ($order->md_id && !in_array($order->order_type, [1, 2])) { $result = OrderForm::findPrice($order->id); MdProfit::handleProfit($order->id, $result['original_price'], $result['md_price'], $order->md_id); }else{ if ($order->is_offline || in_array($order->order_type, [1, 2])) { MdProfit::handleProfit($order->id, $order->total_price, $order->total_price, $order->md_id); } } } if ($order->pay_type === Order::PAY_TYPE_WECHAT) { $notifyForm = new NotifyForm(); $refund_price = OrderGoodsCancel::find()->where(['order_id' => $order->id, 'status' => [ OrderGoodsCancel::STATUS_PASS, OrderGoodsCancel::STATUS_PAY, OrderGoodsCancel::STATUS_PAY_FAIL ]])->sum('refund_price'); $order->pay_price = bcsub($order->pay_price, $refund_price, 2); $notifyForm->addReceiver($order); } return [ 'code' => 0, 'msg' => '处理完成' ]; } catch (\Exception $e) { return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } }