158 lines
6.6 KiB
Python
158 lines
6.6 KiB
Python
from test_est_rea_parity import run
|
|
|
|
|
|
def test_estimate_move_preserves_row_identity_and_blocks_ambiguous_or_total_rows():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const rows=[{PkID:1,Code:'A'},{PkID:2,Code:'B'},{PkID:3,Code:'C'},{LinkIndex:54}];
|
|
const moved=EstBusiness.moveEstimateRows(rows,new Set([1,2]),-1);
|
|
const order=rows.map(row=>row.PkID||0);
|
|
const restored=EstBusiness.moveEstimateRows(rows,new Set(moved),1);
|
|
let blocked=0;
|
|
for (const [data,selection,direction] of [
|
|
[[{Code:'A'},{Code:'A'}],[0],1],
|
|
[[{PkID:1},{LinkIndex:54}],[0],1],
|
|
[[{PkID:1},{PkID:2},{PkID:3}],[0,2],1],
|
|
[[{PkID:1},{Name:'unknown'}],[0],1]]) {
|
|
try{EstBusiness.moveEstimateRows(data,new Set(selection),direction)}catch{blocked++}
|
|
}
|
|
return {moved,order,restored,blocked};
|
|
})()""",
|
|
)
|
|
assert result == {"moved": [0, 1], "order": [2, 3, 1, 0], "restored": [1, 2], "blocked": 4}
|
|
|
|
|
|
def test_duplicate_codes_match_distinct_original_rows_and_track_deletions():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.tables.EstMainDat=[{Code:'A',Name:'first',GN:2,TC:200},
|
|
{Code:'A',Name:'second',GN:4,TC:400}];
|
|
p.baseline={name:'old',tables:{EstMainDat:[{Code:'A',Name:'first',GN:1,TC:100},
|
|
{Code:'A',Name:'second',GN:3,TC:300},{Code:'A',Name:'removed',GN:5,TC:500}]}};
|
|
return EstBusiness.changes(p);
|
|
})()""",
|
|
)
|
|
assert [row["originalTC"] for row in result] == [100, 300, 500]
|
|
assert [row["difference"] for row in result] == [100, 100, -500]
|
|
assert result[-1]["status"] == "deleted"
|
|
|
|
|
|
def test_design_change_costs_include_duplicate_new_and_deleted_cost_rows():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.tables.Wonga=[
|
|
{Gubun:'A',Name:'first',Cost:200},{Gubun:'A',Name:'second',Cost:60},
|
|
{Gubun:'C',Name:'new',Cost:25}];
|
|
p.baseline={name:'old',tables:{EstMainDat:[],Wonga:[
|
|
{Gubun:'A',Name:'first',Cost:100},{Gubun:'A',Name:'second',Cost:50},
|
|
{Gubun:'B',Name:'removed',Cost:30}]}};
|
|
const before=JSON.stringify(p), rows=EstBusiness.costChanges(p);
|
|
const output=EstForms.data('change-costs',p);
|
|
const node={innerHTML:''};globalThis.EstApp={esc:x=>String(x??''),number:x=>String(x??0),byId:()=>node};
|
|
EstExtra.render({project:p,view:'change'});
|
|
return {rows,output,html:node.innerHTML,same:before===JSON.stringify(p)};
|
|
})()""",
|
|
)
|
|
assert result["same"]
|
|
assert [row["difference"] for row in result["rows"]] == [100, 10, 25, -30]
|
|
assert result["output"]["rows"] == result["rows"]
|
|
assert "removed" in result["html"]
|
|
|
|
|
|
def test_stored_original_costs_remain_attached_to_each_duplicate_row():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.tables.Wonga=[
|
|
{Gubun:'A',Name:'new',Cost:10},{Gubun:'A',Name:'existing',Cost:50,Cost_:30}];
|
|
return EstBusiness.costChanges(p);
|
|
})()""",
|
|
)
|
|
assert [row["originalCost"] for row in result] == [0, 30]
|
|
assert [row["difference"] for row in result] == [10, 20]
|
|
|
|
|
|
def test_change_view_includes_named_rows_without_codes():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.tables.EstMainDat=[{PkID:1,Code:'',Name:'earthwork',GN:2,TC:200}];
|
|
p.baseline={name:'base',tables:{EstMainDat:[{PkID:1,Code:'',Name:'earthwork',GN:1,TC:100}]}};
|
|
const node={innerHTML:''};globalThis.EstApp={esc:x=>String(x??''),number:x=>String(x??0),byId:()=>node};
|
|
const state={project:p,view:'change'};EstExtra.render(state);return {html:node.innerHTML,changes:EstBusiness.changes(p)};
|
|
})()""",
|
|
)
|
|
assert "earthwork" in result["html"]
|
|
assert result["changes"][0]["difference"] == 100
|
|
|
|
|
|
def test_original_recalculation_modes_keep_old_quantities_and_only_refresh_selected_prices():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();
|
|
p.tables.StuffcDat=[{PkID:1,Code:'M',ValueIndex:4,InputTC:100}];
|
|
p.tables.EstMainDat=[{PkID:1,Code:'M',LinkIndex:5,GN:2},{PkID:2,LinkIndex:54}];
|
|
const q=EstBusiness.baseline(EstNative.calculate(p));
|
|
const before=JSON.stringify(q.baseline);
|
|
q.tables.StuffcDat[0].InputTC=150;q.tables.EstMainDat[0].GN=7;
|
|
q.tables.EstMainDat.splice(1,0,{PkID:3,Code:'M',LinkIndex:5,GN:1,NewItem:true});
|
|
const modes=[0,1,2].map(method=>EstBusiness.original(q,method).tables.EstMainDat);
|
|
return {modes,unchanged:before===JSON.stringify(q.baseline)};
|
|
})()""",
|
|
)
|
|
assert result["unchanged"]
|
|
for mode, rows in enumerate(result["modes"]):
|
|
assert rows[0]["GN"] == 2
|
|
assert rows[0]["TC"] == (200 if mode == 0 else 300)
|
|
assert rows[1]["TC"] == 150
|
|
assert rows[-1]["TC"] == (350 if mode == 0 else 450)
|
|
|
|
|
|
def test_design_change_includes_deleted_and_new_rows_without_modifying_contract():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.options.SourceRefresh=false;
|
|
p.tables.EstMainDat=[{PkID:1,Code:'A',Name:'kept',GN:2,GU:100},
|
|
{PkID:3,Code:'B',Name:'removed',GN:3,NU:50},{PkID:2,LinkIndex:54}];
|
|
let q=EstBusiness.baseline(EstNative.calculate(p));
|
|
const before=JSON.stringify(q.baseline);
|
|
q.tables.EstMainDat.splice(1,1);
|
|
q.tables.EstMainDat[0].GN=4;
|
|
q.tables.EstMainDat.splice(1,0,{...EstModel.newRow('EstMainDat',q.tables.EstMainDat,q),Code:'C',Name:'new',GN:1,JU:25});
|
|
q=EstNative.calculate(q);
|
|
return {changes:EstBusiness.changes(q),same:before===JSON.stringify(q.baseline)};
|
|
})()""",
|
|
)
|
|
assert result["same"]
|
|
rows = {row["Code"]: row for row in result["changes"] if row["Code"]}
|
|
assert rows["A"]["status"] == "changed"
|
|
assert rows["A"]["difference"] == 200
|
|
assert rows["B"]["status"] == "deleted"
|
|
assert rows["B"]["originalGN"] == 3
|
|
assert rows["B"]["GN"] == rows["B"]["TC"] == 0
|
|
assert rows["B"]["difference"] == -150
|
|
assert rows["C"]["status"] == "new"
|
|
assert rows["C"]["difference"] == 25
|
|
|
|
|
|
def test_blank_codes_have_distinct_keys_and_metadata_changes_are_reported():
|
|
result = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.tables.EstMainDat=[
|
|
{PkID:1,Code:'A',Name:'renamed',GN:1,TC:10},
|
|
{Code:'',Name:'first'},{Code:'',Name:'second'}];
|
|
p.baseline={name:'old',tables:{EstMainDat:[
|
|
{PkID:1,Code:'A',Name:'old',GN:1,TC:10}]}};
|
|
return {rows:EstBusiness.changes(p),keys:p.tables.EstMainDat.map(EstBusiness.rowKey)};
|
|
})()""",
|
|
)
|
|
assert len(set(result["keys"][1:])) == 2
|
|
assert result["rows"][0]["status"] == "changed"
|
|
assert result["rows"][0]["difference"] == 0
|