- 임도품셈 판 대응표 CSV 새 자리(STmate/old/30_원자료) — 불러오기 시험 26 실패 → 0 - 가져온 식 SK = 수식 문서(멈춘 wip/802-4b-1 M02_Doc_Import 를 메인 판에 다시 얹음 · 빈 산근 = 엑셀 0 원 줄) — 줄 쌓기 「수식」 탭 길 열림 · 셈 = 단가기준(엑셀 값 기억 | 연결 값) · 화면 캐시 기록 · 수식 길 저장 `단가기준` - 1,021 블록 전수(실무 여덟 + 표본 밖 셋) 엑셀 검산 · 엑셀 전후 · 우리 전후 모두 같음 · 셈됨 줄지 않음 - 옮기기 도구 「가져온식」 상태 걷음(가져온 줄 문서로 대조) - [내 일위대가로] = 호표 하나 + 하위 → 개인 층 SC · 부르는 단산 = 가져온 식 SK(같은 내용 = 있는 것 · 못 이은 줄 = 고정) - [내 단가산출로] = 단산 블록 판 → 개인 층 가져온 식 SK(개인 층이면 [가져온 식으로 열기] 숨김) - 원문 패널(M01 로직 · M02 단가산출) 맨 위 「단가산출 기초 찾기」 · 가져온 식 SK 첫 화면 = 「어디서 왔나」 카드 (프로그램 · 파일 · 블록 · 행 · 가져온 때 · 표지 · 엑셀 글의 품셈 절 글만) - 수식 탭 [엑셀 단가 그대로 | 우리 단가로](단가산출 화면 · 저장 뒤 페이지 문서 단가기준 맞춤) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
/* =============================================================================
|
|
* M02_Sangeun_Origin.ts
|
|
* 가져온 식 단가산출 「어디서 왔나」 카드 자료(PLAN 807-1 · 요구 699) — 원문 패널 첫 화면.
|
|
* SK `가져온.원본`(파일 · 시트 · 행 · 갈래 EST|STmate · 코드 · 표지 · 가져온때 · 글줄)에서 보이기 자료만 뽑음 ·
|
|
* 품셈 절 글 = 엑셀 글줄에 적힌 「…품셈 N-N-N」 글(책 · 절 번호 · 그 줄 글) — 찾기 · 잇기 없음(보이기만)
|
|
* 화면 · DOM · fetch 없음
|
|
* ========================================================================== */
|
|
|
|
export interface OriginMeta {
|
|
로직?: unknown;
|
|
원본?: {
|
|
파일?: string;
|
|
시트?: string;
|
|
행?: number[];
|
|
갈래?: string;
|
|
코드?: string | number;
|
|
표지?: string[];
|
|
가져온때?: string;
|
|
글줄?: { 행?: number; 글?: string }[];
|
|
};
|
|
}
|
|
|
|
export interface Clause {
|
|
책: string;
|
|
절: string;
|
|
글: string;
|
|
행?: number;
|
|
}
|
|
|
|
export interface Origin {
|
|
프로그램: string;
|
|
파일: string;
|
|
블록: string;
|
|
행: string;
|
|
때: string;
|
|
표지: string[];
|
|
품셈: Clause[];
|
|
}
|
|
|
|
const BOOKS: [RegExp, string][] = [
|
|
[/건설/, "건설표준품셈"],
|
|
[/산림/, "산림표준품셈"],
|
|
[/임도/, "임도품셈"],
|
|
];
|
|
/** 「건설공사표준품셈8-1-3」 · 「산림사업표준품셈 10-4」 · 「[2025년 표준품셈3-4-8]」 · 「임도품셈 5-1-2」 */
|
|
const CLAUSE =
|
|
/((?:건설(?:공사)?|산림(?:사업)?|임도)?\s*(?:표준\s*)?품셈)\s*[[(]?\s*(?:제\s*)?(\d{1,2}(?:-\d{1,3}){1,3})/g;
|
|
|
|
/** 글줄 → 품셈 절(책 · 절 같은 것은 처음 하나) */
|
|
export function clausesOf(lines: { 행?: number; 글?: string }[] = []): Clause[] {
|
|
const out: Clause[] = [];
|
|
const seen = new Set<string>();
|
|
for (const line of lines) {
|
|
const text = String(line.글 ?? "")
|
|
.replace(/\s+/g, " ")
|
|
.trim();
|
|
for (const m of text.matchAll(CLAUSE)) {
|
|
const book = BOOKS.find(([re]) => re.test(m[1]))?.[1] ?? "표준품셈";
|
|
const key = `${book} ${m[2]}`;
|
|
if (seen.has(key)) continue;
|
|
seen.add(key);
|
|
out.push({ 책: book, 절: m[2], 글: text, ...(line.행 !== undefined ? { 행: line.행 } : {}) });
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
const pad = (n: number): string => String(n).padStart(2, "0");
|
|
/** 서버 때(UTC 글) → 이 컴퓨터 시각 「YYYY-MM-DD HH:mm」 · 못 읽음 = 빈 글 */
|
|
const localTime = (s?: string): string => {
|
|
const at = new Date(s ?? "");
|
|
if (!s || Number.isNaN(at.getTime())) return "";
|
|
return `${at.getFullYear()}-${pad(at.getMonth() + 1)}-${pad(at.getDate())} ${pad(at.getHours())}:${pad(at.getMinutes())}`;
|
|
};
|
|
|
|
/** 가져온 식이 아니면 null */
|
|
export function originOf(meta: OriginMeta | null | undefined): Origin | null {
|
|
if (!meta?.로직 || !meta.원본) return null;
|
|
const src = meta.원본;
|
|
const code = src.코드 ?? "";
|
|
const block = src.갈래 === "EST" && code !== "" ? `단산${code}` : String(code);
|
|
const rows = (src.행 ?? []).filter((x) => Number.isFinite(x));
|
|
return {
|
|
프로그램: src.갈래 ?? "",
|
|
파일: src.파일 ?? "",
|
|
블록: block,
|
|
행: rows.length ? `${src.시트 ? `${src.시트} ` : ""}${rows.join("~")}행` : (src.시트 ?? ""),
|
|
때: localTime(src.가져온때),
|
|
표지: [...(src.표지 ?? [])],
|
|
품셈: clausesOf(src.글줄),
|
|
};
|
|
}
|