fix(est-test): handle percent details and subtotals

This commit is contained in:
2026-11-09 23:33:40 +09:00
parent 741805ffde
commit ae31ac00fb
9 changed files with 99 additions and 14 deletions
+51
View File
@@ -91,3 +91,54 @@ def test_jdl_special_machine_detail_is_fixed_only_when_amounts_match():
assert "상세 산식 미변환" in result["before"][6]["Name"]
assert any("특수 기계 상세" in warning for warning in result["warnings"])
assert not result["errors"]
def test_jdl_machine_percent_detail_round_trips_fixed_amounts():
project = run("math", "EstNative.empty()")
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
const empty=JSON.parse(fs.readFileSync(0,'utf8')),blank=structuredClone(empty);
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
['junit.txt',table('junit.txt',[{F_CODE:'J1',F_DES:'machine',F_MPRICE:5},{F_CODE:'J2',F_DES:'ambiguous',F_MPRICE:50}])],
['jpart.txt',table('jpart.txt',[{F_CODE:'J1',F_SEQ:'1',F_DES:'percent',F_UNIT:'%',F_QQTY:10,F_MPRICE:50,F_SPROPER:'1'},
{F_CODE:'J2',F_SEQ:'1',F_DES:'uncertain',F_UNIT:'%',F_QQTY:1,F_MPRICE:50}])]]);
const p=j.read(a.pack(files),empty),before=structuredClone(p.tables.MachMainDat);p.options.AutoCalc=true;
p.tables.MachMainDat[1].GC=6;const q=s.calculate(p),out=j.output(q),entries=a.unpack(out.bytes),back=j.read(out.bytes,blank);
process.stdout.write(JSON.stringify({before,parts:j.parse('jpart.txt',entries.get('jpart.txt')),
rows:back.tables.MachMainDat,errors:q.calculation.errors}));"""
result = json.loads(
subprocess.check_output(
["node", "-e", script], input=json.dumps(project).encode(), cwd=ROOT
)
)
assert result["before"][1]["GC"] == 5
assert result["before"][1]["GN"] == 10
assert result["before"][1]["JdlSourceQuantity"] == 10
assert result["parts"][0]["F_UNIT"] == "%"
assert result["parts"][0]["F_QQTY"] == 100
assert result["rows"][1]["GC"] == 6
assert "상세 산식 미변환" in result["before"][-1]["Name"]
assert not result["errors"]
def test_jdl_fixed_unit_percent_exports_a_consistent_quantity():
project = run("math", "EstNative.empty()")
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs');
const p=JSON.parse(fs.readFileSync(0,'utf8')),empty=structuredClone(p);p.name='percent';
p.tables.HeadTitleDat=[{Code:'U',Name:'unit',GC:10,TC:10}];
p.tables.HeadMainDat=[{Index:1,Code:'U'},
{Index:0,Name:'fixed percent',Unite:'%',CalcIndex:1,JdlSummary:true,GC:10,TC:10}];
p.tables.EstMainDat=[{Code:'U',Name:'unit',LinkIndex:103,GN:2,GU:10,GC:20,TC:20},{LinkIndex:54}];
const out=j.output(p),files=a.unpack(out.bytes),parts=j.parse('unitpart.txt',files.get('unitpart.txt')),
q=j.read(out.bytes,empty);
process.stdout.write(JSON.stringify({part:parts[0],row:q.tables.HeadMainDat[1],total:q.tables.EstMainDat.at(-1).TC}));"""
result = json.loads(
subprocess.check_output(
["node", "-e", script], input=json.dumps(project).encode(), cwd=ROOT
)
)
assert result["part"]["F_UNIT"] == "%"
assert result["part"]["F_QQTY"] == 100
assert result["part"]["F_MPRICE"] == result["part"]["F_MCOST"] == 10
assert result["row"]["GC"] == 10
assert result["total"] == 20
+20
View File
@@ -49,6 +49,26 @@ def test_redundant_price_caption_keeps_quantity_and_source_updates():
assert result["mismatch"]["errors"]
def test_component_total_ignores_following_numeric_substitution():
result = run(
"math",
"""(() => {
const rows = [
{Index:1, Code:'D1'},
{Index:0, LineData:'LL = 5'},
{Index:0, SCheck:-3, LineData:'100 = \\x12100\\x12'},
{Index:0, SCheck:-3, LineData:'\\x1a경비 : 100\\x1a ÷ LL = 100 ÷ 5 = \\x1220\\x12'}
];
const first=EstText.calculate(rows);rows[1].LineData='LL = 4';rows[2].LineData='120 = \\x12100\\x12';
return {first,changed:EstText.calculate(rows)};
})()""",
)
assert result["first"]["errors"] == []
assert result["first"]["rows"][3]["TC"] == 20
assert result["changed"]["errors"] == []
assert result["changed"]["rows"][3]["TC"] == 30
def test_equals_in_description_is_not_a_formula_separator():
result = run(
"math",