feat(est): show standard price design changes
This commit is contained in:
@@ -1,6 +1,31 @@
|
||||
from test_est_rea_parity import run
|
||||
|
||||
|
||||
def test_standard_changes_include_new_deleted_and_changed_link_types():
|
||||
result = run(
|
||||
"math",
|
||||
"""(()=>{
|
||||
const p=EstNative.empty();p.tables.EstMainDat=[
|
||||
{PkID:1,Code:'A',Name:'changed',LinkIndex:21,GN:2,TC:200},
|
||||
{PkID:2,Code:'B',Name:'changed link',LinkIndex:5,GN:1,TC:50},
|
||||
{PkID:4,Code:'D',Name:'new',LinkIndex:21,GN:1,TC:40}];
|
||||
p.baseline={tables:{EstMainDat:[
|
||||
{PkID:1,Code:'A',Name:'changed',LinkIndex:21,GN:1,TC:100},
|
||||
{PkID:2,Code:'B',Name:'changed link',LinkIndex:21,GN:1,TC:50},
|
||||
{PkID:3,Code:'C',Name:'deleted',LinkIndex:21,GN:3,TC:300},
|
||||
{PkID:5,Code:'E',Name:'other',LinkIndex:5,GN:1,TC:10}]}};
|
||||
return {rows:EstStandard.changes(p),print:EstForms.data('standard-change',p)};
|
||||
})()""",
|
||||
)
|
||||
rows = {row["Code"]: row for row in result["rows"]}
|
||||
assert set(rows) == {"A", "B", "C", "D"}
|
||||
assert rows["A"]["difference"] == 100
|
||||
assert rows["B"]["status"] == "변경"
|
||||
assert rows["C"]["status"] == "삭제" and rows["C"]["index"] is None
|
||||
assert rows["D"]["status"] == "신규"
|
||||
assert result["print"]["rows"] == result["rows"]
|
||||
|
||||
|
||||
def test_standard_usage_reports_applied_and_source_prices_without_mutation():
|
||||
result = run(
|
||||
"math",
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
## Codex · EST 독립 테스트 앱 (2026-11-04)
|
||||
- [x] 표준시장단가 설계변경 내역·증감 화면·출력 구현 → 신규·삭제·연결 변경 시험.
|
||||
- 자체 검증: 표준 내역의 신규·삭제·연결 변경과 문서 기능 시험 21개 통과. Edge에서 증감·삭제 행·인쇄·내역 이동 확인.
|
||||
|
||||
- [x] 표준시장단가 사용 내역·기초 단가 비교 화면·출력 구현 → 연결·중복·누락·행 이동 시험.
|
||||
- 자체 검증: 연결 단가·중복·누락·문서 시험 12개 통과, Edge에서 화면·인쇄·해당 내역 이동 확인.
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
작업모드의 `표준시장단가 사용 내역`은 표준시장단가에 연결된 내역별 적용 단가와 현재 기초 단가, 차이와 연결 상태를 보여 줍니다. 원래 내역으로 이동하거나 해당 표를 인쇄·Excel로 출력할 수 있습니다.
|
||||
|
||||
`표준시장단가 설계변경`에서는 기준 내역과 비교한 신규·삭제·변경 및 금액 증감을 확인하고 인쇄·Excel로 출력할 수 있습니다.
|
||||
|
||||
행을 선택한 뒤 편집 메뉴의 `선택 행 자릿수 설정`에서 처리방식과 소수 자릿수를 일괄 적용할 수 있습니다. 기존 계산 설정은 실행 취소로 되돌릴 수 있습니다.
|
||||
|
||||
내역서 편집 메뉴의 `내역 수량 초기화`는 선택한 상세 행 또는 모든 상세 행의 수량을 0으로 바꿉니다. 비율·합계 자동행은 건드리지 않으며 실행 취소할 수 있습니다.
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
<div class="menu">
|
||||
<button data-view="EstMainDat">내역서</button
|
||||
><button data-view="standard">표준시장단가 사용 내역</button
|
||||
><button data-view="standard-change">표준시장단가 설계변경</button
|
||||
><button data-view="change">설계변경</button><button data-view="progress">기성고</button
|
||||
><button data-view="escalation">물가변동</button
|
||||
><button data-view="annual">연차공사</button><button data-view="review">계약심사</button
|
||||
|
||||
@@ -37,6 +37,7 @@ const EstApp = (() => {
|
||||
issues: "자료 오류 검색",
|
||||
attachments: "첨부파일",
|
||||
standard: "표준시장단가 사용 내역",
|
||||
"standard-change": "표준시장단가 설계변경",
|
||||
drawing: "도면·문서",
|
||||
};
|
||||
const esc = (value) =>
|
||||
|
||||
@@ -123,6 +123,7 @@ const EstBusiness = (() => {
|
||||
: null;
|
||||
const original = saved || stored;
|
||||
return {
|
||||
index,
|
||||
key: rowKey(row, index),
|
||||
Code: row.Code || "",
|
||||
Name: row.Name || "",
|
||||
@@ -130,13 +131,23 @@ const EstBusiness = (() => {
|
||||
originalGN: num(original?.GN),
|
||||
TC: num(row.TC),
|
||||
originalTC: num(original?.TC),
|
||||
LinkIndex: row.LinkIndex,
|
||||
originalLinkIndex: original?.LinkIndex ?? row.LinkIndex,
|
||||
difference: num(row.TC) - num(original?.TC),
|
||||
NewItem: !original,
|
||||
status: !original
|
||||
? "new"
|
||||
: ["Code", "Name", "Size", "Unite", "GN", "TC", ...units, ...components].some(
|
||||
(key) => original[key] != null && original[key] !== row[key],
|
||||
)
|
||||
: [
|
||||
"Code",
|
||||
"Name",
|
||||
"Size",
|
||||
"Unite",
|
||||
"GN",
|
||||
"TC",
|
||||
"LinkIndex",
|
||||
...units,
|
||||
...components,
|
||||
].some((key) => original[key] != null && original[key] !== row[key])
|
||||
? "changed"
|
||||
: "unchanged",
|
||||
originalSource: saved ? "baseline" : stored ? "file" : null,
|
||||
@@ -145,11 +156,13 @@ const EstBusiness = (() => {
|
||||
for (const group of groups.values())
|
||||
for (const { row, index } of group) {
|
||||
changes.push({
|
||||
index: null,
|
||||
key: rowKey(row, index),
|
||||
Code: row.Code || "",
|
||||
Name: row.Name || "",
|
||||
originalGN: num(row.GN),
|
||||
originalTC: num(row.TC),
|
||||
originalLinkIndex: row.LinkIndex,
|
||||
GN: 0,
|
||||
TC: 0,
|
||||
difference: -num(row.TC),
|
||||
|
||||
@@ -28,7 +28,7 @@ const EstExtra = (() => {
|
||||
EstAttachments.render();
|
||||
return;
|
||||
}
|
||||
if (state.view === "standard") {
|
||||
if (["standard", "standard-change"].includes(state.view)) {
|
||||
EstStandard.render();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
const EstForms = (() => {
|
||||
const common = ["Code", "Name", "Size", "Unite"];
|
||||
function data(id, project, state = {}) {
|
||||
if (id === "standard-change")
|
||||
return {
|
||||
columns: ["status", "Code", "Name", "originalGN", "GN", "originalTC", "TC", "difference"],
|
||||
rows: EstStandard.changes(project),
|
||||
};
|
||||
if (id === "standard-usage")
|
||||
return {
|
||||
columns: [
|
||||
|
||||
@@ -353,6 +353,7 @@ const EstModel = (() => {
|
||||
"annual-items",
|
||||
"change-costs",
|
||||
"standard-usage",
|
||||
"standard-change",
|
||||
]);
|
||||
for (const [key, value] of Object.entries(project.documents))
|
||||
if (
|
||||
|
||||
@@ -144,6 +144,7 @@ const EstReport = (() => {
|
||||
{ Index: "annual-items", Name: "연차별 내역서", Name2: "연차별 내역서" },
|
||||
{ Index: "change-costs", Name: "설계변경 원가 증감표", Name2: "설계변경 원가 증감표" },
|
||||
{ Index: "standard-usage", Name: "표준시장단가 사용 내역", Name2: "표준시장단가 사용 내역" },
|
||||
{ Index: "standard-change", Name: "표준시장단가 설계변경", Name2: "표준시장단가 설계변경" },
|
||||
);
|
||||
const table = EstApp.state.project.tables[EstApp.state.view];
|
||||
const s = setting(),
|
||||
|
||||
@@ -34,12 +34,24 @@ const EstStandard = (() => {
|
||||
];
|
||||
});
|
||||
}
|
||||
function changes(project) {
|
||||
const labels = { new: "신규", deleted: "삭제", changed: "변경", unchanged: "동일" };
|
||||
return EstBusiness.changes(project)
|
||||
.filter((row) => Number(row.LinkIndex) === 21 || Number(row.originalLinkIndex) === 21)
|
||||
.map((row) => ({ ...row, status: labels[row.status] || row.status }));
|
||||
}
|
||||
function render() {
|
||||
const { state, esc, number, byId } = EstApp,
|
||||
rows = usage(state.project);
|
||||
isChange = state.view === "standard-change",
|
||||
rows = isChange ? changes(state.project) : usage(state.project);
|
||||
page = Math.max(0, Math.min(page, Math.ceil(rows.length / 100) - 1));
|
||||
const visible = rows.slice(page * 100, page * 100 + 100),
|
||||
value = (v) => (v == null ? "" : number(v));
|
||||
if (isChange) {
|
||||
byId("work-content").innerHTML =
|
||||
`<div class="business-tools"><b>표준시장단가 설계변경</b><span>${rows.length}건 · ${page + 1}/${Math.max(1, Math.ceil(rows.length / 100))}쪽</span><button data-standard-page="-1" ${page === 0 ? "disabled" : ""}>이전</button><button data-standard-page="1" ${(page + 1) * 100 >= rows.length ? "disabled" : ""}>다음</button></div><table class="sheet"><thead><tr><th>구분</th><th>코드</th><th>품명</th><th>당초 수량</th><th>변경 수량</th><th>당초 금액</th><th>변경 금액</th><th>증감</th><th>작업</th></tr></thead><tbody>${visible.map((row) => `<tr><td>${esc(row.status)}</td><td>${esc(row.Code)}</td><td>${esc(row.Name)}</td><td>${value(row.originalGN)}</td><td>${value(row.GN)}</td><td>${value(row.originalTC)}</td><td>${value(row.TC)}</td><td>${value(row.difference)}</td><td>${row.index == null ? "" : `<button data-standard-row="${row.index}">내역 열기</button>`}</td></tr>`).join("")}</tbody></table>`;
|
||||
return;
|
||||
}
|
||||
byId("work-content").innerHTML =
|
||||
`<div class="business-tools"><b>표준시장단가 사용 내역</b><span>${rows.length}건 · ${page + 1}/${Math.max(1, Math.ceil(rows.length / 100))}쪽</span><button data-standard-page="-1" ${page === 0 ? "disabled" : ""}>이전</button><button data-standard-page="1" ${(page + 1) * 100 >= rows.length ? "disabled" : ""}>다음</button></div><p>내역에 적용된 단가와 현재 표준시장단가 자료를 비교합니다.</p><table class="sheet"><thead><tr><th>코드</th><th>품명</th><th>규격</th><th>단위</th><th>수량</th><th>내역 단가</th><th>기초 단가</th><th>차이</th><th>금액</th><th>연결</th><th>작업</th></tr></thead><tbody>${visible.map((row) => `<tr><td>${esc(row.Code)}</td><td>${esc(row.Name)}</td><td>${esc(row.Size)}</td><td>${esc(row.Unite)}</td><td>${value(row.GN)}</td><td>${value(row.appliedPrice)}</td><td>${value(row.sourcePrice)}</td><td>${value(row.difference)}</td><td>${value(row.TC)}</td><td>${esc(row.status)}</td><td><button data-standard-row="${row.index}">내역 열기</button></td></tr>`).join("")}</tbody></table>`;
|
||||
}
|
||||
@@ -61,5 +73,5 @@ const EstStandard = (() => {
|
||||
EstApp.render();
|
||||
});
|
||||
}
|
||||
return { usage, render, install };
|
||||
return { usage, changes, render, install };
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user