feat(786-1): 별도계상 줄 품목 고르기 없앰 — 후보 고정 줄 하나 · SC 합 밖 고정 줄
- Row.judge: 별도계상 줄은 M01 · 사전 · 장부 후보 안 찾고 고정 줄 하나(품목 「프로젝트에서」 표지) · 갈래 수 그대로 - Make: 별도계상 고정 줄 = 단가 0 · 메모 「별도계상 · 품목은 프로젝트에서」(합 밖) - Picks.ts: apartPick 표지 셈 - 시험 642_3 · 642_5 · 642_6 Picks 몫을 새 꼴로 고침(옛 단언: 레미콘 자재 목록 별도계상 칸) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
SC(`M02_Hopyo_Build.Builder` 가 줄 차례 · 확인 안 한 줄 = 모두 고정 길 그대로) — 한 엑셀 줄 = 고른 것마다
|
||||
우리 줄(같은 별칭 = 엑셀 품명 · 줄 `본뜬 {호표, 차례, 행}`) · 수량 {손 = 엑셀 수량 × 몫 × 배} ·
|
||||
기초 = 로직 줄(같은 로직 둘째 = 한 줄 SC 사본) · 재료 · 유가 = 자재 목록(별도계상) · 인력 · 기계 · 유가 이음 ·
|
||||
별도계상 줄(`고정` + 별도계상 · 786-1) = 단가 0 고정 줄(합 밖 · 메모 「별도계상 · 품목은 프로젝트에서」) ·
|
||||
율 = 고정 줄 `비율 {기준, 비목}` · 고정 = 엑셀 단가 고정 줄 · 단가산출 · 일위대가 = 참조
|
||||
(`단산N` = 같은 옮기기 블록 SK · `제N호표` = 같은 HP 호표 SC — 하위 먼저 · 확인 안 된 하위 = 모두 고정).
|
||||
SK(블록) = 바탕 없음 + 더한줄 — 기초 `{종류 로직, 입력값, 수량 = 몫}` · 참조 · 단위 줄(`항목`)에 이은
|
||||
@@ -44,6 +45,7 @@ _SUB = {"단가산출": re.compile(r"^단산(\d+)$"), "일위대가": re.compile
|
||||
LINK = {"인력": "노임", "기계": "기계", "유가": "유가"}
|
||||
OLD_PICK = {"인력": "노임", "기계": "기계", "재료": "자재", "유가": "자재"}
|
||||
NEED = "입력 필요"
|
||||
APART_MEMO = "별도계상 · 품목은 프로젝트에서"
|
||||
COVER = "이미 옮긴 것이 있음 — 덮으려면 [덮어 옮기기](덮음)"
|
||||
|
||||
|
||||
@@ -156,6 +158,13 @@ class Lines:
|
||||
ref = {"키": "SC-미리"} if b.dry else hkids.save(wrap, b.same)[0] # 미리 보기 = 쓰기 없음
|
||||
self.lines.append({"참조": ref, "별칭": alias, "메모": memo, "수량": {"손": _num(qty)}})
|
||||
|
||||
def apart(self, line: dict, alias: str | None, mark: dict) -> None:
|
||||
"""별도계상 줄(786-1) = 합 밖 고정 줄 — 단가 0(셈에 안 듦) · 품명 · 규격 · 단위 · 수량 그대로 ·
|
||||
품목은 프로젝트에 복사할 때 정함(메모 표지)."""
|
||||
zero = {**line, "단가": {}, "금액": {}}
|
||||
self.put(zero, {"이음": dict.fromkeys(hfix.fixed.LINKS)}, alias, None, mark)
|
||||
self.lines[-1]["메모"] = f"{APART_MEMO} · {self.lines[-1].get('메모') or ''}".strip(" ·")
|
||||
|
||||
def picks(self, at: int, line: dict, picks: list[dict]) -> None:
|
||||
"""고른 것(검사 · 다시 셈 끝난 것) → 그 엑셀 줄의 우리 줄 · 자재."""
|
||||
alias = str(line.get("이름") or "")[: labor.ALIAS_MAX].strip() or None
|
||||
@@ -175,6 +184,8 @@ class Lines:
|
||||
elif kind == "율":
|
||||
self.put(line, {"이음": {"비율": p["비목"]}}, alias, None, mark)
|
||||
self.lines[-1]["고정"]["비율"] = {"기준": p["기준"], "비목": p["비목"]}
|
||||
elif kind == "고정" and p.get("별도계상"):
|
||||
self.apart(line, alias, mark)
|
||||
elif kind == "고정":
|
||||
self.put(line, {"이음": dict.fromkeys(hfix.fixed.LINKS)}, alias, None, mark)
|
||||
else:
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
그 밖 = 고정.
|
||||
후보 찾기 차례 = 장부(`Ledger.recall` · 고른 것 꼴) › M01 표마다(LB · MT · MO · EQ) › M02 층
|
||||
SK · SC 같은 이름(위 층까지 · 참고).
|
||||
판정 = 제안 있음(장부 짝 · 후보 하나 · 별도계상 · 하위 호표 · 율) · 2차 필요(단가산출 줄 =
|
||||
판정 = 제안 있음(장부 짝 · 후보 하나 · 별도계상 = 고정 줄 하나(`품목` 표지) · 하위 호표 · 율) ·
|
||||
2차 필요(단가산출 줄 =
|
||||
`Bind` · `Solve` 몫) · 후보 여럿 · 후보 없음(고정 금액 제안).
|
||||
고른 것 = `{갈래 기초|단가산출|일위대가|인력|재료|유가|기계|율|고정, 키, 이름, 규격, 단위, 단가,
|
||||
입력값, 출처, 몫, 비목?, 기준?, 별도계상?, 층?, 주인?}`(설계 2-1 · 만들기 = `Make` 몫).
|
||||
@@ -310,9 +311,13 @@ def _rate_pick(line: dict[str, Any]) -> dict[str, Any]:
|
||||
return one
|
||||
|
||||
|
||||
# 별도계상 줄 표지 `품목` — 품목은 프로젝트에 복사할 때 정함(요구 645-2)
|
||||
ITEM_LATER = "프로젝트에서"
|
||||
|
||||
|
||||
def _fixed(line: dict[str, Any], apart: bool = False) -> dict[str, Any]:
|
||||
price = {k: _plain((line.get("단가") or {}).get(k)) or 0 for k in COSTS}
|
||||
more = {"별도계상": True} if apart else {}
|
||||
more = {"별도계상": True, "품목": ITEM_LATER} if apart else {}
|
||||
return pick(
|
||||
"고정", None, line.get("이름"), line.get("규격"), line.get("단위"), 단가=price, **more
|
||||
)
|
||||
@@ -354,12 +359,13 @@ def judge(
|
||||
out["번"] = no
|
||||
qty = {"엑셀": line.get("수량"), "배": 1, "갈래": "같음"}
|
||||
picks: list[dict[str, Any]] = []
|
||||
if why == "별도계상": # 모아서 한 번에 셈 — 품목 후보 · 장부 짝 안 찾음(고정 줄 하나 · 786-1)
|
||||
return {**out, "후보": [_fixed(line, True)], "판정": "제안 있음", "수량": qty}
|
||||
found = None
|
||||
if folder is not None:
|
||||
found = ledger.recall(line, folder, book, doc=doc)
|
||||
if found and found.get("갈래") == "짝":
|
||||
picks = _from_ledger(found)
|
||||
apart = why == "별도계상"
|
||||
for k in kinds if not picks else ():
|
||||
if k == "일위대가" and no is not None:
|
||||
picks.append(pick("일위대가", f"제{no}호표", line.get("이름"), line.get("규격"),
|
||||
@@ -374,8 +380,6 @@ def judge(
|
||||
picks += m01_picks(k, line)
|
||||
if not found:
|
||||
picks += [p for p in (docs or {}).get(mm.plain(line.get("이름")), []) if p["갈래"] in kinds]
|
||||
if apart:
|
||||
picks = [{**p, "별도계상": True} for p in picks] or [_fixed(line, True)]
|
||||
picks = list({(p["갈래"], p.get("키"), p.get("층")): p for p in picks}.values())
|
||||
if found and found.get("갈래") in ("짝", "우리에 없음", "안 씀"):
|
||||
out["장부"] = {k: found.get(k) for k in ("갈래", "층", "제안", "규격다름")}
|
||||
@@ -385,7 +389,7 @@ def judge(
|
||||
found and found.get("갈래") in ("짝", "안 씀", "우리에 없음") and not found.get("규격다름")
|
||||
):
|
||||
verdict = "제안 있음"
|
||||
elif apart or kinds[0] in ("일위대가", "율") or len(picks) == 1:
|
||||
elif kinds[0] in ("일위대가", "율") or len(picks) == 1:
|
||||
verdict = "제안 있음"
|
||||
elif picks:
|
||||
verdict = "후보 여럿"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* · 제안 = 미리 체크로만(캐시에 없으면 서버 제안) · 확인 = 사용자 [확인] · [호표 제안 모두 확인] 누름만(자동 없음)
|
||||
* · 기초 고른 것 `필요` = 엔진이 쓰는데 못 읽은 칸(입력 필요) + 엇갈림 칸 — 값이 비면 그 줄 확인 · 옮김 막음
|
||||
* · 옮기기 몸 = 확인한 줄 · 블록만 · `필요` 걷음 · 줄 `배`(단위 환산 사용자 값) 얹음 · 금액 · 품 칸 안 보냄(서버가 다시 셈)
|
||||
* · 별도계상 줄 = 서버 제안이 고정 줄 하나(`apartPick`) — 고름 없이 [확인] · [옮기기] 됨(막는 칸 없음)
|
||||
* · 칠 = 확인함 success · 품 다름 warning · 고를 것 info · 후보 없음 danger
|
||||
* 화면 · fetch · sessionStorage 없음(`CLAUDE.md` 4장).
|
||||
* ========================================================================== */
|
||||
@@ -95,6 +96,9 @@ export const linePicks = (d: JudgeDraft, no: number, row: JudgeRow): DraftPick[]
|
||||
export const blockPicks = (d: JudgeDraft, s: Solved): DraftPick[] =>
|
||||
d.블록[String(s.번)]?.고른 ?? solvedPicks(s);
|
||||
|
||||
/** 별도계상 줄(786-1) — 고정 줄 하나 · 품목은 프로젝트에 복사할 때 정함 · 고름 없이 확인 · 옮김 */
|
||||
export const apartPick = (p: Pick): boolean => p.갈래 === "고정" && p.별도계상 === true;
|
||||
|
||||
export const samePick = (a: Pick, b: Pick): boolean =>
|
||||
a.갈래 === b.갈래 && a.키 === b.키 && a.이름 === b.이름 && (a.규격 ?? "") === (b.규격 ?? "");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user