Files
Aislo/resources/tester/test_est_change_workflow.py
T

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