feat: 자재 리비전 비교 및 구매 목록 시스템 구현
- 자재 리비전간 비교 기능 추가 (MaterialComparisonPage) - 버그 해결 필요 - 리비전간 추가 구매 필요 자재 분석 페이지 추가 (RevisionPurchasePage) - 자재 비교 결과 컴포넌트 구현 (MaterialComparisonResult) - 자재 비교 API 라우터 추가 (material_comparison.py) - 로직 개선 필요 - 자재 비교 시스템 데이터베이스 스키마 추가 - FileManager, FileUpload 컴포넌트 개선 - BOMManagerPage 제거 및 새로운 구조로 리팩토링 - 자재 분류기 및 스키마 개선 TODO: 자재 비교 알고리즘 정확도 향상 및 예외 처리 강화 필요
This commit is contained in:
@@ -169,9 +169,18 @@ def parse_file_data(file_path):
|
||||
async def upload_file(
|
||||
file: UploadFile = File(...),
|
||||
job_no: str = Form(...),
|
||||
revision: str = Form("Rev.0"),
|
||||
revision: str = Form("Rev.0"), # 기본값은 Rev.0 (새 BOM)
|
||||
parent_file_id: Optional[int] = Form(None), # 리비전 업로드 시 부모 파일 ID
|
||||
bom_name: Optional[str] = Form(None), # BOM 이름 (사용자 입력)
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
print(f"📥 업로드 요청 받음:")
|
||||
print(f" - 파일명: {file.filename}")
|
||||
print(f" - job_no: {job_no}")
|
||||
print(f" - revision: {revision}")
|
||||
print(f" - parent_file_id: {parent_file_id}")
|
||||
print(f" - bom_name: {bom_name}")
|
||||
print(f" - parent_file_id 타입: {type(parent_file_id)}")
|
||||
if not validate_file_extension(file.filename):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
@@ -198,11 +207,67 @@ async def upload_file(
|
||||
parsed_count = len(materials_data)
|
||||
print(f"파싱 완료: {parsed_count}개 자재")
|
||||
|
||||
# 리비전 업로드인 경우만 자동 리비전 생성
|
||||
if parent_file_id is not None:
|
||||
print(f"리비전 업로드 모드: parent_file_id = {parent_file_id}")
|
||||
# 부모 파일의 정보 조회
|
||||
parent_query = text("""
|
||||
SELECT original_filename, revision, bom_name FROM files
|
||||
WHERE id = :parent_file_id AND job_no = :job_no
|
||||
""")
|
||||
|
||||
parent_result = db.execute(parent_query, {
|
||||
"parent_file_id": parent_file_id,
|
||||
"job_no": job_no
|
||||
})
|
||||
parent_file = parent_result.fetchone()
|
||||
|
||||
if not parent_file:
|
||||
raise HTTPException(status_code=404, detail="부모 파일을 찾을 수 없습니다.")
|
||||
|
||||
# 해당 BOM의 최신 리비전 확인 (bom_name 기준)
|
||||
bom_name_to_use = parent_file[2] or parent_file[0] # bom_name 우선, 없으면 original_filename
|
||||
latest_revision_query = text("""
|
||||
SELECT revision FROM files
|
||||
WHERE job_no = :job_no
|
||||
AND (bom_name = :bom_name OR (bom_name IS NULL AND original_filename = :bom_name))
|
||||
ORDER BY revision DESC
|
||||
LIMIT 1
|
||||
""")
|
||||
|
||||
latest_result = db.execute(latest_revision_query, {
|
||||
"job_no": job_no,
|
||||
"bom_name": bom_name_to_use
|
||||
})
|
||||
latest_revision = latest_result.fetchone()
|
||||
|
||||
if latest_revision:
|
||||
latest_rev = latest_revision[0]
|
||||
if latest_rev.startswith("Rev."):
|
||||
try:
|
||||
rev_num = int(latest_rev.replace("Rev.", ""))
|
||||
revision = f"Rev.{rev_num + 1}"
|
||||
except ValueError:
|
||||
revision = "Rev.1"
|
||||
else:
|
||||
revision = "Rev.1"
|
||||
|
||||
print(f"리비전 업로드: {latest_rev} → {revision}")
|
||||
else:
|
||||
revision = "Rev.1"
|
||||
print(f"첫 번째 리비전: {revision}")
|
||||
|
||||
# 파일명을 부모와 동일하게 유지
|
||||
file.filename = parent_file[0]
|
||||
else:
|
||||
# 일반 업로드 (새 BOM)
|
||||
print(f"일반 업로드 모드: 새 BOM 파일 (Rev.0)")
|
||||
|
||||
# 파일 정보 저장
|
||||
print("DB 저장 시작")
|
||||
file_insert_query = text("""
|
||||
INSERT INTO files (filename, original_filename, file_path, job_no, revision, description, file_size, parsed_count, is_active)
|
||||
VALUES (:filename, :original_filename, :file_path, :job_no, :revision, :description, :file_size, :parsed_count, :is_active)
|
||||
INSERT INTO files (filename, original_filename, file_path, job_no, revision, bom_name, description, file_size, parsed_count, is_active)
|
||||
VALUES (:filename, :original_filename, :file_path, :job_no, :revision, :bom_name, :description, :file_size, :parsed_count, :is_active)
|
||||
RETURNING id
|
||||
""")
|
||||
|
||||
@@ -212,6 +277,7 @@ async def upload_file(
|
||||
"file_path": str(file_path),
|
||||
"job_no": job_no,
|
||||
"revision": revision,
|
||||
"bom_name": bom_name or file.filename, # bom_name 우선, 없으면 파일명
|
||||
"description": f"BOM 파일 - {parsed_count}개 자재",
|
||||
"file_size": file.size,
|
||||
"parsed_count": parsed_count,
|
||||
@@ -434,8 +500,28 @@ async def upload_file(
|
||||
else:
|
||||
end_prep = str(end_prep_info) if end_prep_info else ""
|
||||
|
||||
# 재질 정보 - 이미 정제된 material_grade 사용
|
||||
material_spec = material_data.get("material_grade", "")
|
||||
# 재질 정보 - 분류 결과에서 상세 정보 추출
|
||||
material_grade_from_classifier = ""
|
||||
if isinstance(material_info, dict):
|
||||
material_grade_from_classifier = material_info.get("grade", "")
|
||||
|
||||
# 분류기에서 더 상세한 재질 정보가 나왔으면 업데이트
|
||||
if material_grade_from_classifier and material_grade_from_classifier != "UNKNOWN":
|
||||
material_spec = material_grade_from_classifier
|
||||
|
||||
# materials 테이블의 material_grade도 업데이트
|
||||
db.execute(text("""
|
||||
UPDATE materials
|
||||
SET material_grade = :new_material_grade
|
||||
WHERE id = :material_id
|
||||
"""), {
|
||||
"new_material_grade": material_grade_from_classifier,
|
||||
"material_id": material_id
|
||||
})
|
||||
print(f"PIPE material_grade 업데이트: {material_grade_from_classifier}")
|
||||
else:
|
||||
# 기존 파싱 결과 사용
|
||||
material_spec = material_data.get("material_grade", "")
|
||||
|
||||
# 제조방법 추출
|
||||
manufacturing_method = ""
|
||||
@@ -488,6 +574,18 @@ async def upload_file(
|
||||
material_standard = material_info.get("standard", "")
|
||||
material_grade = material_info.get("grade", "")
|
||||
|
||||
# 분류기에서 더 상세한 재질 정보가 나왔으면 업데이트
|
||||
if material_grade and material_grade != "UNKNOWN":
|
||||
db.execute(text("""
|
||||
UPDATE materials
|
||||
SET material_grade = :new_material_grade
|
||||
WHERE id = :material_id
|
||||
"""), {
|
||||
"new_material_grade": material_grade,
|
||||
"material_id": material_id
|
||||
})
|
||||
print(f"FITTING material_grade 업데이트: {material_grade}")
|
||||
|
||||
# main_size와 reduced_size
|
||||
main_size = material_data.get("main_nom") or material_data.get("size_spec", "")
|
||||
reduced_size = material_data.get("red_nom", "")
|
||||
@@ -572,6 +670,18 @@ async def upload_file(
|
||||
if isinstance(material_info, dict):
|
||||
material_standard = material_info.get("standard", "")
|
||||
material_grade = material_info.get("grade", "")
|
||||
|
||||
# 분류기에서 더 상세한 재질 정보가 나왔으면 업데이트
|
||||
if material_grade and material_grade != "UNKNOWN":
|
||||
db.execute(text("""
|
||||
UPDATE materials
|
||||
SET material_grade = :new_material_grade
|
||||
WHERE id = :material_id
|
||||
"""), {
|
||||
"new_material_grade": material_grade,
|
||||
"material_id": material_id
|
||||
})
|
||||
print(f"FLANGE material_grade 업데이트: {material_grade}")
|
||||
|
||||
# 사이즈 정보
|
||||
size_inches = material_data.get("main_nom") or material_data.get("size_spec", "")
|
||||
@@ -718,6 +828,18 @@ async def upload_file(
|
||||
if isinstance(material_info, dict):
|
||||
material_standard = material_info.get("standard", "")
|
||||
material_grade = material_info.get("grade", "")
|
||||
|
||||
# 분류기에서 더 상세한 재질 정보가 나왔으면 업데이트
|
||||
if material_grade and material_grade != "UNKNOWN":
|
||||
db.execute(text("""
|
||||
UPDATE materials
|
||||
SET material_grade = :new_material_grade
|
||||
WHERE id = :material_id
|
||||
"""), {
|
||||
"new_material_grade": material_grade,
|
||||
"material_id": material_id
|
||||
})
|
||||
print(f"BOLT material_grade 업데이트: {material_grade}")
|
||||
|
||||
# 압력 등급 (150LB 등)
|
||||
pressure_rating = ""
|
||||
@@ -821,6 +943,18 @@ async def upload_file(
|
||||
body_material = material_info.get("grade", "")
|
||||
# 트림 재질은 일반적으로 바디와 동일하거나 별도 명시
|
||||
trim_material = body_material
|
||||
|
||||
# 분류기에서 더 상세한 재질 정보가 나왔으면 업데이트
|
||||
if body_material and body_material != "UNKNOWN":
|
||||
db.execute(text("""
|
||||
UPDATE materials
|
||||
SET material_grade = :new_material_grade
|
||||
WHERE id = :material_id
|
||||
"""), {
|
||||
"new_material_grade": body_material,
|
||||
"material_id": material_id
|
||||
})
|
||||
print(f"VALVE material_grade 업데이트: {body_material}")
|
||||
|
||||
# 사이즈 정보
|
||||
size_inches = material_data.get("main_nom") or material_data.get("size_spec", "")
|
||||
@@ -879,6 +1013,8 @@ async def upload_file(
|
||||
"original_filename": file.filename,
|
||||
"file_id": file_id,
|
||||
"materials_count": materials_inserted,
|
||||
"saved_materials_count": materials_inserted,
|
||||
"revision": revision, # 생성된 리비전 정보 추가
|
||||
"parsed_count": parsed_count
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user