fix: 리비전 업로드 시 구매확정 상태 상속 문제 해결
문제점: - 리비전 파일 업로드 시 모든 자재가 purchase_confirmed=false로 새로 저장됨 - 이전 리비전에서 구매확정한 자재가 다시 미구매 상태로 돌아가는 버그 해결방법: 1. perform_simple_revision_comparison 함수에서 구매확정 정보 반환 - purchase_confirmed, purchase_confirmed_at, purchase_confirmed_by - purchased_materials_map 딕셔너리로 반환 2. materials 테이블 insert 시 구매확정 상태 상속 - 자재 식별 키로 purchased_materials_map 확인 - 매칭되면 구매확정 상태와 메타데이터 상속 - 로그 출력: "🔥 구매확정 상태 상속: ..." 3. 디버깅 정보 개선 - 리비전 비교 결과에 excluded_purchased_count 추가 - 첫 번째 자재 저장 시 purchase_confirmed 상태 출력 동작 방식: 1. Rev.1에서 자재 A를 구매확정 → purchase_confirmed=true 2. Rev.2 업로드 시 자재 A가 포함되어 있으면 3. 리비전 비교에서 자재 A를 purchased_materials_map에 저장 4. 새 파일의 자재 A 저장 시 구매확정 상태 상속 5. Rev.2의 자재 A도 purchase_confirmed=true 유지 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -514,7 +514,8 @@ async def upload_file(
|
|||||||
# 🔄 리비전 비교 수행 (RULES.md 코딩 컨벤션 준수)
|
# 🔄 리비전 비교 수행 (RULES.md 코딩 컨벤션 준수)
|
||||||
revision_comparison = None
|
revision_comparison = None
|
||||||
materials_to_classify = materials_data
|
materials_to_classify = materials_data
|
||||||
|
purchased_materials_map = {} # 구매확정된 자재 매핑 (키 -> 구매확정 정보)
|
||||||
|
|
||||||
if revision != "Rev.0": # 리비전 업로드인 경우만 비교
|
if revision != "Rev.0": # 리비전 업로드인 경우만 비교
|
||||||
print(f"🔍 [DEBUG] 리비전 비교 시작 - revision: {revision}, parent_file_id: {parent_file_id}")
|
print(f"🔍 [DEBUG] 리비전 비교 시작 - revision: {revision}, parent_file_id: {parent_file_id}")
|
||||||
try:
|
try:
|
||||||
@@ -522,20 +523,24 @@ async def upload_file(
|
|||||||
print(f"🔍 [DEBUG] perform_simple_revision_comparison 호출 중...")
|
print(f"🔍 [DEBUG] perform_simple_revision_comparison 호출 중...")
|
||||||
revision_comparison = perform_simple_revision_comparison(db, job_no, parent_file_id, materials_data)
|
revision_comparison = perform_simple_revision_comparison(db, job_no, parent_file_id, materials_data)
|
||||||
print(f"🔍 [DEBUG] 리비전 비교 완료: {revision_comparison.keys() if revision_comparison else 'None'}")
|
print(f"🔍 [DEBUG] 리비전 비교 완료: {revision_comparison.keys() if revision_comparison else 'None'}")
|
||||||
|
|
||||||
if revision_comparison.get("has_purchased_materials", False):
|
if revision_comparison.get("has_purchased_materials", False):
|
||||||
print(f"📊 간단한 리비전 비교 결과:")
|
print(f"📊 간단한 리비전 비교 결과:")
|
||||||
print(f" - 구매확정된 자재: {revision_comparison.get('purchased_count', 0)}개")
|
print(f" - 구매확정된 자재: {revision_comparison.get('purchased_count', 0)}개")
|
||||||
print(f" - 미구매 자재: {revision_comparison.get('unpurchased_count', 0)}개")
|
print(f" - 미구매 자재: {revision_comparison.get('unpurchased_count', 0)}개")
|
||||||
print(f" - 신규 자재: {revision_comparison.get('new_count', 0)}개")
|
print(f" - 신규 자재: {revision_comparison.get('new_count', 0)}개")
|
||||||
print(f" - 변경된 자재: {revision_comparison.get('changed_count', 0)}개")
|
print(f" - 제외된 구매확정 자재: {revision_comparison.get('excluded_purchased_count', 0)}개")
|
||||||
|
|
||||||
# 신규 및 변경된 자재만 분류
|
# 신규 및 변경된 자재만 분류
|
||||||
materials_to_classify = revision_comparison.get("materials_to_classify", [])
|
materials_to_classify = revision_comparison.get("materials_to_classify", [])
|
||||||
print(f" - 분류 필요: {len(materials_to_classify)}개")
|
print(f" - 분류 필요: {len(materials_to_classify)}개")
|
||||||
|
|
||||||
|
# 🔥 구매확정된 자재 매핑 정보 저장
|
||||||
|
purchased_materials_map = revision_comparison.get("purchased_materials_map", {})
|
||||||
|
print(f" - 구매확정 자재 매핑: {len(purchased_materials_map)}개")
|
||||||
else:
|
else:
|
||||||
print("📝 이전 구매확정 자료 없음 - 전체 자재 분류")
|
print("📝 이전 구매확정 자료 없음 - 전체 자재 분류")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 리비전 비교 실패, 전체 자재 분류로 진행: {str(e)}")
|
print(f"⚠️ 리비전 비교 실패, 전체 자재 분류로 진행: {str(e)}")
|
||||||
import traceback
|
import traceback
|
||||||
@@ -752,23 +757,42 @@ async def upload_file(
|
|||||||
if not full_material_grade and material_data.get("material_grade"):
|
if not full_material_grade and material_data.get("material_grade"):
|
||||||
full_material_grade = material_data["material_grade"]
|
full_material_grade = material_data["material_grade"]
|
||||||
|
|
||||||
|
# 🔥 구매확정 상태 확인 (리비전인 경우)
|
||||||
|
is_purchase_confirmed = False
|
||||||
|
purchase_confirmed_at = None
|
||||||
|
purchase_confirmed_by = None
|
||||||
|
|
||||||
|
if parent_file_id and purchased_materials_map:
|
||||||
|
# 자재 식별 키 생성 (리비전 비교와 동일한 방식)
|
||||||
|
material_key = f"{description.strip().upper()}|{size_spec or ''}"
|
||||||
|
|
||||||
|
if material_key in purchased_materials_map:
|
||||||
|
# 이전 리비전에서 구매확정된 자재
|
||||||
|
purchased_info = purchased_materials_map[material_key]
|
||||||
|
is_purchase_confirmed = True
|
||||||
|
purchase_confirmed_at = purchased_info.get("purchase_confirmed_at")
|
||||||
|
purchase_confirmed_by = purchased_info.get("purchase_confirmed_by")
|
||||||
|
print(f"🔥 구매확정 상태 상속: {description[:50]}...")
|
||||||
|
|
||||||
# 기본 자재 정보 저장
|
# 기본 자재 정보 저장
|
||||||
material_insert_query = text("""
|
material_insert_query = text("""
|
||||||
INSERT INTO materials (
|
INSERT INTO materials (
|
||||||
file_id, original_description, quantity, unit, size_spec,
|
file_id, original_description, quantity, unit, size_spec,
|
||||||
main_nom, red_nom, material_grade, full_material_grade, line_number, row_number,
|
main_nom, red_nom, material_grade, full_material_grade, line_number, row_number,
|
||||||
classified_category, classification_confidence, is_verified,
|
classified_category, classification_confidence, is_verified,
|
||||||
drawing_name, line_no, created_at
|
drawing_name, line_no, created_at,
|
||||||
|
purchase_confirmed, purchase_confirmed_at, purchase_confirmed_by
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
:file_id, :original_description, :quantity, :unit, :size_spec,
|
:file_id, :original_description, :quantity, :unit, :size_spec,
|
||||||
:main_nom, :red_nom, :material_grade, :full_material_grade, :line_number, :row_number,
|
:main_nom, :red_nom, :material_grade, :full_material_grade, :line_number, :row_number,
|
||||||
:classified_category, :classification_confidence, :is_verified,
|
:classified_category, :classification_confidence, :is_verified,
|
||||||
:drawing_name, :line_no, :created_at
|
:drawing_name, :line_no, :created_at,
|
||||||
|
:purchase_confirmed, :purchase_confirmed_at, :purchase_confirmed_by
|
||||||
)
|
)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 첫 번째 자재에 대해서만 디버그 출력
|
# 첫 번째 자재에 대해서만 디버그 출력
|
||||||
if materials_inserted == 0:
|
if materials_inserted == 0:
|
||||||
print(f"첫 번째 자재 저장:")
|
print(f"첫 번째 자재 저장:")
|
||||||
@@ -777,7 +801,8 @@ async def upload_file(
|
|||||||
print(f" category: {classification_result.get('category', 'UNCLASSIFIED')}")
|
print(f" category: {classification_result.get('category', 'UNCLASSIFIED')}")
|
||||||
print(f" drawing_name: {material_data.get('dwg_name')}")
|
print(f" drawing_name: {material_data.get('dwg_name')}")
|
||||||
print(f" line_no: {material_data.get('line_num')}")
|
print(f" line_no: {material_data.get('line_num')}")
|
||||||
|
print(f" purchase_confirmed: {is_purchase_confirmed}")
|
||||||
|
|
||||||
material_result = db.execute(material_insert_query, {
|
material_result = db.execute(material_insert_query, {
|
||||||
"file_id": file_id,
|
"file_id": file_id,
|
||||||
"original_description": material_data["original_description"],
|
"original_description": material_data["original_description"],
|
||||||
@@ -795,7 +820,10 @@ async def upload_file(
|
|||||||
"is_verified": False,
|
"is_verified": False,
|
||||||
"drawing_name": material_data.get("dwg_name"),
|
"drawing_name": material_data.get("dwg_name"),
|
||||||
"line_no": material_data.get("line_num"),
|
"line_no": material_data.get("line_num"),
|
||||||
"created_at": datetime.now()
|
"created_at": datetime.now(),
|
||||||
|
"purchase_confirmed": is_purchase_confirmed,
|
||||||
|
"purchase_confirmed_at": purchase_confirmed_at,
|
||||||
|
"purchase_confirmed_by": purchase_confirmed_by
|
||||||
})
|
})
|
||||||
|
|
||||||
material_id = material_result.fetchone()[0]
|
material_id = material_result.fetchone()[0]
|
||||||
@@ -4066,12 +4094,12 @@ def perform_simple_revision_comparison(db: Session, job_no: str, parent_file_id:
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 1. 이전 파일의 모든 자재 조회
|
# 1. 이전 파일의 모든 자재 조회 (구매확정 정보 포함)
|
||||||
previous_materials_query = text("""
|
previous_materials_query = text("""
|
||||||
SELECT original_description, classified_category, size_spec, material_grade,
|
SELECT original_description, classified_category, size_spec, material_grade,
|
||||||
main_nom, red_nom, drawing_name, line_no,
|
main_nom, red_nom, drawing_name, line_no,
|
||||||
COALESCE(total_quantity, quantity, 0) as quantity, unit,
|
COALESCE(total_quantity, quantity, 0) as quantity, unit,
|
||||||
purchase_confirmed
|
purchase_confirmed, purchase_confirmed_at, purchase_confirmed_by
|
||||||
FROM materials
|
FROM materials
|
||||||
WHERE file_id = :parent_file_id
|
WHERE file_id = :parent_file_id
|
||||||
ORDER BY id
|
ORDER BY id
|
||||||
@@ -4111,7 +4139,9 @@ def perform_simple_revision_comparison(db: Session, job_no: str, parent_file_id:
|
|||||||
"line_no": material.line_no,
|
"line_no": material.line_no,
|
||||||
"quantity": float(material.quantity or 0),
|
"quantity": float(material.quantity or 0),
|
||||||
"unit": material.unit,
|
"unit": material.unit,
|
||||||
"purchase_confirmed": material.purchase_confirmed
|
"purchase_confirmed": material.purchase_confirmed,
|
||||||
|
"purchase_confirmed_at": material.purchase_confirmed_at,
|
||||||
|
"purchase_confirmed_by": material.purchase_confirmed_by
|
||||||
}
|
}
|
||||||
|
|
||||||
if key in previous_dict:
|
if key in previous_dict:
|
||||||
@@ -4216,6 +4246,7 @@ def perform_simple_revision_comparison(db: Session, job_no: str, parent_file_id:
|
|||||||
"excluded_purchased_count": excluded_purchased_count,
|
"excluded_purchased_count": excluded_purchased_count,
|
||||||
"materials_to_classify": materials_to_classify, # 신규 자재만
|
"materials_to_classify": materials_to_classify, # 신규 자재만
|
||||||
"removed_materials": removed_materials, # 삭제된 자재
|
"removed_materials": removed_materials, # 삭제된 자재
|
||||||
|
"purchased_materials_map": purchased_dict, # 🔥 구매확정된 자재 매핑 정보
|
||||||
"total_previous": len(previous_dict),
|
"total_previous": len(previous_dict),
|
||||||
"total_new": len(new_dict)
|
"total_new": len(new_dict)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user