feat(stmate-test): 적용기준 행자부(I_SET_BASE 1) 요율 조회 화면 연결 — 간접노무비·일반관리비·이윤 = RATE_M
- 요율 조회(scr_kanjub_rate.lookup) — 적용기준 1 이면 rateMLookup(ST_KanJub 0x47a1bc) 값으로 KANNO·ILBAN·IYUN · 그 밖 RATE_R 그대로 - 적용기준 콤보를 바꾸면 제비율표 다시 조회(요율 축에 I_SET_BASE) - 브라우저 확인(봉화2024): 행자부 → 간접노무비 14.5 → 14.6(RATE_M 11줄 RATE1) · 지방계약법 되돌림 14.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -285,6 +285,7 @@
|
||||
}
|
||||
|
||||
const RATE_AXES = [
|
||||
"I_SET_BASE",
|
||||
"I_KONG_TYPE",
|
||||
"I_KONG_KIKAN",
|
||||
"I_ANJUN_TYPE",
|
||||
@@ -310,11 +311,15 @@
|
||||
);
|
||||
const res = R.applyWithLoopCheck(cfg, R.matrixFromRows(rows), calc, {
|
||||
withTbugum: true,
|
||||
extra: { rateMRows: rateMRows(ctx) },
|
||||
});
|
||||
u.kjMsg = res.loop ? res.msg : res.manual ? "요율 수동 확정 상태 — 요율 그대로" : "";
|
||||
return res;
|
||||
}
|
||||
|
||||
// 적용기준 행자부(I_SET_BASE 1)용 RATE_M 행 — 그 STC 의 표
|
||||
const rateMRows = (ctx) => ((ctx.dbfData && ctx.dbfData.rate_tables) || {})["RATE_M.DBF"] || [];
|
||||
|
||||
function bind(ctx, api) {
|
||||
const re = () => api.renderWorkspace();
|
||||
const { cfg, st } = stageCfg(ctx);
|
||||
@@ -329,7 +334,7 @@
|
||||
switchScheme(cfg, schemeOf(k2));
|
||||
}
|
||||
setKey(cfg, key, val);
|
||||
// 요율 축(공사종류·기간·안전공종·고용등급·환경·건설기계·퇴직공제·일반관리비) — 제비율표 다시 조회 후 다시 셈
|
||||
// 요율 축(적용기준·공사종류·기간·안전공종·고용등급·환경·건설기계·퇴직공제·일반관리비) — 제비율표 다시 조회 후 다시 셈
|
||||
if (RATE_AXES.includes(key)) reRate(ctx, api, cfg);
|
||||
re();
|
||||
});
|
||||
@@ -395,7 +400,7 @@
|
||||
api.recompute(),
|
||||
(ctx.computed.stages[n] || {}).kanjub || ctx.computed.kanjubComputed
|
||||
);
|
||||
const res = R.applyWithLoopCheck(cfg, m, calc);
|
||||
const res = R.applyWithLoopCheck(cfg, m, calc, { extra: { rateMRows: rateMRows(ctx) } });
|
||||
u.kjMsg = res.loop
|
||||
? res.msg
|
||||
: res.manual
|
||||
|
||||
@@ -65,6 +65,17 @@ const StmateRate = (() => {
|
||||
return BANDS[BANDS.length - 1];
|
||||
}
|
||||
|
||||
// 원본 차수·조회 규칙 묶음(kanjub_parts.js) — 브라우저 = 전역 · node = require
|
||||
function kanjubNative() {
|
||||
const g = typeof globalThis !== "undefined" ? globalThis : {};
|
||||
if (g.STMATE_KANJUB_PARTS) return g.STMATE_KANJUB_PARTS.NATIVE;
|
||||
try {
|
||||
return require("./kanjub_parts.js").NATIVE;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 요율 조회 — opts: kongType · kikan · scale(직접공사비) · anjunType · anjunScale · koboType · hwan · eqip · tbugum
|
||||
function lookup(m, opts = {}) {
|
||||
const rates = {},
|
||||
@@ -132,6 +143,20 @@ const StmateRate = (() => {
|
||||
)
|
||||
notes.push(`${c} — 표 칸 [${cells[c]}] 이 비어 있음(직접 입력 요율 유지)`);
|
||||
const zeroed = short ? ["KUNBO", "YUNBO", "SLVBO"] : [];
|
||||
// 적용기준 행자부(I_SET_BASE 1) — 간접노무비·일반관리비·이윤만 RATE_M 에서(ST_KanJub 0x47a1bc · REA 36 §4.2)
|
||||
const NATIVE = kanjubNative();
|
||||
if (n0(opts.setBase) === 1 && NATIVE && (opts.rateMRows || []).length) {
|
||||
const rm = NATIVE.rateMLookup(opts.rateMRows, {
|
||||
scale: opts.scale,
|
||||
kongType: opts.kongType,
|
||||
ilban: opts.ilbanType,
|
||||
kikan: opts.kikan,
|
||||
});
|
||||
for (const [c, v] of Object.entries(rm.rates)) {
|
||||
rates[c] = v;
|
||||
cells[c] = ["RATE_M", ...rm.cells[c]];
|
||||
}
|
||||
}
|
||||
return { rates, cells, amounts, band, anjunBand: ab, notes, zeroed };
|
||||
}
|
||||
|
||||
@@ -149,6 +174,7 @@ const StmateRate = (() => {
|
||||
eqip: k.I_EQIP == null ? 0 : n0(k.I_EQIP),
|
||||
tbugum: n0(k.I_TBUGUM),
|
||||
ilbanType: n0(k.I_ILBAN),
|
||||
setBase: n0(k.I_SET_BASE),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -175,14 +201,14 @@ const StmateRate = (() => {
|
||||
cfg,
|
||||
m,
|
||||
calcFn,
|
||||
{ scaleOf = (kj) => kj.dT, maxIter = 6, withTbugum = false } = {},
|
||||
{ scaleOf = (kj) => kj.dT, maxIter = 6, withTbugum = false, extra = {} } = {},
|
||||
) {
|
||||
let kj = calcFn(cfg);
|
||||
if (cfg.rateConfirm && cfg.rateConfirm.manual) return { cfg, kj, loop: false, manual: true };
|
||||
const seen = [],
|
||||
found = {};
|
||||
for (let i = 0; i < maxIter; i++) {
|
||||
const res = lookup(m, Object.assign(optsFromCfg(cfg, kj), { scale: scaleOf(kj) }));
|
||||
const res = lookup(m, Object.assign(optsFromCfg(cfg, kj), extra, { scale: scaleOf(kj) }));
|
||||
const sig = `${res.band.row}/${res.anjunBand.row}`;
|
||||
if (seen.includes(sig) && seen[seen.length - 1] !== sig) {
|
||||
const choices = seen.slice(seen.indexOf(sig)).map((g) => found[g]);
|
||||
@@ -333,6 +359,12 @@ if (typeof module !== "undefined" && module.exports) module.exports = StmateRate
|
||||
return `<table class="dbgrid"><thead><tr><th>행</th>${head}</tr></thead><tbody>${body.join("")}</tbody></table>`;
|
||||
}
|
||||
|
||||
// 조회 입력 + 행자부기준용 RATE_M 행(그 STC 의 표)
|
||||
const optsOf = (ctx, cfg, kj) =>
|
||||
Object.assign(R.optsFromCfg(cfg, kj), {
|
||||
rateMRows: ((ctx.dbfData && ctx.dbfData.rate_tables) || {})["RATE_M.DBF"] || [],
|
||||
});
|
||||
|
||||
function lookupPanel(ctx, m) {
|
||||
const S = global.STMATE_KANJUB_SCREEN;
|
||||
if (!S || !m.length) return "";
|
||||
@@ -340,7 +372,7 @@ if (typeof module !== "undefined" && module.exports) module.exports = StmateRate
|
||||
const kj =
|
||||
(ctx.computed.stages && ctx.computed.stages[n] && ctx.computed.stages[n].kanjub) ||
|
||||
ctx.computed.kanjubComputed;
|
||||
const res = R.lookup(m, R.optsFromCfg(cfg, kj));
|
||||
const res = R.lookup(m, optsOf(ctx, cfg, kj));
|
||||
const rows = Object.entries(res.rates)
|
||||
.map(([c, v]) => {
|
||||
const cur = cfg.rates[c];
|
||||
@@ -451,7 +483,7 @@ if (typeof module !== "undefined" && module.exports) module.exports = StmateRate
|
||||
{ n, cfg } = S.stageCfg(ctx);
|
||||
api.recompute();
|
||||
const kj = (ctx.computed.stages[n] || {}).kanjub || ctx.computed.kanjubComputed;
|
||||
const res = R.lookup(m, R.optsFromCfg(cfg, kj));
|
||||
const res = R.lookup(m, optsOf(ctx, cfg, kj));
|
||||
R.applyToCfg(cfg, res, { withTbugum: !!(api.$("kr-tbugum") || {}).checked });
|
||||
u.kjMsg = res.notes.join(" · ");
|
||||
re();
|
||||
|
||||
Reference in New Issue
Block a user