// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\timer\service\groupon; use app\common\library\helper; use app\timer\library\Tools; use app\timer\model\Order as OrderModel; use app\timer\model\groupon\Task as TaskModel; use app\timer\model\groupon\Setting as SettingModel; use app\common\service\Order as OrderService; use app\common\service\order\Refund as RefundService; use app\common\enum\order\OrderStatus as OrderStatusEnum; use app\common\service\BaseService; /** * 服务类:拼团拼单任务 * Class Task * @package app\timer\service\groupon */ class Task extends BaseService { /** * 拼单失败事件 * @param int $storeId * @return bool * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function taskFailEvent(int $storeId): bool { // 获取已失效的拼单ID集 $model = new TaskModel; $taskIds = $model->getFailTaskIds($storeId); // 记录日志 Tools::taskLogs('GrouponTask', 'taskFailEvent', [ 'title' => '拼单失败事件', 'storeId' => $storeId, 'taskIds' => helper::jsonEncode($taskIds), ]); // 将拼团失败的订单退款处理 $this->refundFailOrder($storeId, $taskIds); // 标记拼单失效状态 return empty($taskIds) || $model->setStatusFail($taskIds); } /** * 拼单模拟成团事件 * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function taskMockEvent(int $storeId) { // 获取模拟成团的拼单 $model = new TaskModel; $taskList = $model->getMockTaskList($storeId); // 拼单任务ID集 $taskIds = helper::getArrayColumn($taskList, 'task_id'); // 批量将拼单模拟成团 if (!empty($taskIds)) { foreach ($taskList as $task) { $model->mockTask($task, $storeId); } } // 记录日志 Tools::taskLogs('GrouponTask', 'taskMockEvent', [ 'title' => '拼单模拟成团事件', 'robotIds' => helper::jsonEncode($taskIds), ]); } /** * 拼单完成事件 * @param int $storeId * @return bool * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function taskCompleteEvent(int $storeId): bool { // 获取已完成的拼单ID集 $model = new TaskModel; $taskIds = $model->getCompleteTaskIds($storeId); // 记录日志 Tools::taskLogs('GrouponTask', 'taskCompleteEvent', [ 'title' => '拼单完成事件', 'storeId' => $storeId, 'taskIds' => helper::jsonEncode($taskIds), ]); // 将已完成拼单的未付款订单取消 $this->cancelCompleteOrder($storeId, $taskIds); return true; } /** * 将拼团失败的订单退款处理 * @param int $storeId * @param array $taskIds * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function refundFailOrder(int $storeId, array $taskIds) { // 是否开启拼单失败自动退款 if (!SettingModel::taskFailAutoRefund($storeId)) { return; } // 查询拼团拼单失败的已付款订单 $model = new OrderModel; $list = $model->getListByGrouponTaskFail($storeId, $taskIds); // 订单ID集 $orderIds = helper::getArrayColumn($list, 'order_id'); // 用于记录退款失败的订单ID $invalidOrderIds = []; if (!empty($orderIds)) { foreach ($list as $order) { try { // 执行订单退款并关闭 (new RefundService)->handle($order) && OrderService::cancelEvent($order); } catch (\Throwable $e) { $invalidOrderIds[] = $order['order_id']; } } // 批量更新订单状态为已取消 $result = array_diff($orderIds, $invalidOrderIds); !empty($result) && $model->onBatchUpdate($result, ['order_status' => OrderStatusEnum::CANCELLED]); } // 记录日志 Tools::taskLogs('GrouponTask', 'refundFailOrder', [ 'title' => '将到期的拼团订单退款处理', 'storeId' => $storeId, 'orderIds' => helper::jsonEncode($orderIds), 'invalidOrderIds' => helper::jsonEncode($invalidOrderIds), ]); } /** * 将已完成拼单的未付款订单取消 * @param int $storeId * @param array $taskIds * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function cancelCompleteOrder(int $storeId, array $taskIds) { // 查询拼团拼单已完成的未付款订单 $model = new OrderModel; $list = $model->getListByGrouponTaskComplete($storeId, $taskIds); // 订单ID集 $orderIds = helper::getArrayColumn($list, 'order_id'); // 用于记录退款失败的订单ID if (!empty($orderIds)) { foreach ($list as $order) { OrderService::cancelEvent($order); } // 批量更新订单状态为已取消 $model->onBatchUpdate($orderIds, ['order_status' => OrderStatusEnum::CANCELLED]); } // 记录日志 Tools::taskLogs('GrouponTask', 'cancelCompleteOrder', [ 'title' => '将已完成拼单的未付款订单取消', 'storeId' => $storeId, 'orderIds' => helper::jsonEncode($orderIds), ]); } }