fix(est): preserve unmatched progress exclusions
This commit is contained in:
@@ -1,6 +1,23 @@
|
||||
from test_est_rea_parity import run
|
||||
|
||||
|
||||
def test_progress_exclusions_preserve_new_rows_and_reject_ambiguous_keys():
|
||||
result = run(
|
||||
"math",
|
||||
"""(()=>{
|
||||
const p=EstNative.empty();p.tables.EstMainDat=[{PkID:1,Code:'A',EscProgress:9},
|
||||
{PkID:2,Code:'B',EscProgress:7}];
|
||||
const before=JSON.stringify(p), saved={rows:[{PkID:1,Code:'A',TotalGN:3}]};
|
||||
const updates=EstBusiness.progressExclusions(p,saved);let blocked=0;
|
||||
try{EstBusiness.progressExclusions(p,{rows:[{Code:'A',TotalGN:1},{Code:'A',TotalGN:2}]})}catch{blocked++}
|
||||
const q=structuredClone(p);q.tables.EstMainDat=[{Code:'A'},{Code:'A'}];
|
||||
try{EstBusiness.progressExclusions(q,{rows:[{Code:'A',TotalGN:1}]})}catch{blocked++}
|
||||
return {updates,blocked,same:before===JSON.stringify(p)};
|
||||
})()""",
|
||||
)
|
||||
assert result == {"updates": [{"index": 0, "value": 3}], "blocked": 2, "same": True}
|
||||
|
||||
|
||||
def test_escalation_preserves_explicit_zero_total_and_falls_back_only_without_wonga():
|
||||
result = run(
|
||||
"math",
|
||||
|
||||
@@ -142,17 +142,14 @@ const EstBusinessActions = (() => {
|
||||
choices: locked.map((round) => [round.id, round.name]),
|
||||
},
|
||||
],
|
||||
(values) =>
|
||||
(values) => {
|
||||
const result = locked.find((round) => round.id === values.id).result;
|
||||
const updates = EstBusiness.progressExclusions(project, result);
|
||||
EstApp.change(() => {
|
||||
const result = locked.find((round) => round.id === values.id).result;
|
||||
const rows = new Map(
|
||||
result.rows.map((row, index) => [EstBusiness.rowKey(row, index), row]),
|
||||
);
|
||||
project.tables.EstMainDat.forEach(
|
||||
(row, index) =>
|
||||
(row.EscProgress = Number(rows.get(EstBusiness.rowKey(row, index))?.TotalGN) || 0),
|
||||
);
|
||||
}, false),
|
||||
for (const { index, value } of updates)
|
||||
project.tables.EstMainDat[index].EscProgress = value;
|
||||
}, false);
|
||||
},
|
||||
);
|
||||
} else if (name === "load-contract" || name === "load-bid") {
|
||||
purpose = name;
|
||||
|
||||
@@ -4,6 +4,27 @@ const EstBusiness = (() => {
|
||||
const copy = (value) => structuredClone(value);
|
||||
const rowKey = (row, index) => String(row.PkID ?? (row.Code || `row:${index}`));
|
||||
const special = (row) => [57, 58, 62, 67].includes(num(row.LinkIndex));
|
||||
function progressExclusions(project, result) {
|
||||
const saved = new Map();
|
||||
result.rows.forEach((row, index) => {
|
||||
const key = rowKey(row, index);
|
||||
if (saved.has(key)) throw Error(`기성 내역 식별자가 중복됩니다: ${key}`);
|
||||
const value = Number(row.TotalGN);
|
||||
if (!Number.isFinite(value)) throw Error(`기성 누계수량 오류: ${key}`);
|
||||
saved.set(key, value);
|
||||
});
|
||||
const counts = new Map();
|
||||
project.tables.EstMainDat.forEach((row, index) => {
|
||||
const key = rowKey(row, index);
|
||||
counts.set(key, (counts.get(key) || 0) + 1);
|
||||
});
|
||||
return project.tables.EstMainDat.flatMap((row, index) => {
|
||||
const key = rowKey(row, index);
|
||||
if (!saved.has(key)) return [];
|
||||
if (counts.get(key) !== 1) throw Error(`현재 내역 식별자가 중복됩니다: ${key}`);
|
||||
return [{ index, value: saved.get(key) }];
|
||||
});
|
||||
}
|
||||
function moveEstimateRows(rows, selection, direction) {
|
||||
const indices = [...selection].sort((a, b) => a - b);
|
||||
if (!indices.length) throw Error("이동할 내역 행을 선택하세요.");
|
||||
@@ -384,6 +405,7 @@ const EstBusiness = (() => {
|
||||
annual,
|
||||
newAnnualName,
|
||||
rowKey,
|
||||
progressExclusions,
|
||||
moveEstimateRows,
|
||||
importContract,
|
||||
importBid,
|
||||
|
||||
Reference in New Issue
Block a user