feat(M02): 실무자료 [저장] = 개인 층 · 복사 때 본뜬 지킴 · 단가산출 지정 영역 B~F 열 (372-2)
엑셀 보기 창 만들기 대상 개인 층 고정 · [삭제]는 화면 층 쓰기 권한 때만 · 층 사이 복사가 실무자료 본뜬(키 · 전국자재)을 덮지 않음(원본 참조 = 복사원본 칸). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
This commit is contained in:
@@ -326,6 +326,14 @@ def refuse_used(folder: Path, kind: str, key: str) -> None:
|
||||
|
||||
|
||||
# ── 층 사이 복사 ──────────────────────────────────────────────────────
|
||||
def origin_mark(doc: dict[str, Any], ref: Ref) -> dict[str, Any]:
|
||||
"""복사 문서의 `본뜬` — 실무자료 본뜬(키 · 전국자재 …)은 지키고 원본 참조는 `복사원본` 칸에 둠."""
|
||||
own = doc.get("본뜬")
|
||||
if isinstance(own, dict) and own.get("층") == "실무자료":
|
||||
return {**doc, "본뜬": {**own, "복사원본": ref}}
|
||||
return {**doc, "본뜬": ref}
|
||||
|
||||
|
||||
def carry(doc: dict[str, Any], source: Here) -> dict[str, Any]:
|
||||
"""복사(원본 층 `source` → 지금 층) — 지금 층이 못 읽는 참조는 그 문서를 지금 층에 새 키로
|
||||
같이 복사(`본뜬` = 원래 참조) · 참조를 새 키로 바꿈. 원본 층 읽기 권한은 부르는 쪽 몫."""
|
||||
@@ -341,7 +349,7 @@ def carry(doc: dict[str, Any], source: Here) -> dict[str, Any]:
|
||||
got = read_ref(ref)
|
||||
if got is None:
|
||||
raise _bad(f"없는 참조 「{ref['키']}」")
|
||||
body = {**got, "담은로직": _moved(got.get("담은로직"), move, depth + 1), "본뜬": ref}
|
||||
body = origin_mark({**got, "담은로직": _moved(got.get("담은로직"), move, depth + 1)}, ref)
|
||||
made = create(kind_of(ref["키"]), body)
|
||||
done[ref_id(ref)] = {"층": target[0], "주인": target[1], "키": made["이름"]}
|
||||
return done[ref_id(ref)]
|
||||
|
||||
@@ -97,7 +97,7 @@ class LibraryBody(BaseModel):
|
||||
|
||||
|
||||
def _copy(kind: str, doc: dict[str, Any], source: refs.Here, ref: dict) -> dict[str, Any]:
|
||||
return refs.create(kind, refs.carry({**doc, "본뜬": ref}, source))
|
||||
return refs.create(kind, refs.carry(refs.origin_mark(doc, ref), source))
|
||||
|
||||
|
||||
@router.post("/layers/{layer}/library/{kind}")
|
||||
|
||||
@@ -127,9 +127,9 @@ export function buildOrder(ones: { 번: number; 아래: number[] }[]): number[]
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 단가산출 행 → 행 전체 범위 A1(`4:9`) */
|
||||
/** 단가산출 행 → B ~ F 열 범위 A1(`B4:F9`) */
|
||||
export const rowsText = (행: number | [number, number]): string =>
|
||||
typeof 행 === "number" ? `${행}:${행}` : `${행[0]}:${행[1]}`;
|
||||
typeof 행 === "number" ? `B${행}:F${행}` : `B${행[0]}:F${행[1]}`;
|
||||
|
||||
export function openHopyoSheet(opt: HopyoSheetOptions): void {
|
||||
let sheet: SpreadsheetHandle | null = null;
|
||||
|
||||
@@ -111,12 +111,15 @@ export function buildHopyoSection(opt: HopyoSectionOptions): HopyoSection {
|
||||
scope,
|
||||
key: file.키,
|
||||
파일: file.파일,
|
||||
canWrite: opt.canWrite,
|
||||
// 사전조합은 어느 화면 층에서든 로그인한 사람 개인 층에 만듦 — 회사 · 마스터는 구조물 카드 [가져오기]
|
||||
target: { layer: "personal", owner: null },
|
||||
canWrite: true,
|
||||
onClose: () => {
|
||||
if (sheetKey === file.키) sheetKey = null;
|
||||
paintList();
|
||||
},
|
||||
onDeleted: () => void refresh(),
|
||||
// [삭제]는 실무자료 파일이 있는 화면 층 쓰기 권한 때만
|
||||
onDeleted: opt.canWrite ? () => void refresh() : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user