feat(797-2): 엑셀 불러오기 소요량 · 계수 이음 — 값 역색인 후보 + 사람 확인 · 고름 = 표 칸 참조 기록
- 새 `M02_Sangeun_QtyLinks` — 가져온 식 줄(호표 수량 · 덧줄 식)의 수를 M01 소요량(QC/QF) · 계수(CC/CF) 칸과 값 역색인(`San_Basis_Index.lookup`)으로 맞춤 · 같은 값 + 같은 단위 성격 + 공종 문맥(인력 = 직종 · 재료 = 칸 이름 추가) · 일반 수 · 비교 글자 · 중간 변수는 자리 아님 · 유일해도 자동 확정 없음
- 고름 = `가져온.연결` 기록(층 M01 · 표 · 줄 · 칸 · 값 · 꼴) · 엑셀 수 = 칸 값일 때만(다르면 400 까닭) · 버림 · 되돌림 · 기록만(셈 · 금액 · 단가 갱신 안 건드림) · 저장 거름(`clean`) = 자리 · 수 맞는 기록만
- 길 `…/sangeun/imported/{qty|qty-pick|qty-drop}` · 가져온 식 만들 때 표지 「참고 · 소요량 후보 N · 사람 확인」 · 「표 칸 없음」(못 옮김 표지 아님)
- 화면 — 가져온 식 모달 머리 판 한 줄(집계 · [이음 보기]) + 모달(줄마다 후보 · [고르기] · [풀기] · [버리기] · [되돌리기] · 부품 상자만)
- 시험 test_797_2_qty_coef_links 9 · 낡은 시험 없음
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* · 줄 1 = 「새」 · 원본(파일 · 시트 · 행) · 검산 표지(같음 / 다름 n · 줄마다 까닭) · 단가 기준 [우리 단가로] / [엑셀 단가로] ·
|
||||
* 바꾸기 전후 금액 · [원본 글 보기]
|
||||
* · 줄 2 = 이음 없는 자원 = 표지 + [이음 고르기]
|
||||
* · 줄 2-2 = 소요량 · 계수 이음(797-2 · 후보 집계 + [이음 보기] → `Hopyo_QtyLinks` 모달)
|
||||
* · 줄 3 = 근거 제안 세 단(확정 · 근접(차이 · 까닭) · 사람 고름 · 793-3a) — 후보마다 [우리 기초로 바꾸기] · [기초 고르기]
|
||||
* · 우리 기초로 바꾼 뒤 = 전후 차이 띠 · 「입력 필요」 붉은 칸(채우기 전엔 그 줄 확인 · 옮김 막힘)
|
||||
* 부품 = 단추 · 배지 · 글 · 입력 · 띠 · 표 · 모달(날 단추 · 입력 없음) · 서버 길은 부르는 쪽.
|
||||
@@ -21,6 +22,7 @@ import { createText } from "@ui/ui_template_text";
|
||||
import { createToolbar } from "@ui/ui_template_toolbar";
|
||||
import { formatMoney } from "../common_util/common_util_money";
|
||||
import { newBadge } from "./M02_MasterTemplete_Hopyo_CheckRows";
|
||||
import { tallyBadges, type QtyTally } from "./M02_MasterTemplete_Hopyo_QtyLinks";
|
||||
import {
|
||||
gapText,
|
||||
isImported,
|
||||
@@ -66,6 +68,8 @@ const TEXT = {
|
||||
Need: ["입력 필요", "Input needed"],
|
||||
Swap: ["환산 계수(기초 1 단위 = 이 단가산출 몇 단위)", "Unit factor (1 basis unit = n of this)"],
|
||||
NeedHint: ["채워야 이 줄을 확인 · 옮김", "Fill to confirm and move this line"],
|
||||
QtyLinks: ["소요량 · 계수 이음 {n}", "Quantity / coefficient links {n}"],
|
||||
QtyOpen: ["이음 보기", "Show links"],
|
||||
Close: ["닫기", "Close"],
|
||||
} as const satisfies Record<string, readonly [string, string]>;
|
||||
export const tx = (k: keyof typeof TEXT): string =>
|
||||
@@ -75,6 +79,8 @@ export interface PanelState {
|
||||
doc: ImportedDoc;
|
||||
/** 이음 없는 자원(서버 price 답) */
|
||||
unlinked: { 자리: string; 이름: string }[];
|
||||
/** 소요량 · 계수 이음 집계(서버 qty 답 · 797-2) */
|
||||
qty: QtyTally | null;
|
||||
/** 마지막 단가 바꿈 전후 */
|
||||
price: { 전: Money4 | null; 후: Money4 | null } | null;
|
||||
/** 우리 기초로 바꾼 뒤 입력 필요 칸 */
|
||||
@@ -89,6 +95,7 @@ export interface PanelActs {
|
||||
toBase: (code: string, cand: BasisCand | null) => void;
|
||||
pickBase: () => void;
|
||||
fill: (name: string, value: string) => void;
|
||||
qty: () => void;
|
||||
}
|
||||
|
||||
const won = (m: Money4 | null | undefined): string => (m ? formatMoney(m.계) : "—");
|
||||
@@ -224,6 +231,12 @@ export function importedPanel(s: PanelState, a: PanelActs): HTMLElement {
|
||||
const tag = createBadge(tx("Unlinked").replace("{n}", String(s.unlinked.length)), "warning");
|
||||
kids.push(createToolbar({ items: [tag, ...items] }));
|
||||
}
|
||||
if (here && s.qty?.자리) {
|
||||
const open = createButton({ label: tx("QtyOpen"), size: 24, variant: "ghost", onClick: a.qty });
|
||||
open.dataset.importedQty = String(s.qty.자리);
|
||||
const tag = createBadge(tx("QtyLinks").replace("{n}", String(s.qty.자리)), "info");
|
||||
kids.push(createToolbar({ items: [tag, ...tallyBadges(s.qty), open] }));
|
||||
}
|
||||
const gone = meta.바꿈;
|
||||
if (!here && gone) {
|
||||
const g = tx("Gap").replace("{a}", won(gone.전)).replace("{b}", won(gone.후));
|
||||
|
||||
Reference in New Issue
Block a user