Files
TK-BOM-Project/frontend/src/utils/purchaseCalculator.js
hyungi 6b6360ecd5
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
feat: 서포트 카테고리 전면 개선
- 서포트 카테고리 UI 개선: 좌우 스크롤, 헤더/본문 동기화, 가운데 정렬
- 동일 항목 합산 기능 구현 (Type + Size + Grade 기준)
- 헤더 구조 변경: 압력/스케줄 제거, 구매수량 단일화, User Requirements 추가
- 우레탄 블럭슈 두께 정보(40t, 27t) Material Grade에 포함
- 서포트 수량 계산 수정: 취합된 숫자 그대로 표시 (4의 배수 계산 제거)
- 서포트 분류 로직 개선: CLAMP, U-BOLT, URETHANE BLOCK SHOE 등 정확한 분류
- 백엔드 서포트 분류기에 User Requirements 추출 기능 추가
- 엑셀 내보내기에 서포트 카테고리 처리 로직 추가
2025-10-17 07:59:35 +09:00

161 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 자재 카테고리별 구매 수량 계산 유틸리티
*/
/**
* 파이프 구매 수량 계산
* @param {number} totalLengthMm - 파이프 총 길이 (mm)
* @param {number} quantity - BOM 수량 (개수)
* @returns {object} 구매 계산 결과
*/
export const calculatePipePurchase = (totalLengthMm, quantity) => {
if (!totalLengthMm || totalLengthMm <= 0 || !quantity || quantity <= 0) {
return {
purchaseQuantity: 0,
standardLength: 6000,
cutLength: 0,
calculation: '길이 정보 없음'
};
}
// 절단 여유분: 절단 개수만큼 3mm 추가 (백엔드와 동일)
const cuttingLoss = quantity * 3;
const requiredLength = totalLengthMm + cuttingLoss;
// 6,000mm 단위로 올림 계산
const pipeCount = Math.ceil(requiredLength / 6000);
return {
purchaseQuantity: pipeCount,
standardLength: 6000,
cutLength: requiredLength,
calculation: `${totalLengthMm}mm + ${cuttingLoss}mm(절단손실) = ${requiredLength}mm → ${pipeCount}`
};
};
/**
* 볼트/너트 구매 수량 계산
* @param {number} bomQuantity - BOM 수량
* @returns {object} 구매 계산 결과
*/
export const calculateBoltPurchase = (bomQuantity) => {
if (!bomQuantity || bomQuantity <= 0) {
return {
purchaseQuantity: 0,
calculation: '수량 정보 없음'
};
}
// +5% 여유분 후 4의 배수로 올림
const withMargin = bomQuantity * 1.05;
const purchaseQuantity = Math.ceil(withMargin / 4) * 4;
return {
purchaseQuantity: purchaseQuantity,
marginQuantity: Math.round(withMargin * 10) / 10, // 소수점 1자리
calculation: `${bomQuantity} × 1.05 = ${Math.round(withMargin * 10) / 10}${purchaseQuantity} SETS`
};
};
/**
* 가스켓 구매 수량 계산
* @param {number} bomQuantity - BOM 수량
* @returns {object} 구매 계산 결과
*/
export const calculateGasketPurchase = (bomQuantity) => {
if (!bomQuantity || bomQuantity <= 0) {
return {
purchaseQuantity: 0,
calculation: '수량 정보 없음'
};
}
// 5의 배수로 올림
const purchaseQuantity = Math.ceil(bomQuantity / 5) * 5;
return {
purchaseQuantity: purchaseQuantity,
calculation: `${bomQuantity}${purchaseQuantity} EA (5의 배수)`
};
};
/**
* 피팅/계기/밸브 구매 수량 계산
* @param {number} bomQuantity - BOM 수량
* @returns {object} 구매 계산 결과
*/
export const calculateStandardPurchase = (bomQuantity) => {
return {
purchaseQuantity: bomQuantity || 0,
calculation: `${bomQuantity || 0} EA (BOM 수량 그대로)`
};
};
/**
* 자재 카테고리별 구매 수량 계산 (통합 함수)
* @param {object} material - 자재 정보
* @returns {object} 구매 계산 결과
*/
export const calculatePurchaseQuantity = (material) => {
const category = material.classified_category || material.category || '';
const bomQuantity = material.quantity || 0;
switch (category.toUpperCase()) {
case 'PIPE':
// 파이프의 경우 길이 정보 필요
const lengthMm = material.pipe_details?.length_mm || 0;
const totalLength = material.pipe_details?.total_length_mm || (lengthMm * bomQuantity);
return {
...calculatePipePurchase(totalLength, bomQuantity),
category: 'PIPE',
unit: '본'
};
case 'BOLT':
case 'NUT':
return {
...calculateBoltPurchase(bomQuantity),
category: 'BOLT',
unit: 'SETS'
};
case 'GASKET':
return {
...calculateGasketPurchase(bomQuantity),
category: 'GASKET',
unit: 'EA'
};
case 'SUPPORT':
// 서포트는 취합된 숫자 그대로
return {
purchaseQuantity: bomQuantity,
calculation: `${bomQuantity} EA (취합된 수량 그대로)`,
category: 'SUPPORT',
unit: 'EA'
};
case 'FITTING':
case 'INSTRUMENT':
case 'VALVE':
case 'FLANGE':
default:
return {
...calculateStandardPurchase(bomQuantity),
category: category || 'STANDARD',
unit: material.unit || 'EA'
};
}
};
/**
* 자재 목록에 대한 구매 수량 계산 (일괄 처리)
* @param {Array} materials - 자재 목록
* @returns {Array} 구매 계산 결과가 포함된 자재 목록
*/
export const calculateBulkPurchase = (materials) => {
return materials.map(material => ({
...material,
purchaseInfo: calculatePurchaseQuantity(material)
}));
};