// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\store\model; use app\api\service\User as UserService; use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum; use app\common\enum\order\DeliveryType; use app\common\enum\order\OrderStatus as OrderStatusEnum; use app\common\enum\order\ReceiptStatus; use app\common\enum\order\refund\AuditStatus as AuditStatusEnum; use app\common\enum\order\refund\RefundStatus as RefundStatusEnum; use app\common\enum\order\refund\RefundType as RefundTypeEnum; use app\common\enum\payment\Method; use app\common\model\OrderRefund as OrderRefundModel; use app\common\service\Message as MessageService; use app\common\service\order\Refund as RefundService; use app\store\model\User as UserModel; use app\store\model\Order as OrderModel; use app\store\model\OrderGoods as OrderGoodsMOdel; use app\common\model\Goods as GoodsModel; /** * 售后单模型 * Class OrderRefund * @package app\api\model */ class OrderRefund extends OrderRefundModel { /** * 获取售后单列表 * @param array $param * @return iterable|\think\model\Collection|\think\Paginator */ public function getList(array $param = []) { // 检索查询条件 $filter = $this->getFilter($param); $filterOr = []; if (!empty($param['searchValue']) && $param['searchType'] == 'all') { $filterOr = [ ['order.order_no', 'like', "%{$param['searchValue']}%"], ['user.nick_name', 'like', "%{$param['searchValue']}%"], ['order.user_id', '=', (int)$param['searchValue']] ]; } // 获取列表数据 $query = $this->alias('refund') ->field('refund.*, order.order_no') ->join('order', 'order.order_id = refund.order_id') ->join('user', 'user.user_id = order.user_id') ->where($filter); if (!empty($filterOr)) { $query = $query->whereOr($filterOr); } $list = $query->order(['refund.create_time' => 'desc', 'refund.' . $this->getPk()])->paginate($param['pageSize'] ?? 15); if ($list->isEmpty()) { return $list; } $list = static::preload($list, ['orderGoods.image', 'orderData', 'user.avatar']); $goodsModel = new GoodsModel; foreach ($list->items() as $key => &$value) { if ($value->orderGoods->origin_goods_id > 0) { $goods_images = $goodsModel->storeUsePlatformGoodsImage([$value->orderGoods->origin_goods_id]); $value->orderGoods->goods_image = $goods_images[$value->orderGoods->origin_goods_id][0]['file']['preview_url'] ?? ""; } } // 加载关联订单数据 return $list; } /** * 获取售后单列表 * @param array $param * @return iterable|\think\model\Collection|\think\Paginator */ public function getNewList(array $param = []) { // 检索查询条件 $filter = $this->getFilter($param); //不是店长查询当前用户订单 if (!UserService::isStore()) { $filter[] = ['user.user_id', '=', UserService::getCurrentLoginUserId()]; } //普通会员和plus会员查询条件 if (!empty($param['user_id'])) { $filter[] = ['user.user_id', '=', $param['user_id']]; } if (!empty($param['delivery_type'])) { $filter[] = ['order.delivery_type', '=', DeliveryType::EXPRESS]; } $filterOr = []; if (!empty($param['searchValue']) && $param['searchType'] == 'all') { // $filterOr = [ // ['order.order_no', 'like', "%{$param['searchValue']}%"], // ['user.nick_name', 'like', "%{$param['searchValue']}%"], // ['order.user_id', '=', (int)$param['searchValue']] // ]; $filterOr = [ ['order.order_no|user.nick_name|order.user_id', 'like', "%{$param['searchValue']}%"] ]; } // 获取列表数据 $query = $this ->alias('refund') ->field('refund.*, order.order_no') ->join('order', 'order.order_id = refund.order_id') ->join('user', 'user.user_id = order.user_id') ->where($filter); if (!empty($filterOr)) { // $query = $query->whereOr($filterOr); $query = $query->where($filterOr); } $list = $query->order(['refund.create_time' => 'desc', 'refund.' . $this->getPk()]) ->paginate(10); // 加载关联订单数据 $list = static::preload($list, ['goods.image', 'orderData', 'user.avatar', 'images.file'], true); foreach ($list['data'] as $key => $row) { $row['orderData']['pay_method_text'] = Method::data()[$row['orderData']['pay_method']]['name'];//支付方式 $row['orderData']['delivery_type_text'] = DeliveryType::data()[$row['orderData']['delivery_type']]['name'];//配送方式 $newRow = array_merge($row, $row['orderData']); $list['data'][$key] = $newRow; unset($list['data'][$key]['orderData']); } return $list; } /** * 获取售后单详情 * @param int $orderRefundId * @return OrderRefund|false|null */ public function getDetail(int $orderRefundId) { $detail = static::detail($orderRefundId, [ 'orderData', 'images.file', 'orderGoods.image', 'express', 'address', 'user' ]) ?: false; $goodsModel = new GoodsModel; if ($detail->orderGoods->origin_goods_id > 0) { $goods_images = $goodsModel->storeUsePlatformGoodsImage([$detail->orderGoods->origin_goods_id]); $detail['orderGoods']['goods_image'] = $goods_images[$detail->orderGoods->origin_goods_id][0]['file']['preview_url'] ?? ""; } return $detail; } /** * 检索查询条件 * @param array $param * @return array */ private function getFilter(array $param = []): array { // 默认查询条件 $params = $this->setQueryDefaultValue($param, [ 'searchType' => '', // 关键词类型 (10订单号 20会员昵称 30会员ID) 'searchValue' => '', // 关键词内容 'refundType' => -1, // 售后类型 'refundStatus' => -1, // 售后单状态 'betweenTime' => [], // 申请时间 ]); // 检查查询条件 $filter = []; // 关键词 if (!empty($params['searchValue'])) { if ($params['searchType'] != 'all') { $searchWhere = [ 10 => ['order.order_no', 'like', "%{$params['searchValue']}%"], 20 => ['user.nick_name', 'like', "%{$params['searchValue']}%"], 30 => ['order.user_id', '=', (int)$params['searchValue']] ]; array_key_exists($params['searchType'], $searchWhere) && $filter[] = $searchWhere[$params['searchType']]; } } // 起止时间 if (!empty($params['betweenTime'])) { $params['betweenTime'] = explode(',', $params['betweenTime']); $times = between_time($params['betweenTime']); $filter[] = ['refund.create_time', '>=', $times['start_time']]; $filter[] = ['refund.create_time', '<', $times['end_time'] + 86400]; } // 售后类型 $params['refundType'] > -1 && $filter[] = ['refund.type', '=', (int)$params['refundType']]; // 处理状态 $params['refundStatus'] > -1 && $filter[] = ['refund.status', '=', (int)$params['refundStatus']]; return $filter; } /** * 商家审核 * @param array $data * @return bool */ public function audit(array $data): bool { if ($data['audit_status'] == AuditStatusEnum::REJECTED && empty($data['refuse_desc'])) { $this->error = '请输入拒绝原因'; return false; } if ($data['audit_status'] == AuditStatusEnum::REVIEWED && empty($data['address_id']) && $this['type'] == RefundTypeEnum::RETURN) { $this->error = '请选择退货地址'; return false; } //如果只是退款 if ($data['audit_status'] == AuditStatusEnum::REVIEWED && $this['type'] == RefundTypeEnum::RETURNPRICE) { return $this->returnPrice($data); } $this->transaction(function () use ($data) { // 拒绝申请, 标记售后单状态为已拒绝 $data['audit_status'] == AuditStatusEnum::REJECTED && $data['status'] = RefundStatusEnum::REJECTED; // 同意换货申请, 标记售后单状态为已完成 // $data['audit_status'] == AuditStatusEnum::REVIEWED && $this['type'] == RefundTypeEnum::EXCHANGE && $data['status'] = RefundStatusEnum::COMPLETED; // 更新售后单状态 $this->save($data); // 同意售后申请, 记录退货地址 if ($data['audit_status'] == AuditStatusEnum::REVIEWED) { (new OrderRefundAddress)->add((int)$this['order_refund_id'], (int)($data['address_id'] ?? 0)); } // 订单详情 $order = Order::detail($this['order_id']); // 发送消息通知 MessageService::send('order.refund', [ 'refund' => $this, // 售后单信息 'order_no' => $order['order_no'] // 订单信息 ], $this['store_id']); }); return true; } public function returnPrice(array $data): bool { // 订单详情 $order = Order::detail($this['order_id']); if ($data['refund_money'] > min($order['pay_price'], $this['orderGoods']['total_pay_price'])) { $this->error = '退款金额不能大于商品实付款金额'; return false; } // 事务处理 $this->transaction(function () use ($order, $data) { // 执行退款操作 if (!(new RefundService)->handle($order, (string)$data['refund_money'])) { throwError('执行订单退款失败'); } // 更新售后单状态 $this->save([ 'refund_money' => $data['refund_money'], 'is_receipt' => 1, 'audit_status' => AuditStatusEnum::REVIEWED, 'status' => RefundStatusEnum::COMPLETED ]); // 消减用户的实际消费金额 // 条件:判断订单是否已结算 if ($order['is_settled']) { (new UserModel)->setDecUserExpend($order['user_id'], $data['refund_money']); } // 发送消息通知 MessageService::send('order.refund', [ 'refund' => $this, // 售后单信息 'order_no' => $order['order_no'], // 订单信息 ], $this['store_id']); }); return true; } /** * 确认收货并退款 * @param array $data * @return bool */ public function receipt(array $data): bool { // 订单详情 $order = Order::detail($this['order_id']); $data['refund_money'] = empty($data['refund_money'])?0:$data['refund_money']; if ($data['refund_money'] > min($order['pay_price'], $this['orderGoods']['total_pay_price'])) { $this->error = '退款金额不能大于商品实付款金额'; return false; } // 事务处理 $this->transaction(function () use ($order, $data) { // 执行退款操作 if (!(new RefundService)->handle($order, (string)$data['refund_money'])) { throwError('执行订单退款失败'); } // 更新售后单状态 $this->save([ 'refund_money' => $data['refund_money'], 'is_receipt' => 1, 'status' => RefundStatusEnum::COMPLETED ]); // 消减用户的实际消费金额 // 条件:判断订单是否已结算 if ($order['is_settled']) { (new UserModel)->setDecUserExpend($order['user_id'], $data['refund_money']); } // 发送消息通知 MessageService::send('order.refund', [ 'refund' => $this, // 售后单信息 'order_no' => $order['order_no'], // 订单信息 ], $this['store_id']); }); return true; } /** * 确认收货并更改换货状态 * @param array $data * @return bool */ public function huanhuo(array $data): bool { // 订单详情 $order = Order::detail($this['order_id']); $data['refund_money'] = empty($data['refund_money'])?0:$data['refund_money']; // 事务处理 $this->transaction(function () use ($order, $data) { // 更新售后单状态 $this->save([ 'refund_money' => $data['refund_money'], 'is_receipt' => 1, 'status' => RefundStatusEnum::COMPLETED ]); // 条件:判断订单是否已结算 if ($order['is_settled']) { (new UserModel)->setDecUserExpend($order['user_id'], $data['refund_money']); } // 更新主订单状态为未发货 (new OrderModel)->update(['order_status'=>OrderStatusEnum::NORMAL,'delivery_status'=>DeliveryStatusEnum::NOT_DELIVERED],['order_id'=>$order['order_id']]); (new OrderGoodsModel)->update(['delivery_status'=>DeliveryStatusEnum::NOT_DELIVERED, 'delivery_num' => 0],['order_id'=>$order['order_id']]); // 发送消息通知 MessageService::send('order.refund', [ 'refund' => $this, // 售后单信息 'order_no' => $order['order_no'], // 订单信息 ], $this['store_id']); }); return true; } /** * 获取待处理售后单数量 * @return int */ public function getRefundTotal(): int { return $this->where('status', '=', RefundStatusEnum::NORMAL)->count(); } }