feat(836-2): M02 단가산출 화면 — 열 때 「M01 이 바뀌어 다시 복사함」 알림(항목 · M01 전 → 후 · 지워진 내 고침) · 자동 층 [단가 갱신] · [재생성] · 「새 값」 · 「사본 없는 줄」 걷음
- 새 formula_doc_renew.ts(확인창 부품 + 표) · [확인] = 저장(다시 안 뜸) · [나중에] = 다음에 또 - line_stack_screen 두 곳(단추 줄 조건 · 열기 뒤 알림) · 프로젝트 층 = 단추 그대로 - 내 기계 글 셋 = 「새 값」 → [단가 갱신] 안내를 자동 따라옴으로 · 알림 글 금액 줄 꼴 다듬음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
* (821-3) 값 줄만 바뀜(M01 단가 · 내 기계 고침) = 「새 값 있음」(같은 자리 · 같은 꼴) · 지운 키(M01 · 내 기계) = 「지워짐 n」 ·
|
||||
* [단가 갱신] 확인 창 = 바뀐 자원 줄(이름 · 바뀐 칸 전 → 후 · 지워짐 = 마지막 값 유지)
|
||||
* (822-1) 값 사본에 없는 셈 줄(옛 저장본 빈틈) = 「사본 없는 줄 n」(지금 값으로 셈 · 저장하면 굳음)
|
||||
* (836-2) 표지 `자동`(프로젝트 층 밖 = M01 자동 따라옴) = 단추 · 「새 값」 · 「사본 없는 줄」 안 그림(지워짐만)
|
||||
* ========================================================================== */
|
||||
|
||||
import { createBadge } from "@ui/ui_template_badge";
|
||||
@@ -18,6 +19,7 @@ import type { FormulaDoc } from "../common_util/common_util_formula_doc";
|
||||
import type { Basis } from "../common_util/common_util_formula_doc_import";
|
||||
import { swappedCount } from "../common_util/common_util_line_stack_pick";
|
||||
import { ft } from "./formula_doc_text";
|
||||
import type { RenewNote } from "./formula_doc_renew";
|
||||
|
||||
export type CopyJob = "단가갱신" | "재생성";
|
||||
|
||||
@@ -32,6 +34,10 @@ export interface CopyMark {
|
||||
따로?: boolean;
|
||||
/** 가져온 식(엑셀 불러오기 · 807-1) 단가기준 — 엑셀 = 엑셀 값 기억 · 우리 = 연결 값 */
|
||||
단가기준?: Basis;
|
||||
/** M01 자동 따라옴(836-2 · 프로젝트 층 밖) — [단가 갱신] · [재생성] · 「새 값」 · 「사본 없는 줄」 없음 */
|
||||
자동?: boolean;
|
||||
/** 열 때 알림(836-2) — M01 에서 바뀐 항목의 지운 고침 */
|
||||
갱신?: RenewNote[];
|
||||
}
|
||||
|
||||
export interface CopyOptions {
|
||||
@@ -58,7 +64,7 @@ export function isStale(m: CopyMark | undefined): boolean {
|
||||
export function copyBadges(m: CopyMark | undefined, edit: boolean): HTMLElement[] {
|
||||
const out: HTMLElement[] = [];
|
||||
const doc = !!m?.M01새판 || !!m?.문서새판?.length;
|
||||
if (doc || m?.단가새값) {
|
||||
if ((doc || m?.단가새값) && !m?.자동) {
|
||||
const b = createBadge(ft(doc ? "New_M01" : "New_Value"), "danger");
|
||||
b.dataset.copyStale = doc ? "doc" : "value";
|
||||
out.push(b);
|
||||
@@ -69,7 +75,7 @@ export function copyBadges(m: CopyMark | undefined, edit: boolean): HTMLElement[
|
||||
b.dataset.copyGone = m.지운키.join(",");
|
||||
out.push(b);
|
||||
}
|
||||
if (m?.사본없음) {
|
||||
if (m?.사본없음 && !m.자동) {
|
||||
const b = createBadge(`${ft("Gap")} ${m.사본없음}`, "warning");
|
||||
b.title = ft("Gap_Note");
|
||||
b.dataset.copyGap = String(m.사본없음);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/* =============================================================================
|
||||
* formula_doc_renew.ts
|
||||
* M01 자동 따라옴 알림(PLAN 836-2 · 요구 854) — M02 단가산출(프로젝트 층 밖)을 열 때
|
||||
* M01 에서 바뀐 항목에 얹힌 내 고침을 지우고 다시 복사한 것을 한 번 보임(서버 `M02_Sk_AutoRenew.notes`)
|
||||
* 표 = 항목 · M01 전 → 후 · 지워진 내 고침 · [확인] = 저장(다시 안 뜸) · [나중에] = 다음에 열면 또 뜸
|
||||
* 고침 없는 항목은 조용히 따라옴(알림 없음)
|
||||
* ========================================================================== */
|
||||
|
||||
import { askConfirm, el } from "@ui/ui_template_elements";
|
||||
import { createTable } from "@ui/ui_template_table";
|
||||
import { ft } from "./formula_doc_text";
|
||||
|
||||
/** 서버 알림 한 줄 — 갈래 = 문서(바탕 수식) · 부름(굳힌 부른 문서) · 기계(기계 덮음) */
|
||||
export interface RenewNote {
|
||||
키: string;
|
||||
이름?: string;
|
||||
갈래?: string;
|
||||
M01?: string[];
|
||||
내고침?: string[];
|
||||
}
|
||||
|
||||
/** 칸 안 여러 줄 — 줄마다 한 덩이 */
|
||||
const lines = (xs: string[] | undefined): HTMLElement =>
|
||||
el("div", { children: (xs ?? []).map((t) => el("div", { text: t })) });
|
||||
|
||||
/** 알림 창 — 확인이면 true(부르는 쪽이 저장) */
|
||||
export function askRenew(notes: RenewNote[]): Promise<boolean> {
|
||||
const table = createTable(
|
||||
[
|
||||
{ label: ft("Renew_Item"), width: "28%" },
|
||||
{ label: ft("Renew_M01") },
|
||||
{ label: ft("Renew_Mine") },
|
||||
],
|
||||
notes.map((n) => [lines([n.이름 || n.키, n.키]), lines(n.M01), lines(n.내고침)]),
|
||||
{ density: "data" },
|
||||
);
|
||||
table.dataset.renewNotes = String(notes.length);
|
||||
return askConfirm({
|
||||
title: ft("Renew_Title"),
|
||||
message: ft("Renew_Ask"),
|
||||
okLabel: ft("Renew_Ok"),
|
||||
cancelLabel: ft("Renew_Later"),
|
||||
detail: table,
|
||||
});
|
||||
}
|
||||
@@ -78,6 +78,16 @@ const TEXT = {
|
||||
Changed: ["바뀐 자원", "Changed resources"],
|
||||
Before_After: ["계", "Sum"],
|
||||
Job_Done: ["적용함", "Applied"],
|
||||
Renew_Title: ["M01 이 바뀌어 다시 복사함", "Re-copied from updated M01"],
|
||||
Renew_Ask: [
|
||||
"M01 에서 바뀐 항목에 있던 내 고침을 지우고 M01 에서 다시 복사함 — [확인] 하면 저장(다시 안 뜸)",
|
||||
"Your edits on items changed in M01 were removed and re-copied — OK saves (no repeat)",
|
||||
],
|
||||
Renew_Item: ["항목", "Item"],
|
||||
Renew_M01: ["M01 전 → 후", "M01 before → after"],
|
||||
Renew_Mine: ["지워진 내 고침", "Removed edits"],
|
||||
Renew_Ok: ["확인", "OK"],
|
||||
Renew_Later: ["나중에", "Later"],
|
||||
Basis_Excel: ["엑셀 단가 그대로", "Excel prices"],
|
||||
Basis_Ours: ["우리 단가로", "Our prices"],
|
||||
Dirty_First: [
|
||||
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
swapBadge,
|
||||
} from "./formula_doc_copy";
|
||||
import { docFoot } from "./formula_doc_foot";
|
||||
import { askRenew } from "./formula_doc_renew";
|
||||
import { buildOptions } from "./formula_doc_options";
|
||||
import { ft } from "./formula_doc_text";
|
||||
import { addTaken, type Taken } from "../common_util/common_util_line_stack_copy";
|
||||
@@ -306,7 +307,7 @@ export function createStackScreen(opt: StackScreenOptions) {
|
||||
const busy = dirty();
|
||||
const tools = [
|
||||
...(mark?.단가기준 && opt.page ? [basisPick(mark.단가기준)] : []), // 모달 = 머리 판 단추(793-3b)
|
||||
...(cp && edit() && key ? copyTools(true, (job) => void runJob(job)) : []),
|
||||
...(cp && edit() && key && !mark?.자동 ? copyTools(true, (job) => void runJob(job)) : []), // 836-2 자동 = 없음
|
||||
...(edit() && key && !opt.page
|
||||
? [
|
||||
createButton({
|
||||
@@ -517,6 +518,9 @@ export function createStackScreen(opt: StackScreenOptions) {
|
||||
recalc();
|
||||
draw();
|
||||
opt.page?.(); // 캐시에서 이어 받은 고침 — 페이지 [저장] · [되돌림] 켬
|
||||
const notes = (mark as CopyMark | undefined)?.갱신; // 836-2 M01 자동 따라옴 알림(take 가 채움)
|
||||
if (cp && edit() && !dirty() && notes?.length)
|
||||
void askRenew(notes).then((ok) => ok && save({ 할일: "갱신확인", 판: version }, ""));
|
||||
} catch (e) {
|
||||
if (mine === seq)
|
||||
head.replaceChildren(
|
||||
|
||||
@@ -33,7 +33,7 @@ const TEXT = {
|
||||
Copied: "「{value}」 값을 복사 — 고친 뒤 [저장]",
|
||||
Own_Value: "개인 값",
|
||||
Own_Note:
|
||||
"개인 값 = 이 기계 고유 값(가격 · 손료계수 · 연료 ℓ · 잡품 % · 조종원 수) · 단가(노임 · 유가)는 M01 값 · 단가산출엔 만들 때 복사 → 고친 뒤 「새 값」 → [단가 갱신]",
|
||||
"개인 값 = 이 기계 고유 값(가격 · 손료계수 · 연료 ℓ · 잡품 % · 조종원 수) · 단가(노임 · 유가)는 M01 값 · 단가산출(프로젝트 밖)은 고치면 저절로 따라옴",
|
||||
Server_Hourly: "서버 셈 시간당",
|
||||
Hourly_None: "시간당 못 셈",
|
||||
Uses: "쓰는 단가산출",
|
||||
@@ -59,7 +59,7 @@ const TEXT = {
|
||||
Win_M01: "M01 기계",
|
||||
Win_Copy: "이 단가산출에 복사된 값",
|
||||
Win_Live: "원본 지금 값",
|
||||
Win_Newer: "원본에 새 값 있음 — [단가 갱신] 으로 반영",
|
||||
Win_Newer: "원본에 새 값 있음 — 프로젝트 사본은 [단가 갱신] 으로 반영",
|
||||
Win_Swap: "이 기계로 바꾸기",
|
||||
Win_Edit: "고쳐 쓰기",
|
||||
Win_Blank: "빈 양식에서 새 기계",
|
||||
@@ -67,7 +67,7 @@ const TEXT = {
|
||||
Win_Cancel: "취소",
|
||||
Win_Edit_Note:
|
||||
"[확인] = 이 단가산출에 초안으로 끼움 · 단가산출 [저장] 때 내 기계로 저장 · 저장 안 하고 나가면 사라짐",
|
||||
Win_Uses: "이 기계를 쓰는 다른 단가산출 {value} 건 — 저장하면 그쪽에 「새 값」 배지",
|
||||
Win_Uses: "이 기계를 쓰는 다른 단가산출 {value} 건 — 저장하면 그쪽도 새 값으로 셈",
|
||||
Win_Hint: "왼쪽에서 기계를 고르면 값이 보임",
|
||||
Win_View: "조회",
|
||||
Why_M01: "기계 값은 M01 기계 상세에서",
|
||||
|
||||
@@ -125,7 +125,7 @@ def diff(a: Any, b: Any) -> list[str]:
|
||||
if dc.fp(x) == dc.fp(y):
|
||||
continue
|
||||
name = str((y or x or {}).get("이름") or f"금액 {n + 1}")
|
||||
show = lambda z: "—" if not z else f"{z.get('수량') or ''} × {z.get('단가') or ''}" # noqa: E731
|
||||
show = lambda z: " × ".join(str(z[k]) for k in ("수량", "단가") if z and z.get(k)) or "—" # noqa: E731
|
||||
out.append(f"{name} {show(x)} → {show(y)}")
|
||||
for slot in ("식", "끝수", "결과단위"):
|
||||
if dc.fp(a.get(slot)) != dc.fp(b.get(slot)):
|
||||
|
||||
Reference in New Issue
Block a user