feat: 서포트 카테고리 전면 개선
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
- 서포트 카테고리 UI 개선: 좌우 스크롤, 헤더/본문 동기화, 가운데 정렬 - 동일 항목 합산 기능 구현 (Type + Size + Grade 기준) - 헤더 구조 변경: 압력/스케줄 제거, 구매수량 단일화, User Requirements 추가 - 우레탄 블럭슈 두께 정보(40t, 27t) Material Grade에 포함 - 서포트 수량 계산 수정: 취합된 숫자 그대로 표시 (4의 배수 계산 제거) - 서포트 분류 로직 개선: CLAMP, U-BOLT, URETHANE BLOCK SHOE 등 정확한 분류 - 백엔드 서포트 분류기에 User Requirements 추출 기능 추가 - 엑셀 내보내기에 서포트 카테고리 처리 로직 추가
This commit is contained in:
@@ -706,7 +706,8 @@ def classify_bolt(dat_file: str, description: str, main_nom: str, length: Option
|
||||
"nominal_size_fraction": dimensions_result.get('nominal_size_fraction', main_nom),
|
||||
"length": dimensions_result.get('length', ''),
|
||||
"diameter": dimensions_result.get('diameter', ''),
|
||||
"dimension_description": dimensions_result.get('dimension_description', '')
|
||||
"dimension_description": dimensions_result.get('dimension_description', ''),
|
||||
"bolts_per_flange": dimensions_result.get('bolts_per_flange', 1)
|
||||
},
|
||||
|
||||
"grade_strength": {
|
||||
@@ -966,12 +967,19 @@ def extract_bolt_dimensions(main_nom: str, description: str) -> Dict:
|
||||
except:
|
||||
nominal_size_fraction = actual_bolt_size
|
||||
|
||||
# 플랜지당 볼트 세트 수 추출 (예: (8), (4))
|
||||
bolts_per_flange = 1 # 기본값
|
||||
flange_bolt_pattern = re.search(r'\((\d+)\)', description)
|
||||
if flange_bolt_pattern:
|
||||
bolts_per_flange = int(flange_bolt_pattern.group(1))
|
||||
|
||||
dimensions = {
|
||||
"nominal_size": actual_bolt_size, # 실제 볼트 사이즈
|
||||
"nominal_size_fraction": nominal_size_fraction, # 분수 변환값
|
||||
"length": "",
|
||||
"diameter": "",
|
||||
"dimension_description": nominal_size_fraction # 분수로 표시
|
||||
"dimension_description": nominal_size_fraction, # 분수로 표시
|
||||
"bolts_per_flange": bolts_per_flange # 플랜지당 볼트 세트 수
|
||||
}
|
||||
|
||||
# 길이 정보 추출 (개선된 패턴)
|
||||
@@ -984,6 +992,8 @@ def extract_bolt_dimensions(main_nom: str, description: str) -> Dict:
|
||||
r'X\s*(\d+(?:\.\d+)?)\s*MM', # M8 X 20MM 형태
|
||||
r',\s*(\d+(?:\.\d+)?)\s*LG', # ", 145.0000 LG" 형태 (PSV, LT 볼트용)
|
||||
r',\s*(\d+(?:\.\d+)?)\s+(?:CK|PSV|LT)', # ", 140 CK" 형태 (PSV 볼트용)
|
||||
r'PSV\s+(\d+(?:\.\d+)?)', # PSV 140 형태 (PSV 볼트 전용)
|
||||
r'(\d+(?:\.\d+)?)\s+PSV', # 140 PSV 형태 (PSV 볼트 전용)
|
||||
r'(\d+(?:\.\d+)?)\s*MM(?:\s|,|$)', # 75MM 형태 (단독)
|
||||
r'(\d+(?:\.\d+)?)\s*mm(?:\s|,|$)' # 75mm 형태 (단독)
|
||||
]
|
||||
|
||||
@@ -182,6 +182,14 @@ def classify_flange(dat_file: str, description: str, main_nom: str,
|
||||
dat_upper = dat_file.upper()
|
||||
|
||||
# 1. 플랜지 키워드 확인 (재질만 있어도 통합 분류기가 이미 플랜지로 분류했으므로 진행)
|
||||
# 사이트 글라스와 스트레이너는 밸브로 분류되어야 함
|
||||
if 'SIGHT GLASS' in desc_upper or 'STRAINER' in desc_upper or '사이트글라스' in desc_upper or '스트레이너' in desc_upper:
|
||||
return {
|
||||
"category": "VALVE",
|
||||
"overall_confidence": 1.0,
|
||||
"reason": "SIGHT GLASS 또는 STRAINER는 밸브로 분류"
|
||||
}
|
||||
|
||||
flange_keywords = ['FLG', 'FLANGE', '플랜지', 'ORIFICE', 'SPECTACLE', 'PADDLE', 'SPACER']
|
||||
has_flange_keyword = any(keyword in desc_upper or keyword in dat_upper for keyword in flange_keywords)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from .fitting_classifier import classify_fitting
|
||||
# Level 1: 명확한 타입 키워드 (최우선)
|
||||
LEVEL1_TYPE_KEYWORDS = {
|
||||
"BOLT": ["FLANGE BOLT", "U-BOLT", "U BOLT", "BOLT", "STUD", "NUT", "SCREW", "WASHER", "볼트", "너트", "스터드", "나사", "와셔", "유볼트"],
|
||||
"VALVE": ["VALVE", "GATE", "BALL", "GLOBE", "CHECK", "BUTTERFLY", "NEEDLE", "RELIEF", "밸브", "게이트", "볼", "글로브", "체크", "버터플라이", "니들", "릴리프"],
|
||||
"VALVE": ["VALVE", "GATE", "BALL", "GLOBE", "CHECK", "BUTTERFLY", "NEEDLE", "RELIEF", "SIGHT GLASS", "STRAINER", "밸브", "게이트", "볼", "글로브", "체크", "버터플라이", "니들", "릴리프", "사이트글라스", "스트레이너"],
|
||||
"FLANGE": ["FLG", "FLANGE", "플랜지", "프랜지", "ORIFICE", "SPECTACLE", "PADDLE", "SPACER", "BLIND", "REDUCING FLANGE", "RED FLANGE"],
|
||||
"PIPE": ["PIPE", "TUBE", "파이프", "배관", "SMLS", "SEAMLESS"],
|
||||
"FITTING": ["SOCK-O-LET", "WELD-O-LET", "ELL-O-LET", "THREAD-O-LET", "ELB-O-LET", "NIP-O-LET", "COUP-O-LET", "SOCKOLET", "WELDOLET", "ELLOLET", "THREADOLET", "ELBOLET", "NIPOLET", "COUPOLET", "OLET", "ELBOW", "ELL", "TEE", "REDUCER", "CAP", "COUPLING", "NIPPLE", "SWAGE", "PLUG", "엘보", "티", "리듀서", "캡", "니플", "커플링", "플러그", "CONC", "ECC"],
|
||||
@@ -110,6 +110,17 @@ def classify_material_integrated(description: str, main_nom: str = "",
|
||||
"reason": "스페셜 키워드 발견"
|
||||
}
|
||||
|
||||
# VALVE 카테고리 우선 확인 (SIGHT GLASS, STRAINER)
|
||||
if ('SIGHT GLASS' in desc_upper or 'STRAINER' in desc_upper or
|
||||
'사이트글라스' in desc_upper or '스트레이너' in desc_upper):
|
||||
return {
|
||||
"category": "VALVE",
|
||||
"confidence": 1.0,
|
||||
"evidence": ["VALVE_SPECIAL_KEYWORD"],
|
||||
"classification_level": "LEVEL0_VALVE",
|
||||
"reason": "SIGHT GLASS 또는 STRAINER 키워드 발견"
|
||||
}
|
||||
|
||||
# SUPPORT 카테고리 우선 확인 (BOLT 카테고리보다 먼저)
|
||||
# U-BOLT, CLAMP, URETHANE BLOCK 등
|
||||
if ('U-BOLT' in desc_upper or 'U BOLT' in desc_upper or '유볼트' in desc_upper or
|
||||
|
||||
@@ -108,7 +108,22 @@ def classify_support(dat_file: str, description: str, main_nom: str,
|
||||
# 4. 사이즈 정보 추출
|
||||
size_result = extract_support_size(description, main_nom)
|
||||
|
||||
# 5. 최종 결과 조합
|
||||
# 5. 사용자 요구사항 추출
|
||||
user_requirements = extract_support_user_requirements(description)
|
||||
|
||||
# 6. 우레탄 블럭슈 두께 정보 추출 및 Material Grade 보강
|
||||
enhanced_material_grade = material_result.get('grade', 'UNKNOWN')
|
||||
if support_type_result.get("support_type") == "URETHANE_BLOCK":
|
||||
# 두께 정보 추출 (40t, 27t 등)
|
||||
thickness_match = re.search(r'(\d+)\s*[tT](?![oO])', description.upper())
|
||||
if thickness_match:
|
||||
thickness = f"{thickness_match.group(1)}t"
|
||||
if enhanced_material_grade == 'UNKNOWN' or not enhanced_material_grade:
|
||||
enhanced_material_grade = thickness
|
||||
elif thickness not in enhanced_material_grade:
|
||||
enhanced_material_grade = f"{enhanced_material_grade} {thickness}"
|
||||
|
||||
# 7. 최종 결과 조합
|
||||
return {
|
||||
"category": "SUPPORT",
|
||||
|
||||
@@ -118,10 +133,10 @@ def classify_support(dat_file: str, description: str, main_nom: str,
|
||||
"load_rating": load_result.get("load_rating", ""),
|
||||
"load_capacity": load_result.get("capacity", ""),
|
||||
|
||||
# 재질 정보 (공통 모듈)
|
||||
# 재질 정보 (공통 모듈) - 우레탄 블럭슈 두께 정보 포함
|
||||
"material": {
|
||||
"standard": material_result.get('standard', 'UNKNOWN'),
|
||||
"grade": material_result.get('grade', 'UNKNOWN'),
|
||||
"grade": enhanced_material_grade,
|
||||
"material_type": material_result.get('material_type', 'UNKNOWN'),
|
||||
"confidence": material_result.get('confidence', 0.0)
|
||||
},
|
||||
@@ -129,6 +144,9 @@ def classify_support(dat_file: str, description: str, main_nom: str,
|
||||
# 사이즈 정보
|
||||
"size_info": size_result,
|
||||
|
||||
# 사용자 요구사항
|
||||
"user_requirements": user_requirements,
|
||||
|
||||
# 전체 신뢰도
|
||||
"overall_confidence": calculate_support_confidence({
|
||||
"type": support_type_result.get('confidence', 0),
|
||||
@@ -183,6 +201,34 @@ def classify_support_type(dat_file: str, description: str) -> Dict:
|
||||
"evidence": ["NO_SUPPORT_TYPE_FOUND"]
|
||||
}
|
||||
|
||||
def extract_support_user_requirements(description: str) -> List[str]:
|
||||
"""서포트 사용자 요구사항 추출"""
|
||||
|
||||
desc_upper = description.upper()
|
||||
requirements = []
|
||||
|
||||
# 표면처리 관련
|
||||
if 'GALV' in desc_upper or 'GALVANIZED' in desc_upper:
|
||||
requirements.append('GALVANIZED')
|
||||
if 'HDG' in desc_upper or 'HOT DIP' in desc_upper:
|
||||
requirements.append('HOT DIP GALVANIZED')
|
||||
if 'PAINT' in desc_upper or 'PAINTED' in desc_upper:
|
||||
requirements.append('PAINTED')
|
||||
|
||||
# 재질 관련
|
||||
if 'SS' in desc_upper or 'STAINLESS' in desc_upper:
|
||||
requirements.append('STAINLESS STEEL')
|
||||
if 'CARBON' in desc_upper:
|
||||
requirements.append('CARBON STEEL')
|
||||
|
||||
# 특수 요구사항
|
||||
if 'FIRE SAFE' in desc_upper:
|
||||
requirements.append('FIRE SAFE')
|
||||
if 'SEISMIC' in desc_upper or '내진' in desc_upper:
|
||||
requirements.append('SEISMIC')
|
||||
|
||||
return requirements
|
||||
|
||||
def classify_load_rating(description: str) -> Dict:
|
||||
"""하중 등급 분류"""
|
||||
|
||||
|
||||
@@ -89,6 +89,24 @@ VALVE_TYPES = {
|
||||
"typical_connections": ["FLANGED", "THREADED"],
|
||||
"pressure_range": "150LB ~ 600LB",
|
||||
"special_features": ["LUBRICATED", "NON_LUBRICATED"]
|
||||
},
|
||||
|
||||
"SIGHT_GLASS": {
|
||||
"dat_file_patterns": ["SIGHT_", "SG_"],
|
||||
"description_keywords": ["SIGHT GLASS", "SIGHT", "사이트글라스", "사이트 글라스"],
|
||||
"characteristics": "유체 확인용 관찰창",
|
||||
"typical_connections": ["FLANGED", "THREADED"],
|
||||
"pressure_range": "150LB ~ 600LB",
|
||||
"special_features": ["TRANSPARENT", "VISUAL_INSPECTION"]
|
||||
},
|
||||
|
||||
"STRAINER": {
|
||||
"dat_file_patterns": ["STRAINER_", "STR_"],
|
||||
"description_keywords": ["STRAINER", "스트레이너", "여과기"],
|
||||
"characteristics": "이물질 여과용",
|
||||
"typical_connections": ["FLANGED", "THREADED"],
|
||||
"pressure_range": "150LB ~ 600LB",
|
||||
"special_features": ["MESH_FILTER", "Y_TYPE", "BASKET_TYPE"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,8 +230,13 @@ def classify_valve(dat_file: str, description: str, main_nom: str, length: float
|
||||
desc_upper = description.upper()
|
||||
dat_upper = dat_file.upper()
|
||||
|
||||
# 1. 밸브 키워드 확인 (재질만 있어도 통합 분류기가 이미 밸브로 분류했으므로 진행)
|
||||
valve_keywords = ['VALVE', 'GATE', 'BALL', 'GLOBE', 'CHECK', 'BUTTERFLY', 'NEEDLE', 'RELIEF', 'SOLENOID', '밸브', '게이트', '볼', '글로브', '체크', '버터플라이', '니들', '릴리프', '솔레노이드']
|
||||
# 1. 사이트 글라스와 스트레이너 우선 확인
|
||||
if 'SIGHT GLASS' in desc_upper or 'STRAINER' in desc_upper or '사이트글라스' in desc_upper or '스트레이너' in desc_upper:
|
||||
# 사이트 글라스와 스트레이너는 항상 밸브로 분류
|
||||
pass
|
||||
|
||||
# 밸브 키워드 확인 (재질만 있어도 통합 분류기가 이미 밸브로 분류했으므로 진행)
|
||||
valve_keywords = ['VALVE', 'GATE', 'BALL', 'GLOBE', 'CHECK', 'BUTTERFLY', 'NEEDLE', 'RELIEF', 'SOLENOID', 'SIGHT GLASS', 'STRAINER', '밸브', '게이트', '볼', '글로브', '체크', '버터플라이', '니들', '릴리프', '솔레노이드', '사이트글라스', '스트레이너']
|
||||
has_valve_keyword = any(keyword in desc_upper or keyword in dat_upper for keyword in valve_keywords)
|
||||
|
||||
# 밸브 재질 확인 (A216, A217, A351, A352)
|
||||
|
||||
Reference in New Issue
Block a user