593 lines
27 KiB
Python
593 lines
27 KiB
Python
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import text
|
|
from typing import List, Dict, Optional
|
|
import json
|
|
from datetime import datetime
|
|
|
|
from app.services.integrated_classifier import classify_material_integrated, should_exclude_material
|
|
from app.services.bolt_classifier import classify_bolt
|
|
from app.services.flange_classifier import classify_flange
|
|
from app.services.fitting_classifier import classify_fitting
|
|
from app.services.gasket_classifier import classify_gasket
|
|
from app.services.instrument_classifier import classify_instrument
|
|
from app.services.valve_classifier import classify_valve
|
|
from app.services.support_classifier import classify_support
|
|
from app.services.plate_classifier import classify_plate
|
|
from app.services.structural_classifier import classify_structural
|
|
from app.services.pipe_classifier import classify_pipe_for_purchase, extract_end_preparation_info
|
|
from app.services.material_grade_extractor import extract_full_material_grade
|
|
|
|
class MaterialService:
|
|
"""자재 처리 및 저장을 담당하는 서비스"""
|
|
|
|
@staticmethod
|
|
def process_and_save_materials(
|
|
db: Session,
|
|
file_id: int,
|
|
materials_data: List[Dict],
|
|
revision_comparison: Optional[Dict] = None,
|
|
parent_file_id: Optional[int] = None,
|
|
purchased_materials_map: Optional[Dict] = None
|
|
) -> int:
|
|
"""
|
|
자재 목록을 분류하고 DB에 저장합니다.
|
|
|
|
Args:
|
|
db: DB 세션
|
|
file_id: 파일 ID
|
|
materials_data: 파싱된 자재 데이터 목록
|
|
revision_comparison: 리비전 비교 결과
|
|
parent_file_id: 이전 리비전 파일 ID
|
|
purchased_materials_map: 구매 확정된 자재 매핑 정보
|
|
|
|
Returns:
|
|
저장된 자재 수
|
|
"""
|
|
materials_inserted = 0
|
|
|
|
# 변경/신규 자재 키 집합 (리비전 추적용)
|
|
changed_materials_keys = set()
|
|
new_materials_keys = set()
|
|
|
|
# 리비전 업로드인 경우 변경사항 분석
|
|
if parent_file_id is not None:
|
|
MaterialService._analyze_changes(
|
|
db, parent_file_id, materials_data,
|
|
changed_materials_keys, new_materials_keys
|
|
)
|
|
|
|
# 변경 없는 자재 (확정된 자재) 먼저 처리
|
|
if revision_comparison and revision_comparison.get("has_previous_confirmation", False):
|
|
unchanged_materials = revision_comparison.get("unchanged_materials", [])
|
|
for material_data in unchanged_materials:
|
|
MaterialService._save_unchanged_material(db, file_id, material_data)
|
|
materials_inserted += 1
|
|
|
|
# 분류가 필요한 자재 처리 (신규 또는 변경된 자재)
|
|
# revision_comparison에서 필터링된 목록이 있으면 그것을 사용, 아니면 전체
|
|
materials_to_classify = materials_data
|
|
if revision_comparison and revision_comparison.get("materials_to_classify"):
|
|
materials_to_classify = revision_comparison.get("materials_to_classify")
|
|
|
|
print(f"🔧 자재 분류 및 저장 시작: {len(materials_to_classify)}개")
|
|
|
|
for material_data in materials_to_classify:
|
|
MaterialService._classify_and_save_single_material(
|
|
db, file_id, material_data,
|
|
changed_materials_keys, new_materials_keys,
|
|
purchased_materials_map
|
|
)
|
|
materials_inserted += 1
|
|
|
|
return materials_inserted
|
|
|
|
@staticmethod
|
|
def _analyze_changes(db: Session, parent_file_id: int, materials_data: List[Dict],
|
|
changed_keys: set, new_keys: set):
|
|
"""이전 리비전과 비교하여 변경/신규 자재를 식별합니다."""
|
|
try:
|
|
prev_materials_query = text("""
|
|
SELECT original_description, size_spec, material_grade, main_nom,
|
|
drawing_name, line_no, quantity
|
|
FROM materials
|
|
WHERE file_id = :parent_file_id
|
|
""")
|
|
prev_materials = db.execute(prev_materials_query, {"parent_file_id": parent_file_id}).fetchall()
|
|
|
|
prev_dict = {}
|
|
for pm in prev_materials:
|
|
key = MaterialService._generate_material_key(
|
|
pm.drawing_name, pm.line_no, pm.original_description,
|
|
pm.size_spec, pm.material_grade
|
|
)
|
|
prev_dict[key] = float(pm.quantity) if pm.quantity else 0
|
|
|
|
for mat in materials_data:
|
|
new_key = MaterialService._generate_material_key(
|
|
mat.get("dwg_name"), mat.get("line_num"), mat["original_description"],
|
|
mat.get("size_spec"), mat.get("material_grade")
|
|
)
|
|
|
|
if new_key in prev_dict:
|
|
if abs(prev_dict[new_key] - float(mat.get("quantity", 0))) > 0.001:
|
|
changed_keys.add(new_key)
|
|
else:
|
|
new_keys.add(new_key)
|
|
|
|
except Exception as e:
|
|
print(f"❌ 변경사항 분석 실패: {e}")
|
|
|
|
@staticmethod
|
|
def _generate_material_key(dwg, line, desc, size, grade):
|
|
"""자재 고유 키 생성"""
|
|
parts = []
|
|
if dwg: parts.append(str(dwg))
|
|
elif line: parts.append(str(line))
|
|
|
|
parts.append(str(desc))
|
|
parts.append(str(size or ''))
|
|
parts.append(str(grade or ''))
|
|
return "|".join(parts)
|
|
|
|
@staticmethod
|
|
def _save_unchanged_material(db: Session, file_id: int, material_data: Dict):
|
|
"""변경 없는(확정된) 자재 저장"""
|
|
previous_item = material_data.get("previous_item", {})
|
|
|
|
query = text("""
|
|
INSERT INTO materials (
|
|
file_id, original_description, classified_category, confidence,
|
|
quantity, unit, size_spec, material_grade, specification,
|
|
reused_from_confirmation, created_at
|
|
) VALUES (
|
|
:file_id, :desc, :category, 1.0,
|
|
:qty, :unit, :size, :grade, :spec,
|
|
TRUE, :created_at
|
|
)
|
|
""")
|
|
|
|
db.execute(query, {
|
|
"file_id": file_id,
|
|
"desc": material_data["original_description"],
|
|
"category": previous_item.get("category", "UNCLASSIFIED"),
|
|
"qty": material_data["quantity"],
|
|
"unit": material_data.get("unit", "EA"),
|
|
"size": material_data.get("size_spec", ""),
|
|
"grade": previous_item.get("material", ""),
|
|
"spec": previous_item.get("specification", ""),
|
|
"created_at": datetime.now()
|
|
})
|
|
|
|
@staticmethod
|
|
def _classify_and_save_single_material(
|
|
db: Session, file_id: int, material_data: Dict,
|
|
changed_keys: set, new_keys: set, purchased_map: Optional[Dict]
|
|
):
|
|
"""단일 자재 분류 및 저장 (상세 정보 포함)"""
|
|
description = material_data["original_description"]
|
|
main_nom = material_data.get("main_nom", "")
|
|
red_nom = material_data.get("red_nom", "")
|
|
length_val = material_data.get("length")
|
|
|
|
# 1. 통합 분류
|
|
integrated_result = classify_material_integrated(description, main_nom, red_nom, length_val)
|
|
classification_result = integrated_result
|
|
|
|
# 2. 상세 분류
|
|
if not should_exclude_material(description):
|
|
category = integrated_result.get('category')
|
|
if category == "PIPE":
|
|
classification_result = classify_pipe_for_purchase("", description, main_nom, length_val)
|
|
elif category == "FITTING":
|
|
classification_result = classify_fitting("", description, main_nom, red_nom)
|
|
elif category == "FLANGE":
|
|
classification_result = classify_flange("", description, main_nom, red_nom)
|
|
elif category == "VALVE":
|
|
classification_result = classify_valve("", description, main_nom)
|
|
elif category == "BOLT":
|
|
classification_result = classify_bolt("", description, main_nom)
|
|
elif category == "GASKET":
|
|
classification_result = classify_gasket("", description, main_nom)
|
|
elif category == "INSTRUMENT":
|
|
classification_result = classify_instrument("", description, main_nom)
|
|
elif category == "SUPPORT":
|
|
classification_result = classify_support("", description, main_nom)
|
|
elif category == "PLATE":
|
|
classification_result = classify_plate("", description, main_nom)
|
|
elif category == "STRUCTURAL":
|
|
classification_result = classify_structural("", description, main_nom)
|
|
|
|
# 신뢰도 조정
|
|
if integrated_result.get('confidence', 0) < 0.5:
|
|
classification_result['overall_confidence'] = min(
|
|
classification_result.get('overall_confidence', 1.0),
|
|
integrated_result.get('confidence', 0.0) + 0.2
|
|
)
|
|
else:
|
|
classification_result = {"category": "EXCLUDE", "overall_confidence": 0.95}
|
|
|
|
# 3. 구매 확정 정보 상속 확인
|
|
is_purchase_confirmed = False
|
|
purchase_confirmed_at = None
|
|
purchase_confirmed_by = None
|
|
|
|
if purchased_map:
|
|
key = f"{description.strip().upper()}|{material_data.get('size_spec', '')}"
|
|
if key in purchased_map:
|
|
info = purchased_map[key]
|
|
is_purchase_confirmed = True
|
|
purchase_confirmed_at = info.get("purchase_confirmed_at")
|
|
purchase_confirmed_by = info.get("purchase_confirmed_by")
|
|
|
|
# 4. 자재 기본 정보 저장
|
|
full_grade = extract_full_material_grade(description) or material_data.get("material_grade", "")
|
|
|
|
insert_query = text("""
|
|
INSERT INTO materials (
|
|
file_id, original_description, quantity, unit, size_spec,
|
|
main_nom, red_nom, material_grade, full_material_grade, line_number, row_number,
|
|
classified_category, classification_confidence, is_verified,
|
|
drawing_name, line_no, created_at,
|
|
purchase_confirmed, purchase_confirmed_at, purchase_confirmed_by,
|
|
revision_status
|
|
) VALUES (
|
|
:file_id, :desc, :qty, :unit, :size,
|
|
:main, :red, :grade, :full_grade, :line_num, :row_num,
|
|
:category, :confidence, :verified,
|
|
:dwg, :line, :created_at,
|
|
:confirmed, :confirmed_at, :confirmed_by,
|
|
:status
|
|
) RETURNING id
|
|
""")
|
|
|
|
# 리비전 상태 결정
|
|
mat_key = MaterialService._generate_material_key(
|
|
material_data.get("dwg_name"), material_data.get("line_num"), description,
|
|
material_data.get("size_spec"), material_data.get("material_grade")
|
|
)
|
|
rev_status = 'changed' if mat_key in changed_keys else ('active' if mat_key in new_keys else None)
|
|
|
|
result = db.execute(insert_query, {
|
|
"file_id": file_id,
|
|
"desc": description,
|
|
"qty": material_data["quantity"],
|
|
"unit": material_data["unit"],
|
|
"size": material_data.get("size_spec", ""),
|
|
"main": main_nom,
|
|
"red": red_nom,
|
|
"grade": material_data.get("material_grade", ""),
|
|
"full_grade": full_grade,
|
|
"line_num": material_data.get("line_number"),
|
|
"row_num": material_data.get("row_number"),
|
|
"category": classification_result.get("category", "UNCLASSIFIED"),
|
|
"confidence": classification_result.get("overall_confidence", 0.0),
|
|
"verified": False,
|
|
"dwg": material_data.get("dwg_name"),
|
|
"line": material_data.get("line_num"),
|
|
"created_at": datetime.now(),
|
|
"confirmed": is_purchase_confirmed,
|
|
"confirmed_at": purchase_confirmed_at,
|
|
"confirmed_by": purchase_confirmed_by,
|
|
"status": rev_status
|
|
})
|
|
|
|
material_id = result.fetchone()[0]
|
|
|
|
# 5. 상세 정보 저장 (별도 메서드로 분리)
|
|
MaterialService._save_material_details(
|
|
db, material_id, file_id, classification_result, material_data
|
|
)
|
|
|
|
@staticmethod
|
|
def _save_material_details(db: Session, material_id: int, file_id: int,
|
|
result: Dict, data: Dict):
|
|
"""카테고리별 상세 정보 저장"""
|
|
category = result.get("category")
|
|
|
|
if category == "PIPE":
|
|
MaterialService._save_pipe_details(db, material_id, file_id, result, data)
|
|
elif category == "FITTING":
|
|
MaterialService._save_fitting_details(db, material_id, file_id, result, data)
|
|
elif category == "FLANGE":
|
|
MaterialService._save_flange_details(db, material_id, file_id, result, data)
|
|
elif category == "BOLT":
|
|
MaterialService._save_bolt_details(db, material_id, file_id, result, data)
|
|
elif category == "VALVE":
|
|
MaterialService._save_valve_details(db, material_id, file_id, result, data)
|
|
elif category == "GASKET":
|
|
MaterialService._save_gasket_details(db, material_id, file_id, result, data)
|
|
elif category == "SUPPORT":
|
|
MaterialService._save_support_details(db, material_id, file_id, result, data)
|
|
elif category == "PLATE":
|
|
MaterialService._save_plate_details(db, material_id, file_id, result, data)
|
|
elif category == "STRUCTURAL":
|
|
MaterialService._save_structural_details(db, material_id, file_id, result, data)
|
|
|
|
@staticmethod
|
|
def _save_plate_details(db: Session, mid: int, fid: int, res: Dict, data: Dict):
|
|
"""판재 정보 업데이트 (현재는 materials 테이블에 요약 정보 저장)"""
|
|
details = res.get("details", {})
|
|
spec = f"{details.get('thickness')}T x {details.get('dimensions')}"
|
|
db.execute(text("""
|
|
UPDATE materials
|
|
SET size_spec = :size, material_grade = :mat
|
|
WHERE id = :id
|
|
"""), {"size": spec, "mat": details.get("material"), "id": mid})
|
|
|
|
@staticmethod
|
|
def _save_structural_details(db: Session, mid: int, fid: int, res: Dict, data: Dict):
|
|
"""형강 정보 업데이트 (현재는 materials 테이블에 요약 정보 저장)"""
|
|
details = res.get("details", {})
|
|
spec = f"{details.get('type')} {details.get('dimension')}"
|
|
db.execute(text("""
|
|
UPDATE materials
|
|
SET size_spec = :size
|
|
WHERE id = :id
|
|
"""), {"size": spec, "id": mid})
|
|
|
|
# --- 각 카테고리별 상세 저장 메서드들 (기존 로직 이관) ---
|
|
|
|
@staticmethod
|
|
def inherit_purchase_requests(db: Session, current_file_id: int, parent_file_id: int):
|
|
"""이전 리비전의 구매신청 정보를 상속합니다."""
|
|
try:
|
|
print(f"🔄 구매신청 정보 상속 처리 시작...")
|
|
|
|
# 1. 이전 리비전에서 그룹별 구매신청 수량 집계
|
|
prev_purchase_summary = text("""
|
|
SELECT
|
|
m.original_description,
|
|
m.size_spec,
|
|
m.material_grade,
|
|
m.drawing_name,
|
|
COUNT(DISTINCT pri.material_id) as purchased_count,
|
|
SUM(pri.quantity) as total_purchased_qty,
|
|
MIN(pri.request_id) as request_id
|
|
FROM materials m
|
|
JOIN purchase_request_items pri ON m.id = pri.material_id
|
|
WHERE m.file_id = :parent_file_id
|
|
GROUP BY m.original_description, m.size_spec, m.material_grade, m.drawing_name
|
|
""")
|
|
|
|
prev_purchases = db.execute(prev_purchase_summary, {"parent_file_id": parent_file_id}).fetchall()
|
|
|
|
# 2. 새 리비전에서 같은 그룹의 자재에 수량만큼 구매신청 상속
|
|
for prev_purchase in prev_purchases:
|
|
purchased_count = prev_purchase.purchased_count
|
|
|
|
# 새 리비전에서 같은 그룹의 자재 조회 (순서대로)
|
|
new_group_materials = text("""
|
|
SELECT id, quantity
|
|
FROM materials
|
|
WHERE file_id = :file_id
|
|
AND original_description = :description
|
|
AND COALESCE(size_spec, '') = :size_spec
|
|
AND COALESCE(material_grade, '') = :material_grade
|
|
AND COALESCE(drawing_name, '') = :drawing_name
|
|
ORDER BY id
|
|
LIMIT :limit
|
|
""")
|
|
|
|
new_materials = db.execute(new_group_materials, {
|
|
"file_id": current_file_id,
|
|
"description": prev_purchase.original_description,
|
|
"size_spec": prev_purchase.size_spec or '',
|
|
"material_grade": prev_purchase.material_grade or '',
|
|
"drawing_name": prev_purchase.drawing_name or '',
|
|
"limit": purchased_count
|
|
}).fetchall()
|
|
|
|
# 구매신청 수량만큼만 상속
|
|
for new_mat in new_materials:
|
|
inherit_query = text("""
|
|
INSERT INTO purchase_request_items (
|
|
request_id, material_id, quantity, unit, user_requirement
|
|
) VALUES (
|
|
:request_id, :material_id, :quantity, 'EA', ''
|
|
)
|
|
ON CONFLICT DO NOTHING
|
|
""")
|
|
db.execute(inherit_query, {
|
|
"request_id": prev_purchase.request_id,
|
|
"material_id": new_mat.id,
|
|
"quantity": new_mat.quantity
|
|
})
|
|
|
|
inherited_count = len(new_materials)
|
|
if inherited_count > 0:
|
|
print(f" ✅ {prev_purchase.original_description[:30]}... (도면: {prev_purchase.drawing_name or 'N/A'}) → {inherited_count}/{purchased_count}개 상속")
|
|
|
|
# 커밋은 호출하는 쪽에서 일괄 처리하거나 여기서 처리
|
|
# db.commit()
|
|
print(f"✅ 구매신청 정보 상속 완료")
|
|
|
|
except Exception as e:
|
|
print(f"❌ 구매신청 정보 상속 실패: {str(e)}")
|
|
# 상속 실패는 전체 프로세스를 중단하지 않음
|
|
|
|
@staticmethod
|
|
def _save_pipe_details(db, mid, fid, res, data):
|
|
# PIPE 상세 저장 로직
|
|
end_prep_info = extract_end_preparation_info(data["original_description"])
|
|
|
|
# 1. End Prep 정보 저장
|
|
db.execute(text("""
|
|
INSERT INTO pipe_end_preparations (
|
|
material_id, file_id, end_preparation_type, end_preparation_code,
|
|
machining_required, cutting_note, original_description, confidence
|
|
) VALUES (
|
|
:mid, :fid, :type, :code, :req, :note, :desc, :conf
|
|
)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": end_prep_info["end_preparation_type"],
|
|
"code": end_prep_info["end_preparation_code"],
|
|
"req": end_prep_info["machining_required"],
|
|
"note": end_prep_info["cutting_note"],
|
|
"desc": end_prep_info["original_description"],
|
|
"conf": end_prep_info["confidence"]
|
|
})
|
|
|
|
# 2. Pipe Details 저장
|
|
length_info = res.get("length_info", {})
|
|
length_mm = length_info.get("length_mm") or data.get("length", 0.0)
|
|
|
|
mat_info = res.get("material", {})
|
|
sch_info = res.get("schedule", {})
|
|
|
|
# 재질 정보 업데이트
|
|
if mat_info.get("grade"):
|
|
db.execute(text("UPDATE materials SET material_grade = :g WHERE id = :id"),
|
|
{"g": mat_info.get("grade"), "id": mid})
|
|
|
|
db.execute(text("""
|
|
INSERT INTO pipe_details (
|
|
material_id, file_id, outer_diameter, schedule,
|
|
material_spec, manufacturing_method, length_mm
|
|
) VALUES (:mid, :fid, :od, :sch, :spec, :method, :len)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"od": data.get("main_nom") or data.get("size_spec"),
|
|
"sch": sch_info.get("schedule", "UNKNOWN") if isinstance(sch_info, dict) else str(sch_info),
|
|
"spec": mat_info.get("grade", "") if isinstance(mat_info, dict) else "",
|
|
"method": res.get("manufacturing", {}).get("method", "UNKNOWN") if isinstance(res.get("manufacturing"), dict) else "UNKNOWN",
|
|
"len": length_mm or 0.0
|
|
})
|
|
|
|
@staticmethod
|
|
def _save_fitting_details(db, mid, fid, res, data):
|
|
fit_type = res.get("fitting_type", {})
|
|
mat_info = res.get("material", {})
|
|
|
|
if mat_info.get("grade"):
|
|
db.execute(text("UPDATE materials SET material_grade = :g WHERE id = :id"),
|
|
{"g": mat_info.get("grade"), "id": mid})
|
|
|
|
db.execute(text("""
|
|
INSERT INTO fitting_details (
|
|
material_id, file_id, fitting_type, fitting_subtype,
|
|
connection_method, pressure_rating, material_grade,
|
|
main_size, reduced_size
|
|
) VALUES (:mid, :fid, :type, :subtype, :conn, :rating, :grade, :main, :red)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": fit_type.get("type", "UNKNOWN") if isinstance(fit_type, dict) else str(fit_type),
|
|
"subtype": fit_type.get("subtype", "UNKNOWN") if isinstance(fit_type, dict) else "UNKNOWN",
|
|
"conn": res.get("connection_method", {}).get("method", "UNKNOWN") if isinstance(res.get("connection_method"), dict) else "UNKNOWN",
|
|
"rating": res.get("pressure_rating", {}).get("rating", "UNKNOWN") if isinstance(res.get("pressure_rating"), dict) else "UNKNOWN",
|
|
"grade": mat_info.get("grade", "") if isinstance(mat_info, dict) else "",
|
|
"main": data.get("main_nom") or data.get("size_spec"),
|
|
"red": data.get("red_nom", "")
|
|
})
|
|
|
|
@staticmethod
|
|
def _save_flange_details(db, mid, fid, res, data):
|
|
flg_type = res.get("flange_type", {})
|
|
mat_info = res.get("material", {})
|
|
|
|
if mat_info.get("grade"):
|
|
db.execute(text("UPDATE materials SET material_grade = :g WHERE id = :id"),
|
|
{"g": mat_info.get("grade"), "id": mid})
|
|
|
|
db.execute(text("""
|
|
INSERT INTO flange_details (
|
|
material_id, file_id, flange_type, pressure_rating,
|
|
facing_type, material_grade, size_inches
|
|
) VALUES (:mid, :fid, :type, :rating, :face, :grade, :size)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": flg_type.get("type", "UNKNOWN") if isinstance(flg_type, dict) else str(flg_type),
|
|
"rating": res.get("pressure_rating", {}).get("rating", "UNKNOWN") if isinstance(res.get("pressure_rating"), dict) else "UNKNOWN",
|
|
"face": res.get("face_finish", {}).get("finish", "UNKNOWN") if isinstance(res.get("face_finish"), dict) else "UNKNOWN",
|
|
"grade": mat_info.get("grade", "") if isinstance(mat_info, dict) else "",
|
|
"size": data.get("main_nom") or data.get("size_spec")
|
|
})
|
|
|
|
@staticmethod
|
|
def _save_bolt_details(db, mid, fid, res, data):
|
|
fast_type = res.get("fastener_type", {})
|
|
mat_info = res.get("material", {})
|
|
dim_info = res.get("dimensions", {})
|
|
|
|
if mat_info.get("grade"):
|
|
db.execute(text("UPDATE materials SET material_grade = :g WHERE id = :id"),
|
|
{"g": mat_info.get("grade"), "id": mid})
|
|
|
|
# 볼트 타입 결정 (특수 용도 고려)
|
|
bolt_type = fast_type.get("type", "UNKNOWN") if isinstance(fast_type, dict) else str(fast_type)
|
|
special_apps = res.get("special_applications", {}).get("detected_applications", [])
|
|
if "LT" in special_apps: bolt_type = "LT_BOLT"
|
|
elif "PSV" in special_apps: bolt_type = "PSV_BOLT"
|
|
|
|
# 코팅 타입
|
|
desc_upper = data["original_description"].upper()
|
|
coating = "UNKNOWN"
|
|
if "GALV" in desc_upper: coating = "GALVANIZED"
|
|
elif "ZINC" in desc_upper: coating = "ZINC_PLATED"
|
|
|
|
db.execute(text("""
|
|
INSERT INTO bolt_details (
|
|
material_id, file_id, bolt_type, thread_type,
|
|
diameter, length, material_grade, coating_type
|
|
) VALUES (:mid, :fid, :type, :thread, :dia, :len, :grade, :coating)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": bolt_type,
|
|
"thread": res.get("thread_specification", {}).get("standard", "UNKNOWN") if isinstance(res.get("thread_specification"), dict) else "UNKNOWN",
|
|
"dia": dim_info.get("nominal_size", data.get("main_nom", "")),
|
|
"len": dim_info.get("length", ""),
|
|
"grade": mat_info.get("grade", "") if isinstance(mat_info, dict) else "",
|
|
"coating": coating
|
|
})
|
|
|
|
@staticmethod
|
|
def _save_valve_details(db, mid, fid, res, data):
|
|
val_type = res.get("valve_type", {})
|
|
mat_info = res.get("material", {})
|
|
|
|
if mat_info.get("grade"):
|
|
db.execute(text("UPDATE materials SET material_grade = :g WHERE id = :id"),
|
|
{"g": mat_info.get("grade"), "id": mid})
|
|
|
|
db.execute(text("""
|
|
INSERT INTO valve_details (
|
|
material_id, file_id, valve_type, connection_method,
|
|
pressure_rating, body_material, size_inches
|
|
) VALUES (:mid, :fid, :type, :conn, :rating, :body, :size)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": val_type.get("type", "UNKNOWN") if isinstance(val_type, dict) else str(val_type),
|
|
"conn": res.get("connection_method", {}).get("method", "UNKNOWN") if isinstance(res.get("connection_method"), dict) else "UNKNOWN",
|
|
"rating": res.get("pressure_rating", {}).get("rating", "UNKNOWN") if isinstance(res.get("pressure_rating"), dict) else "UNKNOWN",
|
|
"body": mat_info.get("grade", "") if isinstance(mat_info, dict) else "",
|
|
"size": data.get("main_nom") or data.get("size_spec")
|
|
})
|
|
|
|
@staticmethod
|
|
def _save_gasket_details(db, mid, fid, res, data):
|
|
gask_type = res.get("gasket_type", {})
|
|
|
|
db.execute(text("""
|
|
INSERT INTO gasket_details (
|
|
material_id, file_id, gasket_type, pressure_rating, size_inches
|
|
) VALUES (:mid, :fid, :type, :rating, :size)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": gask_type.get("type", "UNKNOWN") if isinstance(gask_type, dict) else str(gask_type),
|
|
"rating": res.get("pressure_rating", {}).get("rating", "UNKNOWN") if isinstance(res.get("pressure_rating"), dict) else "UNKNOWN",
|
|
"size": data.get("main_nom") or data.get("size_spec")
|
|
})
|
|
|
|
@staticmethod
|
|
def _save_support_details(db, mid, fid, res, data):
|
|
db.execute(text("""
|
|
INSERT INTO support_details (
|
|
material_id, file_id, support_type, pipe_size
|
|
) VALUES (:mid, :fid, :type, :size)
|
|
"""), {
|
|
"mid": mid, "fid": fid,
|
|
"type": res.get("support_type", "UNKNOWN"),
|
|
"size": res.get("size_info", {}).get("pipe_size", "")
|
|
})
|