From 11380fced5f754440e0efaa7a7e35a6579aeae07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2=D1=8C=D0=B5=D0=B2?= Date: Wed, 10 Jun 2026 15:46:57 +0300 Subject: [PATCH] =?UTF-8?q?fix(tgu-ui):=20=D0=B3=D0=B0=D1=81=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=C2=AB=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D1=87=D0=B5=D1=80=D0=BD=D0=BE=D0=B2=D0=B8=D0=BA=C2=BB=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=81=D1=82=D0=B0=D1=80=D1=82=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=B2=D1=88=D0=B5=D0=B3=D0=BE=20=D0=BF=D0=BB=D0=B0=D0=BD=D0=B0?= =?UTF-8?q?=20(replace=E2=86=92422)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Кнопка предлагала replace-черновик для уже стартовавшего плана, хотя бэк (CreateDraftUseCase.createReplaceDraft) возвращает 422 «окно выдачи заморожено». Гард canCreateDraftFromPlan теперь требует startInFuture (зеркалит редактор); для стартовавших eligible-планов вместо кнопки — amber-подсказка про fork-forward. --- .../features/tgu-planning/TguPlanDetails.tsx | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) 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 минут — подтвердить нельзя.