use super::models::*; use super::printer::{spawn_print_task, start_printing_locked, begin_next_locked}; use axum::{extract::{Path as AxumPath, State}, http::StatusCode, Json}; pub async fn job_advance( State(store): State, AxumPath(job_id): AxumPath, ) -> Result, (StatusCode, String)> { let (view, spawn_info) = { let mut m = store.lock().unwrap(); let job = m.get_mut(&job_id).ok_or_else(|| (StatusCode::NOT_FOUND, "Задание не найдено".into()))?; let si = match job.phase { // Старт печати текущего файла (первого или после очистки) JobPhase::WaitingStart | JobPhase::AwaitingClearOutput => { let idx = job.current.unwrap_or(0); Some(start_printing_locked(job, idx)) } JobPhase::AwaitingPickup => { let c = job.current.unwrap_or(0); if job.duplex_first_pass_done { // Первый проход двусторонней печати завершен -> просим переложить job.duplex_first_pass_done = false; job.files[c].status = FileStatus::AwaitingFlip; job.phase = JobPhase::AwaitingFlip; None } else { // Файл полностью напечатан job.files[c].status = FileStatus::Done; // Ищем следующий файл if let Some(next_si) = begin_next_locked(job, c) { let next_idx = job.current.unwrap(); // Проверяем, является ли СЛЕДУЮЩИЙ файл двусторонним let is_next_duplex = job.files[next_idx].settings.as_ref() .map(|s| s.sides.as_deref() == Some("Двусторонняя")) .unwrap_or(false); if is_next_duplex { // Следующий двусторонний -> просим очистить лоток ПЕРЕД его стартом // ВАЖНО: Мы НЕ спавним задачу печати здесь. // Мы меняем статус и ждем вызова advance (кнопки или автостарта) job.files[next_idx].status = FileStatus::AwaitingClearOutput; job.phase = JobPhase::AwaitingClearOutput; None } else { // Следующий односторонний -> печатаем сразу Some(next_si) } } else { None // Задание завершено } } } JobPhase::AwaitingFlip => { let c = job.current.unwrap(); job.files[c].status = FileStatus::Printing; job.phase = JobPhase::Printing; Some(SpawnInfo { job_id: job.id.clone(), idx: c, path: job.files[c].path.to_path_buf(), settings: job.files[c].settings.clone(), is_second_pass: true, }) } _ => None, }; (job.view(), si) }; if let Some(si) = spawn_info { spawn_print_task(store.clone(), si); } Ok(Json(view)) }