From 6015525efd01b0b0e5de12fe81bc6e40bb2300f6 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 15 Nov 2026 18:29:05 +0900 Subject: [PATCH] =?UTF-8?q?feat(842-2):=20=EA=B8=B0=EA=B3=84=20=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=20=E2=80=94=20M01=20=EA=B8=B0=EA=B3=84=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=E3=80=8C=EC=82=AC=EC=9A=A9=E3=80=8D=20?= =?UTF-8?q?=EC=8A=A4=EC=9C=84=EC=B9=98=20=C2=B7=20=EB=81=88=20=EA=B8=B0?= =?UTF-8?q?=EA=B3=84=EB=8A=94=20=EC=B0=BE=EA=B8=B0=20=C2=B7=20=EA=B3=A0?= =?UTF-8?q?=EB=A5=B4=EA=B8=B0=20=C2=B7=20=EC=9E=87=EA=B8=B0=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=BA=8C=20=C2=B7=20=ED=95=B4=EC=83=81=20=EA=B8=B0?= =?UTF-8?q?=EA=B3=84=2079=20=EB=8C=80=20=EB=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 표지 = 기계 줄 맨 위 칸 `비활성: true`(없음 = 켜짐 · 값 묶음 밖) · 틀 검사 = 기계 줄에만 true(check_master OFF) - M01 기계 목록 = 끝 열 「사용」 스위치(초안 → 페이지 [저장] · 자동저장 없음) · 끈 줄 흐림 · 머리 「비활성 같이 보기」(끄면 서버 rows state 「켜짐」) - 뺌 = 요소 찾기 창(elements · 찾아 넣기 · 단가산출 기계 창) · logic-lib rows · M01 시험 계산 기계 고르기 표 · 내 기계 「비슷한 기계에서 시작」 · 불러오기 기계 잇기(M02_Machine_Find 표) · 기계경비식 「기계」 옵션(새 GET /api/m02/df/machine-off · 고른 값은 남기고 「· 비활성 기계」 꼬리) - 셈 길은 그대로 — 끈 기계를 쓰던 단가산출 · 사본 값 같음 - 자료 = 해상장비 79 대(펌프 준설선 13 · 그래브 준설선 10 · 하천골재채취선 7 · 기중기선 5 · 예선 9 · 양묘선 11 · 토운선 6 · 이우선 2 · 대선 16) 끔 - 시험 = test_842_2_machine_off 새로 · test_804_10 옵션 글 단언을 새 글로 고침(끈 기계 거름이 들어간 줄) Co-Authored-By: Claude Opus 5.5 --- A00_Common/calc_sheet.ts | 4 +- A00_Common/formula_doc_options.ts | 23 +++- A00_Common/formula_doc_text.ts | 1 + M01_MasterData/M01_MasterData_Machine.py | 2 +- M01_MasterData/M01_MasterData_Store.py | 8 +- .../M01_MasterData_UI_Logic_PickTable.ts | 3 +- M01_MasterData/M01_MasterData_UI_Machine.css | 14 +++ M01_MasterData/M01_MasterData_UI_Machine.ts | 47 ++++++- M02_MasterTemplete/DataFlow/M02_DF_Api.ts | 6 + M02_MasterTemplete/DataFlow/M02_DF_Router.py | 11 ++ M02_MasterTemplete/M02_Logic_Lib_Read.py | 3 +- M02_MasterTemplete/M02_Machine_Find.py | 2 +- M02_MasterTemplete/M02_MyMachine_Look.py | 2 +- resources/master_data/scripts/check_master.py | 5 + resources/master_data/기계/EQ000541.json | 1 + resources/master_data/기계/EQ000542.json | 1 + resources/master_data/기계/EQ000543.json | 1 + resources/master_data/기계/EQ000544.json | 1 + resources/master_data/기계/EQ000545.json | 1 + resources/master_data/기계/EQ000546.json | 1 + resources/master_data/기계/EQ000547.json | 1 + resources/master_data/기계/EQ000548.json | 1 + resources/master_data/기계/EQ000549.json | 1 + resources/master_data/기계/EQ000550.json | 1 + resources/master_data/기계/EQ000551.json | 1 + resources/master_data/기계/EQ000552.json | 1 + resources/master_data/기계/EQ000553.json | 1 + resources/master_data/기계/EQ000554.json | 1 + resources/master_data/기계/EQ000555.json | 1 + resources/master_data/기계/EQ000556.json | 1 + resources/master_data/기계/EQ000557.json | 1 + resources/master_data/기계/EQ000558.json | 1 + resources/master_data/기계/EQ000559.json | 1 + resources/master_data/기계/EQ000560.json | 1 + resources/master_data/기계/EQ000561.json | 1 + resources/master_data/기계/EQ000562.json | 1 + resources/master_data/기계/EQ000563.json | 1 + resources/master_data/기계/EQ000564.json | 1 + resources/master_data/기계/EQ000565.json | 1 + resources/master_data/기계/EQ000566.json | 1 + resources/master_data/기계/EQ000567.json | 1 + resources/master_data/기계/EQ000568.json | 1 + resources/master_data/기계/EQ000569.json | 1 + resources/master_data/기계/EQ000570.json | 1 + resources/master_data/기계/EQ000571.json | 1 + resources/master_data/기계/EQ000572.json | 1 + resources/master_data/기계/EQ000573.json | 1 + resources/master_data/기계/EQ000574.json | 1 + resources/master_data/기계/EQ000575.json | 1 + resources/master_data/기계/EQ000576.json | 1 + resources/master_data/기계/EQ000577.json | 1 + resources/master_data/기계/EQ000578.json | 1 + resources/master_data/기계/EQ000579.json | 1 + resources/master_data/기계/EQ000580.json | 1 + resources/master_data/기계/EQ000581.json | 1 + resources/master_data/기계/EQ000582.json | 1 + resources/master_data/기계/EQ000583.json | 1 + resources/master_data/기계/EQ000584.json | 1 + resources/master_data/기계/EQ000585.json | 1 + resources/master_data/기계/EQ000586.json | 1 + resources/master_data/기계/EQ000587.json | 1 + resources/master_data/기계/EQ000588.json | 1 + resources/master_data/기계/EQ000589.json | 1 + resources/master_data/기계/EQ000590.json | 1 + resources/master_data/기계/EQ000591.json | 1 + resources/master_data/기계/EQ000592.json | 1 + resources/master_data/기계/EQ000593.json | 1 + resources/master_data/기계/EQ000594.json | 1 + resources/master_data/기계/EQ000595.json | 1 + resources/master_data/기계/EQ000596.json | 1 + resources/master_data/기계/EQ000597.json | 1 + resources/master_data/기계/EQ000598.json | 1 + resources/master_data/기계/EQ000599.json | 1 + resources/master_data/기계/EQ000600.json | 1 + resources/master_data/기계/EQ000601.json | 1 + resources/master_data/기계/EQ000602.json | 1 + resources/master_data/기계/EQ000603.json | 1 + resources/master_data/기계/EQ000604.json | 1 + resources/master_data/기계/EQ000605.json | 1 + resources/master_data/기계/EQ000606.json | 1 + resources/master_data/기계/EQ000607.json | 1 + resources/master_data/기계/EQ000608.json | 1 + resources/master_data/기계/EQ000609.json | 1 + resources/master_data/기계/EQ000610.json | 1 + resources/master_data/기계/EQ000611.json | 1 + resources/master_data/기계/EQ000612.json | 1 + resources/master_data/기계/EQ000613.json | 1 + resources/master_data/기계/EQ000614.json | 1 + resources/master_data/기계/EQ000615.json | 1 + resources/master_data/기계/EQ000616.json | 1 + resources/master_data/기계/EQ000617.json | 1 + resources/master_data/기계/EQ000618.json | 1 + resources/master_data/기계/EQ000619.json | 1 + .../test_804_10_machine_option_names.py | 7 +- resources/tester/test_842_2_machine_off.py | 118 ++++++++++++++++++ ui_template/ui_template_locale_machine.ts | 2 + 96 files changed, 315 insertions(+), 22 deletions(-) create mode 100644 resources/tester/test_842_2_machine_off.py diff --git a/A00_Common/calc_sheet.ts b/A00_Common/calc_sheet.ts index 5096b3401..28a90cf75 100644 --- a/A00_Common/calc_sheet.ts +++ b/A00_Common/calc_sheet.ts @@ -17,7 +17,7 @@ import { createInputField, createSelectField } from "@ui/ui_template_input"; import { currentLanguageIndex } from "@ui/ui_template_locale"; import { createText } from "@ui/ui_template_text"; import { formatLineMoney, formatMoney } from "../common_util/common_util_money"; -import { nameMachines, optionText } from "./formula_doc_options"; +import { liveOptions, nameMachines, optionText } from "./formula_doc_options"; import "./calc_sheet.css"; export interface SheetLine { @@ -164,7 +164,7 @@ export function varRow(spec: SheetInput, value: string, onInput: (v: string) => let control: HTMLElement; if (spec.고르기?.length) { const list = [...(value ? [] : [""]), ...spec.고르기.map(String)]; - const items = () => list.map((o) => ({ value: o, text: optionText(o) })); // 기계 번호 = 이름(요구 692-2) + const items = () => liveOptions(list, value).map((o) => ({ value: o, text: optionText(o) })); // 기계 번호 = 이름(요구 692-2) · 끈 기계 뺌(842-2) const f = createSelectField({ options: items(), value, diff --git a/A00_Common/formula_doc_options.ts b/A00_Common/formula_doc_options.ts index 6a33a6095..5ba453f62 100644 --- a/A00_Common/formula_doc_options.ts +++ b/A00_Common/formula_doc_options.ts @@ -9,21 +9,31 @@ import { createButton } from "@ui/ui_template_button"; import { createInputField, createSelectField } from "@ui/ui_template_input"; import { varId, type DocVar, type FormulaDoc } from "../common_util/common_util_formula_doc"; -import { cfMachineNames } from "../M02_MasterTemplete/DataFlow/M02_DF_Api"; +import { cfMachineNames, cfMachineOff } from "../M02_MasterTemplete/DataFlow/M02_DF_Api"; import { mt } from "../M02_MasterTemplete/M02_MyMachine_Text"; +import { ft } from "./formula_doc_text"; const MACHINE = /^\d{4}-\d{4}$/; let names: Record = {}; +let off = new Set(); // 842-2 끈 기계 원문번호 +const machineInfo = (): Promise> => + Promise.all([cfMachineNames(), cfMachineOff()]).then( + ([got, gone]) => ((off = new Set(gone)), got), + ); -/** 고르기 글 — 기계 원문번호는 이름 · 규격을 앞에 */ +/** 고르기 글 — 기계 원문번호는 이름 · 규격을 앞에 · 끈 기계는 「· 비활성 기계」(842-2) */ export const optionText = (x: string, known: Record = names): string => - known[x] ? `${known[x]} (${x})` : x; + known[x] ? `${known[x]} (${x})${off.has(x) ? ` · ${ft("Machine_Off")}` : ""}` : x; + +/** 고르기 목록 — 끈 기계 뺌(지금 고른 값은 남김 · 842-2) */ +export const liveOptions = (list: string[], now: string): string[] => + list.filter((x) => x === now || !off.has(x)); /** 목록이 모두 원문번호(빈 칸 빼고)면 이름을 받아 `redraw`(글만 다시) — 수식 탭 옵션 · 단가산출 상세 옵션 */ export function nameMachines(list: string[], redraw: () => void): void { const codes = list.filter(Boolean); if (codes.length && codes.every((x) => MACHINE.test(x)) && codes.some((x) => !(x in names))) - void cfMachineNames().then((got) => { + void machineInfo().then((got) => { names = got; redraw(); }); @@ -35,7 +45,7 @@ export function machineText(x: unknown, redraw: () => void): string | null { if (typeof x !== "string" || !MACHINE.test(x)) return null; if (!(x in names) && !asked) { asked = true; - void cfMachineNames().then((got) => { + void machineInfo().then((got) => { names = { ...names, ...got }; redraw(); }); @@ -59,7 +69,8 @@ export function buildOptions( const now = k in given ? given[k] : v.연결?.값; if (kind === "선택") { const list = (v.연결?.목록 ?? []).map(String); - const items = () => list.map((x) => ({ value: x, text: optionText(x) })); + const items = () => + liveOptions(list, String(now ?? "")).map((x) => ({ value: x, text: optionText(x) })); const f = createSelectField({ label, options: items(), diff --git a/A00_Common/formula_doc_text.ts b/A00_Common/formula_doc_text.ts index 2a4a8e06c..27742051b 100644 --- a/A00_Common/formula_doc_text.ts +++ b/A00_Common/formula_doc_text.ts @@ -49,6 +49,7 @@ const TEXT = { By_Line: ["식 줄로 정의", "Defined by a line"], Pick_First: ["찾아 고름", "Search and pick"], Material: ["재료 고르기", "Material pick"], + Machine_Off: ["비활성 기계", "Inactive machine"], None: ["없음", "None"], Open_Sub: ["식 펼침", "Show equation"], Bad_Sign: ["기호 꼴 아님 · 같은 기호 있음", "Bad or duplicate symbol"], diff --git a/M01_MasterData/M01_MasterData_Machine.py b/M01_MasterData/M01_MasterData_Machine.py index e04fdd85b..81c374133 100644 --- a/M01_MasterData/M01_MasterData_Machine.py +++ b/M01_MasterData/M01_MasterData_Machine.py @@ -236,7 +236,7 @@ def find(q: str, limit: int = 30) -> list[dict]: for r in _rows(): hay = " ".join(str(r.get(k) or "") for k in ("이름", "규격", "별칭", "상세구분", "키")) hay = hay.lower() - if all(w in hay for w in words): + if all(w in hay for w in words) and not r.get("비활성"): # 끈 기계 뺌(842-2) out.append(_brief(r)) if len(out) >= limit: break diff --git a/M01_MasterData/M01_MasterData_Store.py b/M01_MasterData/M01_MasterData_Store.py index 2549d3f7e..05ccdcf96 100644 --- a/M01_MasterData/M01_MasterData_Store.py +++ b/M01_MasterData/M01_MasterData_Store.py @@ -241,8 +241,10 @@ def rows( hits = [r for r in hits if sub in {r.get(s) for s in cm.MERGED.values()}] if detail: # 인력 상세구분 · 기계 상세구분(기종) hits = [r for r in hits if r.get("상세구분") == detail] - if state: # 인력 상태 - hits = [r for r in hits if r.get("상태") == state] + if state: # 인력 상태 · 기계 「켜짐」 = 비활성 뺌(842-2) + hits = [ + r for r in hits if (not r.get(cm.OFF) if state == "켜짐" else r.get("상태") == state) + ] if unlinked: # 품셈재료 — 아직 못 이은 줄 hits = [r for r in hits if not r.get("연결")] page, size = max(page, 1), min(max(size, 1), 500) @@ -463,7 +465,7 @@ def elements(group: str, q: str, limit: int) -> dict: if data.get("그룹") != group: continue for row in data.get(items_key(data)) or []: - if _hit(row, q): + if _hit(row, q) and not row.get(cm.OFF): # 끈 기계 뺌(842-2) more = {"별칭": row.get("별칭") or ""} if group == "로직" else {} # 208-1 hits.append({**_brief(str(row.get("키")), row), "file": name, **more}) return {"total": len(hits), "items": hits[: min(max(limit, 1), 200)]} diff --git a/M01_MasterData/M01_MasterData_UI_Logic_PickTable.ts b/M01_MasterData/M01_MasterData_UI_Logic_PickTable.ts index 38ee4882f..4f06ec36f 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_PickTable.ts +++ b/M01_MasterData/M01_MasterData_UI_Logic_PickTable.ts @@ -70,7 +70,8 @@ export function openPickTable(opt: PickTableOptions): void { const mine = ++seq; try { const q = search.value.trim(); - const got = await fetchRows(FILES[opt.kind], page, size, q); + const on = opt.kind === "기계" ? "켜짐" : ""; // 끈 기계 뺌(842-2) + const got = await fetchRows(FILES[opt.kind], page, size, q, false, "", "", on); if (mine !== seq) return; // 최신 응답만 if (!got.total && fallback) { const next = [...(q.includes(" ") ? [q.split(/\s+/)[0]] : []), ...(opt.alt ?? [])].find( diff --git a/M01_MasterData/M01_MasterData_UI_Machine.css b/M01_MasterData/M01_MasterData_UI_Machine.css index 1a4c5f741..9e6d2deec 100644 --- a/M01_MasterData/M01_MasterData_UI_Machine.css +++ b/M01_MasterData/M01_MasterData_UI_Machine.css @@ -66,3 +66,17 @@ table.m01-master__grid.m01-machine__grid { max-height: 240px; overflow: auto; } + +/* 「사용」 열(842-2) — 스위치 · 끈 줄은 흐림 */ +.m01-machine__grid th.m01-machine__use { + width: 64px; +} + +.m01-machine__grid td.m01-machine__use { + text-align: center; +} + +.m01-machine__row.is-off td:not(.m01-machine__use) { + color: var(--color-text-muted); + opacity: 0.6; +} diff --git a/M01_MasterData/M01_MasterData_UI_Machine.ts b/M01_MasterData/M01_MasterData_UI_Machine.ts index 0f723db3b..b0faf760b 100644 --- a/M01_MasterData/M01_MasterData_UI_Machine.ts +++ b/M01_MasterData/M01_MasterData_UI_Machine.ts @@ -3,14 +3,17 @@ * M01 기계 목록(PLAN 821-2 · 요구 790-2) — 표는 목록용 열만(이름 · 규격 · 구분 · 가격 · 손료계수 · * 주연료 · 조종원 · 시간당 경비(서버 값) · 별칭 · 비고) · 줄을 누르면 상세 페이지 · [새 기계] = 양식. * 단위 · 출처 열 없음 · 고친 것 · 새 줄 · 지울 줄은 초안(노랑 · 새 · 지움 표시) — 저장은 페이지 [저장]. + * 「사용」 열(842-2) = 스위치 · 끄면 줄 맨 위 칸 `비활성: true`(초안 → [저장]) · 끈 줄은 흐림 · + * 머리 「비활성 같이 보기」 끄면 서버가 끈 줄을 뺌(`rows` state 「켜짐」). * ========================================================================== */ import { createButton, el, showToast } from "@ui/ui_template_elements"; import { t as L } from "@ui/ui_template_locale"; import { createEmpty } from "@ui/ui_template_empty"; +import { createToggle } from "@ui/ui_template_toggle"; import { guessRows, pageKeepFirst, watchFit } from "@ui/ui_template_pager"; import { fetchRows, type Row, type RowsPage } from "./M01_MasterData_Api_Fetch"; -import { onDraftChange, peek, same } from "./M01_MasterData_Draft"; +import { editRow, onDraftChange, peek, same } from "./M01_MasterData_Draft"; import { fetchMachineHourly } from "./M01_MasterData_Machine_Api"; import { buildPager } from "./M01_MasterData_UI_Cells"; import { saveView, type Pick } from "./M01_MasterData_UI_Side"; @@ -38,6 +41,8 @@ const COLS: [string, (r: Row) => string][] = [ ], ]; const val = (r: Row): Record => (r["값"] ?? {}) as Record; +const OFF = "비활성"; // 842-2 기계 줄 맨 위 칸 — true 만 · 켜짐 = 칸 없음 +let showOff = true; // 「비활성 같이 보기」(페이지 안에서 기억) /** 돌려받은 함수 = 걷기. `open(target)` = 상세(키 · 새 줄 `add:<차례>` · 새 기계 `new`). */ export function renderMachines( @@ -53,9 +58,31 @@ export function renderMachines( const hourly = new Map(); const hourText = (key: string): string => hourly.get(key) ?? "…"; + /** 「사용」 칸 — 스위치(새 줄은 빈 칸) · 바꾸면 초안 */ + const useCell = (row: Row, cur: Row, key: string): HTMLElement => { + const td = el("td", { className: "m01-machine__use" }); + if (!key || !data) return td; + const version = data.version; + const sw = createToggle({ + label: "", + size: 20, + checked: !cur[OFF], + onChange: (on) => { + const next: Row = { ...cur }; + if (on) delete next[OFF]; + else next[OFF] = true; + editRow(file, version, key, row, next); + }, + }); + sw.root.setAttribute("aria-label", L("M01_MachineUse")); + sw.root.addEventListener("click", (e) => e.stopPropagation()); + td.classList.toggle("is-changed", !!cur[OFF] !== !!row[OFF]); + td.append(sw.root); + return td; + }; const line = (row: Row, cur: Row, cls: string, target: string, key = ""): HTMLElement => { const tr = el("tr", { - className: `m01-machine__row ${cls}`.trim(), + className: `m01-machine__row ${cls} ${cur[OFF] ? "is-off" : ""}`.trim(), attrs: { "data-key": key || target }, children: [ ...COLS.map(([, get]) => { @@ -71,6 +98,7 @@ export function renderMachines( }), el("td", { text: String(cur["별칭"] ?? ""), attrs: { title: String(cur["별칭"] ?? "") } }), el("td", { text: String(cur["비고"] ?? ""), attrs: { title: String(cur["비고"] ?? "") } }), + useCell(row, cur, key), ], }); tr.addEventListener("click", () => open(target)); @@ -91,12 +119,21 @@ export function renderMachines( } const add = createButton({ label: L("M01_MachineNew"), variant: "ghost", iconStart: "plus" }); add.addEventListener("click", () => open("new")); + const offSwitch = createToggle({ + label: L("M01_MachineShowOff"), + checked: showOff, + onChange: (on) => { + showOff = on; + page = 1; + void load(); + }, + }); const empty = d.rows.length || draft?.adds.length ? [] : [createEmpty({ text: L("M01_NoRows"), small: true })]; host.replaceChildren( - el("div", { className: "ui-toolbar m01-master__bar", children: [add] }), + el("div", { className: "ui-toolbar m01-master__bar", children: [add, offSwitch.root] }), el("div", { className: "ui-table-wrap m01-master__grid-wrap m01-machine__wrap", children: [ @@ -111,6 +148,7 @@ export function renderMachines( el("th", { text: `${L("M01_MachineHourly")}(원)` }), el("th", { text: "별칭" }), el("th", { text: "비고" }), + el("th", { className: "m01-machine__use", text: L("M01_MachineUse") }), ], }), ], @@ -152,7 +190,8 @@ export function renderMachines( const load = async (): Promise => { const mine = ++ticket; try { - const got = await fetchRows(file, page, size, q, false, pick.sub, pick.detail, pick.state); + const state = showOff ? pick.state : "켜짐"; + const got = await fetchRows(file, page, size, q, false, pick.sub, pick.detail, state); if (mine !== ticket) return; data = got; saveView(pick.group, { page: data.page }); diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Api.ts b/M02_MasterTemplete/DataFlow/M02_DF_Api.ts index 0319e83e8..ec9d43423 100644 --- a/M02_MasterTemplete/DataFlow/M02_DF_Api.ts +++ b/M02_MasterTemplete/DataFlow/M02_DF_Api.ts @@ -28,3 +28,9 @@ export function cfMachineNames(): Promise> { .catch(() => ((machineNames = null), {})); return machineNames; } + +/** 끈 기계 원문번호(842-2) — 이름과 함께 한 번 받아 둠(못 받으면 빈 목록) */ +export const cfMachineOff = (): Promise => + fetch(`${API_BASE_URL}/m02/df/machine-off`, { credentials: "include" }) + .then((r) => (r.ok ? (r.json() as Promise) : [])) + .catch(() => []); diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Router.py b/M02_MasterTemplete/DataFlow/M02_DF_Router.py index f33abcc85..cf9f8c29d 100644 --- a/M02_MasterTemplete/DataFlow/M02_DF_Router.py +++ b/M02_MasterTemplete/DataFlow/M02_DF_Router.py @@ -33,6 +33,17 @@ def get_machine_names() -> dict: return out +@router.get("/machine-off") +def get_machine_off() -> list[str]: + """끈 기계 원문번호(842-2) — 그 번호 기계가 모두 「비활성」 · 옵션 고르기 목록에서 뺌(고른 값은 남김).""" + on, off = set(), set() + for data in store.loaded()[0].values(): + if data.get("그룹") == "기계": + for row in data.get(store.items_key(data)) or []: + (off if row.get("비활성") else on).add(str(row.get("원문번호") or "")) + return sorted(off - on - {""}) + + @router.get("/standards") def get_standards() -> dict: try: diff --git a/M02_MasterTemplete/M02_Logic_Lib_Read.py b/M02_MasterTemplete/M02_Logic_Lib_Read.py index d59d19d34..7fcfd649b 100644 --- a/M02_MasterTemplete/M02_Logic_Lib_Read.py +++ b/M02_MasterTemplete/M02_Logic_Lib_Read.py @@ -48,7 +48,8 @@ def get_materials( def get_rows(file: str, page: int = 1, size: int = 50, q: str = "", sub: str = "") -> dict: if not file.startswith(ROW_FILES): raise HTTPException(status_code=403, detail="요소 파일(인력 · 재료 · 기계)만 읽음") - return m01.get_rows(file, page, size, q, False, sub, "", "") + on = "켜짐" if file.startswith("기계") else "" # 끈 기계 뺌(842-2) + return m01.get_rows(file, page, size, q, False, sub, "", on) @router.get("/table") diff --git a/M02_MasterTemplete/M02_Machine_Find.py b/M02_MasterTemplete/M02_Machine_Find.py index fe6fb7ef0..a418da93d 100644 --- a/M02_MasterTemplete/M02_Machine_Find.py +++ b/M02_MasterTemplete/M02_Machine_Find.py @@ -145,7 +145,7 @@ class Row: @lru_cache(maxsize=4) def _table(whole: Any) -> tuple[list[Row], frozenset[str], dict[str, Row]]: - rows = [Row(r) for r in whole.numbers.get("EQ", {}).values()] + rows = [Row(r) for r in whole.numbers.get("EQ", {}).values() if not r.get("비활성")] # 842-2 words = frozenset(w for r in rows for w in r.words) return rows, words, {r.key: r for r in rows} diff --git a/M02_MasterTemplete/M02_MyMachine_Look.py b/M02_MasterTemplete/M02_MyMachine_Look.py index 4b5638572..a6bfa6b9e 100644 --- a/M02_MasterTemplete/M02_MyMachine_Look.py +++ b/M02_MasterTemplete/M02_MyMachine_Look.py @@ -54,7 +54,7 @@ def find(q: str, limit: int = 30) -> list[dict]: if all(w in f"{r.get('이름')} {r.get('규격')} {r.get('키')}".lower() for w in words) ] exact = (m01.loaded()[1].numbers.get("EQ") or {}).get(q.strip()) - head = [exact] if exact is not None and not mym.mine(exact.get("키")) else [] + head = [exact] if exact and not mym.mine(exact.get("키")) and not exact.get("비활성") else [] m01_rows = [*head, *_m01m().find(q, limit)] seen = set() for r in m01_rows: diff --git a/resources/master_data/scripts/check_master.py b/resources/master_data/scripts/check_master.py index fb6e21dfe..4a739b488 100644 --- a/resources/master_data/scripts/check_master.py +++ b/resources/master_data/scripts/check_master.py @@ -136,6 +136,9 @@ COLS = { } COLS["한국은행환율"] = COLS["유가전력"] ALIAS = "별칭" # 요소 줄 덧칸(815-2) — 열 한 벌 밖 · 있으면 빈 글 아님 +OFF = ( + "비활성" # 기계 줄 맨 위 칸(842-2) — 있으면 true 만 · 없음 = 켜짐 · 찾기 · 고르기 · 잇기에서 뺌 +) def _cols_of(row: dict) -> tuple: @@ -299,6 +302,8 @@ def check_form(name: str, data: dict) -> list[str]: out += _check_labor(where, row) if ALIAS in row and not (isinstance(row[ALIAS], str) and row[ALIAS].strip()): out.append(f"{where} · 「{ALIAS}」 이 빈 글 · 글 아님(빈 칸이면 칸을 두지 않음)") + if OFF in row and (row[OFF] is not True or data.get("그룹") != "기계"): + out.append(f"{where} · 「{OFF}」 는 기계 줄에만 true(켜짐이면 칸을 두지 않음)") if cols and _cols_of(row) != cols: out.append(f"{where} · 열이 한 벌이 아님 — 「{' · '.join(cols)}」") if book == "자재품목" and row.get(mm.LOAD) not in mm.LOADS: diff --git a/resources/master_data/기계/EQ000541.json b/resources/master_data/기계/EQ000541.json index 1839f9ebf..d4f2f1b69 100644 --- a/resources/master_data/기계/EQ000541.json +++ b/resources/master_data/기계/EQ000541.json @@ -1,5 +1,6 @@ { "키": "EQ000541", + "비활성": true, "원문번호": "9010-0003", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000542.json b/resources/master_data/기계/EQ000542.json index 9892d06b5..f11ff6c28 100644 --- a/resources/master_data/기계/EQ000542.json +++ b/resources/master_data/기계/EQ000542.json @@ -1,5 +1,6 @@ { "키": "EQ000542", + "비활성": true, "원문번호": "9010-0006", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000543.json b/resources/master_data/기계/EQ000543.json index 2e4229187..bd6cc1faa 100644 --- a/resources/master_data/기계/EQ000543.json +++ b/resources/master_data/기계/EQ000543.json @@ -1,5 +1,6 @@ { "키": "EQ000543", + "비활성": true, "원문번호": "9010-0010", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000544.json b/resources/master_data/기계/EQ000544.json index 75c66054e..4afc4e36b 100644 --- a/resources/master_data/기계/EQ000544.json +++ b/resources/master_data/기계/EQ000544.json @@ -1,5 +1,6 @@ { "키": "EQ000544", + "비활성": true, "원문번호": "9010-0012", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000545.json b/resources/master_data/기계/EQ000545.json index 0a00dead6..f6142e364 100644 --- a/resources/master_data/기계/EQ000545.json +++ b/resources/master_data/기계/EQ000545.json @@ -1,5 +1,6 @@ { "키": "EQ000545", + "비활성": true, "원문번호": "9010-0020", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000546.json b/resources/master_data/기계/EQ000546.json index 463d5e117..0f08d054d 100644 --- a/resources/master_data/기계/EQ000546.json +++ b/resources/master_data/기계/EQ000546.json @@ -1,5 +1,6 @@ { "키": "EQ000546", + "비활성": true, "원문번호": "9010-0022", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000547.json b/resources/master_data/기계/EQ000547.json index 9217eba2c..60ec69f14 100644 --- a/resources/master_data/기계/EQ000547.json +++ b/resources/master_data/기계/EQ000547.json @@ -1,5 +1,6 @@ { "키": "EQ000547", + "비활성": true, "원문번호": "9010-0033", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000548.json b/resources/master_data/기계/EQ000548.json index 70bef7ead..550482728 100644 --- a/resources/master_data/기계/EQ000548.json +++ b/resources/master_data/기계/EQ000548.json @@ -1,5 +1,6 @@ { "키": "EQ000548", + "비활성": true, "원문번호": "9010-0040", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000549.json b/resources/master_data/기계/EQ000549.json index 8795e26a7..8fd4888b0 100644 --- a/resources/master_data/기계/EQ000549.json +++ b/resources/master_data/기계/EQ000549.json @@ -1,5 +1,6 @@ { "키": "EQ000549", + "비활성": true, "원문번호": "9010-0044", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000550.json b/resources/master_data/기계/EQ000550.json index 06bc5f9a5..7797b99fd 100644 --- a/resources/master_data/기계/EQ000550.json +++ b/resources/master_data/기계/EQ000550.json @@ -1,5 +1,6 @@ { "키": "EQ000550", + "비활성": true, "원문번호": "9010-0060", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000551.json b/resources/master_data/기계/EQ000551.json index 295c56179..26358a3eb 100644 --- a/resources/master_data/기계/EQ000551.json +++ b/resources/master_data/기계/EQ000551.json @@ -1,5 +1,6 @@ { "키": "EQ000551", + "비활성": true, "원문번호": "9010-0080", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000552.json b/resources/master_data/기계/EQ000552.json index 76ae30401..3918c4f2d 100644 --- a/resources/master_data/기계/EQ000552.json +++ b/resources/master_data/기계/EQ000552.json @@ -1,5 +1,6 @@ { "키": "EQ000552", + "비활성": true, "원문번호": "9010-0120", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000553.json b/resources/master_data/기계/EQ000553.json index c53b79b50..822a72163 100644 --- a/resources/master_data/기계/EQ000553.json +++ b/resources/master_data/기계/EQ000553.json @@ -1,5 +1,6 @@ { "키": "EQ000553", + "비활성": true, "원문번호": "9010-0200", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000554.json b/resources/master_data/기계/EQ000554.json index 2d1545f49..0bbed482b 100644 --- a/resources/master_data/기계/EQ000554.json +++ b/resources/master_data/기계/EQ000554.json @@ -1,5 +1,6 @@ { "키": "EQ000554", + "비활성": true, "원문번호": "9020-0010", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000555.json b/resources/master_data/기계/EQ000555.json index 108db749d..beb252db0 100644 --- a/resources/master_data/기계/EQ000555.json +++ b/resources/master_data/기계/EQ000555.json @@ -1,5 +1,6 @@ { "키": "EQ000555", + "비활성": true, "원문번호": "9020-0015", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000556.json b/resources/master_data/기계/EQ000556.json index 70c4bb822..3df5b57a0 100644 --- a/resources/master_data/기계/EQ000556.json +++ b/resources/master_data/기계/EQ000556.json @@ -1,5 +1,6 @@ { "키": "EQ000556", + "비활성": true, "원문번호": "9020-0016", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000557.json b/resources/master_data/기계/EQ000557.json index b329fb4dd..d0db041e0 100644 --- a/resources/master_data/기계/EQ000557.json +++ b/resources/master_data/기계/EQ000557.json @@ -1,5 +1,6 @@ { "키": "EQ000557", + "비활성": true, "원문번호": "9020-0022", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000558.json b/resources/master_data/기계/EQ000558.json index bc03f1703..66e0b8766 100644 --- a/resources/master_data/기계/EQ000558.json +++ b/resources/master_data/기계/EQ000558.json @@ -1,5 +1,6 @@ { "키": "EQ000558", + "비활성": true, "원문번호": "9020-0035", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000559.json b/resources/master_data/기계/EQ000559.json index f6104294b..d17a36935 100644 --- a/resources/master_data/기계/EQ000559.json +++ b/resources/master_data/기계/EQ000559.json @@ -1,5 +1,6 @@ { "키": "EQ000559", + "비활성": true, "원문번호": "9020-0050", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000560.json b/resources/master_data/기계/EQ000560.json index 395924a52..79a07e8d3 100644 --- a/resources/master_data/기계/EQ000560.json +++ b/resources/master_data/기계/EQ000560.json @@ -1,5 +1,6 @@ { "키": "EQ000560", + "비활성": true, "원문번호": "9020-0072", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000561.json b/resources/master_data/기계/EQ000561.json index 314ffbe08..20c4d5719 100644 --- a/resources/master_data/기계/EQ000561.json +++ b/resources/master_data/기계/EQ000561.json @@ -1,5 +1,6 @@ { "키": "EQ000561", + "비활성": true, "원문번호": "9020-0160", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000562.json b/resources/master_data/기계/EQ000562.json index d8ba7c73c..88de32d7b 100644 --- a/resources/master_data/기계/EQ000562.json +++ b/resources/master_data/기계/EQ000562.json @@ -1,5 +1,6 @@ { "키": "EQ000562", + "비활성": true, "원문번호": "9020-0180", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000563.json b/resources/master_data/기계/EQ000563.json index bdbc5d5a8..9682e81a9 100644 --- a/resources/master_data/기계/EQ000563.json +++ b/resources/master_data/기계/EQ000563.json @@ -1,5 +1,6 @@ { "키": "EQ000563", + "비활성": true, "원문번호": "9020-0200", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000564.json b/resources/master_data/기계/EQ000564.json index 43ec31e9d..3df52de3a 100644 --- a/resources/master_data/기계/EQ000564.json +++ b/resources/master_data/기계/EQ000564.json @@ -1,5 +1,6 @@ { "키": "EQ000564", + "비활성": true, "원문번호": "9030-0016", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000565.json b/resources/master_data/기계/EQ000565.json index 16255c9f9..c320508d5 100644 --- a/resources/master_data/기계/EQ000565.json +++ b/resources/master_data/기계/EQ000565.json @@ -1,5 +1,6 @@ { "키": "EQ000565", + "비활성": true, "원문번호": "9030-0018", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000566.json b/resources/master_data/기계/EQ000566.json index 18bf173e1..94c03366a 100644 --- a/resources/master_data/기계/EQ000566.json +++ b/resources/master_data/기계/EQ000566.json @@ -1,5 +1,6 @@ { "키": "EQ000566", + "비활성": true, "원문번호": "9030-0025", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000567.json b/resources/master_data/기계/EQ000567.json index b77ba95e0..2079853b7 100644 --- a/resources/master_data/기계/EQ000567.json +++ b/resources/master_data/기계/EQ000567.json @@ -1,5 +1,6 @@ { "키": "EQ000567", + "비활성": true, "원문번호": "9030-0035", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000568.json b/resources/master_data/기계/EQ000568.json index 9acfabab7..89ee33dfd 100644 --- a/resources/master_data/기계/EQ000568.json +++ b/resources/master_data/기계/EQ000568.json @@ -1,5 +1,6 @@ { "키": "EQ000568", + "비활성": true, "원문번호": "9030-0045", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000569.json b/resources/master_data/기계/EQ000569.json index 0133de0b2..b2bb05ddf 100644 --- a/resources/master_data/기계/EQ000569.json +++ b/resources/master_data/기계/EQ000569.json @@ -1,5 +1,6 @@ { "키": "EQ000569", + "비활성": true, "원문번호": "9030-0050", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000570.json b/resources/master_data/기계/EQ000570.json index 416b0aa32..4adc657f9 100644 --- a/resources/master_data/기계/EQ000570.json +++ b/resources/master_data/기계/EQ000570.json @@ -1,5 +1,6 @@ { "키": "EQ000570", + "비활성": true, "원문번호": "9030-0080", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000571.json b/resources/master_data/기계/EQ000571.json index 45d77d123..c805647e1 100644 --- a/resources/master_data/기계/EQ000571.json +++ b/resources/master_data/기계/EQ000571.json @@ -1,5 +1,6 @@ { "키": "EQ000571", + "비활성": true, "원문번호": "9030-0100", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000572.json b/resources/master_data/기계/EQ000572.json index a1241b24e..bbdbaeeb2 100644 --- a/resources/master_data/기계/EQ000572.json +++ b/resources/master_data/기계/EQ000572.json @@ -1,5 +1,6 @@ { "키": "EQ000572", + "비활성": true, "원문번호": "9030-0240", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000573.json b/resources/master_data/기계/EQ000573.json index 3658e92f4..c2cfb8f31 100644 --- a/resources/master_data/기계/EQ000573.json +++ b/resources/master_data/기계/EQ000573.json @@ -1,5 +1,6 @@ { "키": "EQ000573", + "비활성": true, "원문번호": "9040-0010", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000574.json b/resources/master_data/기계/EQ000574.json index f2c1d250c..74de70983 100644 --- a/resources/master_data/기계/EQ000574.json +++ b/resources/master_data/기계/EQ000574.json @@ -1,5 +1,6 @@ { "키": "EQ000574", + "비활성": true, "원문번호": "9040-0030", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000575.json b/resources/master_data/기계/EQ000575.json index c4defd972..3bb0c05a2 100644 --- a/resources/master_data/기계/EQ000575.json +++ b/resources/master_data/기계/EQ000575.json @@ -1,5 +1,6 @@ { "키": "EQ000575", + "비활성": true, "원문번호": "9040-0050", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000576.json b/resources/master_data/기계/EQ000576.json index 0ed3923d7..2657affa9 100644 --- a/resources/master_data/기계/EQ000576.json +++ b/resources/master_data/기계/EQ000576.json @@ -1,5 +1,6 @@ { "키": "EQ000576", + "비활성": true, "원문번호": "9040-0060", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000577.json b/resources/master_data/기계/EQ000577.json index 6316ad307..966029ef8 100644 --- a/resources/master_data/기계/EQ000577.json +++ b/resources/master_data/기계/EQ000577.json @@ -1,5 +1,6 @@ { "키": "EQ000577", + "비활성": true, "원문번호": "9040-0100", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000578.json b/resources/master_data/기계/EQ000578.json index 88b2288f9..d83eb9fb0 100644 --- a/resources/master_data/기계/EQ000578.json +++ b/resources/master_data/기계/EQ000578.json @@ -1,5 +1,6 @@ { "키": "EQ000578", + "비활성": true, "원문번호": "9040-0120", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000579.json b/resources/master_data/기계/EQ000579.json index 3f1d05daf..69edf1f64 100644 --- a/resources/master_data/기계/EQ000579.json +++ b/resources/master_data/기계/EQ000579.json @@ -1,5 +1,6 @@ { "키": "EQ000579", + "비활성": true, "원문번호": "9040-0200", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000580.json b/resources/master_data/기계/EQ000580.json index f51441e75..596389ef5 100644 --- a/resources/master_data/기계/EQ000580.json +++ b/resources/master_data/기계/EQ000580.json @@ -1,5 +1,6 @@ { "키": "EQ000580", + "비활성": true, "원문번호": "9040-0250", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000581.json b/resources/master_data/기계/EQ000581.json index 5b55ee87a..2c346868e 100644 --- a/resources/master_data/기계/EQ000581.json +++ b/resources/master_data/기계/EQ000581.json @@ -1,5 +1,6 @@ { "키": "EQ000581", + "비활성": true, "원문번호": "9040-0300", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000582.json b/resources/master_data/기계/EQ000582.json index 5dca2f855..7908f835a 100644 --- a/resources/master_data/기계/EQ000582.json +++ b/resources/master_data/기계/EQ000582.json @@ -1,5 +1,6 @@ { "키": "EQ000582", + "비활성": true, "원문번호": "9040-0380", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000583.json b/resources/master_data/기계/EQ000583.json index de40ef190..ec5b26e13 100644 --- a/resources/master_data/기계/EQ000583.json +++ b/resources/master_data/기계/EQ000583.json @@ -1,5 +1,6 @@ { "키": "EQ000583", + "비활성": true, "원문번호": "9040-0680", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000584.json b/resources/master_data/기계/EQ000584.json index 5e3ac32ba..01446a5fb 100644 --- a/resources/master_data/기계/EQ000584.json +++ b/resources/master_data/기계/EQ000584.json @@ -1,5 +1,6 @@ { "키": "EQ000584", + "비활성": true, "원문번호": "9050-0075", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000585.json b/resources/master_data/기계/EQ000585.json index 54bb26c36..8c75051fa 100644 --- a/resources/master_data/기계/EQ000585.json +++ b/resources/master_data/기계/EQ000585.json @@ -1,5 +1,6 @@ { "키": "EQ000585", + "비활성": true, "원문번호": "9050-0150", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000586.json b/resources/master_data/기계/EQ000586.json index cbded9bfa..822f22769 100644 --- a/resources/master_data/기계/EQ000586.json +++ b/resources/master_data/기계/EQ000586.json @@ -1,5 +1,6 @@ { "키": "EQ000586", + "비활성": true, "원문번호": "9050-0450", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000587.json b/resources/master_data/기계/EQ000587.json index d4b6f7df7..fae595627 100644 --- a/resources/master_data/기계/EQ000587.json +++ b/resources/master_data/기계/EQ000587.json @@ -1,5 +1,6 @@ { "키": "EQ000587", + "비활성": true, "원문번호": "9050-0750", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000588.json b/resources/master_data/기계/EQ000588.json index ebb241031..045a1c3a8 100644 --- a/resources/master_data/기계/EQ000588.json +++ b/resources/master_data/기계/EQ000588.json @@ -1,5 +1,6 @@ { "키": "EQ000588", + "비활성": true, "원문번호": "9050-0850", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000589.json b/resources/master_data/기계/EQ000589.json index 52f21345e..a3cbe5322 100644 --- a/resources/master_data/기계/EQ000589.json +++ b/resources/master_data/기계/EQ000589.json @@ -1,5 +1,6 @@ { "키": "EQ000589", + "비활성": true, "원문번호": "9060-0060", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000590.json b/resources/master_data/기계/EQ000590.json index c99745f7d..d553866eb 100644 --- a/resources/master_data/기계/EQ000590.json +++ b/resources/master_data/기계/EQ000590.json @@ -1,5 +1,6 @@ { "키": "EQ000590", + "비활성": true, "원문번호": "9060-0100", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000591.json b/resources/master_data/기계/EQ000591.json index 53d6ab138..6eb165972 100644 --- a/resources/master_data/기계/EQ000591.json +++ b/resources/master_data/기계/EQ000591.json @@ -1,5 +1,6 @@ { "키": "EQ000591", + "비활성": true, "원문번호": "9060-0200", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000592.json b/resources/master_data/기계/EQ000592.json index c6b56cab2..1b7c3aa36 100644 --- a/resources/master_data/기계/EQ000592.json +++ b/resources/master_data/기계/EQ000592.json @@ -1,5 +1,6 @@ { "키": "EQ000592", + "비활성": true, "원문번호": "9060-0300", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000593.json b/resources/master_data/기계/EQ000593.json index 9a7735a00..e03ef763d 100644 --- a/resources/master_data/기계/EQ000593.json +++ b/resources/master_data/기계/EQ000593.json @@ -1,5 +1,6 @@ { "키": "EQ000593", + "비활성": true, "원문번호": "9060-0500", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000594.json b/resources/master_data/기계/EQ000594.json index 178791708..3378f3682 100644 --- a/resources/master_data/기계/EQ000594.json +++ b/resources/master_data/기계/EQ000594.json @@ -1,5 +1,6 @@ { "키": "EQ000594", + "비활성": true, "원문번호": "9060-0600", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000595.json b/resources/master_data/기계/EQ000595.json index 0d96887c3..23ebb16ff 100644 --- a/resources/master_data/기계/EQ000595.json +++ b/resources/master_data/기계/EQ000595.json @@ -1,5 +1,6 @@ { "키": "EQ000595", + "비활성": true, "원문번호": "9070-0015", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000596.json b/resources/master_data/기계/EQ000596.json index c73656607..6bbc507eb 100644 --- a/resources/master_data/기계/EQ000596.json +++ b/resources/master_data/기계/EQ000596.json @@ -1,5 +1,6 @@ { "키": "EQ000596", + "비활성": true, "원문번호": "9070-0020", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000597.json b/resources/master_data/기계/EQ000597.json index 7f9c6e8b8..17c3fea70 100644 --- a/resources/master_data/기계/EQ000597.json +++ b/resources/master_data/기계/EQ000597.json @@ -1,5 +1,6 @@ { "키": "EQ000597", + "비활성": true, "원문번호": "9080-0050", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000598.json b/resources/master_data/기계/EQ000598.json index cd8495d6b..be15c22f9 100644 --- a/resources/master_data/기계/EQ000598.json +++ b/resources/master_data/기계/EQ000598.json @@ -1,5 +1,6 @@ { "키": "EQ000598", + "비활성": true, "원문번호": "9080-0080", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000599.json b/resources/master_data/기계/EQ000599.json index 4e6b9cbbd..e48844144 100644 --- a/resources/master_data/기계/EQ000599.json +++ b/resources/master_data/기계/EQ000599.json @@ -1,5 +1,6 @@ { "키": "EQ000599", + "비활성": true, "원문번호": "9080-0100", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000600.json b/resources/master_data/기계/EQ000600.json index 87e4ce69c..2f9f2101d 100644 --- a/resources/master_data/기계/EQ000600.json +++ b/resources/master_data/기계/EQ000600.json @@ -1,5 +1,6 @@ { "키": "EQ000600", + "비활성": true, "원문번호": "9080-0120", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000601.json b/resources/master_data/기계/EQ000601.json index b80b6bdc9..1c4ec6e42 100644 --- a/resources/master_data/기계/EQ000601.json +++ b/resources/master_data/기계/EQ000601.json @@ -1,5 +1,6 @@ { "키": "EQ000601", + "비활성": true, "원문번호": "9080-0150", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000602.json b/resources/master_data/기계/EQ000602.json index 8091e65ce..694f563c7 100644 --- a/resources/master_data/기계/EQ000602.json +++ b/resources/master_data/기계/EQ000602.json @@ -1,5 +1,6 @@ { "키": "EQ000602", + "비활성": true, "원문번호": "9080-0200", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000603.json b/resources/master_data/기계/EQ000603.json index 75c60f3a5..9bd3ec41f 100644 --- a/resources/master_data/기계/EQ000603.json +++ b/resources/master_data/기계/EQ000603.json @@ -1,5 +1,6 @@ { "키": "EQ000603", + "비활성": true, "원문번호": "9080-0300", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000604.json b/resources/master_data/기계/EQ000604.json index b115fd082..7f82076cf 100644 --- a/resources/master_data/기계/EQ000604.json +++ b/resources/master_data/기계/EQ000604.json @@ -1,5 +1,6 @@ { "키": "EQ000604", + "비활성": true, "원문번호": "9080-0500", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000605.json b/resources/master_data/기계/EQ000605.json index 9d16ad256..80f789c3e 100644 --- a/resources/master_data/기계/EQ000605.json +++ b/resources/master_data/기계/EQ000605.json @@ -1,5 +1,6 @@ { "키": "EQ000605", + "비활성": true, "원문번호": "9080-0700", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000606.json b/resources/master_data/기계/EQ000606.json index fdc11f01c..636ea1e3d 100644 --- a/resources/master_data/기계/EQ000606.json +++ b/resources/master_data/기계/EQ000606.json @@ -1,5 +1,6 @@ { "키": "EQ000606", + "비활성": true, "원문번호": "9080-1000", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000607.json b/resources/master_data/기계/EQ000607.json index 877cb8f8c..7b2a36d93 100644 --- a/resources/master_data/기계/EQ000607.json +++ b/resources/master_data/기계/EQ000607.json @@ -1,5 +1,6 @@ { "키": "EQ000607", + "비활성": true, "원문번호": "9080-1100", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000608.json b/resources/master_data/기계/EQ000608.json index d4be80869..f4848ca4e 100644 --- a/resources/master_data/기계/EQ000608.json +++ b/resources/master_data/기계/EQ000608.json @@ -1,5 +1,6 @@ { "키": "EQ000608", + "비활성": true, "원문번호": "9080-1400", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000609.json b/resources/master_data/기계/EQ000609.json index 6c9197fef..df3b22dca 100644 --- a/resources/master_data/기계/EQ000609.json +++ b/resources/master_data/기계/EQ000609.json @@ -1,5 +1,6 @@ { "키": "EQ000609", + "비활성": true, "원문번호": "9080-1500", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000610.json b/resources/master_data/기계/EQ000610.json index c4ab3d357..44ed09caa 100644 --- a/resources/master_data/기계/EQ000610.json +++ b/resources/master_data/기계/EQ000610.json @@ -1,5 +1,6 @@ { "키": "EQ000610", + "비활성": true, "원문번호": "9080-1750", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000611.json b/resources/master_data/기계/EQ000611.json index 2273100a2..51ec11398 100644 --- a/resources/master_data/기계/EQ000611.json +++ b/resources/master_data/기계/EQ000611.json @@ -1,5 +1,6 @@ { "키": "EQ000611", + "비활성": true, "원문번호": "9080-2000", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000612.json b/resources/master_data/기계/EQ000612.json index cb79bec9c..4314c063c 100644 --- a/resources/master_data/기계/EQ000612.json +++ b/resources/master_data/기계/EQ000612.json @@ -1,5 +1,6 @@ { "키": "EQ000612", + "비활성": true, "원문번호": "9080-3000", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000613.json b/resources/master_data/기계/EQ000613.json index 57e60801e..fa94dcc27 100644 --- a/resources/master_data/기계/EQ000613.json +++ b/resources/master_data/기계/EQ000613.json @@ -1,5 +1,6 @@ { "키": "EQ000613", + "비활성": true, "원문번호": "9090-0800", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000614.json b/resources/master_data/기계/EQ000614.json index 303e6693c..a1a7c5d0d 100644 --- a/resources/master_data/기계/EQ000614.json +++ b/resources/master_data/기계/EQ000614.json @@ -1,5 +1,6 @@ { "키": "EQ000614", + "비활성": true, "원문번호": "9090-1000", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000615.json b/resources/master_data/기계/EQ000615.json index 605f58ab4..8025d8c5f 100644 --- a/resources/master_data/기계/EQ000615.json +++ b/resources/master_data/기계/EQ000615.json @@ -1,5 +1,6 @@ { "키": "EQ000615", + "비활성": true, "원문번호": "9090-1200", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000616.json b/resources/master_data/기계/EQ000616.json index 40bec0836..c77d0b7a4 100644 --- a/resources/master_data/기계/EQ000616.json +++ b/resources/master_data/기계/EQ000616.json @@ -1,5 +1,6 @@ { "키": "EQ000616", + "비활성": true, "원문번호": "9090-1300", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000617.json b/resources/master_data/기계/EQ000617.json index 3501dc60e..6cf232d29 100644 --- a/resources/master_data/기계/EQ000617.json +++ b/resources/master_data/기계/EQ000617.json @@ -1,5 +1,6 @@ { "키": "EQ000617", + "비활성": true, "원문번호": "9090-1400", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000618.json b/resources/master_data/기계/EQ000618.json index ef18bced2..1fcea2b94 100644 --- a/resources/master_data/기계/EQ000618.json +++ b/resources/master_data/기계/EQ000618.json @@ -1,5 +1,6 @@ { "키": "EQ000618", + "비활성": true, "원문번호": "9090-1500", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/master_data/기계/EQ000619.json b/resources/master_data/기계/EQ000619.json index b0ba59898..de778e4e7 100644 --- a/resources/master_data/기계/EQ000619.json +++ b/resources/master_data/기계/EQ000619.json @@ -1,5 +1,6 @@ { "키": "EQ000619", + "비활성": true, "원문번호": "9090-1600", "원문": "건설품셈", "구분": "[90]해상장비", diff --git a/resources/tester/test_804_10_machine_option_names.py b/resources/tester/test_804_10_machine_option_names.py index 23b60eede..45a01fcb7 100644 --- a/resources/tester/test_804_10_machine_option_names.py +++ b/resources/tester/test_804_10_machine_option_names.py @@ -35,8 +35,11 @@ def test_기계_이름_표_문서_목록_전수() -> None: def test_옵션_부품_글만_바꿈() -> None: src = (ROOT / "A00_Common/formula_doc_options.ts").read_text(encoding="utf-8") - assert "known[x] ? `${known[x]} (${x})` : x" in src - assert "list.map((x) => ({ value: x, text: optionText(x) }))" in src + assert "known[x] ? `${known[x]} (${x})${off.has(x)" in src # 842-2 끈 기계 꼬리 + assert ( + 'liveOptions(list, String(now ?? "")).map((x) => ({ value: x, text: optionText(x) }))' + in src + ) assert "nameMachines(list, () => f.setOptions(items(), f.select.value));" in src api = (ROOT / "M02_MasterTemplete/DataFlow/M02_DF_Api.ts").read_text(encoding="utf-8") assert "machineNames ??= fetch(" in api # 한 번만 받음 diff --git a/resources/tester/test_842_2_machine_off.py b/resources/tester/test_842_2_machine_off.py new file mode 100644 index 000000000..00a072fed --- /dev/null +++ b/resources/tester/test_842_2_machine_off.py @@ -0,0 +1,118 @@ +"""842-2 기계 비활성 — 지킴 시험(쓰기는 임시 사본만). + +① 틀 검사 — 기계 줄 맨 위 칸 `비활성` = true 만 · 다른 그룹 줄 · false 는 오류 +② 저장 왕복 — M01 저장 길이 표지를 받고(그 대 파일 하나) 지우면 칸이 사라짐 · 셈 값 그대로 +③ 끈 기계는 찾기 · 고르기 · 잇기에서 안 나옴 — 요소 찾기 창 · 비슷한 기계 · 불러오기 기계 잇기 · + 목록 거름 「켜짐」 · 끈 원문번호 목록 · 셈(시간당)은 그대로 +""" + +from __future__ import annotations + +import copy +import shutil +import sys +from pathlib import Path + +import pytest + +from M01_MasterData import M01_MasterData_Store as store + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT / "resources" / "master_data" / "scripts")) +import master_machine_files as mmf # noqa: E402 + +from M01_MasterData import M01_MasterData_Machine as m01m # noqa: E402 +from M02_MasterTemplete import M02_Machine_Find as mfind # noqa: E402 +from M02_MasterTemplete import M02_Machine_Hourly as mh # noqa: E402 +from M02_MasterTemplete.DataFlow import M02_DF_Router as dfr # noqa: E402 + +REAL = store.FOLDER +cm, mk, M = store.cm, store.mk, mmf.NAME + + +@pytest.fixture +def master(tmp_path: Path, monkeypatch) -> Path: + for path in REAL.glob("*.json"): + if not path.name.startswith("_") or path.name == mk.BOOK.name: + shutil.copy(path, tmp_path / path.name) + shutil.copytree(REAL / mmf.DIR, tmp_path / mmf.DIR) + monkeypatch.setattr(store, "FOLDER", tmp_path) + return tmp_path + + +def _rows() -> list[dict]: + return store.read(M)[0]["줄"] + + +def _part(*changes: dict) -> dict: + return {"file": M, "version": store.read(M)[1], "changes": list(changes)} + + +# ① 틀 검사 ────────────────────────────────────────────────────────── +def test_form_check() -> None: + data = copy.deepcopy(store.read(M)[0]) + data["줄"] = data["줄"][:3] + assert cm.check_form(M, data) == [] + data["줄"][0][cm.OFF] = True + assert cm.check_form(M, data) == [] + data["줄"][0][cm.OFF] = False + assert any(cm.OFF in e for e in cm.check_form(M, data)) + labor = copy.deepcopy(store.read("인력.json")[0]) + labor["줄"] = labor["줄"][:1] + labor["줄"][0][cm.OFF] = True + assert any(cm.OFF in e for e in cm.check_form("인력.json", labor)) + + +# ② 저장 왕복 ─────────────────────────────────────────────────────── +def test_save_round_trip(master: Path) -> None: + key = next(r["키"] for r in _rows() if not r.get(cm.OFF) and r["이름"].startswith("불도저")) + row = copy.deepcopy(next(r for r in _rows() if r["키"] == key)) + before = mh.hourly(key) + snap = {p.name: p.read_bytes() for p in (master / mmf.DIR).glob("*.json")} + store.save([_part({"op": "edit", "key": key, "row": {**row, cm.OFF: True}})]) + after = {p.name: p.read_bytes() for p in (master / mmf.DIR).glob("*.json")} + assert {n for n in after if after[n] != snap[n]} == {f"{key}.json"} + got = next(r for r in _rows() if r["키"] == key) + assert got[cm.OFF] is True and got["값"] == row["값"] + assert mh.hourly(key) == before # 셈은 그대로(쓰던 단가산출 · 사본이 깨지지 않음) + assert key not in {x["ref"] for x in store.elements("기계", "불도저", 200)["items"]} + store.save([_part({"op": "edit", "key": key, "row": row})]) + assert (master / mmf.DIR / f"{key}.json").read_bytes() == snap[f"{key}.json"] + + +# ③ 찾기 · 고르기 · 잇기에서 뺌 ────────────────────────────────────── +def _off() -> list[dict]: + got = [r for r in _rows() if r.get(cm.OFF)] + if not got: + pytest.skip("끈 기계 없음") + return got + + +def test_hidden_everywhere() -> None: + off = _off() + keys = {r["키"] for r in off} + for r in off[:: max(1, len(off) // 6)]: + name = str(r["상세구분"] or r["이름"]).replace(" ", "") + assert not keys & {x["ref"] for x in store.elements("기계", name, 200)["items"]} + assert not keys & {x["키"] for x in m01m.find(name, 200)} + with mfind.m01_only(): + got = mfind.find(r["이름"], r.get("규격") or "") + assert got["키"] not in keys and not keys & {x["키"] for x in got["후보"]} + listed = store.rows(M, 1, 500, "", state="켜짐") + assert not keys & {r["키"] for r in listed["rows"]} + assert listed["total"] == len(_rows()) - len(keys) + assert store.rows(M, 1, 1, "")["total"] == len(_rows()) # 같이 보기 = 전부 + codes = {str(r["원문번호"]) for r in off} - { + str(r["원문번호"]) for r in _rows() if not r.get(cm.OFF) + } + assert set(dfr.get_machine_off()) == codes + assert all(c in dfr.get_machine_names() for c in codes) # 고른 값 글은 그대로 + + +def test_sea_machines_off() -> None: + """842-2 ㉣ 해상 기계([90]해상장비 = 선원류 칸 있는 대)는 끔 — 사용자가 다시 켤 수 있으므로 켠 대는 알림만.""" + sea = [r for r in _rows() if "해상" in str(r.get("구분"))] + assert len(sea) == 79 + on = [r["키"] for r in sea if not r.get(cm.OFF)] + if on: + pytest.skip(f"다시 켠 해상 기계 {len(on)} 대 — 사용자 판단") diff --git a/ui_template/ui_template_locale_machine.ts b/ui_template/ui_template_locale_machine.ts index 3ac2833a4..4bf5609e8 100644 --- a/ui_template/ui_template_locale_machine.ts +++ b/ui_template/ui_template_locale_machine.ts @@ -49,6 +49,8 @@ export const ui_locales_machine = { M01_MachineNew: ["새 기계", "New machine"], M01_MachineBack: ["목록으로", "Back to list"], M01_MachineHourly: ["시간당 경비", "Hourly cost"], + M01_MachineUse: ["사용", "Active"], + M01_MachineShowOff: ["비활성 같이 보기", "Show inactive"], M01_MachineMeta: ["원문 · 구분", "Source · group"], M01_MachineUses: ["쓰는 곳", "Used by"], M01_MachineNoUses: ["쓰는 곳 없음", "Not used"],