// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\timer\model\groupon; use app\common\library\helper; use app\common\model\groupon\Task as TaskModel; use app\timer\model\groupon\Goods as GrouponGoodsModel; use app\common\enum\groupon\TaskStatus as TaskStatusEnum; use app\timer\library\Tools; /** * 拼团拼单模型 * Class Task * @package app\timer\model\groupon */ class Task extends TaskModel { /** * 获取已过期但未结束的拼单ID集 * @param int $storeId * @return array */ public function getFailTaskIds(int $storeId): array { return $this->where('end_time', '<=', time()) ->where('status', '=', TaskStatusEnum::NORMAL) ->where('is_delete', '=', 0) ->where('store_id', '=', $storeId) ->column('task_id'); } /** * 获取已完成的拼单ID集 * @param int $storeId * @return array */ public function getCompleteTaskIds(int $storeId): array { // 获取一小时内完成的拼单 // 完成时间 > 当前时间 - 1小时 return $this->where('complete_time', '>', time() - 60 * 60) ->where('status', '<>', TaskStatusEnum::NORMAL) ->where('is_delete', '=', 0) ->where('store_id', '=', $storeId) ->column('task_id'); } /** * 将拼单任务状态标记结束 * @param array $taskIds 拼单任务ID集 * @return bool */ public function setStatusFail(array $taskIds): bool { return static::updateBase([ 'complete_time' => time(), 'status' => TaskStatusEnum::FAIL ], [['task_id', 'in', $taskIds]]); } /** * 获取模拟成团的拼单 * @param int $storeId * @return \app\timer\model\groupon\Task[]|array|\think\Collection * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getMockTaskList(int $storeId) { // 拼单过期时间需有一定间隔, 因要兼容定时任务的延时, 此处设置12分钟 (定时任务每10分钟执行 ) $compatibleTime = time() + (12 * 60); // 查询满足条件的记录 $groupGoodsName = GrouponGoodsModel::getTableName(); return $this->alias($this->alias) ->field("$this->alias.*") ->join($groupGoodsName, "{$groupGoodsName}.groupon_goods_id = {$this->alias}.groupon_goods_id") ->where("{$groupGoodsName}.is_mock_task", '=', 1) ->where("{$this->alias}.end_time", '<=', $compatibleTime) ->where("{$this->alias}.end_time", '>', time()) ->where("{$this->alias}.status", '=', TaskStatusEnum::NORMAL) ->where("{$this->alias}.is_delete", '=', 0) ->where("{$this->alias}.store_id", '=', $storeId) ->order(["{$this->alias}.end_time" => 'asc']) ->select(); } /** * 指定的拼单模拟成团 * @param \app\timer\model\groupon\Task $task * @param int $storeId * @return bool */ public function mockTask(self $task, int $storeId): bool { // 剩余拼单人数 $robotPeopleNum = $task['people'] - $task['actual_people']; // 获取随机的机器人成员ID集 $robotIds = Robot::getRandomRobot($robotPeopleNum, $storeId); // 记录日志 Tools::taskLogs('GrouponTask', 'mockTask', [ 'title' => '指定的拼单模拟成团', 'taskId' => $task['task_id'], 'robotPeopleNum' => $robotPeopleNum, 'robotIds' => helper::jsonEncode($robotIds), ]); // 如果机器人数量小于模拟成团所需人数则不执行 if (empty($robotIds)) { return false; } // 批量加入机器人成员 TaskUsers::mockJoin($robotIds, $task, $storeId); // 更新拼单状态为已完成 return $task->save([ 'robot_people' => $robotPeopleNum, 'complete_time' => time(), 'status' => TaskStatusEnum::SUCCESS ]); } }