자재별 구매 수량 계산 시스템 구현
- 파이프: 6,000mm 단위 + 절단여유분 2mm/조각 계산 - 볼트/너트: +5% 후 4의 배수로 올림 - 가스켓: 5의 배수로 올림 - 피팅/계기/밸브: BOM 수량 그대로 - MaterialsPage에 '필요 수량' 칼럼 추가 - 엑셀 내보내기에 구매 수량 정보 포함 - 리비전 비교시 구매 수량 변화량도 계산
This commit is contained in:
151
frontend/src/utils/purchaseCalculator.js
Normal file
151
frontend/src/utils/purchaseCalculator.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* 자재 카테고리별 구매 수량 계산 유틸리티
|
||||
*/
|
||||
|
||||
/**
|
||||
* 파이프 구매 수량 계산
|
||||
* @param {number} lengthMm - 파이프 총 길이 (mm)
|
||||
* @param {number} quantity - BOM 수량 (개수)
|
||||
* @returns {object} 구매 계산 결과
|
||||
*/
|
||||
export const calculatePipePurchase = (lengthMm, quantity) => {
|
||||
if (!lengthMm || lengthMm <= 0 || !quantity || quantity <= 0) {
|
||||
return {
|
||||
purchaseQuantity: 0,
|
||||
standardLength: 6000,
|
||||
cutLength: 0,
|
||||
calculation: '길이 정보 없음'
|
||||
};
|
||||
}
|
||||
|
||||
// 절단 여유분: 조각마다 2mm 추가
|
||||
const cutLength = lengthMm + (quantity * 2);
|
||||
|
||||
// 6,000mm 단위로 올림 계산
|
||||
const pipeCount = Math.ceil(cutLength / 6000);
|
||||
|
||||
return {
|
||||
purchaseQuantity: pipeCount,
|
||||
standardLength: 6000,
|
||||
cutLength: cutLength,
|
||||
calculation: `${lengthMm}mm + ${quantity * 2}mm(여유분) = ${cutLength}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 '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)
|
||||
}));
|
||||
};
|
||||
Reference in New Issue
Block a user