feat: 자재 분류 시스템 개선 및 상세 테이블 추가
- 모든 자재 카테고리별 상세 테이블 생성 (fitting, valve, flange, bolt, gasket, instrument) - PIPE, FITTING, VALVE 분류 결과를 각 상세 테이블에 저장하는 로직 구현 - 프론트엔드 라우팅 정리 및 BOM 현황 페이지 기능 개선 - 자재확인 페이지 에러 처리 개선 TODO: FLANGE, BOLT, GASKET, INSTRUMENT 저장 로직 추가 필요
This commit is contained in:
462
backend/scripts/06_insert_material_standards_data.py
Normal file
462
backend/scripts/06_insert_material_standards_data.py
Normal file
@@ -0,0 +1,462 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
자재 규격/재질 기준표 데이터를 DB에 삽입하는 스크립트
|
||||
기존 materials_schema.py의 딕셔너리 데이터를 DB 테이블로 변환
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from app.database import DATABASE_URL
|
||||
from app.models import (
|
||||
MaterialStandard, MaterialCategory, MaterialSpecification,
|
||||
MaterialGrade, MaterialPattern, SpecialMaterial,
|
||||
SpecialMaterialGrade, SpecialMaterialPattern
|
||||
)
|
||||
|
||||
# 기존 materials_schema.py의 데이터 (일부만 예시로 포함)
|
||||
MATERIAL_STANDARDS_DATA = {
|
||||
"ASTM_ASME": {
|
||||
"name": "미국재질학회",
|
||||
"country": "USA",
|
||||
"categories": {
|
||||
"FORGED_GRADES": {
|
||||
"name": "단조품",
|
||||
"specifications": {
|
||||
"A182": {
|
||||
"name": "탄소강 단조품",
|
||||
"material_type": "carbon_alloy",
|
||||
"manufacturing": "FORGED",
|
||||
"subtypes": {
|
||||
"carbon_alloy": {
|
||||
"manufacturing": "FORGED",
|
||||
"grades": {
|
||||
"F1": {
|
||||
"composition": "0.5Mo",
|
||||
"temp_max": "482°C",
|
||||
"applications": "중온용"
|
||||
},
|
||||
"F5": {
|
||||
"composition": "5Cr-0.5Mo",
|
||||
"temp_max": "649°C",
|
||||
"applications": "고온용"
|
||||
},
|
||||
"F11": {
|
||||
"composition": "1.25Cr-0.5Mo",
|
||||
"temp_max": "593°C",
|
||||
"applications": "일반 고온용"
|
||||
},
|
||||
"F22": {
|
||||
"composition": "2.25Cr-1Mo",
|
||||
"temp_max": "649°C",
|
||||
"applications": "고온 고압용"
|
||||
},
|
||||
"F91": {
|
||||
"composition": "9Cr-1Mo-V",
|
||||
"temp_max": "649°C",
|
||||
"applications": "초고온용"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
r"ASTM\s+A182\s+(?:GR\s*)?F(\d+)",
|
||||
r"A182\s+(?:GR\s*)?F(\d+)",
|
||||
r"ASME\s+SA182\s+(?:GR\s*)?F(\d+)"
|
||||
]
|
||||
},
|
||||
"stainless": {
|
||||
"manufacturing": "FORGED",
|
||||
"grades": {
|
||||
"F304": {
|
||||
"composition": "18Cr-8Ni",
|
||||
"applications": "일반용",
|
||||
"corrosion_resistance": "보통"
|
||||
},
|
||||
"F304L": {
|
||||
"composition": "18Cr-8Ni-저탄소",
|
||||
"applications": "용접용",
|
||||
"corrosion_resistance": "보통"
|
||||
},
|
||||
"F316": {
|
||||
"composition": "18Cr-10Ni-2Mo",
|
||||
"applications": "내식성",
|
||||
"corrosion_resistance": "우수"
|
||||
},
|
||||
"F316L": {
|
||||
"composition": "18Cr-10Ni-2Mo-저탄소",
|
||||
"applications": "용접+내식성",
|
||||
"corrosion_resistance": "우수"
|
||||
},
|
||||
"F321": {
|
||||
"composition": "18Cr-8Ni-Ti",
|
||||
"applications": "고온안정화",
|
||||
"stabilizer": "Titanium"
|
||||
},
|
||||
"F347": {
|
||||
"composition": "18Cr-8Ni-Nb",
|
||||
"applications": "고온안정화",
|
||||
"stabilizer": "Niobium"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
r"ASTM\s+A182\s+F(\d{3}[LH]*)",
|
||||
r"A182\s+F(\d{3}[LH]*)",
|
||||
r"ASME\s+SA182\s+F(\d{3}[LH]*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"A105": {
|
||||
"name": "탄소강 단조품",
|
||||
"description": "탄소강 단조품",
|
||||
"composition": "탄소강",
|
||||
"applications": "일반 압력용 단조품",
|
||||
"manufacturing": "FORGED",
|
||||
"pressure_rating": "150LB ~ 9000LB",
|
||||
"patterns": [
|
||||
r"ASTM\s+A105(?:\s+(?:GR\s*)?([ABC]))?",
|
||||
r"A105(?:\s+(?:GR\s*)?([ABC]))?",
|
||||
r"ASME\s+SA105"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"WELDED_GRADES": {
|
||||
"name": "용접품",
|
||||
"specifications": {
|
||||
"A234": {
|
||||
"name": "탄소강 용접 피팅",
|
||||
"material_type": "carbon",
|
||||
"manufacturing": "WELDED_FABRICATED",
|
||||
"subtypes": {
|
||||
"carbon": {
|
||||
"manufacturing": "WELDED_FABRICATED",
|
||||
"grades": {
|
||||
"WPA": {
|
||||
"yield_strength": "30 ksi",
|
||||
"applications": "저압용",
|
||||
"temp_range": "-29°C ~ 400°C"
|
||||
},
|
||||
"WPB": {
|
||||
"yield_strength": "35 ksi",
|
||||
"applications": "일반용",
|
||||
"temp_range": "-29°C ~ 400°C"
|
||||
},
|
||||
"WPC": {
|
||||
"yield_strength": "40 ksi",
|
||||
"applications": "고압용",
|
||||
"temp_range": "-29°C ~ 400°C"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
r"ASTM\s+A234\s+(?:GR\s*)?WP([ABC])",
|
||||
r"A234\s+(?:GR\s*)?WP([ABC])",
|
||||
r"ASME\s+SA234\s+(?:GR\s*)?WP([ABC])"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"KS": {
|
||||
"name": "한국산업표준",
|
||||
"country": "KOREA",
|
||||
"categories": {
|
||||
"PIPE_GRADES": {
|
||||
"name": "배관용",
|
||||
"specifications": {
|
||||
"D3507": {
|
||||
"name": "배관용 탄소강관",
|
||||
"description": "배관용 탄소강관",
|
||||
"manufacturing": "SEAMLESS",
|
||||
"patterns": [
|
||||
r"KS\s+D\s*3507\s+SPPS\s*(\d+)"
|
||||
]
|
||||
},
|
||||
"D3583": {
|
||||
"name": "압력배관용 탄소강관",
|
||||
"description": "압력배관용 탄소강관",
|
||||
"manufacturing": "SEAMLESS",
|
||||
"patterns": [
|
||||
r"KS\s+D\s*3583\s+STPG\s*(\d+)"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"JIS": {
|
||||
"name": "일본공업규격",
|
||||
"country": "JAPAN",
|
||||
"categories": {
|
||||
"PIPE_GRADES": {
|
||||
"name": "배관용",
|
||||
"specifications": {
|
||||
"G3452": {
|
||||
"name": "배관용 탄소강관",
|
||||
"description": "배관용 탄소강관",
|
||||
"manufacturing": "WELDED",
|
||||
"patterns": [
|
||||
r"JIS\s+G\s*3452\s+SGP"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SPECIAL_MATERIALS_DATA = {
|
||||
"SUPER_ALLOYS": {
|
||||
"INCONEL": {
|
||||
"description": "니켈 기반 초합금",
|
||||
"composition": "Ni-Cr",
|
||||
"applications": "고온 산화 환경",
|
||||
"temp_max": "1177°C",
|
||||
"manufacturing": "FORGED_OR_CAST",
|
||||
"grades": {
|
||||
"600": {
|
||||
"composition": "Ni-Cr",
|
||||
"temp_max": "1177°C",
|
||||
"applications": "고온 산화 환경"
|
||||
},
|
||||
"625": {
|
||||
"composition": "Ni-Cr-Mo",
|
||||
"temp_max": "982°C",
|
||||
"applications": "고온 부식 환경"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
r"INCONEL\s*(\d+)"
|
||||
]
|
||||
}
|
||||
},
|
||||
"TITANIUM": {
|
||||
"TITANIUM": {
|
||||
"description": "티타늄 및 티타늄 합금",
|
||||
"composition": "Ti",
|
||||
"applications": "화학공정, 항공우주",
|
||||
"temp_max": "1177°C",
|
||||
"manufacturing": "FORGED_OR_SEAMLESS",
|
||||
"grades": {
|
||||
"1": {
|
||||
"purity": "상업용 순티타늄",
|
||||
"strength": "낮음",
|
||||
"applications": "화학공정"
|
||||
},
|
||||
"2": {
|
||||
"purity": "상업용 순티타늄 (일반)",
|
||||
"strength": "보통",
|
||||
"applications": "일반용"
|
||||
},
|
||||
"5": {
|
||||
"composition": "Ti-6Al-4V",
|
||||
"strength": "고강도",
|
||||
"applications": "항공우주"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
r"TITANIUM(?:\s+(?:GR|GRADE)\s*(\d+))?",
|
||||
r"Ti(?:\s+(?:GR|GRADE)\s*(\d+))?",
|
||||
r"ASTM\s+B\d+\s+(?:GR|GRADE)\s*(\d+)"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def insert_material_standards():
|
||||
"""자재 규격 데이터를 DB에 삽입"""
|
||||
engine = create_engine(DATABASE_URL)
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
|
||||
try:
|
||||
print("자재 규격 데이터 삽입 시작...")
|
||||
|
||||
# 1. 자재 규격 표준 삽입
|
||||
for standard_code, standard_data in MATERIAL_STANDARDS_DATA.items():
|
||||
standard = MaterialStandard(
|
||||
standard_code=standard_code,
|
||||
standard_name=standard_data["name"],
|
||||
country=standard_data["country"],
|
||||
description=f"{standard_data['name']} 규격"
|
||||
)
|
||||
session.add(standard)
|
||||
session.flush() # ID 생성
|
||||
|
||||
print(f" - {standard_code} ({standard_data['name']}) 추가됨")
|
||||
|
||||
# 2. 카테고리 삽입
|
||||
for category_code, category_data in standard_data["categories"].items():
|
||||
category = MaterialCategory(
|
||||
standard_id=standard.id,
|
||||
category_code=category_code,
|
||||
category_name=category_data["name"],
|
||||
description=f"{category_data['name']} 분류"
|
||||
)
|
||||
session.add(category)
|
||||
session.flush()
|
||||
|
||||
print(f" - {category_code} ({category_data['name']}) 추가됨")
|
||||
|
||||
# 3. 규격 삽입
|
||||
for spec_code, spec_data in category_data["specifications"].items():
|
||||
specification = MaterialSpecification(
|
||||
category_id=category.id,
|
||||
spec_code=spec_code,
|
||||
spec_name=spec_data["name"],
|
||||
description=spec_data.get("description", ""),
|
||||
material_type=spec_data.get("material_type"),
|
||||
manufacturing=spec_data.get("manufacturing"),
|
||||
pressure_rating=spec_data.get("pressure_rating")
|
||||
)
|
||||
session.add(specification)
|
||||
session.flush()
|
||||
|
||||
print(f" - {spec_code} ({spec_data['name']}) 추가됨")
|
||||
|
||||
# 4. 패턴 삽입
|
||||
if "patterns" in spec_data:
|
||||
for i, pattern in enumerate(spec_data["patterns"]):
|
||||
pattern_obj = MaterialPattern(
|
||||
specification_id=specification.id,
|
||||
pattern=pattern,
|
||||
description=f"{spec_code} 패턴 {i+1}",
|
||||
priority=i+1
|
||||
)
|
||||
session.add(pattern_obj)
|
||||
|
||||
# 5. 등급 삽입 (subtypes가 있는 경우)
|
||||
if "subtypes" in spec_data:
|
||||
for subtype_name, subtype_data in spec_data["subtypes"].items():
|
||||
# subtypes의 grades 처리
|
||||
if "grades" in subtype_data:
|
||||
for grade_code, grade_data in subtype_data["grades"].items():
|
||||
grade = MaterialGrade(
|
||||
specification_id=specification.id,
|
||||
grade_code=grade_code,
|
||||
composition=grade_data.get("composition"),
|
||||
applications=grade_data.get("applications"),
|
||||
temp_max=grade_data.get("temp_max"),
|
||||
temp_range=grade_data.get("temp_range"),
|
||||
yield_strength=grade_data.get("yield_strength"),
|
||||
corrosion_resistance=grade_data.get("corrosion_resistance"),
|
||||
stabilizer=grade_data.get("stabilizer"),
|
||||
base_grade=grade_data.get("base_grade")
|
||||
)
|
||||
session.add(grade)
|
||||
print(f" - {grade_code} 등급 추가됨")
|
||||
|
||||
# 5. 등급 삽입 (직접 grades가 있는 경우)
|
||||
elif "grades" in spec_data:
|
||||
for grade_code, grade_data in spec_data["grades"].items():
|
||||
grade = MaterialGrade(
|
||||
specification_id=specification.id,
|
||||
grade_code=grade_code,
|
||||
composition=grade_data.get("composition"),
|
||||
applications=grade_data.get("applications"),
|
||||
temp_max=grade_data.get("temp_max"),
|
||||
temp_range=grade_data.get("temp_range"),
|
||||
yield_strength=grade_data.get("yield_strength"),
|
||||
corrosion_resistance=grade_data.get("corrosion_resistance"),
|
||||
stabilizer=grade_data.get("stabilizer"),
|
||||
base_grade=grade_data.get("base_grade")
|
||||
)
|
||||
session.add(grade)
|
||||
print(f" - {grade_code} 등급 추가됨")
|
||||
|
||||
session.commit()
|
||||
print("자재 규격 데이터 삽입 완료!")
|
||||
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
print(f"오류 발생: {e}")
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def insert_special_materials():
|
||||
"""특수 재질 데이터를 DB에 삽입"""
|
||||
engine = create_engine(DATABASE_URL)
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
|
||||
try:
|
||||
print("특수 재질 데이터 삽입 시작...")
|
||||
|
||||
for material_type, materials in SPECIAL_MATERIALS_DATA.items():
|
||||
for material_name, material_data in materials.items():
|
||||
# 특수 재질 추가
|
||||
special_material = SpecialMaterial(
|
||||
material_type=material_type,
|
||||
material_name=material_name,
|
||||
description=material_data.get("description", ""),
|
||||
composition=material_data.get("composition"),
|
||||
applications=material_data.get("applications"),
|
||||
temp_max=material_data.get("temp_max"),
|
||||
manufacturing=material_data.get("manufacturing")
|
||||
)
|
||||
session.add(special_material)
|
||||
session.flush()
|
||||
|
||||
print(f" - {material_name} ({material_type}) 추가됨")
|
||||
|
||||
# 등급 추가
|
||||
if "grades" in material_data:
|
||||
for grade_code, grade_data in material_data["grades"].items():
|
||||
grade = SpecialMaterialGrade(
|
||||
material_id=special_material.id,
|
||||
grade_code=grade_code,
|
||||
composition=grade_data.get("composition"),
|
||||
applications=grade_data.get("applications"),
|
||||
temp_max=grade_data.get("temp_max"),
|
||||
strength=grade_data.get("strength"),
|
||||
purity=grade_data.get("purity"),
|
||||
corrosion=grade_data.get("corrosion")
|
||||
)
|
||||
session.add(grade)
|
||||
print(f" - {grade_code} 등급 추가됨")
|
||||
|
||||
# 패턴 추가
|
||||
if "patterns" in material_data:
|
||||
for i, pattern in enumerate(material_data["patterns"]):
|
||||
pattern_obj = SpecialMaterialPattern(
|
||||
material_id=special_material.id,
|
||||
pattern=pattern,
|
||||
description=f"{material_name} 패턴 {i+1}",
|
||||
priority=i+1
|
||||
)
|
||||
session.add(pattern_obj)
|
||||
|
||||
session.commit()
|
||||
print("특수 재질 데이터 삽입 완료!")
|
||||
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
print(f"오류 발생: {e}")
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def main():
|
||||
"""메인 실행 함수"""
|
||||
print("자재 규격/재질 기준표 DB 데이터 삽입 시작")
|
||||
print("=" * 50)
|
||||
|
||||
# 1. 자재 규격 데이터 삽입
|
||||
insert_material_standards()
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
|
||||
# 2. 특수 재질 데이터 삽입
|
||||
insert_special_materials()
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("모든 데이터 삽입 완료!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user