diff --git a/services/pcp-tgu-ui-service/src/features/tgu-planning/TguPlanDetails.tsx b/services/pcp-tgu-ui-service/src/features/tgu-planning/TguPlanDetails.tsx index 5de6831..66f7089 100644 --- a/services/pcp-tgu-ui-service/src/features/tgu-planning/TguPlanDetails.tsx +++ b/services/pcp-tgu-ui-service/src/features/tgu-planning/TguPlanDetails.tsx @@ -82,14 +82,20 @@ export function TguPlanDetails({ const duration = formatDuration(plan.endMs - plan.startMs); // Окно решения закрылось, если с момента старта плана прошло больше grace-периода. const decisionWindowClosed = Date.now() > plan.startMs + DECISION_GRACE_MINUTES * 60_000; - // Закладку нельзя подтверждать, пока начало плана ещё в будущем: план закладывается на КА - // по факту наступления своего старта, а не заранее. - const layinStartInFuture = plan.startMs > Date.now(); + // Начало плана ещё в будущем. Нужно и для закладки (план закладывается по факту старта, + // не заранее), и для replace-черновика (после старта окно выдачи заморожено — бэк вернёт 422). + const startInFuture = plan.startMs > Date.now(); // «Создать черновик на основе плана» (replace, окно 1:1, все включения) доступно для - // персистентных правимых баз. DRAFT уже имеет свои действия; PLANNED — виртуальная проекция, - // не база; LAID_IN — replace 1:1 запрещён (слот зафиксирован, только fork-forward). - const canCreateDraftFromPlan = + // персистентных правимых баз, у которых старт ещё не наступил. DRAFT уже имеет свои действия; + // PLANNED — виртуальная проекция, не база; LAID_IN — replace 1:1 запрещён (слот зафиксирован); + // стартовавший план — окно выдачи заморожено (CreateDraftUseCase.createReplaceDraft → 422), + // продолжение возможно только fork-forward (отдельный поток). Гард зеркалит редактор, чтобы + // не предлагать кнопку, которая заведомо упадёт «Unprocessable Content». + const draftableStatus = plan.status !== "DRAFT" && plan.status !== "PLANNED" && plan.status !== "LAID_IN"; + const canCreateDraftFromPlan = draftableStatus && startInFuture; + // Статус позволял бы replace-черновик, но план уже стартовал — объясняем, почему кнопки нет. + const draftBlockedByStart = draftableStatus && !startInFuture; const reject = () => { const reason = window.prompt("Reason для REJECTED", "UI_TEST_REJECTED"); @@ -229,15 +235,23 @@ export function TguPlanDetails({ )} + {draftBlockedByStart && ( +
+ Черновик-копию (replace, то же окно) можно создать только до старта плана — окно + выдачи уже заморожено. Продолжение цепочки на будущую ЗРВ (fork-forward) выполняется + отдельно. +
+ )} + {plan.status === "AWAITING_LAYIN" && onConfirmLayin && (
ТЕСТОВЫЙ ФУНКЦИОНАЛ
- {layinStartInFuture && ( + {startInFuture && (
Начало плана ещё в будущем — подтвердить закладку можно только после наступления его старта.
)} - {!layinStartInFuture && layinConflict && ( + {!startInFuture && layinConflict && (
По КА уже есть заложенный план со стартом в пределах ±10 минут — подтвердить нельзя.