fix(est): reject reserved annual names

This commit is contained in:
2026-11-07 02:43:36 +09:00
parent 042d574fee
commit 6cea0c97f2
3 changed files with 19 additions and 1 deletions
@@ -39,3 +39,19 @@ def test_annual_copy_rejects_invalid_or_forward_references():
})()""",
)
assert "참조 항목 없음" in result
def test_annual_rejects_names_that_shadow_contract_references():
result = run(
"math",
"""(()=>{
const p=EstNative.empty();p.tables.EstMainDat=[{Code:'R',GN:1,GC:100,TC:100,CalcIndex:1}];
return ['기준','계약','계약수량','first'].map(name=>{
p.annual=[{name,formula:'[기준]*0.5'},{name:'next',formula:'[기준]-['+name+']'}];
return EstBusiness.annual(p,false);
});
})()""",
)
assert all(item["errors"] for item in result[:3])
assert result[3]["errors"] == []
assert result[3]["results"][1]["project"]["tables"]["EstMainDat"][0]["TC"] == 50
+1 -1
View File
@@ -41,7 +41,7 @@ Ctrl+S는 입력 중인 셀도 확정한 뒤 저장합니다. 연속 저장 요
단가 변경은 산근 소계(61), 비목 참조 비율(58), 선택 구간 합계(62)를 거쳐 내역으로 전달됩니다. 산출근거 편집기의 `구간지정`·`구간합계` 표지로 A~Z 묶음을 제어합니다. 소계 표지 1,433개를 추가한 대용량 원본 대조는 115,145개 일치·해석 오류 0이며, 원본 산근 낙찰 행(52)의 성분 계산과 연결 편집도 회귀 시험합니다.
연차공사의 `[기준]*0.5` 수식은 수량과 각 성분 금액에 각각 적용됩니다. 금액은 정수 절사하고, 다음 차수의 `[기준]-[1차]`로 절사 후 잔액을 배분합니다. 차수 사본은 단가를 비운 고정 금액으로 저장하여 다시 열어도 금액을 유지합니다. `[계약수량]`은 이전 작업 파일과의 호환 표기로 `[기준]`과 같은 역할을 합니다.
연차공사의 `[기준]*0.5` 수식은 수량과 각 성분 금액에 각각 적용됩니다. 금액은 정수 절사하고, 다음 차수의 `[기준]-[1차]`로 절사 후 잔액을 배분합니다. 차수 사본은 단가를 비운 고정 금액으로 저장하여 다시 열어도 금액을 유지합니다. `[계약수량]`은 이전 작업 파일과의 호환 표기로 `[기준]`과 같은 역할을 합니다. 참조가 충돌하지 않도록 차수 이름에는 `기준`, `계약`, `계약수량`을 사용할 수 없습니다.
연차의 조달수수료는 원본처럼 연결 종류 99로 전환해 금액을 배분하며 요율은 유지합니다. 관급 합계와 안전관리비의 수수료 제외 계산에 배분액을 반영하고, 합산 제외 행은 제외 상태를 유지합니다. 차수 내역 열기는 해당 내역서를 표시하며, 저장하면 원본과 다른 파일 ID를 부여해 원본을 덮어쓰지 않습니다.
+2
View File
@@ -222,6 +222,8 @@ const EstBusiness = (() => {
const names = (project.annual || []).map((year) => String(year.name || "").trim());
if (names.some((name) => !name.trim()) || new Set(names).size !== names.length)
return { results, errors: ["차수 이름은 비어 있거나 중복될 수 없습니다."] };
if (names.some((name) => ["기준", "계약", "계약수량"].includes(name)))
return { results, errors: ["차수 이름에 기준·계약·계약수량은 사용할 수 없습니다."] };
for (const year of project.annual || []) {
const next = full ? copy(project) : EstNative.empty();
if (!full) {