feat(795-4): B09 사본 규칙 — 만든 때 그대로 · [단가 갱신] 값만 · [재생성] 따로 · 시점 섞임 고침
- 구조물 · 서고 사본 단가 묶음 = M02 일위대가 · SC · SK 로직 사본 줄 먼저(`collect(over)`) · M01 에서 지워진 키 = `사본_남은줄.json`
- 단가 책 새 줄([저장] · 첫 굳힘) = 연결 사본 `단가.json` 자원 줄(구조물 지정 때 값 · `Linked.frozen_rows`) · 없는 자원만 지금 M01 + 책 `now_keys` · 입력 `now` · 알림 한 줄
- POST …/estimation/prices 기본 = 단가 갱신(값만 · 사본 재적용 없음) · job 재생성 = 옛 [업데이트] · 미리 보기 단가 갱신 = 바뀐 자원 · 총괄 · 대가 합 전 → 후
- B09 화면 단추 [업데이트] → [단가 갱신] · 미리 보기 창 [재생성] → 재생성 미리 보기 → [적용] · 안내 글 둘 이름 맞춤
- 옮기기 도구(보기만) — 프로젝트 층 못셈 14 = 「못셈(옛 SP 참조)」 갈래 · B09 구조물 · 서고 사본 대조(그대로 · 재생성 금액)
- 새 시험 test_795_4_b09_copy(8) · 낡은 시험 고침: test_203_1 · test_296 = 단추 이름 「업데이트」 · 호버 글 · 몸 `{ user }` 를 박아 둔 것 → 795-4 이름 · job 덧칸으로
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,14 +10,14 @@
|
||||
[초기화](요구 298-2 C1 · C3 · C4 · C5 · 301 · 본문 없음) — 사용자 값 전부(내역 · 자재 ·
|
||||
원가 · 공기) · 단가 책 · `estimation` 설정 구획 지움 · 서고 사본 정리 · 견적서 파일 남김 →
|
||||
답 = GET 꼴(기준 = 지금 B08 저장본 + 지금 M01 단가) · 단계 = [저장]과 같음
|
||||
POST /api/projects/{id}/estimation/prices {user?}
|
||||
[업데이트] — 원본이 바뀐 구조물 사본 재적용(703-3 · `B09_Estimation_Refresh`) →
|
||||
수요 단가 전부를 지금 M01 값으로 새로 굳힘 · user = 화면 캐시(296 · 지운 줄 · 그 사본은
|
||||
수요에서 뺌 · 저장은 안 함) · M01 원본이 지워진 줄 = 굳힌 값 그대로 · 덮개 그대로 ·
|
||||
답 notes 첫 줄 = 바뀐 수
|
||||
POST /api/projects/{id}/estimation/prices/preview {user?}
|
||||
[업데이트] 미리 보기(703-3) — 바뀌는 단가 줄 · 다시 가져올 사본 · 지킬 고친 칸 ·
|
||||
노임 판(쓰지 않음)
|
||||
POST /api/projects/{id}/estimation/prices {user?, job?}
|
||||
[단가 갱신](795-4 · 기본) — 수요 단가 전부를 지금 M01 값으로 새로 굳힘 · 사본(로직) 그대로 ·
|
||||
job 「재생성」 = 원본이 바뀐 구조물 사본 재적용(703-3 · `B09_Estimation_Refresh`) 먼저 ·
|
||||
user = 화면 캐시(296 · 지운 줄 · 그 사본은 수요에서 뺌 · 저장은 안 함) ·
|
||||
M01 원본이 지워진 줄 = 굳힌 값 그대로 · 덮개 그대로 · 답 notes 첫 줄 = 바뀐 수
|
||||
POST /api/projects/{id}/estimation/prices/preview {user?, job?}
|
||||
미리 보기(쓰지 않음) — 단가 갱신 = 바뀐 자원 · 총괄 금액 전 → 후(795-4) ·
|
||||
재생성 = 바뀌는 단가 줄 · 다시 가져올 사본 · 지킬 고친 칸 · 노임 판(703-3)
|
||||
POST /api/projects/{id}/estimation/calc {user}
|
||||
조작 중 서버 셈(702-3 · 단가연결 즉시 금액) — 화면 캐시로 GET 꼴 셈 · 저장 안 함
|
||||
POST /api/projects/{id}/estimation/logic-preview {code, given, rate, picks}
|
||||
@@ -75,6 +75,7 @@ from B08_Quantity.B08_Quantity_Router_Milestone import site_info
|
||||
from B09_Estimation import B09_Estimation_Bill_Library as library
|
||||
from B09_Estimation import B09_Estimation_Daega_Paste as daega_paste
|
||||
from B09_Estimation import B09_Estimation_Daega_Personal as personal
|
||||
from B09_Estimation import B09_Estimation_Linked as linked
|
||||
from B09_Estimation import B09_Estimation_Past as past
|
||||
from B09_Estimation import B09_Estimation_Prices as prices
|
||||
from B09_Estimation import B09_Estimation_Refresh as refresh
|
||||
@@ -234,10 +235,12 @@ async def payload(
|
||||
draft: dict[str, Any] | None = None,
|
||||
reuse_b08: bool = False,
|
||||
keys: list[str] | None = None,
|
||||
book: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""셈 답 한 벌 — keys = 방금 센 단가 수요(같은 저장 값 · [저장]) · 마스터 자국은 한 번만."""
|
||||
"""셈 답 한 벌 — keys = 방금 센 단가 수요(같은 저장 값 · [저장]) · 마스터 자국은 한 번만 ·
|
||||
book = 안 쓴 단가 책(795-4 미리 보기 · 없으면 저장본)."""
|
||||
with m01_cache.steady():
|
||||
return await _payload(project_id, root, draft, reuse_b08, keys)
|
||||
return await _payload(project_id, root, draft, reuse_b08, keys, book)
|
||||
|
||||
|
||||
async def _payload(
|
||||
@@ -246,6 +249,7 @@ async def _payload(
|
||||
draft: dict[str, Any] | None,
|
||||
reuse_b08: bool,
|
||||
keys: list[str] | None,
|
||||
book: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
notes: list[str] = []
|
||||
b08 = await _b08_for(project_id, notes, reuse_b08)
|
||||
@@ -254,8 +258,11 @@ async def _payload(
|
||||
notes.append(
|
||||
"연결된 구조물 조합 사본 없음 — 노무 · 경비 · 중기 단가 줄은 사본이 연결되면 생김"
|
||||
)
|
||||
book = await asyncio.to_thread(store.read_book, root)
|
||||
inputs = await asyncio.to_thread(prices.build_inputs, book, keys, b08["materials"])
|
||||
book = book or await asyncio.to_thread(store.read_book, root)
|
||||
frozen = await asyncio.to_thread(linked.frozen_rows, root) # 795-4 사본 단가 기준 시점
|
||||
inputs = await asyncio.to_thread(prices.build_inputs, book, keys, b08["materials"], frozen)
|
||||
if late := inputs["now"]:
|
||||
notes.append(f"사본 기준 시점에 없는 자원 {len(late)} — 지금 M01 값: {' · '.join(late)}")
|
||||
hauls = await asyncio.to_thread(haul_routes, root)
|
||||
# 702-3 draft = 화면 캐시로 셈(저장 안 함) · 없으면 저장 값
|
||||
user = await asyncio.to_thread(store.read_user, root) if draft is None else draft
|
||||
@@ -309,7 +316,8 @@ async def _save(project_id: UUID, root: Path, body: dict[str, Any]) -> dict[str,
|
||||
await asyncio.to_thread(library.prune, root, calc) # 204-2 줄이 안 잇는 서고 사본
|
||||
keys = await _demand(root)
|
||||
book = await asyncio.to_thread(store.read_book, root)
|
||||
book = await asyncio.to_thread(prices.extend_book, book, keys)
|
||||
frozen = await asyncio.to_thread(linked.frozen_rows, root) # 795-4 새 줄 = 사본 기준 시점
|
||||
book = await asyncio.to_thread(prices.extend_book, book, keys, frozen)
|
||||
await asyncio.to_thread(store.write_book, root, book)
|
||||
# [저장](B1) 단계 표시는 셈과 함께 · 수요 = 방금 센 것(저장 값 · 사본 그대로)
|
||||
out, _ = await asyncio.gather(
|
||||
@@ -352,12 +360,15 @@ async def refresh_prices(
|
||||
body: dict[str, Any] | None = Body(None),
|
||||
session: dict[str, Any] = Depends(verify_session),
|
||||
) -> dict[str, Any]:
|
||||
"""[업데이트] 한 곳(703-3) — 원본이 바뀐 구조물 사본 재적용 → 단가 책 다시 굳힘 ·
|
||||
덮개 그대로."""
|
||||
"""[단가 갱신](795-4) — 단가 책 다시 굳힘 · 사본 · 덮개 그대로 ·
|
||||
job 「재생성」 = 원본이 바뀐 구조물 사본 재적용(703-3) 먼저."""
|
||||
root = await _project_root(project_id)
|
||||
raw = (body or {}).get("user")
|
||||
draft = store.clean_user(raw) if isinstance(raw, dict) else None # 296 화면 캐시(저장 안 함)
|
||||
again = await asyncio.to_thread(refresh.reapply_changed, root, importer(session))
|
||||
regen = (body or {}).get("job") == refresh.REGEN
|
||||
again = {"다시": [], "막힘": []}
|
||||
if regen:
|
||||
again = await asyncio.to_thread(refresh.reapply_changed, root, importer(session))
|
||||
keys = await _demand(root, draft)
|
||||
old = await asyncio.to_thread(store.read_book, root)
|
||||
book = await asyncio.to_thread(prices.refresh_book, keys, old)
|
||||
@@ -366,9 +377,9 @@ async def refresh_prices(
|
||||
diff = prices.book_diff(old, book)
|
||||
kept = draft or out.get("user") or {}
|
||||
cells = refresh.cover_cells(kept.get("daega_cover")) + refresh.cover_cells(kept.get("sg_cover"))
|
||||
head = f"재생성 — 구조물 사본 {len(again['다시'])} 다시 가져옴 · " if regen else "단가 갱신 — "
|
||||
out["notes"] = [
|
||||
f"업데이트 — 단가 줄 {diff['new'] + diff['changed']} 바뀜 · 구조물 사본 "
|
||||
f"{len(again['다시'])} 다시 가져옴 · 고친 칸 {cells} 그대로",
|
||||
f"{head}단가 줄 {diff['new'] + diff['changed']} 바뀜 · 고친 칸 {cells} 그대로",
|
||||
*(f"재적용 못 함 {why}" for why in again["막힘"]),
|
||||
*(out.get("notes") or []),
|
||||
]
|
||||
@@ -379,14 +390,21 @@ async def refresh_prices(
|
||||
async def refresh_preview(
|
||||
project_id: UUID, body: dict[str, Any] | None = Body(None)
|
||||
) -> dict[str, Any]:
|
||||
"""[업데이트] 미리 보기(703-3) — 바뀌는 단가 줄 · 다시 가져올 사본 · 지킬 고친 칸 · 노임 판."""
|
||||
"""미리 보기 — 단가 갱신(795-4) = 바뀐 자원 · 총괄 금액 전 → 후 ·
|
||||
재생성(703-3) = 바뀌는 단가 줄 · 다시 가져올 사본 · 지킬 고친 칸 · 노임 판."""
|
||||
root = await _project_root(project_id)
|
||||
raw = (body or {}).get("user")
|
||||
draft = store.clean_user(raw) if isinstance(raw, dict) else None
|
||||
keys = await _demand(root, draft)
|
||||
book = await asyncio.to_thread(store.read_book, root)
|
||||
user = draft if draft is not None else await asyncio.to_thread(store.read_user, root)
|
||||
return await asyncio.to_thread(refresh.preview, root, book, keys, user.get("daega_cover"))
|
||||
if (body or {}).get("job") == refresh.REGEN:
|
||||
return await asyncio.to_thread(refresh.preview, root, book, keys, user.get("daega_cover"))
|
||||
new = await asyncio.to_thread(prices.refresh_book, keys, book)
|
||||
before = await payload(project_id, root, draft, True, keys)
|
||||
after = await payload(project_id, root, draft, True, keys, new)
|
||||
cells = refresh.cover_cells(user.get("daega_cover")) + refresh.cover_cells(user.get("sg_cover"))
|
||||
return refresh.price_preview(book, new, before["sheets"], after["sheets"], cells)
|
||||
|
||||
|
||||
@router.post("/{project_id}/estimation/calc")
|
||||
|
||||
Reference in New Issue
Block a user