diff --git a/B06_Section/B06_Section_Api_Types.ts b/B06_Section/B06_Section_Api_Types.ts index 3629355d..c5d1a4a0 100644 --- a/B06_Section/B06_Section_Api_Types.ts +++ b/B06_Section/B06_Section_Api_Types.ts @@ -560,6 +560,8 @@ export interface CrossSectionPatch { ditch_type?: string | null; paved?: boolean; two_stage_slope?: boolean; + /** 측구를 둘지 **사용자 선택**(결과 `ditch_enabled` 와 다른 칸, 2026-09-09). */ + ditch_choice?: boolean | null; /** 절·성토 면적(㎡) — 브라우저가 계산해 보낸다(2026-09-06 사용자 확정). */ cut_area_m2?: number; fill_area_m2?: number; diff --git a/B06_Section/B06_Section_Cross_Design_Session.ts b/B06_Section/B06_Section_Cross_Design_Session.ts index 7b6ec3f9..5e5f74df 100644 --- a/B06_Section/B06_Section_Cross_Design_Session.ts +++ b/B06_Section/B06_Section_Cross_Design_Session.ts @@ -20,6 +20,9 @@ export interface CrossDesignChoice { ditch_type?: string | null; paved?: boolean; two_stage_slope?: boolean; + /** 측구를 둘지 **사용자가 정한 선택**(`null` = 자동 판정). 결과(`ditch_enabled`)가 아니다. + * ⚠ 이 칸이 없으면 측구 토글이 눌려도 캐시에 안 담겨 **화면에서 안 돈다**(2026-09-09). */ + ditch_choice?: boolean | null; } type ChoiceMap = Record; diff --git a/B06_Section/B06_Section_Cross_Refresh.ts b/B06_Section/B06_Section_Cross_Refresh.ts index f2d44caa..fa240d14 100644 --- a/B06_Section/B06_Section_Cross_Refresh.ts +++ b/B06_Section/B06_Section_Cross_Refresh.ts @@ -289,7 +289,11 @@ function refreshLocally(input: CrossRefreshInput): number[] | null { (design.two_stage_slope === undefined ? true : Boolean(design.two_stage_slope)), // ⚠ **선택과 결과를 갈라 넘긴다**(2026-09-09). 선택이 있으면 그것을 따르고, // 없으면 옛 저장분의 결과를 **자동값과 다를 때만** 선택으로 살린다. - ditchChoice: typeof design.ditch_choice === "boolean" ? design.ditch_choice : null, + ditchChoice: choice + ? (choice.ditch_choice ?? null) + : typeof design.ditch_choice === "boolean" + ? design.ditch_choice + : null, ditchEnabled: typeof design.ditch_enabled === "boolean" ? design.ditch_enabled : null, // 세월교 월류 하강은 계획선 편집으로 바뀌지 않는다 — 저장분 값을 그대로 잇는다. surfaceDropM: typeof design.surface_drop_m === "number" ? design.surface_drop_m : 0, diff --git a/B06_Section/B06_Section_Schema.py b/B06_Section/B06_Section_Schema.py index b6ef1a76..b1171532 100644 --- a/B06_Section/B06_Section_Schema.py +++ b/B06_Section/B06_Section_Schema.py @@ -170,6 +170,9 @@ class CrossSectionPatch(BaseModel): ditch_type: str | None = None paved: bool | None = None two_stage_slope: bool | None = None + # 측구를 둘지 **사용자 선택**(결과 `ditch_enabled` 와 다른 칸, 2026-09-09). None 은 + # 「안 보냄」이라 병합에서 걷힌다 — 「자동」을 patch 로 되돌릴 길은 아직 없다. + ditch_choice: bool | None = None # 구조물이 선 측점의 폐회로 절·성토 면적(㎡) — 브라우저가 계산해 보낸다 # (2026-09-06 사용자 확정: 「일단은 브라우저 계산으로」). 서버는 초기값을 만들 때만 # 같은 코드를 Node 로 돌린다(`B06_Section_Server_Calc_Node.ts`). diff --git a/B06_Section/B06_Section_UI_Page.ts b/B06_Section/B06_Section_UI_Page.ts index 837ec2ce..567e9119 100644 --- a/B06_Section/B06_Section_UI_Page.ts +++ b/B06_Section/B06_Section_UI_Page.ts @@ -240,6 +240,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { ditch_type: change.ditch_type, paved: change.paved, two_stage_slope: change.two_stage_slope, + ditch_choice: change.ditch_choice, }; sectionView.refreshCard(chainageM); } @@ -254,6 +255,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { ditch_type: change.ditch_type, paved: change.paved, two_stage_slope: change.two_stage_slope, + ditch_choice: change.ditch_choice, }); // (3) 계산은 브라우저 안에서 — B05·B06 이 같이 쓰는 창구 하나로 돌린다. await reconcileStaleDesigns({ force: true }); diff --git a/B06_Section/B06_Section_UI_Page_Persist.ts b/B06_Section/B06_Section_UI_Page_Persist.ts index e45c50c3..e69a3d1d 100644 --- a/B06_Section/B06_Section_UI_Page_Persist.ts +++ b/B06_Section/B06_Section_UI_Page_Persist.ts @@ -382,6 +382,9 @@ export function collectSectionEdits(ctx: SectionPersistContext): { if (choice.ditch_type !== undefined) patch.ditch_type = choice.ditch_type; if (choice.paved !== undefined) patch.paved = choice.paved; if (choice.two_stage_slope !== undefined) patch.two_stage_slope = choice.two_stage_slope; + // ⚠ 「자동」(null)은 patch 로 못 보낸다 — 서버 병합이 최상위 null 을 걷는다. 카드 토글은 + // 자동으로 되돌아가지 않으므로(켬/끔 둘 뿐) 지금은 손해가 없다(2026-09-09). + if (typeof choice.ditch_choice === "boolean") patch.ditch_choice = choice.ditch_choice; }); if (detail) { // 구조물 폐회로 면적 — **카드를 그리지 않은 측점까지** 여기서 다 계산한다