feat: 자재 관리 페이지 대규모 개선
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
- 파이프 수량 계산 로직 수정 (단관 개수가 아닌 실제 길이 기반 계산) - UI 전면 개편 (DevonThink 스타일의 간결하고 세련된 디자인) - 자재별 그룹핑 로직 개선: * 플랜지: 동일 사양별 그룹핑, WN 스케줄 표시, ORIFICE 풀네임 표시 * 피팅: 상세 타입 표시 (니플 길이, 엘보 각도/연결, 티 타입, 리듀서 타입 등) * 밸브: 동일 사양별 그룹핑, 타입/연결방식/압력 표시 * 볼트: 크기/재질/길이별 그룹핑 (8SET → 개별 집계) * 가스켓: 동일 사양별 그룹핑, 재질/상세내역/두께 분리 표시 * UNKNOWN: 원본 설명 전체 표시, 동일 항목 그룹핑 - 전체 카테고리 버튼 제거 (표시 복잡도 감소) - 카테고리별 동적 컬럼 헤더 및 레이아웃 적용
This commit is contained in:
@@ -29,13 +29,13 @@ PIPE_MANUFACTURING = {
|
||||
# ========== PIPE 끝 가공별 분류 ==========
|
||||
PIPE_END_PREP = {
|
||||
"BOTH_ENDS_BEVELED": {
|
||||
"codes": ["BOE", "BOTH END", "BOTH BEVELED", "양쪽개선"],
|
||||
"codes": ["BBE", "BOE", "BOTH END", "BOTH BEVELED", "양쪽개선"],
|
||||
"cutting_note": "양쪽 개선",
|
||||
"machining_required": True,
|
||||
"confidence": 0.95
|
||||
},
|
||||
"ONE_END_BEVELED": {
|
||||
"codes": ["BE", "BEV", "PBE", "PIPE BEVELED END"],
|
||||
"codes": ["BE", "BEV", "PBE", "PIPE BEVELED END", "POE"],
|
||||
"cutting_note": "한쪽 개선",
|
||||
"machining_required": True,
|
||||
"confidence": 0.95
|
||||
@@ -45,9 +45,85 @@ PIPE_END_PREP = {
|
||||
"cutting_note": "무 개선",
|
||||
"machining_required": False,
|
||||
"confidence": 0.95
|
||||
},
|
||||
"THREADED": {
|
||||
"codes": ["TOE", "THE", "THREADED", "나사", "스레드"],
|
||||
"cutting_note": "나사 가공",
|
||||
"machining_required": True,
|
||||
"confidence": 0.90
|
||||
}
|
||||
}
|
||||
|
||||
# ========== 구매용 파이프 분류 (끝단 가공 제외) ==========
|
||||
def get_purchase_pipe_description(description: str) -> str:
|
||||
"""구매용 파이프 설명 - 끝단 가공 정보 제거"""
|
||||
|
||||
# 모든 끝단 가공 코드들을 수집
|
||||
end_prep_codes = []
|
||||
for prep_data in PIPE_END_PREP.values():
|
||||
end_prep_codes.extend(prep_data["codes"])
|
||||
|
||||
# 설명에서 끝단 가공 코드 제거
|
||||
clean_description = description.upper()
|
||||
|
||||
# 끝단 가공 코드들을 길이 순으로 정렬 (긴 것부터 처리)
|
||||
end_prep_codes.sort(key=len, reverse=True)
|
||||
|
||||
for code in end_prep_codes:
|
||||
# 단어 경계를 고려하여 제거 (부분 매칭 방지)
|
||||
pattern = r'\b' + re.escape(code) + r'\b'
|
||||
clean_description = re.sub(pattern, '', clean_description, flags=re.IGNORECASE)
|
||||
|
||||
# 끝단 가공 관련 패턴들 추가 제거
|
||||
# BOE-POE, POE-TOE 같은 조합 패턴들
|
||||
end_prep_patterns = [
|
||||
r'\b[A-Z]{2,3}E-[A-Z]{2,3}E\b', # BOE-POE, POE-TOE 등
|
||||
r'\b[A-Z]{2,3}E-[A-Z]{2,3}\b', # BOE-TO, POE-TO 등
|
||||
r'\b[A-Z]{2,3}-[A-Z]{2,3}E\b', # BO-POE, PO-TOE 등
|
||||
r'\b[A-Z]{2,3}-[A-Z]{2,3}\b', # BO-PO, PO-TO 등
|
||||
]
|
||||
|
||||
for pattern in end_prep_patterns:
|
||||
clean_description = re.sub(pattern, '', clean_description, flags=re.IGNORECASE)
|
||||
|
||||
# 남은 하이픈과 공백 정리
|
||||
clean_description = re.sub(r'\s*-\s*', ' ', clean_description) # 하이픈 제거
|
||||
clean_description = re.sub(r'\s+', ' ', clean_description).strip() # 연속 공백 정리
|
||||
|
||||
return clean_description
|
||||
|
||||
def extract_end_preparation_info(description: str) -> Dict:
|
||||
"""파이프 설명에서 끝단 가공 정보 추출"""
|
||||
|
||||
desc_upper = description.upper()
|
||||
|
||||
# 끝단 가공 코드 찾기
|
||||
for prep_type, prep_data in PIPE_END_PREP.items():
|
||||
for code in prep_data["codes"]:
|
||||
if code in desc_upper:
|
||||
return {
|
||||
"end_preparation_type": prep_type,
|
||||
"end_preparation_code": code,
|
||||
"machining_required": prep_data["machining_required"],
|
||||
"cutting_note": prep_data["cutting_note"],
|
||||
"confidence": prep_data["confidence"],
|
||||
"matched_pattern": code,
|
||||
"original_description": description,
|
||||
"clean_description": get_purchase_pipe_description(description)
|
||||
}
|
||||
|
||||
# 기본값: PBE (양쪽 무개선)
|
||||
return {
|
||||
"end_preparation_type": "NO_BEVEL", # PBE로 매핑될 예정
|
||||
"end_preparation_code": "PBE",
|
||||
"machining_required": False,
|
||||
"cutting_note": "양쪽 무개선 (기본값)",
|
||||
"confidence": 0.5,
|
||||
"matched_pattern": "DEFAULT",
|
||||
"original_description": description,
|
||||
"clean_description": get_purchase_pipe_description(description)
|
||||
}
|
||||
|
||||
# ========== PIPE 스케줄별 분류 ==========
|
||||
PIPE_SCHEDULE = {
|
||||
"patterns": [
|
||||
@@ -62,6 +138,23 @@ PIPE_SCHEDULE = {
|
||||
]
|
||||
}
|
||||
|
||||
def classify_pipe_for_purchase(dat_file: str, description: str, main_nom: str,
|
||||
length: Optional[float] = None) -> Dict:
|
||||
"""구매용 파이프 분류 - 끝단 가공 정보 제외"""
|
||||
|
||||
# 끝단 가공 정보 제거한 설명으로 분류
|
||||
clean_description = get_purchase_pipe_description(description)
|
||||
|
||||
# 기본 파이프 분류 수행
|
||||
result = classify_pipe(dat_file, clean_description, main_nom, length)
|
||||
|
||||
# 구매용임을 표시
|
||||
result["purchase_classification"] = True
|
||||
result["original_description"] = description
|
||||
result["clean_description"] = clean_description
|
||||
|
||||
return result
|
||||
|
||||
def classify_pipe(dat_file: str, description: str, main_nom: str,
|
||||
length: Optional[float] = None) -> Dict:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user