Merge remote-tracking branches 'origin/main_desktop_1', 'origin/sub_desktop_1' and 'origin/sub_laptop_1' into sub_laptop_2
This commit is contained in:
@@ -166,15 +166,25 @@ def subs(file: str = "", group: str = "") -> dict:
|
||||
)
|
||||
)
|
||||
|
||||
heads = data.get(slot) or {}
|
||||
if heads:
|
||||
subs_list = [
|
||||
{"name": name, "book": head.get("원문"), "details": details_of(name, head)}
|
||||
for name, head in heads.items()
|
||||
]
|
||||
else:
|
||||
# 머리에 구분 묶음이 등록 안 된 파일(재료_자재품목) — 줄에서 바로 모음
|
||||
subs_list = [
|
||||
{"name": name, "book": None, "details": details_of(name, {})}
|
||||
for name in dict.fromkeys(r["구분"] for r in lines if r.get("구분"))
|
||||
]
|
||||
|
||||
return {
|
||||
"file": file,
|
||||
"version": version,
|
||||
"slot": slot,
|
||||
"states": list(_STATES) if has_state else [],
|
||||
"subs": [
|
||||
{"name": name, "book": head.get("원문"), "details": details_of(name, head)}
|
||||
for name, head in (data.get(slot) or {}).items()
|
||||
],
|
||||
"subs": subs_list,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ export interface FilterArgs {
|
||||
const MATERIAL_NAMES: Record<string, string> = { 유가전력: "유가·전력" };
|
||||
/** 재료 컨테이너 차례 — 여기 없는 파일은 뒤에 */
|
||||
const FUEL = "유가전력";
|
||||
const MATERIAL = "자재품목";
|
||||
const MATERIAL_ORDER = ["자재품목", "유가전력", "품셈재료"];
|
||||
|
||||
/** 파일 이름 → 목록 글자 — 「소요량_건설품셈_10장_창호…」 → 「건설품셈_10장_창호…」 */
|
||||
@@ -138,6 +139,8 @@ export function buildSide(
|
||||
const buttons = new Map<string, HTMLElement>();
|
||||
// 하위 거름은 서버가 준 목록(파일 머리에 등록된 구분·세부분류) — 새 조사가 늘어도 화면은 그대로
|
||||
const kinds = new Map<Group, SubInfo[]>();
|
||||
/** 재료 그룹 안 파일별 구분 목록(자재품목·유가전력 각자) — file 이름이 열쇠 */
|
||||
const materialKinds = new Map<string, SubInfo[]>();
|
||||
const states = new Map<Group, string[]>();
|
||||
const runs = new Map<string, () => void>();
|
||||
let restoring = false;
|
||||
@@ -311,16 +314,16 @@ export function buildSide(
|
||||
.flatMap((f) => {
|
||||
const name = fileLabel(f.file);
|
||||
const label = group === "재료" ? (MATERIAL_NAMES[name] ?? name) : name;
|
||||
if (group === "재료" && name === FUEL)
|
||||
if (group === "재료" && (name === FUEL || name === MATERIAL))
|
||||
return [
|
||||
filter({
|
||||
id: `${group}\n${f.file}`,
|
||||
store: `m01.filter.${group}.${name}`,
|
||||
subs: kinds.get(group) ?? [],
|
||||
subs: materialKinds.get(f.file) ?? [],
|
||||
total: f.rows,
|
||||
title: label,
|
||||
subLabel: L("M01_FuelSub"),
|
||||
detailLabel: L("M01_FuelDetail"),
|
||||
subLabel: name === FUEL ? L("M01_FuelSub") : L("M01_LaborSub"),
|
||||
detailLabel: name === FUEL ? L("M01_FuelDetail") : L("M01_LaborDetail"),
|
||||
onPick: (sub, detail, tail) =>
|
||||
open(f, sub, sub || detail ? `${label} · ${tail}` : label, detail),
|
||||
}),
|
||||
@@ -348,7 +351,10 @@ export function buildSide(
|
||||
states.set(group as Group, got.states ?? []);
|
||||
} else if (group === "재료") {
|
||||
const fuel = list.find((f) => fileLabel(f.file) === FUEL);
|
||||
if (fuel) kinds.set(group, (await fetchSubsAll({ file: fuel.file })).subs);
|
||||
if (fuel) materialKinds.set(fuel.file, (await fetchSubsAll({ file: fuel.file })).subs);
|
||||
const material = list.find((f) => fileLabel(f.file) === MATERIAL);
|
||||
if (material)
|
||||
materialKinds.set(material.file, (await fetchSubsAll({ file: material.file })).subs);
|
||||
} else if (group === "소요량" || group === "계수") {
|
||||
kinds.set(group, (await fetchSubsAll({ group })).subs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# 「시험입력」 칸 검증 (읽기 전용) — 틀린 것만
|
||||
|
||||
대상: sub1 커밋(로직 65줄에 시험 계산 전용 「시험입력」 칸 추가). 아래는 확인 중 어긋난 것만 적음 — 65개 중 맞는 것은 안 적음.
|
||||
|
||||
## ① 값 확인 — 표에 있는지 · 원문 첫 값인지
|
||||
|
||||
**확정 오류 1건**
|
||||
|
||||
- `GC000724` 스테인리스 강관 용접접합(원문번호 1-3-1) — 시험입력 `규격=65.0`.
|
||||
원문(건설품셈 기계설비 1-3-1) 표 첫 값은 **ø6**(둘째 값이 65) — 표 `QC001403`에도 6이 첫 줄. 65는 표에 있는 값이라 계산은 안 멈추지만 「원문 절 첫 값」 규칙에 어긋남 — `6.0`으로 고칠 것.
|
||||
|
||||
**범위형 표에서 "첫 구간의 아래끝" 대신 "위끝"을 씀(기능은 맞으나 문자 그대로 첫 값은 아님) — 11건**
|
||||
|
||||
규격·직경 입력이 걸리는 소요량표가 `[아래끝,위끝]` 범위 줄(예: `QC001418` 규격 80~150)인 경우, 시험입력이 첫 구간 안에는 드나 아래끝이 아니라 위끝을 씀:
|
||||
|
||||
- `GC000742`(규격=150, 원문 첫 구간 80~150 — 아래끝 80) · `GC000769`(25, 구간 15~25) · `GC000772`(25, 구간 20~25) · `GC000773`(25, 구간 15~25) · `GC000774`(25, 구간 15~25) · `GC000775`·`GC000776`·`GC000778`(15, 구간 13~15) · `GF000226`·`GF000227`·`GF000228`·`GF000229`·`GF000230`(직경=60, 구간 40~60)
|
||||
|
||||
값 자체는 첫 구간을 정확히 집어 계산은 맞게 도나, "표 첫 값"을 문자 그대로 읽으면 아래끝이 맞음 — 일관성만 다름(급하지 않음).
|
||||
|
||||
**돌 종류를 고르기 첫 값이 아닌 걸로 override — 근거 있음, 오류 아님**
|
||||
|
||||
- `GF000219` 돌쌓기 메쌓기 — `돌="깬잡석"`(고르기 목록 3번째, 첫 값은 "견치돌"). 그 줄 비고에 "원문에 없는 조합: 뒷길이=25·돌=견치돌…" 이 적혀 있어 — 기본값 조합이 애초 표(QF000421)에 없어서 일부러 돌린 것으로 보임. 오류로 안 침.
|
||||
|
||||
## ② 시험입력 칸이 정본 계산에 새는지 — 코드로 확인, 안 샘
|
||||
|
||||
`시험입력` 문자열을 코드 전체에서 찾은 결과 `resources/master_data/scripts/check_master.py` 의 `시험입력()` 함수(576~588행)와 `calc_all()`(계산전부 모드 전용, 599행)에서만 읽음. `master_formula.run()` · M01 API(`M01_MasterData_Store.py`) · 화면 계산 경로 어디에도 이 칸을 읽는 코드가 없음 — 정본 계산(사람이 화면에서 값을 넣는 경로)에는 안 샘. 이미 `resources/tester/test_masterdata_check.py::test_시험입력이_기본값을_이김` 이 이 동작을 못박아 둠.
|
||||
|
||||
## ③ 계산전부 남은 멈춤 84 — sub1 보고와 갈래가 다름
|
||||
|
||||
지금 다시 돌린 `check_master.py 계산전부` 결과: **통과 1272 · 멈춤 82**(sub1 보고 84와 다름 — 2건 차이).
|
||||
|
||||
갈래별 재분류(에러 문구 기준):
|
||||
|
||||
| 갈래 | 지금 실수 | sub1 보고 | 같은지 |
|
||||
|---|---|---|---|
|
||||
| 관리자 값 미확보(`값 없음 — 관리자가 채울 값`) | 52 | 65 | **다름** |
|
||||
| 품셈재료 규격 미지정(`후보 여럿 — 규격 선택 필요`) | 13 | 13 | 같음 |
|
||||
| 재료 고르기 후보 없음(`후보 없음 — {조건}`) | 6 | (보고에 없는 갈래) | **다름** |
|
||||
| 지역(`지역 값 없음`) | 6 | 1 | **다름** |
|
||||
| 표 조합(`맞는 줄 0개`) | 5 | 5 | 같음 |
|
||||
| 합계 | 82 | 84 | **다름** |
|
||||
|
||||
- 「품셈재료 규격 미지정」·「표 조합」 두 갈래는 사람 수(13·5)까지 정확히 맞음.
|
||||
- 「관리자 값 미확보」는 sub1 보고보다 13건 적음 — sub1이 「재료 고르기 후보 없음」(사람 6개, 조건 자체가 자재품목에 아예 없는 경우)을 같은 갈래로 합쳐 세었을 가능성(52+6=58, 그래도 65에는 7 모자람 — 완전히는 안 맞음).
|
||||
- 「지역」은 sub1 보고(1건)보다 5건 많음 — 원인을 뜯어보니:
|
||||
- `GF000183`(자재지역=울진로 시험입력 들어 있음)은 **모래(MP000004) 자체가 시장가(재료_자재품목.json)에 없음**(전국 통틀어 "모래"가 이름에 든 줄이 "모래적사장(FRP)" 저장조 1건뿐 — 실제 모래 자재 없음) — 지역을 울진으로 두든 포항으로 두든 이 재료는 늘 멈춤. sub1 보고의 「지역 1」은 아마 이 줄을 가리킨 것으로 보임.
|
||||
- `GC000933`·`GC000934`·`GC000938`·`GF000176` 4줄은 **애초 이번 65개 시험입력 패치에 안 들어 있음** — 자재지역 입력을 요구하는 로직인데 시험입력이 없어 기본값(고르기·범위 없는 입력의 시험 기본 1)이 지역 값으로 새어 들어가 `지역 값 없음 — 1` 로 멈춤. 패치 커버리지가 빠진 자리 — sub1 보고에 안 셈.
|
||||
- 참고: `GC000211`·`GC000677`·`GC000685`(모래를 쓰지만 자재지역=포항 시험입력 있음)는 그 모래 수량식이 기본 입력에서 0으로 떨어져 걸리지 않고 통과함 — 모래 데이터가 없다는 근본 문제는 이 세 줄에도 그대로 있으나 지금 표본 입력으로는 안 드러남.
|
||||
- 레미콘(MP000001) 지역픽은 울진 후보 19개가 있어 지역 자체는 문제 없음 — 위 「후보 여럿」 갈래(규격 미지정 13건)에 걸리는 것이 레미콘 쪽 진짜 원인.
|
||||
|
||||
## 확인 범위
|
||||
|
||||
- ①은 65개 전수 확인(표 참조 자동 추출 + 원문 md 대조), 자재지역 계열은 연결된 재료·시장가 존재 여부까지 확인.
|
||||
- ②는 코드 전수 grep + 기존 시험 1건 확인.
|
||||
- ③은 지금 이 순간의 `계산전부` 재실행 결과와 sub1 커밋 메시지 문구를 비교 — sub1이 어떤 스크립트·표본으로 84를 셌는지 원문(스크립트)이 저장소에 없어 재현은 못함.
|
||||
@@ -0,0 +1,59 @@
|
||||
# 관리자가 채울 재료 값 (읽기 전용 · 자동 생성)
|
||||
|
||||
일괄 시험 계산(`check_master 계산전부`)이 「값 없음 — 관리자가 채울 값」 으로 멈춘 자리 — 재료 45 종 · 로직 56 개.
|
||||
|
||||
값을 어디서 가져올지(자재품목 줄 잇기 · 시중물가)는 관리자 몫 — 여기서는 이름만 모음.
|
||||
|
||||
| 키 | 이름 | 막힌 로직 수 | 로직 키 |
|
||||
|---|---|---|---|
|
||||
| MP000253 | 코크스 | 3 | GC000931 · GC000935 · GC000936 |
|
||||
| MP000290 | Nozzle | 3 | GC000933 · GC000934 · GC000938 |
|
||||
| MP000293 | 세유 | 3 | GC000939 · GC000986 · GC000993 |
|
||||
| MP000048 | JOINT FILLER | 2 | GF000197 · GF000208 |
|
||||
| MP000094 | 쉬즈관 | 2 | GC000230 · GC000237 |
|
||||
| MP000216 | 철구(Shot ball) | 2 | GC000375 · GC000822 |
|
||||
| MP000299 | 탄소봉 | 2 | GC000941 · GC000942 |
|
||||
| MP000359 | 중유 | 2 | GC000943 · GC000948 |
|
||||
| MP000023 | VR관(소켓식) | 1 | GF000173 |
|
||||
| MP000052 | 스페이셔(몰탈 블록) | 1 | GF000200 |
|
||||
| MP000055 | 스티로폴 | 1 | GF000202 |
|
||||
| MP000060 | 콘크리트 표면 강화재(하드너) | 1 | GF000209 |
|
||||
| MP000065 | 틈메우기돌 | 1 | GF000223 |
|
||||
| MP000066 | 철망태(사각형 돌망태) | 1 | GF000235 |
|
||||
| MP000070 | 깃발 | 1 | GF000081 |
|
||||
| MP000076 | 피복제 | 1 | GC000145 |
|
||||
| MP000082 | 에폭시 | 1 | GC000337 |
|
||||
| MP000095 | BASECHANNEL | 1 | GC000001 |
|
||||
| MP000113 | 축중계(이동식) | 1 | GC000003 |
|
||||
| MP000129 | 보호막 | 1 | GC000061 |
|
||||
| MP000134 | 모래주머니 | 1 | GC000181 |
|
||||
| MP000144 | 보조강재 | 1 | GC000559 |
|
||||
| MP000150 | 질석 | 1 | GC000573 |
|
||||
| MP000169 | 정배지 | 1 | GC000618 |
|
||||
| MP000172 | 알루미늄핀 | 1 | GC000623 |
|
||||
| MP000176 | 표준보강메시 | 1 | GC000628 |
|
||||
| MP000177 | 고강도메시 | 1 | GC000629 |
|
||||
| MP000201 | 실리콘 | 1 | GC000752 |
|
||||
| MP000202 | IV전선 | 1 | GC000409 |
|
||||
| MP000209 | 버너 | 1 | GC000360 |
|
||||
| MP000211 | 테르밋용재 | 1 | GC000361 |
|
||||
| MP000215 | 용접봉 | 1 | GC000374 |
|
||||
| MP000218 | 철편(Grit) | 1 | GC000376 |
|
||||
| MP000235 | 슈 | 1 | GC000433 |
|
||||
| MP000239 | 베인 전용로드 | 1 | GC000435 |
|
||||
| MP000241 | 표준사 | 1 | GC000436 |
|
||||
| MP000242 | 단독콘 | 1 | GC000438 |
|
||||
| MP000250 | Lagging Sheet | 1 | GC000901 |
|
||||
| MP000269 | 세유 | 1 | GC000932 |
|
||||
| MP000294 | 전기용접 | 1 | GC000940 |
|
||||
| MP000310 | Tar Epoxy | 1 | GC000944 |
|
||||
| MP000314 | drill | 1 | GC000947 |
|
||||
| MP000319 | Tar Epoxy | 1 | GC000950 |
|
||||
| MP000357 | 카트리지 | 1 | GC000646 |
|
||||
| MP000363 | 아스팔트싱글 | 1 | GC000654 |
|
||||
|
||||
## 값 말고 다른 까닭으로 남은 멈춤 (손대지 않음)
|
||||
|
||||
- 레미콘 규격 미지정 14 — 원문(산림 12장 · 13장 · 건설 7-3-1)이 강도·슬럼프를 밝히지 않고 「무근 · 철근」 만 적음 · 규격은 설계 확정 거리.
|
||||
- 단위 환산 필요 4 — 가새 「조」 · 스레트실테이프 「㎝」 두 줄 · 철재 거푸집 「본」. `ref/_단위_환산_원문.md` 에 값 없음(또는 범위값)이라 그대로 둠.
|
||||
- 모래 「울진」 줄 없음 1(GF000183) — 자재품목에 그 지역 모래 줄이 없음.
|
||||
@@ -240,7 +240,7 @@
|
||||
"종류": "재료",
|
||||
"요소": {"구분": "거푸집·가설재", "상세구분": "가설건축물"},
|
||||
"이름": "콘테이너형 가설건축물 3.0x3.0m",
|
||||
"단위": "개",
|
||||
"단위": "동",
|
||||
"수량": "만약(규모 == '3.0x3.0m', 손율 / 100, 0)",
|
||||
"비목": "재료비"
|
||||
},
|
||||
@@ -248,7 +248,7 @@
|
||||
"종류": "재료",
|
||||
"요소": {"구분": "거푸집·가설재", "상세구분": "가설건축물"},
|
||||
"이름": "콘테이너형 가설건축물 3.0x6.0m",
|
||||
"단위": "개",
|
||||
"단위": "동",
|
||||
"수량": "만약(규모 == '3.0x6.0m', 손율 / 100, 0)",
|
||||
"비목": "재료비"
|
||||
},
|
||||
@@ -256,7 +256,7 @@
|
||||
"종류": "재료",
|
||||
"요소": {"구분": "거푸집·가설재", "상세구분": "가설건축물"},
|
||||
"이름": "콘테이너형 가설건축물 3.0x9.0m",
|
||||
"단위": "개",
|
||||
"단위": "동",
|
||||
"수량": "만약(규모 == '3.0x9.0m', 손율 / 100, 0)",
|
||||
"비목": "재료비"
|
||||
}
|
||||
|
||||
@@ -1557,6 +1557,7 @@
|
||||
"출처": "건설품셈 공통 5-1-9",
|
||||
"소유": "공용",
|
||||
"비고": "지층별 굴착연장 입력(없는 층 0) · 한 비트로 전 층 · 해석: 개량형·해머비트는 해머비트 압축기(대수 입력) · 오거(케이싱)는 케이싱 쓸 때 · 굴착기 = 굴착기(무한궤도) · 해머비트 손료 · 펌프차 별도 · 부속장비·소모자재 = 인력편성 노무비 × 요율 · 해석: 소모자재 손료 비목 = 재료비 · 해석: 편성 인력 × 작업소요시간 ÷ 1일 8시간 = 인 · 편성 기계 × 작업소요시간 = 시간(건설품셈 공통 1-1) · 「원문에 없는 조합: 비트=오거비트 · 말뚝직경=500∼600 · 말뚝길이=10m미만 / 비트=오거비트 · 말뚝직경=500∼600 · 말뚝길이=10~20m / 비트=오거비트 · 말뚝직경=500∼600 · 말뚝길이=20m~30m / 비트=개량형비트 · 말뚝직경=500이상 · 말뚝길이=10m미만 / 비트=개량형비트 · 말뚝직경=500이상 · 말뚝길이=10~20m 외 10」",
|
||||
"시험입력": {"혼합층연장": 0, "연암연장": 0, "경암연장": 0},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "비트",
|
||||
@@ -3534,6 +3535,7 @@
|
||||
"출처": "건설품셈 공통 5-3-1",
|
||||
"소유": "공용",
|
||||
"비고": "직경 400∼800 · t_3 원문 글(케이싱 미사용 5 · 사용 8분)을 식에 적음 · t_5 는 천공홀 직접 용접 때만 · 해석: 개량형·해머비트는 해머비트 압축기 · 굴착기 = 굴착기(무한궤도) · 말뚝 재료 · 서비스케이싱 · 해머비트 손료 별도 · 해석: 소모자재 손료 비목 = 재료비 · 해석: 편성 인력 × 작업소요시간 ÷ 1일 8시간 = 인 · 편성 기계 × 작업소요시간 = 시간(건설품셈 공통 1-1) · 「원문에 없는 조합: 비트=오거비트 · 말뚝길이=10m미만 · 직경=400 · 기초=도로/철도 교량기초 / 비트=오거비트 · 말뚝길이=10m미만 · 직경=400 · 기초=건축기초 / 비트=오거비트 · 말뚝길이=10m미만 · 직경=450 · 기초=도로/철도 교량기초 / 비트=오거비트 · 말뚝길이=10m미만 · 직경=450 · 기초=건축기초 / 비트=오거비트 · 말뚝길이=10m미만 · 직경=500 · 기초=도로/철도 교량기초 외 67」",
|
||||
"시험입력": {"혼합층연장": 0, "연암연장": 0, "경암연장": 0},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "직경",
|
||||
@@ -4078,6 +4080,7 @@
|
||||
"출처": "건설품셈 공통 5-3-2",
|
||||
"소유": "공용",
|
||||
"비고": "항타가 필요하면 5-3-1 t_3 참고 · 해머비트 손료 별도 · 해석: 개량형·해머비트는 해머비트 압축기 · 해석: 편성 인력 × 작업소요시간 ÷ 1일 8시간 = 인 · 편성 기계 × 작업소요시간 = 시간(건설품셈 공통 1-1) · 해석: 소모자재 손료 비목 = 재료비",
|
||||
"시험입력": {"혼합층연장": 0, "연암연장": 0, "경암연장": 0},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "비트",
|
||||
@@ -4713,6 +4716,7 @@
|
||||
"출처": "건설품셈 공통 5-3-5",
|
||||
"소유": "공용",
|
||||
"비고": "T 단위 시간(hr) · 공법 R.C.D 는 올케이싱 굴착 뒤 후속 굴착 · 케이싱·비트 손료 별도 · 극경암은 천공시간 증 · 해석: 크레인 = 크레인(타이어) · 해석: 소모자재 손료 비목 = 재료비 · 해석: 편성 인력 × 작업소요시간 ÷ 1일 8시간 = 인 · 편성 기계 × 작업소요시간 = 시간(건설품셈 공통 1-1)",
|
||||
"시험입력": {"점질토연장": 0, "사질토연장": 0, "자갈연장": 0, "연암연장": 0, "경암연장": 0},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "공법",
|
||||
|
||||
@@ -8468,6 +8468,7 @@
|
||||
"출처": "건설품셈 기계설비 13-6-3",
|
||||
"소유": "공용",
|
||||
"비고": "소모자재는 원문 참고표 Tainter 칸 · 공정별 품의 합(ton당) · 검사 · 교정은 기술관리, 도장을 뺀 품의 10%(원문 줄) — 각 직종에 더함 · 해석: 원문 「〃」 · 「수량」 칸 = 앞 직종(플랜트제관공) · 해석: 목공 = 건축목공 · 「건설기계운전조 · Crane운전조」 = 건설기계운전사 · 「윈치운전조」 = 일반기계운전사(조 = 1인) · 건설노임에 없는 직종(기계기사 · 측량사 · 마킹공 등)은 인력_자체(값은 관리자가 채움) · 막힘: 장비 중 기계 목록에 없는 것 — Lathe 365.76㎝×5.60㎾ · Planer 121.92㎝×243.84㎝ · Boring machine Horizontal Type 2.24㎾ · Gouging machine 중형 · Gas cutting machine Auto형 · Gas cutting machine Mannual · Gas heating touch 중형 · Over head crane 30ton · Over head crane 20ton · Hydro Press 300ton · Bending roller 701.04㎝ · Edge bending roller 701.04㎝ · Shearing machine · Drilling machine 2.24㎾ · Drilling machine Radial 3.73㎾ · Portable drill 0.73㎾ — 그 줄 빠짐",
|
||||
"시험입력": {"자재지역": "포항"},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "전력 계약종별",
|
||||
@@ -8780,6 +8781,7 @@
|
||||
"출처": "건설품셈 기계설비 13-6-3",
|
||||
"소유": "공용",
|
||||
"비고": "소모자재는 원문 참고표 Roller 칸 · 공정별 품의 합(ton당) · 검사 · 교정은 기술관리, 도장을 뺀 품의 10%(원문 줄) — 각 직종에 더함 · 해석: 원문 「〃」 · 「수량」 칸 = 앞 직종(플랜트제관공) · 해석: 목공 = 건축목공 · 「건설기계운전조 · Crane운전조」 = 건설기계운전사 · 「윈치운전조」 = 일반기계운전사(조 = 1인) · 건설노임에 없는 직종(기계기사 · 측량사 · 마킹공 등)은 인력_자체(값은 관리자가 채움) · 막힘: 장비 중 기계 목록에 없는 것 — Lathe 365.76㎝×5.60㎾ · Planer 121.92㎝×243.84㎝ · Boring machine Horizontal Type 2.24㎾ · Gouging machine 중형 · Gas cutting machine Auto 중형 · Gas cutting machine Mannual · Gas heating touch 중형 · over head crane 30 ton · Hydro Press 100 ton · Bending roller 701.04㎝ · Shearing machine · Drilling machine 2.24㎾ · Drilling machine Radial 3.73㎾ · Portable drill 0.373㎾ — 그 줄 빠짐",
|
||||
"시험입력": {"자재지역": "포항"},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "전력 계약종별",
|
||||
@@ -9989,6 +9991,7 @@
|
||||
"출처": "건설품셈 기계설비 13-6-6",
|
||||
"소유": "공용",
|
||||
"비고": "공정별 품의 합(ton당) · 검사 · 교정은 기술관리, 도장, 전원배선을 뺀 품의 10%(원문 줄) — 각 직종에 더함 · 해석: 원문 「〃」 · 「수량」 칸 = 앞 직종(플랜트제관공) · 해석: 목공 = 건축목공 · 「건설기계운전조 · Crane운전조」 = 건설기계운전사 · 「윈치운전조」 = 일반기계운전사(조 = 1인) · 건설노임에 없는 직종(기계기사 · 측량사 · 마킹공 등)은 인력_자체(값은 관리자가 채움) · 막힘: 장비 중 기계 목록에 없는 것 — Gas Cutting machine 중형 · Portable Drill 1.12㎾ · Portable Grinder 0.37㎾ · Guy Derrick 10 ton · Truck 5 ton · Angle Griner 0.37 ㎾ — 그 줄 빠짐",
|
||||
"시험입력": {"자재지역": "포항"},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "전력 계약종별",
|
||||
@@ -12129,10 +12132,11 @@
|
||||
"종류": "재료",
|
||||
"요소": {"구분": "잡재료", "상세구분": "용접·가스"},
|
||||
"이름": "전기용접봉",
|
||||
"단위": "㎾h",
|
||||
"수량": "595",
|
||||
"단위": "㎏",
|
||||
"수량": "22.5",
|
||||
"비목": "재료비",
|
||||
"출처": "건설품셈 기계설비 13-6-13"
|
||||
"출처": "건설품셈 기계설비 13-6-13",
|
||||
"비고": "원문 소모자재 표 「용접 전기용접봉 22.5㎏」 · 같은 표의 「전력 595㎾h」 는 별도 계상(전력 계약종별 입력 자리 없음)"
|
||||
}
|
||||
],
|
||||
"덧줄": [],
|
||||
|
||||
@@ -1887,6 +1887,7 @@
|
||||
"출처": "산림품셈 12-11-2 1",
|
||||
"소유": "공용",
|
||||
"비고": "흄관 별산(원문 비고)이나 수량이 있어 줄로 얹음 · 기초콘크리트·거푸집 설계수량",
|
||||
"시험입력": {"자재지역": "포항"},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "관경",
|
||||
@@ -2118,6 +2119,7 @@
|
||||
"출처": "산림품셈 12-11-3",
|
||||
"소유": "공용",
|
||||
"비고": "파형강관 별산(원문 비고)이나 수량이 있어 줄로 얹음 · 6m 직관 10% 감액(주②)은 모래 문장에 붙어 있어 대상 불명 — 미반영",
|
||||
"시험입력": {"자재지역": "포항"},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "관경",
|
||||
|
||||
@@ -592,6 +592,7 @@
|
||||
"출처": "산림품셈 13-5-1",
|
||||
"소유": "공용",
|
||||
"비고": "해석: 채움 콘크리트 = 레디믹스트콘크리트 · 해석: 돌 이름을 채움·고임돌 표 종별로 맞춤(조약돌·호박돌 및 야면석 → 야면석 · 채움은 호박돌) · 줄눈 모르타르는 원문대로 메붙임에도 얹음 · 뒷길이 70 은 찾기 실패 — 원문 표에 70 없음 · 「원문에 없는 조합: 뒷길이=25 · 붙임=메붙임 · 돌=깬돌 / 뒷길이=25 · 붙임=메붙임 · 돌=호박돌 및 야면석 / 뒷길이=25 · 붙임=찰붙임 · 돌=깬돌 / 뒷길이=25 · 붙임=찰붙임 · 돌=조약돌 및 야면석 / 뒷길이=30 · 붙임=메붙임 · 돌=호박돌 및 야면석 외 17」",
|
||||
"시험입력": {"뒷길이": 30, "붙임": "메붙임", "돌": "깬돌"},
|
||||
"입력": [
|
||||
{
|
||||
"이름": "뒷길이",
|
||||
|
||||
@@ -362,7 +362,11 @@ def test_구분_목록(client: TestClient) -> None:
|
||||
assert machine["slot"] == "구분" and names[0] == "[00]토공기계" and names[-1] == "임업기계"
|
||||
earthwork = next(s for s in machine["subs"] if s["name"] == "[00]토공기계")
|
||||
assert earthwork["book"] == "건설품셈" and "불도저" in earthwork["details"]
|
||||
assert _get(client, "/api/m01/subs", file="재료_자재품목.json")["subs"] == []
|
||||
material = _get(client, "/api/m01/subs", file="재료_자재품목.json")
|
||||
material_names = [s["name"] for s in material["subs"]]
|
||||
assert "기계·설비" in material_names
|
||||
steel = next(s for s in material["subs"] if s["name"] == "철근·강재")
|
||||
assert steel["details"]
|
||||
|
||||
|
||||
def test_못_이은_줄만_거름(client: TestClient) -> None:
|
||||
|
||||
@@ -913,7 +913,7 @@ def test_로직_일괄_시험계산():
|
||||
"""로직 전부를 시험 입력으로 돌림 — 멈춤은 데이터 결손(관리자 값·규격 미지정)만."""
|
||||
files = cm.load()
|
||||
passed, stuck = cm.calc_all(files, mf.Master(files))
|
||||
assert passed >= 1272
|
||||
assert passed >= 1279
|
||||
남은_까닭 = (
|
||||
"관리자가 채울 값",
|
||||
"규격 선택 필요",
|
||||
@@ -984,3 +984,10 @@ def test_테스트_대상_로직_입력에_설명(whole):
|
||||
assert specs, key
|
||||
빈칸 = [s["이름"] for s in specs if not str(s.get("설명") or "").strip()]
|
||||
assert 빈칸 == [], (key, 빈칸)
|
||||
|
||||
|
||||
def test_표_조건_조합이_없어_멈추지_않음():
|
||||
"""표에 없는 조합(오거비트 혼합층 등)으로는 시험 계산을 돌리지 않음 — 「맞는 줄 0개」 0건."""
|
||||
files = cm.load()
|
||||
_, stuck = cm.calc_all(files, mf.Master(files))
|
||||
assert [x for x in stuck if "맞는 줄" in x] == []
|
||||
|
||||
Reference in New Issue
Block a user