// +---------------------------------------------------------------------- namespace App\Services\Common; use App\Models\AccountLogModel; use App\Models\ActionLogModel; use App\Models\GoodsModel; use App\Models\MemberModel; use App\Models\MessageModel; use App\Models\OrderModel; use App\Models\OrderGoodsModel; use App\Models\StoreModel; use App\Services\BaseService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 订单管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class OrderService * @package App\Services\Common */ class OrderService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * OrderService constructor. */ public function __construct() { $this->model = new OrderModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 15) { $query = $this->model->where('mark', 1); // 店铺筛选 if (isset($params['store_id']) && $params['store_id'] > 0) { $query->where('store_id', $params['store_id']); } // 用户筛选 if (isset($params['user_id']) && $params['user_id'] > 0) { $query->where('user_id', $params['user_id']); } // 状态筛选 if (isset($params['status']) && $params['status'] > 0) { $query->where('status', $params['status']); } // 售后类型筛选(1-售后,2-退款) if (isset($params['after_type']) && $params['after_type'] > 0) { $query->where('after_type', $params['after_type']); } // 退款状态筛选 if (isset($params['refund_status']) && $params['refund_status'] > 0) { $query->where('refund_status', $params['refund_status']); } // 关键词搜索(订单号、商品名称、收货人手机) if (isset($params['keyword']) && $params['keyword']) { $keyword = $params['keyword']; $query->where(function ($q) use ($keyword) { $q->where('order_no', 'like', '%' . $keyword . '%') ->orWhere('receiver_name', 'like', '%' . $keyword . '%') ->orWhere('receiver_mobile', 'like', '%' . $keyword . '%') ->orWhereHas('orderGoods', function ($q2) use ($keyword) { $q2->where('goods_name', 'like', '%' . $keyword . '%'); }); }); } $list = $query->with(['user', 'orderGoods', 'store']) ->orderBy('create_time', 'desc') ->orderBy('id', 'desc') ->paginate($pageSize); $list = $list ? $list->toArray() : []; if ($list && isset($list['data'])) { foreach ($list['data'] as &$item) { $item['create_time'] = $item['create_time'] ? date('Y-m-d H:i:s', strtotime($item['create_time'])) : ''; $item['update_time'] = $item['update_time'] ? date('Y-m-d H:i:s', strtotime($item['update_time'])) : ''; $item['user'] = $item['user'] ?? []; $item['store'] = $item['store'] ?? []; // 获取第一个商品信息(thumb已通过Model访问器处理) $item['goods'] = isset($item['order_goods'][0]) ? $item['order_goods'][0] : null; } } return [ 'msg' => '操作成功', 'code' => 0, 'data' => $list['data'] ?? [], 'count' => $list['total'] ?? 0, ]; } /** * 获取订单详情 */ public function getInfo($id) { $info = $this->model->where('id', $id)->where('mark', 1) ->with(['user', 'orderGoods', 'store']) ->first(); if (!$info) { return ['code' => 1, 'msg' => '订单不存在']; } $info = $info->toArray(); $info['create_time'] = $info['create_time'] ? date('Y-m-d H:i:s', strtotime($info['create_time'])) : ''; $info['update_time'] = $info['update_time'] ? date('Y-m-d H:i:s', strtotime($info['update_time'])) : ''; if (isset($info['order_goods'])) { foreach ($info['order_goods'] as &$goods) { $goods['thumb'] = $goods['thumb'] ? get_image_url($goods['thumb']) : ''; $goods['create_time'] = $goods['create_time'] ? date('Y-m-d H:i:s', strtotime($goods['create_time'])) : ''; $goods['update_time'] = $goods['update_time'] ? date('Y-m-d H:i:s', strtotime($goods['update_time'])) : ''; } } return ['code' => 0, 'msg' => '操作成功', 'data' => $info]; } /** * 查询 * @param $params * @return \Illuminate\Database\Eloquent\Builder */ public function getQuery($params) { $where = ['a.mark' => 1]; $userId = isset($params['user_id']) ? $params['user_id'] : 0; return $this->model->with(['user', 'goods'])->from('orders as a') ->leftJoin('member as b', 'a.user_id', '=', 'b.id') ->leftJoin('goods as c', 'c.id', '=', 'a.goods_id') ->where($where) ->where(function ($query) use ($params) { $keyword = isset($params['keyword']) ? $params['keyword'] : ''; if ($keyword) { $query->where('a.order_no', 'like', "%{$keyword}%"); } // 接单人 $account = isset($params['account']) ? $params['account'] : ''; if ($account) { $query->where(function ($query) use ($account) { $query->where('b.nickname', 'like', "%{$account}%")->orWhere('b.mobile', 'like', "%{$account}%"); }); } // 商品 $goodsId = isset($params['goods_id']) ? intval($params['goods_id']) : 0; $goods = isset($params['goods']) ? trim($params['goods']) : ''; if ($goods) { $query->where(function ($query) use ($goods) { $query->where('c.goods_name', 'like', "%{$goods}%"); if (preg_match("/^(1[0-9]+|[1-9]+)$/", $goods)) { $query->where('a.goods_id', intval($goods)); } else { $query->where('c.goods_name', 'like', "%{$goods}%"); } }); } if ($goodsId > 0) { $query->where('a.goods_id', intval($goodsId)); } }) ->where(function ($query) use ($params) { $status = isset($params['status']) ? $params['status'] : 0; if ($status == 0) { $query->whereIn('a.status', [2, 3]); } else if ($status) { $query->where('a.status', $status); } }) ->where(function ($query) use ($userId) { if ($userId) { $query->where('a.user_id', '=', $userId); } }); } /** * 按日期统计订单数 * @param string $beginAt 开始时间 * @param string $endAt 结束时间 * @param int[] $status 状态:数组或数值 * @return mixed */ public function getCountByTime($beginAt = '', $endAt = '', $status = 3) { $cacheKey = "caches:orders:count_{$status}_{$beginAt}_{$endAt}"; $data = RedisService::get($cacheKey); if ($data) { return $data; } $where = ['mark' => 1]; $data = $this->model->where($where)->where(function ($query) use ($beginAt, $endAt, $status) { if ($beginAt && $endAt) { $query->whereBetween('create_time', [strtotime($beginAt), strtotime($endAt)]); } else if ($beginAt) { $query->where('create_time', '>=', strtotime($beginAt)); } if ($status && is_array($status)) { $query->whereIn('status', $status); } else if ($status) { $query->where('status', $status); } })->count('id'); if ($data) { RedisService::set($cacheKey, $data, rand(300, 600)); } return $data; } /** * 按日期统计订单金额 * @param string $beginAt 开始时间 * @param string $endAt 结束时间 * @param int[] $status 状态:数组或数值 * @return mixed */ public function getTotalByTime($beginAt = '', $endAt = '', $status = 3) { $cacheKey = "caches:orders:total_{$status}_{$beginAt}_{$endAt}"; $data = RedisService::get($cacheKey); if ($data) { return $data; } $where = ['mark' => 1]; $data = $this->model->where($where)->where(function ($query) use ($beginAt, $endAt, $status) { if ($beginAt && $endAt) { $query->whereBetween('create_time', [strtotime($beginAt), strtotime($endAt)]); } else if ($beginAt) { $query->where('create_time', '>=', strtotime($beginAt)); } if ($status && is_array($status)) { $query->whereIn('status', $status); } else if ($status) { $query->where('status', $status); } })->sum('total'); if ($data) { RedisService::set($cacheKey, $data, rand(300, 600)); } return $data; } /** * 添加或编辑 * @return array * @since 2020/11/11 * @author laravel开发员 */ public function edit() { $params = request()->post(); return parent::edit($params); // TODO: Change the autogenerated stub } /** * 订单审核 * @return bool */ public function confirm($adminId, $params) { $id = isset($params['id']) ? intval($params['id']) : 0; $remark = isset($params['remark']) ? trim($params['remark']) : ''; $checkStatus = isset($params['status']) ? intval($params['status']) : 0; if (!in_array($checkStatus, [2, 9])) { $this->error = '请选择审核状态'; return false; } $info = $this->model->with(['user', 'goods'])->where(['id' => $id, 'mark' => 1])->first(); $userInfo = isset($info['user']) ? $info['user'] : []; $goods = isset($info['goods']) ? $info['goods'] : []; $status = isset($info['status']) ? $info['status'] : 0; $orderUserId = isset($info['user_id']) ? $info['user_id'] : 0; $goodsId = isset($info['goods_id']) ? $info['goods_id'] : 0; if (empty($info) || empty($goods) || empty($userInfo) || $goodsId <= 0 || $orderUserId <= 0) { $this->error = '订单信息不存在或参数错误'; return false; } if ($status != 1) { $this->error = '订单状态不可操作'; return false; } // 审核通过 if ($checkStatus == 2) { if ($this->model->where(['goods_id' => $goodsId, 'status' => 3, 'mark' => 1])->value('id')) { $this->error = '该货物订单已完成'; return false; } if ($this->model->where(['goods_id' => $goodsId, 'status' => 2, 'mark' => 1])->value('id')) { $this->error = '该货物存在订单进行中,已审核通过其他司机'; return false; } } DB::beginTransaction(); if (!$this->model->where(['id' => $id])->update(['status' => $checkStatus, 'confirm_admin_id' => $adminId, 'confirm_at' => date('Y-m-d H:i:s'), 'remark' => $remark, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单审核失败'; return false; } if ($checkStatus == 2 && !GoodsModel::where(['id' => $goodsId])->update(['picker_status' => 2, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单审核失败'; return false; } // // 用户数据更新 $updateData = ['update_time' => time()]; if ($checkStatus == 2) { // 接单数量 $updateData['picker_order_num'] = DB::raw("picker_order_num + 1"); } else { // 审核不过自动设置不可接单 $updateData['picker_status'] = 2; } if (!MemberModel::where(['id' => $orderUserId])->update($updateData)) { DB::rollBack(); $this->error = '订单审核失败'; return false; } DB::commit(); RedisService::keyDel("caches:orders:checkOrder:*"); RedisService::keyDel("caches:members:info*"); ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "订单审核", 'content' => json_encode(request()->post(), 256), 'module' => 'admin']); ActionLogModel::record(); $this->error = '订单审核成功'; return ['id' => $id]; } /** * 订单取消 * @return bool */ public function cancel($adminId, $params) { $id = isset($params['id']) ? intval($params['id']) : 0; $remark = isset($params['remark']) ? trim($params['remark']) : ''; $info = $this->model->with(['user', 'goods'])->where(['id' => $id, 'mark' => 1])->first(); $userInfo = isset($info['user']) ? $info['user'] : []; $goods = isset($info['goods']) ? $info['goods'] : []; $status = isset($info['status']) ? $info['status'] : 0; $orderUserId = isset($info['user_id']) ? $info['user_id'] : 0; $goodsId = isset($info['goods_id']) ? $info['goods_id'] : 0; if (empty($info) || empty($goods) || empty($userInfo) || $goodsId <= 0 || $orderUserId <= 0) { $this->error = '订单信息不存在或参数错误'; return false; } if ($status == 9) { $this->error = '订单已取消'; return false; } if ($status == 3) { $this->error = '订单已完成'; return false; } DB::beginTransaction(); if (!$this->model->where(['id' => $id])->update(['status' => 9, 'confirm_admin_id' => $adminId, 'confirm_at' => date('Y-m-d H:i:s'), 'remark' => $remark, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单取消失败'; return false; } $pickerOrderNum = isset($userInfo['picker_order_num']) ? $userInfo['picker_order_num'] : 0; if (!MemberModel::where(['id' => $orderUserId])->update(['picker_order_num' => $pickerOrderNum ? DB::raw("picker_order_num - 1") : 0, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单取消失败'; return false; } if (!GoodsModel::where(['id' => $goodsId])->update(['picker_status' => 1, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单取消失败'; return false; } DB::commit(); RedisService::keyDel("caches:orders:checkOrder:*"); ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "订单取消", 'content' => json_encode(request()->post(), 256), 'module' => 'admin']); ActionLogModel::record(); $this->error = '订单取消成功'; return ['id' => $id]; } /** * 订单完成 * @return bool */ public function complete($adminId, $params) { $id = isset($params['id']) ? intval($params['id']) : 0; $remark = isset($params['remark']) ? trim($params['remark']) : ''; $info = $this->model->with(['user', 'goods'])->where(['id' => $id, 'mark' => 1])->first(); $userInfo = isset($info['user']) ? $info['user'] : []; $goods = isset($info['goods']) ? $info['goods'] : []; $status = isset($info['status']) ? $info['status'] : 0; $orderUserId = isset($info['user_id']) ? $info['user_id'] : 0; $goodsId = isset($info['goods_id']) ? $info['goods_id'] : 0; $bonus = isset($info['bonus']) ? $info['bonus'] : 0; $orderUser = isset($info['user']) ? $info['user'] : []; if (empty($info) || empty($goods) || empty($userInfo) || $goodsId <= 0 || $orderUserId <= 0) { $this->error = '订单信息不存在或参数错误'; return false; } if ($status != 2) { $this->error = '订单状态不可操作'; return false; } DB::beginTransaction(); if (!$this->model->where(['id' => $id])->update(['status' => 3, 'confirm_admin_id' => $adminId, 'confirm_at' => date('Y-m-d H:i:s'), 'remark' => $remark, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单确认完成失败'; return false; } // 收入结算 if ($bonus > 0) { $updateData = [ 'balance' => DB::raw("balance + {$bonus}"), 'income_total' => DB::raw("income_total + {$bonus}"), 'complete_order_num' => DB::raw("complete_order_num + 1"), 'update_time' => time() ]; if (!MemberModel::where(['id' => $orderUserId])->update($updateData)) { DB::rollBack(); $this->error = '订单确认完成收入结算失败'; return false; } // 收入记录 $balance = isset($userInfo['balance']) ? $userInfo['balance'] : 0; $log = [ 'user_id' => $orderUserId, 'source_order_no' => isset($info['order_no']) ? $info['order_no'] : '', 'type' => 1, 'money' => $bonus, 'before_money' => $balance, 'date' => date('Y-m-d'), 'create_time' => time(), 'remark' => '订单收入', 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { DB::rollBack(); $this->error = '订单确认完成收入结算失败'; return false; } } if (!GoodsModel::where(['id' => $goodsId])->update(['picker_status' => 3, 'update_time' => time()])) { DB::rollBack(); $this->error = '订单确认完成失败'; return false; } // 公告消息 $realname = isset($orderUser['realname']) ? $orderUser['realname'] : ''; $realname = $realname ? get_realname($realname) : '师傅'; $shipperAddress = isset($goods['shipper_address']) ? get_address($goods['shipper_address']) : ''; $receiverAddress = isset($goods['receiver_address']) ? get_address($goods['receiver_address']) : ''; $title = "{$realname}已完成从{$shipperAddress}到{$receiverAddress}的订单"; NoticeService::make()->saveNotice($title); RedisService::keyDel("caches:orders:checkOrder:*"); ActionLogModel::setRecord(session('userId'), ['type' => 1, 'title' => "订单确认完成", 'content' => json_encode(request()->post(), 256), 'module' => 'admin']); ActionLogModel::record(); DB::commit(); $this->error = '订单确认完成成功'; return ['id' => $id]; } /** * 删除订单 */ public function delete() { $id = request()->post('id'); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } if (is_array($id)) { $result = $this->model->whereIn('id', $id)->update(['mark' => 0]); } else { $result = $this->model->where('id', $id)->update(['mark' => 0]); } if ($result) { ActionLogModel::setTitle("删除订单"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '删除成功']; } return ['code' => 1, 'msg' => '删除失败']; } /** * 更新订单状态 */ public function status() { $id = request()->post('id'); $status = request()->post('status'); $refundStatus = request()->post('refund_status'); $refundRemark = request()->post('refund_remark', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } $updateData = ['update_time' => time()]; // 更新订单状态 if ($status !== null) { $updateData['status'] = $status; // 如果是完成订单,计算佣金 if ($status == 4) { $order = $this->model->find($id); if ($order) { $updateData['bonus'] = round($order->pay_total * 0.05, 2); } } } // 更新退款状态 if ($refundStatus !== null) { $updateData['refund_status'] = $refundStatus; $updateData['refund_remark'] = $refundRemark; // 如果同意退款,保持原订单状态不变 // 退款状态通过 refund_status 字段管理 } $result = $this->model->where('id', $id)->update($updateData); if ($result !== false) { ActionLogModel::setTitle("更新订单状态"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '操作成功']; } return ['code' => 1, 'msg' => '操作失败']; } /** * 完成支付 */ public function completePay() { $id = request()->post('id'); $transactionId = request()->post('transaction_id', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } if ($order->status != 1) { return ['code' => 1, 'msg' => '订单状态不正确']; } $updateData = [ 'status' => 2, // 已付款 'transaction_id' => $transactionId ?: 'PAY' . time() . rand(1000, 9999), 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { ActionLogModel::setTitle("订单完成支付"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '支付完成']; } return ['code' => 1, 'msg' => '操作失败']; } /** * 订单发货 */ public function deliverOrder() { $id = request()->post('id'); $deliveryCompany = request()->post('delivery_company', ''); $deliveryNo = request()->post('delivery_no', ''); $deliveryCode = request()->post('delivery_code', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } if ($order->status != 2) { return ['code' => 1, 'msg' => '订单状态不正确,只有已付款订单可以发货']; } if (!$deliveryNo) { return ['code' => 1, 'msg' => '请填写快递单号']; } $updateData = [ 'status' => 3, // 已发货 'delivery_company' => $deliveryCompany, 'delivery_no' => $deliveryNo, 'delivery_code' => $deliveryCode, 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { ActionLogModel::setTitle("订单发货"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '发货成功']; } return ['code' => 1, 'msg' => '操作失败']; } /** * 订单完成(管理后台) */ public function completeOrder() { $id = request()->post('id'); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } if ($order->status != 3) { return ['code' => 1, 'msg' => '订单状态不正确,只有已发货订单可以完成']; } // 调用用户端的订单完成方法,触发收益结算等业务逻辑 $apiOrderService = \App\Services\Api\OrderService::make(); $result = $apiOrderService->complete($order->user_id, $id); if ($result) { ActionLogModel::setTitle("订单完成"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '确认收货成功']; } // 获取错误信息 $error = $apiOrderService->getError(); return ['code' => 1, 'msg' => $error ?: '操作失败', 'error' => $error]; } /** * 取消订单 */ public function cancelOrder() { $id = request()->post('id'); $cancelReason = request()->post('cancel_reason', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } if ($order->status != 1) { return ['code' => 1, 'msg' => '只有待付款订单可以取消']; } $updateData = [ 'mark' => 0, // 标记为删除 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { ActionLogModel::setTitle("取消订单"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '订单已取消']; } return ['code' => 1, 'msg' => '操作失败']; } /** * 申请退款 */ public function applyRefund() { $id = request()->post('id'); $afterType = request()->post('after_type', 2); // 默认退款 $afterRealname = request()->post('after_realname', ''); $afterPhone = request()->post('after_phone', ''); $afterRemark = request()->post('after_remark', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } if (!$afterRealname) { return ['code' => 1, 'msg' => '请填写联系人姓名']; } if (!$afterPhone) { return ['code' => 1, 'msg' => '请填写联系电话']; } if (!$afterRemark) { return ['code' => 1, 'msg' => '请填写退款原因']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } // 只有已付款、已发货、已完成的订单可以申请退款 if (!in_array($order->status, [2, 3, 4])) { return ['code' => 1, 'msg' => '该订单状态不允许申请退款']; } if ($order->refund_status != 0) { return ['code' => 1, 'msg' => '该订单已申请过退款']; } $updateData = [ 'refund_status' => 3, // 待审核 'after_type' => $afterType, // 1-售后,2-退款 'after_realname' => $afterRealname, 'after_phone' => $afterPhone, 'after_remark' => $afterRemark, 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { $typeText = $afterType == 1 ? '售后' : '退款'; ActionLogModel::setTitle("申请{$typeText}"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => "{$typeText}申请已提交"]; } return ['code' => 1, 'msg' => '操作失败']; } /** * 同意退款(审核通过,状态变为已审核) */ public function agreeRefund() { $id = request()->post('id'); $refundRemark = request()->post('refund_remark', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } if ($order->refund_status != 3) { return ['code' => 1, 'msg' => '该订单未申请退款或已处理']; } $updateData = [ 'refund_status' => 2, // 已审核(待确认退款) 'refund_remark' => $refundRemark ?: '退款申请已通过,待确认退款', 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { ActionLogModel::setTitle("同意退款"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '已同意退款,请确认退款']; } return ['code' => 1, 'msg' => '操作失败']; } /** * 确认退款(最终完成退款) */ public function confirmRefund() { $id = request()->post('id'); $refundAmount = request()->post('refund_amount', 0); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } if ($refundAmount <= 0) { return ['code' => 1, 'msg' => '请输入退款金额']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } // 允许待审核(3)和已审核(2)状态的订单进行退款 if (!in_array($order->refund_status, [2, 3])) { return ['code' => 1, 'msg' => '该订单状态不允许退款']; } if ($refundAmount > $order->pay_total) { return ['code' => 1, 'msg' => '退款金额不能大于订单金额']; } // 使用事务 DB::beginTransaction(); try { // 调用支付服务退款 $paymentService = \App\Services\PaymentService::make(); $refundData = [ 'money' => $refundAmount, 'pay_type' => $order->pay_type, 'order_no' => $order->order_no, 'out_trade_no' => $order->out_trade_no, 'transaction_id' => $order->transaction_id, 'remark' => '订单退款' ]; $refundResult = $paymentService->refund($refundData, 'store'); if (!$refundResult) { DB::rollBack(); return ['code' => 1, 'msg' => '退款失败:' . $paymentService->getError() ?: '退款失败']; } // 更新订单状态 $updateData = [ 'refund_status' => 1, // 已退款 'refund_amount' => $refundAmount, 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { DB::commit(); ActionLogModel::setTitle("确认退款"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '退款成功']; } DB::rollBack(); return ['code' => 1, 'msg' => '更新订单状态失败']; } catch (\Exception $e) { DB::rollBack(); return ['code' => 1, 'msg' => '退款失败:' . $e->getMessage()]; } } /** * 拒绝退款 */ public function rejectRefund() { $id = request()->post('id'); $refundRemark = request()->post('refund_remark', ''); if (!$id) { return ['code' => 1, 'msg' => '参数错误']; } if (!$refundRemark) { return ['code' => 1, 'msg' => '请填写拒绝原因']; } $order = $this->model->find($id); if (!$order) { return ['code' => 1, 'msg' => '订单不存在']; } if ($order->refund_status != 3) { return ['code' => 1, 'msg' => '该订单未申请退款或已处理']; } $updateData = [ 'refund_status' => 4, // 审核驳回 'refund_remark' => $refundRemark, 'update_time' => time() ]; $result = $this->model->where('id', $id)->update($updateData); if ($result) { ActionLogModel::setTitle("拒绝退款"); ActionLogModel::record(); RedisService::keyDel("caches:orders:*"); return ['code' => 0, 'msg' => '已拒绝退款']; } return ['code' => 1, 'msg' => '操作失败']; } /** * 订单统计 * @param int $storeId 商户ID,0表示平台管理员查看全部数据 */ public function getStatistics($storeId = 0) { // 总订单数 $total = $this->model->where('mark', 1) ->when($storeId > 0, function ($query) use ($storeId) { return $query->where('store_id', $storeId); }) ->count(); // 总交易额(已完成订单) $totalAmount = $this->model->where('mark', 1) ->where('status', 4) ->when($storeId > 0, function ($query) use ($storeId) { return $query->where('store_id', $storeId); }) ->sum('pay_total'); // 待处理订单(待付款 + 已付款) $pending = $this->model->where('mark', 1) ->whereIn('status', [1, 2]) ->when($storeId > 0, function ($query) use ($storeId) { return $query->where('store_id', $storeId); }) ->count(); // 待退款订单 $refunding = $this->model->where('mark', 1) ->where('refund_status', 3) ->when($storeId > 0, function ($query) use ($storeId) { return $query->where('store_id', $storeId); }) ->count(); return [ 'code' => 0, 'msg' => '操作成功', 'data' => [ 'total' => $total, 'totalAmount' => number_format($totalAmount, 2, '.', ''), 'pending' => $pending, 'refunding' => $refunding ] ]; } /** * 导出订单数据 */ public function exportData($params) { $query = $this->model->where('mark', 1); // 店铺筛选 if (isset($params['store_id']) && $params['store_id'] > 0) { $query->where('store_id', $params['store_id']); } // 用户筛选 if (isset($params['user_id']) && $params['user_id'] > 0) { $query->where('user_id', $params['user_id']); } // 状态筛选 if (isset($params['status']) && $params['status'] > 0) { $query->where('status', $params['status']); } // 售后类型筛选 if (isset($params['after_type']) && $params['after_type'] > 0) { $query->where('after_type', $params['after_type']); } // 退款状态筛选 if (isset($params['refund_status']) && $params['refund_status'] > 0) { $query->where('refund_status', $params['refund_status']); } // 关键词搜索 if (isset($params['keyword']) && $params['keyword']) { $keyword = $params['keyword']; $query->where(function ($q) use ($keyword) { $q->where('order_no', 'like', '%' . $keyword . '%') ->orWhere('receiver_name', 'like', '%' . $keyword . '%') ->orWhere('receiver_mobile', 'like', '%' . $keyword . '%'); }); } $list = $query->with(['user', 'orderGoods', 'store']) ->orderBy('create_time', 'desc') ->limit(5000) ->get(); if (!$list || $list->isEmpty()) { return response()->json(['code' => 1, 'msg' => '没有可导出的数据']); } // 状态映射 $statusMap = [1 => '待付款', 2 => '已付款', 3 => '已发货', 4 => '已完成', 9 => '已取消']; $refundStatusMap = [0 => '无', 1 => '已退款', 2 => '已审核', 3 => '待审核']; // 构建导出数据 $data = []; foreach ($list as $item) { $goodsNames = []; if ($item->orderGoods) { foreach ($item->orderGoods as $goods) { $goodsNames[] = $goods->goods_name . ' x' . $goods->num; } } $data[] = [ $item->order_no, $item->user->nickname ?? '', $item->user->mobile ?? '', implode(';', $goodsNames), $item->total ?? 0, $item->pay_total ?? 0, $statusMap[$item->status] ?? '未知', $refundStatusMap[$item->refund_status] ?? '无', $item->receiver_name ?? '', $item->receiver_mobile ?? '', $item->receiver_address ?? '', $item->create_time ? date('Y-m-d H:i:s', strtotime($item->create_time)) : '', ]; } $headings = ['订单号', '用户昵称', '用户手机', '商品信息', '订单金额', '实付金额', '订单状态', '退款状态', '收货人', '收货电话', '收货地址', '下单时间']; $export = new \App\Exports\Export($data, $headings, '订单列表'); $filename = '订单列表_' . date('YmdHis') . '.xlsx'; return \Maatwebsite\Excel\Facades\Excel::download($export, $filename); } }