setName('update_appointment_status') ->setDescription('挂号单:已预约过号35分钟→已过号;已过号超8小时→已取消') ->addOption('dry', null, Option::VALUE_NONE, '仅预览不执行'); } protected function execute(Input $input, Output $output) { $dryRun = $input->getOption('dry'); $now = time(); $table = (new Appointment())->getTable(); $dtExpr = "CONCAT(appointment_date, ' ', IFNULL(appointment_time, '00:00:00'))"; // 1. 已预约 → 已过号:预约时间早于「当前 − 35 分钟」 $missedWhere = "status = 1 AND {$dtExpr} < DATE_SUB(NOW(), INTERVAL 35 MINUTE)"; $missedSql = "UPDATE {$table} SET status = 4, update_time = ? WHERE {$missedWhere}"; // 2. 已过号 → 已取消:预约时间早于或等于「当前 − 8 小时」 $cancelWhere = "status = 4 AND {$dtExpr} <= DATE_SUB(NOW(), INTERVAL 8 HOUR)"; $cancelSql = "UPDATE {$table} SET status = 2, update_time = ? WHERE {$cancelWhere}"; if ($dryRun) { $missedPreview = Db::query("SELECT id FROM {$table} WHERE {$missedWhere}"); $cancelPreview = Db::query("SELECT id FROM {$table} WHERE {$cancelWhere}"); $output->writeln('[预览] 将改为已过号(1→4): ' . count($missedPreview) . ' 条'); $output->writeln('[预览] 将改为已取消(4→2,过号超8小时): ' . count($cancelPreview) . ' 条'); $output->writeln('[说明] 真实执行时先执行 1→4,再执行 4→2;同一次内刚由 1 变 4 且已超 8 小时的会再被改为 2。'); return; } $missedCount = Db::execute($missedSql, [$now]); $cancelCount = Db::execute($cancelSql, [$now]); $output->writeln("已过号(1→4): {$missedCount} 条"); $output->writeln("已取消(4→2,过号超8小时): {$cancelCount} 条"); Log::info("update_appointment_status: 已过号 {$missedCount}, 已取消 {$cancelCount}"); } }