feat(est): print progress and price adjustments

This commit is contained in:
2026-11-07 08:48:25 +09:00
parent b3bd093d42
commit cffeb84ce4
3 changed files with 99 additions and 5 deletions
+25
View File
@@ -1,6 +1,31 @@
from test_est_rea_parity import run
def test_progress_and_escalation_print_use_selected_calculations():
result = run(
"math",
"""(()=>{
const p=EstNative.empty();p.options.SourceRefresh=false;p.options.EscDesignTotal=1000;
p.tables.EstMainDat=[{PkID:1,Code:'R',Name:'work',GN:10,GU:100,AGU:100,EscActual:3},{LinkIndex:54}];
p.progress=[{id:'one',name:'first',inputs:{'1':{Gum:2}}}];
const q=EstProgress.lock(EstNative.calculate(p),'one');
q.tables.EstMainDat[0].GU=200;
q.progress.push({id:'two',name:'second',inputs:{'1':{Gum:3}}});
return {locked:EstForms.data('progress-summary',q,{roundId:'one'}),
draft:EstForms.data('progress-summary',q,{roundId:'two'}),
escalation:EstForms.data('escalation-summary',p),
empty:EstForms.data('progress-summary',EstNative.empty())};
})()""",
)
assert result["locked"]["rows"][0]["GumTC"] == 200
assert result["locked"]["rows"][0]["GU"] == 100
assert result["draft"]["rows"][0]["GumTC"] == 600
assert result["draft"]["rows"][0]["TotalTC"] == 800
assert result["escalation"]["rows"][0]["EscExcluded"] == 3
assert result["escalation"]["rows"][0]["EscApplied"] == 7
assert result["empty"]["errors"]
def test_resource_report_separates_each_work_item_without_changing_aggregate():
result = run(
"math",
+63 -1
View File
@@ -1,6 +1,54 @@
const EstForms = (() => {
const common = ["Code", "Name", "Size", "Unite"];
function data(id, project) {
function data(id, project, state = {}) {
if (id === "progress-summary") {
const round =
project.progress.find((item) => item.id === state.roundId) || project.progress.at(-1);
if (!round) return { columns: ["Name"], rows: [], errors: ["기성 회차가 없습니다."] };
const result =
round.locked && round.result ? round.result : EstProgress.calculate(project, round.id);
return {
columns: [
"Code",
"Name",
"Unite",
"GN",
"TC",
"JunGN",
"JunTC",
"GumGN",
"GumTC",
"SaGN",
"SaTC",
"TotalGN",
"TotalTC",
],
rows: result.rows,
errors: result.errors,
detail: `${round.name || "기성"} (${round.locked ? "확정" : "작성 중"})`,
};
}
if (id === "escalation-summary") {
const result = EstEscalation.calculate(project);
return {
columns: [
"Code",
"Name",
"Unite",
"GN",
"EscExcluded",
"EscApplied",
"TC",
"ENC",
"EGC",
"EJC",
"ESC",
],
rows: result.rows,
errors: result.errors,
detail: `도급액 ${result.contractTotal} · 조정액 ${result.adjustment} · 조정률 ${result.rate}%`,
};
}
if (id === 171) {
const output = EstReview.calculate(project);
const rows = output.baseline.tables.EstMainDat.map((row, index) => ({
@@ -179,6 +227,20 @@ const EstForms = (() => {
SheetName: "산출서",
Error: "계산 오류",
Reason: "심사 사유",
JunGN: "전회 수량",
JunTC: "전회 금액",
GumGN: "금회 수량",
GumTC: "금회 금액",
SaGN: "사정 수량",
SaTC: "사정 금액",
TotalGN: "누계 수량",
TotalTC: "누계 금액",
EscExcluded: "제외 수량",
EscApplied: "적용 수량",
ENC: "노무비 증감",
EGC: "재료비 증감",
EJC: "경비 증감",
ESC: "산출경비 증감",
TargetCode: "연결 내역",
TU: "단가",
TC: "금액",
+11 -4
View File
@@ -20,7 +20,7 @@ const EstReport = (() => {
const { state, esc } = EstApp;
const settings = setting(),
form = catalog.find((row) => String(row.Index) === settings.form),
output = form ? EstForms.data(form.Index, state.project) : null;
output = form ? EstForms.data(form.Index, state.project, state) : null;
const number = (value) =>
new Intl.NumberFormat("ko-KR", { maximumFractionDigits: 12 }).format(Number(value) || 0);
const root = document.createElement("div");
@@ -76,15 +76,18 @@ const EstReport = (() => {
.forEach((node) => node.removeAttribute("contenteditable"));
const title = form?.Name2 || EstApp.titles[state.view] || state.view;
const detail =
state.view === "quantity"
output?.detail ||
(state.view === "quantity"
? state.project.quantitySheets?.find((sheet) => sheet.Code === state.quantitySheet)?.Name
: state.view === "progress"
? state.project.progress.find((round) => round.id === state.roundId)?.name
: state.group
? EstNative.groups(state.project.tables[state.view] || []).get(state.group)?.rows[0]
?.Name
: "";
const totals = state.project.calculation;
: "");
const totals = ["progress-summary", "escalation-summary"].includes(form?.Index)
? null
: state.project.calculation;
const errors = [...(totals?.errors || []), ...(output?.errors || [])];
const source = `<!doctype html><html lang="ko"><head><meta charset="UTF-8"><title>${esc(state.project.name)} · ${esc(title)}</title>
<style>@page{size:${settings.paper} ${settings.orientation};margin:${settings.margin}mm}*{box-sizing:border-box}body{font:${settings.font}pt "Malgun Gothic",sans-serif;color:#111;margin:0}
@@ -127,6 +130,10 @@ const EstReport = (() => {
...row,
...original.get(row.Index),
}));
catalog.push(
{ Index: "progress-summary", Name: "기성 내역서", Name2: "기성 내역서" },
{ Index: "escalation-summary", Name: "물가변동 내역서", Name2: "물가변동 내역서" },
);
const table = EstApp.state.project.tables[EstApp.state.view];
const s = setting(),
{ esc } = EstApp;