- 원본 처리 근거대로 커서 자리 품명 나누기, 삭제할 칸, 빈 단위만 채움 - 내역·일위대가 행을 새 자재(M)·견적(W) 단가로 등록하고 연결, 중복·호표 거부 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
103 lines
4.5 KiB
Python
103 lines
4.5 KiB
Python
"""EST 테스트 앱 품명정리와 자재·견적단가 등록(원본 TfrmNameDevide·popMainStuffcReg·popMainEstimateReg)."""
|
|
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
FILES = [
|
|
"native-math.js",
|
|
"native-formula.js",
|
|
"native-machine.js",
|
|
"native-rows.js",
|
|
"native-text.js",
|
|
"native-quantity.cjs",
|
|
"native-wonga.js",
|
|
"native-engine.js",
|
|
"native-row-match.js",
|
|
"native-escalation.js",
|
|
"native-progress.js",
|
|
"native-business.js",
|
|
"native-review.js",
|
|
"native-resources.js",
|
|
"native-schedule.js",
|
|
"native-model.js",
|
|
"native-verify.js",
|
|
"native-name-reg.js",
|
|
]
|
|
|
|
|
|
def run_js(code: str):
|
|
runner = f"""
|
|
const fs = require('fs'), vm = require('vm');
|
|
const ctx = vm.createContext({{ structuredClone, console }});
|
|
for (const f of {json.dumps(FILES)})
|
|
vm.runInContext(fs.readFileSync('tools/est-test/' + f, 'utf8'), ctx, {{ filename: f }});
|
|
ctx.source = JSON.parse(fs.readFileSync('tools/est-test/sample.json', 'utf8'));
|
|
process.stdout.write(JSON.stringify(vm.runInContext({json.dumps(code)}, ctx)));
|
|
"""
|
|
return json.loads(subprocess.check_output(["node", "-e", runner], cwd=ROOT).decode("utf-8"))
|
|
|
|
|
|
def test_divide_splits_at_position_and_syncs_title():
|
|
result = run_js(
|
|
"""(() => {
|
|
const p = { tables: {
|
|
HeadMainDat: [{ Index: 1, Code: 'U1', Name: '거푸집 설치 합판', Size: '3회', Unite: '' }, { Code: 'L1', LinkIndex: 6 },
|
|
{ Index: 2, Code: 'U2', Name: '거푸집 해체 강재', Size: '', Unite: '㎡' }],
|
|
HeadTitleDat: [{ Code: 'U1', Name: '거푸집 설치 합판' }, { Code: 'U2', Name: '거푸집 해체 강재' }] } };
|
|
const n = EstNameReg.divide(p, [0, 1, 2], 4, 0, '㎡');
|
|
const c = { tables: { HeadMainDat: [{ Index: 1, Code: 'X', Name: 'AB-CD', Size: '' }] } };
|
|
EstNameReg.divide(c, [0], 2, 1, '');
|
|
let bad = ''; try { EstNameReg.divide(p, [1], 4, 0, ''); } catch (e) { bad = e.message.slice(0, 6); }
|
|
const r = p.tables.HeadMainDat;
|
|
return { n, a: [r[0].Name, r[0].Size, r[0].Unite], b: [r[2].Name, r[2].Size, r[2].Unite],
|
|
title: p.tables.HeadTitleDat[0].Size, bad, cut: c.tables.HeadMainDat[0].Size };
|
|
})()"""
|
|
)
|
|
assert result["n"] == 2
|
|
assert result["a"] == ["거푸집 ", "설치 합판3회", "㎡"]
|
|
assert result["b"] == ["거푸집 ", "해체 강재", "㎡"]
|
|
assert result["title"] == "설치 합판3회"
|
|
assert result["bad"] == "품명을 정리"
|
|
assert result["cut"] == "CD"
|
|
|
|
|
|
def test_register_stuff_and_estimate_link_row_and_keep_price():
|
|
result = run_js(
|
|
r"""(() => {
|
|
const calc = (x) => EstNative.calculate(EstModel.validate(x));
|
|
const p = calc(structuredClone(source));
|
|
const i = p.tables.EstMainDat.findIndex((r) => Number(r.GU) > 0 && !Number(r.Level) && Number(r.LinkIndex) === 5);
|
|
p.tables.EstMainDat[i].Name = '시험 자재 등록품';
|
|
const before = p.tables.EstMainDat[i].TC;
|
|
const code = EstNameReg.register(p, 'EstMainDat', i, 'stuff');
|
|
const rec = p.tables.StuffcDat.find((r) => r.Code === code);
|
|
const j = p.tables.EstMainDat.findIndex((r, k) => k !== i && Number(r.JU) + Number(r.NU) > 0 && !Number(r.Level) && r.Name);
|
|
p.tables.EstMainDat[j].Name = '시험 견적 등록품';
|
|
const w = EstNameReg.register(p, 'EstMainDat', j, 'estimate');
|
|
const est = p.tables.EstiMateDat.find((r) => r.Code === w);
|
|
const after = calc(p);
|
|
const errors = [];
|
|
for (const fn of [() => EstNameReg.register(p, 'EstMainDat', i, 'stuff'),
|
|
() => EstNameReg.register(p, 'HeadMainDat', p.tables.HeadMainDat.findIndex((r) => Number(r.Index) > 0), 'stuff')])
|
|
try { fn(); } catch (e) { errors.push(e.message.slice(0, 6)); }
|
|
return { code: /^M\d{10}$/.test(code), price: rec.Cost1 === Number(p.tables.EstMainDat[i].GU) && rec.TC === rec.Cost1,
|
|
link: [p.tables.EstMainDat[i].LinkIndex, p.tables.EstMainDat[i].Code === code],
|
|
same: after.tables.EstMainDat[i].TC === before, w: /^W\d{10}$/.test(w),
|
|
est: est.TC === est.NC + est.GC + est.JC && est.ONC === est.NC, estLink: p.tables.EstMainDat[j].LinkIndex,
|
|
errors, calcErrors: after.calculation.errors.length };
|
|
})()"""
|
|
)
|
|
assert result == {
|
|
"code": True,
|
|
"price": True,
|
|
"link": [5, True],
|
|
"same": True,
|
|
"w": True,
|
|
"est": True,
|
|
"estLink": 101,
|
|
"errors": ["같은 명칭의", "호표는 자재"],
|
|
"calcErrors": 0,
|
|
}
|