where('draw_no', $drawNo)->first(); if (! $draw) { return ApiResponse::error('draw not found', 'e2e_draw_missing', null, 404); } DB::table('draws') ->where('id', $draw->id) ->update([ 'status' => DrawStatus::Closed->value, 'close_time' => now()->subSeconds(5), 'draw_time' => now()->subSeconds(3), ]); return $this->inspectById((int) $draw->id); } /** 将冷静期结束时间改到过去,便于 tick 推进 cooldown → settling。 */ public function finishCooldown(Request $request, string $drawNo): JsonResponse { $draw = DB::table('draws')->where('draw_no', $drawNo)->first(); if (! $draw) { return ApiResponse::error('draw not found', 'e2e_draw_missing', null, 404); } DB::table('draws') ->where('id', $draw->id) ->update([ 'cooling_end_time' => now()->subSeconds(5), 'draw_time' => now()->subMinutes(2), 'close_time' => now()->subMinutes(3), ]); return $this->inspectById((int) $draw->id); } public function reopen(Request $request, string $drawNo): JsonResponse { $draw = DB::table('draws')->where('draw_no', $drawNo)->first(); if (! $draw) { return ApiResponse::error('draw not found', 'e2e_draw_missing', null, 404); } DB::table('draws') ->where('id', $draw->id) ->update([ 'status' => DrawStatus::Open->value, 'start_time' => now()->subMinutes(5), 'close_time' => now()->addMinutes(20), 'draw_time' => now()->addMinutes(21), 'cooling_end_time' => null, ]); return $this->inspectById((int) $draw->id); } public function inspect(Request $request, string $drawNo): JsonResponse { $draw = DB::table('draws')->where('draw_no', $drawNo)->first(); if (! $draw) { return ApiResponse::error('draw not found', 'e2e_draw_missing', null, 404); } return $this->inspectById((int) $draw->id); } /** 同步跑一次 lottery:draw-tick(不开调度)。返回该 tick 推进的 draw_no 列表。 */ public function tick(Request $request): JsonResponse { try { $exit = \Illuminate\Support\Facades\Artisan::call('lottery:draw-tick'); } catch (\Throwable $e) { return ApiResponse::error( 'draw-tick failed: '.$e->getMessage(), 'e2e_tick_failed', ['trace' => array_slice(explode("\n", $e->getTraceAsString()), 0, 5)], 500, ); } return ApiResponse::success([ 'exit_code' => $exit, 'output' => \Illuminate\Support\Facades\Artisan::output(), ]); } private function inspectById(int $id): JsonResponse { $d = DB::table('draws')->where('id', $id)->first(); return ApiResponse::success([ 'id' => (int) $d->id, 'draw_no' => $d->draw_no, 'status' => (string) $d->status, 'business_date' => $d->business_date, 'start_time' => $d->start_time, 'close_time' => $d->close_time, 'draw_time' => $d->draw_time, 'cooling_end_time' => $d->cooling_end_time, 'current_result_version' => (int) $d->current_result_version, 'settle_version' => (int) $d->settle_version, 'is_reopened' => (bool) $d->is_reopened, ]); } }