57 lines
1.4 KiB
TypeScript
57 lines
1.4 KiB
TypeScript
|
|
import { useCallback } from "react";
|
||
|
|
import { CalculationRule } from "./types";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 계산 필드 자동 업데이트 훅
|
||
|
|
*/
|
||
|
|
export function useCalculation(calculationRules: CalculationRule[] = []) {
|
||
|
|
/**
|
||
|
|
* 단일 행의 계산 필드 업데이트
|
||
|
|
*/
|
||
|
|
const calculateRow = useCallback(
|
||
|
|
(row: any): any => {
|
||
|
|
if (calculationRules.length === 0) return row;
|
||
|
|
|
||
|
|
const updatedRow = { ...row };
|
||
|
|
|
||
|
|
for (const rule of calculationRules) {
|
||
|
|
try {
|
||
|
|
// formula에서 필드명 추출 및 값으로 대체
|
||
|
|
let formula = rule.formula;
|
||
|
|
|
||
|
|
for (const dep of rule.dependencies) {
|
||
|
|
const value = parseFloat(row[dep]) || 0;
|
||
|
|
formula = formula.replace(new RegExp(dep, "g"), value.toString());
|
||
|
|
}
|
||
|
|
|
||
|
|
// 계산 실행 (eval 대신 Function 사용)
|
||
|
|
const result = new Function(`return ${formula}`)();
|
||
|
|
updatedRow[rule.result] = result;
|
||
|
|
} catch (error) {
|
||
|
|
console.error(`계산 오류 (${rule.formula}):`, error);
|
||
|
|
updatedRow[rule.result] = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return updatedRow;
|
||
|
|
},
|
||
|
|
[calculationRules]
|
||
|
|
);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 전체 데이터의 계산 필드 업데이트
|
||
|
|
*/
|
||
|
|
const calculateAll = useCallback(
|
||
|
|
(data: any[]): any[] => {
|
||
|
|
return data.map((row) => calculateRow(row));
|
||
|
|
},
|
||
|
|
[calculateRow]
|
||
|
|
);
|
||
|
|
|
||
|
|
return {
|
||
|
|
calculateRow,
|
||
|
|
calculateAll,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|