feat: BOM 페이지 개선 및 구매관리 기능 향상
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
- BOM 페이지에서 모든 카테고리 이모지 제거 (깔끔한 UI) - 구매신청된 자재 비활성화 기능 개선 - 구매관리 페이지에서 선택된 프로젝트만 표시하도록 수정 - 파이프 카테고리 Excel 내보내기 개선: * 끝단처리, 압력등급 컬럼 제거 * 사용자요구(분류기 추출) 및 추가요청사항 컬럼 추가 * 품목명에서 끝단처리 정보 제거 * 납기일 P열 고정 및 관리항목 자동 채움 - 파이프 분류기에서 사용자 요구사항 추출 기능 추가 - 재질별 스케줄 표시 개선 (SUS: SCH 40S, Carbon: SCH 40)
This commit is contained in:
@@ -7,6 +7,60 @@ import re
|
||||
from typing import Dict, List, Optional
|
||||
from .material_classifier import classify_material, get_manufacturing_method_from_material
|
||||
|
||||
# ========== PIPE USER 요구사항 키워드 ==========
|
||||
PIPE_USER_REQUIREMENTS = {
|
||||
"IMPACT_TEST": {
|
||||
"keywords": ["IMPACT", "충격시험", "CHARPY", "CVN", "IMPACT TEST", "충격", "NOTCH"],
|
||||
"description": "충격시험 요구",
|
||||
"confidence": 0.95
|
||||
},
|
||||
"ASME_CODE": {
|
||||
"keywords": ["ASME", "ASME CODE", "CODE", "B31.1", "B31.3", "B31.4", "B31.8", "VIII"],
|
||||
"description": "ASME 코드 준수",
|
||||
"confidence": 0.95
|
||||
},
|
||||
"STRESS_RELIEF": {
|
||||
"keywords": ["STRESS RELIEF", "SR", "응력제거", "열처리", "HEAT TREATMENT"],
|
||||
"description": "응력제거 열처리",
|
||||
"confidence": 0.90
|
||||
},
|
||||
"RADIOGRAPHIC_TEST": {
|
||||
"keywords": ["RT", "RADIOGRAPHIC", "방사선시험", "X-RAY", "엑스레이"],
|
||||
"description": "방사선 시험",
|
||||
"confidence": 0.90
|
||||
},
|
||||
"ULTRASONIC_TEST": {
|
||||
"keywords": ["UT", "ULTRASONIC", "초음파시험", "초음파"],
|
||||
"description": "초음파 시험",
|
||||
"confidence": 0.90
|
||||
},
|
||||
"MAGNETIC_PARTICLE": {
|
||||
"keywords": ["MT", "MAGNETIC PARTICLE", "자분탐상", "자분"],
|
||||
"description": "자분탐상 시험",
|
||||
"confidence": 0.90
|
||||
},
|
||||
"LIQUID_PENETRANT": {
|
||||
"keywords": ["PT", "LIQUID PENETRANT", "침투탐상", "침투"],
|
||||
"description": "침투탐상 시험",
|
||||
"confidence": 0.90
|
||||
},
|
||||
"HYDROSTATIC_TEST": {
|
||||
"keywords": ["HYDROSTATIC", "수압시험", "PRESSURE TEST", "압력시험"],
|
||||
"description": "수압 시험",
|
||||
"confidence": 0.90
|
||||
},
|
||||
"LOW_TEMPERATURE": {
|
||||
"keywords": ["LOW TEMP", "저온", "LTCS", "LOW TEMPERATURE", "CRYOGENIC"],
|
||||
"description": "저온용",
|
||||
"confidence": 0.85
|
||||
},
|
||||
"HIGH_TEMPERATURE": {
|
||||
"keywords": ["HIGH TEMP", "고온", "HTCS", "HIGH TEMPERATURE"],
|
||||
"description": "고온용",
|
||||
"confidence": 0.85
|
||||
}
|
||||
}
|
||||
|
||||
# ========== PIPE 제조 방법별 분류 ==========
|
||||
PIPE_MANUFACTURING = {
|
||||
"SEAMLESS": {
|
||||
@@ -138,6 +192,27 @@ PIPE_SCHEDULE = {
|
||||
]
|
||||
}
|
||||
|
||||
def extract_pipe_user_requirements(description: str) -> List[str]:
|
||||
"""
|
||||
파이프 설명에서 User 요구사항 추출
|
||||
|
||||
Args:
|
||||
description: 파이프 설명
|
||||
|
||||
Returns:
|
||||
발견된 요구사항 리스트
|
||||
"""
|
||||
desc_upper = description.upper()
|
||||
found_requirements = []
|
||||
|
||||
for req_type, req_data in PIPE_USER_REQUIREMENTS.items():
|
||||
for keyword in req_data["keywords"]:
|
||||
if keyword in desc_upper:
|
||||
found_requirements.append(req_data["description"])
|
||||
break # 같은 타입에서 중복 방지
|
||||
|
||||
return found_requirements
|
||||
|
||||
def classify_pipe_for_purchase(dat_file: str, description: str, main_nom: str,
|
||||
length: Optional[float] = None) -> Dict:
|
||||
"""구매용 파이프 분류 - 끝단 가공 정보 제외"""
|
||||
@@ -215,13 +290,16 @@ def classify_pipe(dat_file: str, description: str, main_nom: str,
|
||||
# 3. 끝 가공 분류
|
||||
end_prep_result = classify_pipe_end_preparation(description)
|
||||
|
||||
# 4. 스케줄 분류
|
||||
schedule_result = classify_pipe_schedule(description)
|
||||
# 4. 스케줄 분류 (재질 정보 전달)
|
||||
schedule_result = classify_pipe_schedule(description, material_result)
|
||||
|
||||
# 5. 길이(절단 치수) 처리
|
||||
length_info = extract_pipe_length_info(length, description)
|
||||
|
||||
# 6. 최종 결과 조합
|
||||
# 6. User 요구사항 추출
|
||||
user_requirements = extract_pipe_user_requirements(description)
|
||||
|
||||
# 7. 최종 결과 조합
|
||||
return {
|
||||
"category": "PIPE",
|
||||
|
||||
@@ -260,6 +338,9 @@ def classify_pipe(dat_file: str, description: str, main_nom: str,
|
||||
"length_mm": length_info.get('length_mm')
|
||||
},
|
||||
|
||||
# User 요구사항
|
||||
"user_requirements": user_requirements,
|
||||
|
||||
# 전체 신뢰도
|
||||
"overall_confidence": calculate_pipe_confidence({
|
||||
"material": material_result.get('confidence', 0),
|
||||
@@ -328,19 +409,43 @@ def classify_pipe_end_preparation(description: str) -> Dict:
|
||||
"matched_code": "DEFAULT"
|
||||
}
|
||||
|
||||
def classify_pipe_schedule(description: str) -> Dict:
|
||||
"""파이프 스케줄 분류"""
|
||||
def classify_pipe_schedule(description: str, material_result: Dict = None) -> Dict:
|
||||
"""파이프 스케줄 분류 - 재질별 표현 개선"""
|
||||
|
||||
desc_upper = description.upper()
|
||||
|
||||
# 재질 정보 확인
|
||||
material_type = "CARBON" # 기본값
|
||||
if material_result:
|
||||
material_grade = material_result.get('grade', '').upper()
|
||||
material_standard = material_result.get('standard', '').upper()
|
||||
|
||||
# 스테인리스 스틸 판단
|
||||
if any(sus_indicator in material_grade or sus_indicator in material_standard
|
||||
for sus_indicator in ['SUS', 'SS', 'A312', 'A358', 'A376', '304', '316', '321', '347']):
|
||||
material_type = "STAINLESS"
|
||||
|
||||
# 1. 스케줄 패턴 확인
|
||||
for pattern in PIPE_SCHEDULE["patterns"]:
|
||||
match = re.search(pattern, desc_upper)
|
||||
if match:
|
||||
schedule_num = match.group(1)
|
||||
|
||||
# 재질별 스케줄 표현
|
||||
if material_type == "STAINLESS":
|
||||
# 스테인리스 스틸: SCH 40S, SCH 80S
|
||||
if schedule_num in ["10", "20", "40", "80", "120", "160"]:
|
||||
schedule_display = f"SCH {schedule_num}S"
|
||||
else:
|
||||
schedule_display = f"SCH {schedule_num}"
|
||||
else:
|
||||
# 카본 스틸: SCH 40, SCH 80
|
||||
schedule_display = f"SCH {schedule_num}"
|
||||
|
||||
return {
|
||||
"schedule": f"SCH {schedule_num}",
|
||||
"schedule": schedule_display,
|
||||
"schedule_number": schedule_num,
|
||||
"material_type": material_type,
|
||||
"confidence": 0.95,
|
||||
"matched_pattern": pattern
|
||||
}
|
||||
@@ -353,6 +458,7 @@ def classify_pipe_schedule(description: str) -> Dict:
|
||||
return {
|
||||
"schedule": f"{thickness}mm THK",
|
||||
"wall_thickness": f"{thickness}mm",
|
||||
"material_type": material_type,
|
||||
"confidence": 0.9,
|
||||
"matched_pattern": pattern
|
||||
}
|
||||
@@ -360,6 +466,7 @@ def classify_pipe_schedule(description: str) -> Dict:
|
||||
# 3. 기본값
|
||||
return {
|
||||
"schedule": "UNKNOWN",
|
||||
"material_type": material_type,
|
||||
"confidence": 0.0
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user