feat(est): link quantity to individual rows
This commit is contained in:
@@ -151,18 +151,34 @@ const EstQuantity = (() => {
|
||||
const quantities = new Map();
|
||||
for (const item of items) {
|
||||
const code = item.TargetCode ?? item.LinkCode;
|
||||
if (!code) continue;
|
||||
const targets = project.tables.EstMainDat.filter((r) => r.Code === code && !Number(r.Level));
|
||||
if (!targets.length) throw Error(`연결 내역코드 없음: ${code}`);
|
||||
if (targets.length > 1) throw Error(`연결 내역코드 중복: ${code}`);
|
||||
quantities.set(code, (quantities.get(code) || 0) + Number(item.GN || 0));
|
||||
if (!code && !item.TargetKey) continue;
|
||||
const targets = project.tables.EstMainDat.map((row, index) => ({ row, index })).filter(
|
||||
({ row }) =>
|
||||
!Number(row.Level) &&
|
||||
(item.TargetKey
|
||||
? row.PkID != null && `id:${row.PkID}` === item.TargetKey
|
||||
: row.Code === code),
|
||||
);
|
||||
if (!targets.length) throw Error(`연결 내역 없음: ${item.TargetKey || code}`);
|
||||
if (targets.length > 1) throw Error(`연결 내역 중복: ${item.TargetKey || code}`);
|
||||
const index = targets[0].index;
|
||||
quantities.set(index, (quantities.get(index) || 0) + Number(item.GN || 0));
|
||||
}
|
||||
if (!quantities.size) throw Error("연결할 내역코드를 먼저 입력하세요.");
|
||||
return quantities;
|
||||
}
|
||||
function applyTotals(project, quantities) {
|
||||
for (const row of project.tables.EstMainDat)
|
||||
if (quantities.has(row.Code) && !Number(row.Level)) row.GN = quantities.get(row.Code);
|
||||
for (const [index, value] of quantities) project.tables.EstMainDat[index].GN = value;
|
||||
}
|
||||
function targetSelect(project, item, section, index) {
|
||||
const { esc } = EstApp;
|
||||
const rows = project.tables.EstMainDat.filter((row) => row.PkID != null && !Number(row.Level));
|
||||
return `<select data-quantity-select="${section}" data-index="${index}" aria-label="연결 내역 행"><option value="">내역 행 선택</option>${rows
|
||||
.map((row) => {
|
||||
const key = `id:${row.PkID}`;
|
||||
return `<option value="${esc(key)}" ${item.TargetKey === key ? "selected" : ""}>${esc(row.Name || "내역")} · ${esc(row.Code || "코드 없음")} · ${esc(row.PkID)}</option>`;
|
||||
})
|
||||
.join("")}</select>`;
|
||||
}
|
||||
function newCode(items) {
|
||||
const codes = new Set(items.map((row) => row.Code));
|
||||
@@ -186,7 +202,7 @@ const EstQuantity = (() => {
|
||||
{ esc, number, byId } = EstApp;
|
||||
byId("work-content").innerHTML =
|
||||
selector(state) +
|
||||
`<div class="business-tools"><label>산출서명 <input data-quantity-name value="${esc(sheet.Name)}"></label><button data-quantity-add>산출 행 추가</button><button data-quantity-apply>내역 수량 반영</button><button data-quantity-delete-sheet>산출서 삭제</button></div><table class="sheet"><thead><tr><th>산출코드</th><th>품명</th><th>규격</th><th>저장 수량</th><th>재계산 수량</th><th>연결 내역코드</th></tr></thead><tbody>${output.items.map((item, index) => `<tr><td>${esc(item.Code)}</td><td><input data-quantity-item="Name" data-index="${index}" value="${esc(item.Name || "")}" aria-label="품명"></td><td><input data-quantity-item="Size" data-index="${index}" value="${esc(item.Size || "")}" aria-label="규격"></td><td>${number(sheet.items[index].GN)}</td><td>${number(item.GN)}</td><td><input data-quantity-target="${index}" value="${esc(item.TargetCode ?? item.LinkCode ?? "")}" aria-label="연결 내역코드"></td></tr>`).join("")}</tbody></table><p class="business-note">${esc(output.errors.join(" / "))} 산출 행의 결과 표지로 수량 항목을 연결합니다. 신규 산출서와 행 변경은 JSON으로 저장합니다.</p><table class="sheet"><thead><tr><th>줄</th><th>산출근거 편집</th><th>작업</th></tr></thead><tbody>${sheet.rows.map((row, index) => `<tr><td>${index + 1}</td><td><textarea data-quantity-line="${index}" rows="1" style="min-width:750px" aria-label="산출근거 ${index + 1}">${esc(EstText.display(output.rows[index].LineData))}</textarea></td><td><button data-quantity-add data-index="${index}">아래 추가</button><button data-quantity-move="-1" data-index="${index}" ${index === 0 ? "disabled" : ""}>↑</button><button data-quantity-move="1" data-index="${index}" ${index === sheet.rows.length - 1 ? "disabled" : ""}>↓</button><button data-quantity-delete-row="${index}">삭제</button></td></tr>`).join("")}</tbody></table>`;
|
||||
`<div class="business-tools"><label>산출서명 <input data-quantity-name value="${esc(sheet.Name)}"></label><button data-quantity-add>산출 행 추가</button><button data-quantity-apply>내역 수량 반영</button><button data-quantity-delete-sheet>산출서 삭제</button></div><table class="sheet"><thead><tr><th>산출코드</th><th>품명</th><th>규격</th><th>저장 수량</th><th>재계산 수량</th><th>연결 내역코드</th></tr></thead><tbody>${output.items.map((item, index) => `<tr><td>${esc(item.Code)}</td><td><input data-quantity-item="Name" data-index="${index}" value="${esc(item.Name || "")}" aria-label="품명"></td><td><input data-quantity-item="Size" data-index="${index}" value="${esc(item.Size || "")}" aria-label="규격"></td><td>${number(sheet.items[index].GN)}</td><td>${number(item.GN)}</td><td><input data-quantity-target="${index}" value="${esc(item.TargetCode ?? item.LinkCode ?? "")}" aria-label="연결 내역코드">${targetSelect(state.project, item, "sheet", index)}</td></tr>`).join("")}</tbody></table><p class="business-note">${esc(output.errors.join(" / "))} 산출 행의 결과 표지로 수량 항목을 연결합니다. 신규 산출서와 행 변경은 JSON으로 저장합니다.</p><table class="sheet"><thead><tr><th>줄</th><th>산출근거 편집</th><th>작업</th></tr></thead><tbody>${sheet.rows.map((row, index) => `<tr><td>${index + 1}</td><td><textarea data-quantity-line="${index}" rows="1" style="min-width:750px" aria-label="산출근거 ${index + 1}">${esc(EstText.display(output.rows[index].LineData))}</textarea></td><td><button data-quantity-add data-index="${index}">아래 추가</button><button data-quantity-move="-1" data-index="${index}" ${index === 0 ? "disabled" : ""}>↑</button><button data-quantity-move="1" data-index="${index}" ${index === sheet.rows.length - 1 ? "disabled" : ""}>↓</button><button data-quantity-delete-row="${index}">삭제</button></td></tr>`).join("")}</tbody></table>`;
|
||||
}
|
||||
function install() {
|
||||
document.addEventListener("change", (event) => {
|
||||
@@ -197,6 +213,23 @@ const EstQuantity = (() => {
|
||||
EstApp.render();
|
||||
return;
|
||||
}
|
||||
if (node.dataset.quantitySelect !== undefined) {
|
||||
const item =
|
||||
node.dataset.quantitySelect === "manual"
|
||||
? state.project.quantities[Number(node.dataset.index)]
|
||||
: state.project.quantitySheets?.find((s) => s.Code === state.quantitySheet)?.items[
|
||||
Number(node.dataset.index)
|
||||
];
|
||||
if (!item) return;
|
||||
const row = state.project.tables.EstMainDat.find(
|
||||
(r) => r.PkID != null && `id:${r.PkID}` === node.value && !Number(r.Level),
|
||||
);
|
||||
EstApp.change(() => {
|
||||
item.TargetKey = row ? node.value : "";
|
||||
item.TargetCode = row?.Code || "";
|
||||
}, false);
|
||||
return;
|
||||
}
|
||||
const sheet = state.project.quantitySheets?.find((s) => s.Code === state.quantitySheet);
|
||||
if (!sheet) return;
|
||||
if (node.dataset.quantityName !== undefined)
|
||||
@@ -213,10 +246,11 @@ const EstQuantity = (() => {
|
||||
false,
|
||||
);
|
||||
if (node.dataset.quantityTarget !== undefined)
|
||||
EstApp.change(
|
||||
() => (sheet.items[Number(node.dataset.quantityTarget)].TargetCode = node.value),
|
||||
false,
|
||||
);
|
||||
EstApp.change(() => {
|
||||
const item = sheet.items[Number(node.dataset.quantityTarget)];
|
||||
item.TargetCode = node.value;
|
||||
item.TargetKey = "";
|
||||
}, false);
|
||||
});
|
||||
document.addEventListener("click", (event) => {
|
||||
const { state } = EstApp;
|
||||
@@ -298,6 +332,7 @@ const EstQuantity = (() => {
|
||||
manual,
|
||||
totals,
|
||||
applyTotals,
|
||||
targetSelect,
|
||||
newCode,
|
||||
selector,
|
||||
render,
|
||||
|
||||
Reference in New Issue
Block a user