fix(est): propagate assigned prices into final totals
This commit is contained in:
@@ -10,6 +10,8 @@ const EstText = (() => {
|
||||
const numeric = (s) => Number(String(s).replaceAll(",", ""));
|
||||
const sumCurrency = (values) =>
|
||||
values.reduce((n, value) => n + EstMath.even(num(value) * 10000), 0) / 10000;
|
||||
const autoTotal = (row) =>
|
||||
num(row.LinkIndex) !== 62 && String(row.LineData || "").includes("\x1a");
|
||||
const stripLabels = (text) =>
|
||||
String(text)
|
||||
.replace(/\x0e[^\x0e]*\x0e|\x13[^\x13]*\x13|\x15[^\x15]*\x15|\([가-힣][^()]*\)/g, "")
|
||||
@@ -87,7 +89,7 @@ const EstText = (() => {
|
||||
const levels = [],
|
||||
componentRows = [];
|
||||
for (let j = index + 1; j < rows.length && num(rows[j].Index) <= 0; j++)
|
||||
if (String(rows[j].LineData || "").includes("\x1a")) levels.push(num(rows[j].Level));
|
||||
if (autoTotal(rows[j])) levels.push(num(rows[j].Level));
|
||||
else if (component[num(rows[j].SCheck)] && marker.test(String(rows[j].LineData || "")))
|
||||
componentRows.push(j);
|
||||
finalLevel = levels.length ? Math.min(...levels) : -1;
|
||||
@@ -153,7 +155,7 @@ const EstText = (() => {
|
||||
const values = [];
|
||||
for (let j = index - 1; j >= 0 && !(num(rows[j].Index) > 0); j--)
|
||||
for (const match of String(rows[j].LineData || "").matchAll(
|
||||
/\x06([A-Z])\x06\s*([\x12\x0c])([-\d.,]+)\2/g,
|
||||
/\x06([A-Z])\x06\s*([\x03\x12\x0c])([-\d.,]+)\2/g,
|
||||
))
|
||||
if (match[1] === group) values.unshift(numeric(match[3]));
|
||||
if (!values.length) selectionError = `합계 구간 ${group}에 지정된 결과가 없습니다.`;
|
||||
@@ -166,7 +168,7 @@ const EstText = (() => {
|
||||
const previous = rows[j];
|
||||
if (num(previous.Index) !== -1) {
|
||||
const results = [
|
||||
...String(previous.LineData || "").matchAll(/([\x12\x0c])([-\d.,]+)\1/g),
|
||||
...String(previous.LineData || "").matchAll(/([\x03\x12\x0c])([-\d.,]+)\1/g),
|
||||
];
|
||||
if (results.length) values.push(numeric(results.at(-1)[2]));
|
||||
}
|
||||
@@ -219,6 +221,7 @@ const EstText = (() => {
|
||||
);
|
||||
else if (currentSource && sc === 0 && /\x0e/.test(original))
|
||||
text = text.replace(/\x03([-\d.,]+)\x03/g, () => `\x03${num(currentSource.TC)}\x03`);
|
||||
row.LineData = text;
|
||||
text = text.replace(
|
||||
/\x11([-\d.,]+)\x11/g,
|
||||
(whole, value) => `\x11${changed.get(numeric(value)) ?? numeric(value)}\x11`,
|
||||
@@ -273,8 +276,7 @@ const EstText = (() => {
|
||||
for (let j = index - 1; j >= 0; j--) {
|
||||
const previous = rows[j];
|
||||
if (!previous.LineData) continue;
|
||||
if (!String(previous.LineData).includes("\x1a") || !component[num(previous.SCheck)])
|
||||
break;
|
||||
if (!autoTotal(previous) || !component[num(previous.SCheck)]) break;
|
||||
section.push(num(previous.TC));
|
||||
}
|
||||
calculated = sumCurrency(section);
|
||||
@@ -316,7 +318,7 @@ const EstText = (() => {
|
||||
? []
|
||||
: [
|
||||
...assignmentText.matchAll(
|
||||
/(?:^\s*| {2,}|[,,]\s*|(?<=[가-힣])\s+|[::]\s*)([A-Za-z][A-Za-z0-9]*)\s*=/g,
|
||||
/(?:^\s*| {2,}|[,,]\s*|(?<=[가-힣])\s+|[::]\s*|['"]\s*)([A-Za-z][A-Za-z0-9]*)\s*=/g,
|
||||
),
|
||||
];
|
||||
for (let j = 0; j < assignments.length; j++) {
|
||||
@@ -325,6 +327,8 @@ const EstText = (() => {
|
||||
let body = text.slice(assignment.index + assignment[0].length, end);
|
||||
if (!matched && /^\s*\*.*\*\s*$/.test(text)) body = body.replace(/\*\s*$/, "");
|
||||
body = body.replace(/\{[^}]*\}/g, "");
|
||||
if (/['"]\s*[A-Za-z][A-Za-z0-9]*\s*=/.test(assignment[0]))
|
||||
body = body.replace(/['"]\s*$/, "");
|
||||
if (!matched) body = body.split("{")[0];
|
||||
body = body.split(/\s+[::]\s*/)[0].replace(/[,,]\s*$/, "");
|
||||
if (body.includes("─") && calculated !== null) {
|
||||
@@ -394,7 +398,7 @@ const EstText = (() => {
|
||||
row.Precision ??
|
||||
explicit?.digits ??
|
||||
(sc < 0 || num(row.LinkIndex) !== 0
|
||||
? (num(row.Level) === finalLevel && text.includes("\x1a")) ||
|
||||
? (num(row.Level) === finalLevel && autoTotal(row)) ||
|
||||
index === singleComponent ||
|
||||
options.CostValueTrunc
|
||||
? 0
|
||||
@@ -475,7 +479,7 @@ const EstText = (() => {
|
||||
row.LineData = rendered;
|
||||
changed.set(oldValue, firstValue);
|
||||
checks.push({ slot: index, stored: oldValue, calculated: firstValue });
|
||||
if (text.includes("\x1a") && component[sc]) {
|
||||
if (autoTotal(row) && component[sc]) {
|
||||
if (num(row.Level) === finalLevel) totals[component[sc]] = calculated;
|
||||
}
|
||||
} else if (!matched && component[sc] && text.includes("\x03") && !text.includes("\x1a")) {
|
||||
@@ -485,13 +489,36 @@ const EstText = (() => {
|
||||
1,
|
||||
);
|
||||
row.LineData = text;
|
||||
} else if (!matched && text.includes("\x1a") && component[sc]) {
|
||||
const value = clean(text).split(":").slice(1).join(":").trim();
|
||||
} else if (!matched && autoTotal(row) && component[sc]) {
|
||||
let value = clean(text).split(":").slice(1).join(":").trim();
|
||||
// Bare final totals can contain an already truncated amount rather than an equation.
|
||||
// Rebuild only when the original component rows establish that subtotal relationship.
|
||||
const savedValue = clean(original).split(":").slice(1).join(":").trim();
|
||||
if (num(row.Level) === finalLevel && /^[-\d.,]+$/.test(savedValue)) {
|
||||
const before = [],
|
||||
after = [];
|
||||
for (let j = index - 1; j >= 0 && num(rows[j].Index) <= 0; j--) {
|
||||
if (num(rows[j].SCheck) !== sc) continue;
|
||||
if (autoTotal(rows[j])) break;
|
||||
const results = [...String(input[j].LineData || "").matchAll(/\x12([-\d.,]+)\x12/g)];
|
||||
if (!results.length && input[j].TC == null) continue;
|
||||
before.push(results.length ? numeric(results.at(-1)[1]) : num(input[j].TC));
|
||||
after.push(num(rows[j].TC));
|
||||
if (num(rows[j].LinkIndex) === 61) break;
|
||||
}
|
||||
if (before.length && floating(sumCurrency(before), 0, 2) === numeric(savedValue))
|
||||
value = String(sumCurrency(after));
|
||||
}
|
||||
const calculated = floating(
|
||||
EstExpression.evaluate(expression(value || "0"), (key) => variables[key]),
|
||||
num(row.Level) === finalLevel ? 0 : 1,
|
||||
);
|
||||
row.TC = calculated;
|
||||
if (value !== clean(text).split(":").slice(1).join(":").trim()) {
|
||||
const start = text.indexOf(":") + 1,
|
||||
end = text.lastIndexOf("\x1a");
|
||||
row.LineData = text.slice(0, start) + calculated + text.slice(end);
|
||||
}
|
||||
if (num(row.Level) === finalLevel) totals[component[sc]] = calculated;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user