diff --git a/backend/app/routers/files.py b/backend/app/routers/files.py index 85dd770..1f04a55 100644 --- a/backend/app/routers/files.py +++ b/backend/app/routers/files.py @@ -514,7 +514,8 @@ async def upload_file( # ๐Ÿ”„ ๋ฆฌ๋น„์ „ ๋น„๊ต ์ˆ˜ํ–‰ (RULES.md ์ฝ”๋”ฉ ์ปจ๋ฒค์…˜ ์ค€์ˆ˜) revision_comparison = None materials_to_classify = materials_data - + purchased_materials_map = {} # ๊ตฌ๋งคํ™•์ •๋œ ์ž์žฌ ๋งคํ•‘ (ํ‚ค -> ๊ตฌ๋งคํ™•์ • ์ •๋ณด) + if revision != "Rev.0": # ๋ฆฌ๋น„์ „ ์—…๋กœ๋“œ์ธ ๊ฒฝ์šฐ๋งŒ ๋น„๊ต print(f"๐Ÿ” [DEBUG] ๋ฆฌ๋น„์ „ ๋น„๊ต ์‹œ์ž‘ - revision: {revision}, parent_file_id: {parent_file_id}") try: @@ -522,20 +523,24 @@ async def upload_file( print(f"๐Ÿ” [DEBUG] perform_simple_revision_comparison ํ˜ธ์ถœ ์ค‘...") 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'}") - + if revision_comparison.get("has_purchased_materials", False): print(f"๐Ÿ“Š ๊ฐ„๋‹จํ•œ ๋ฆฌ๋น„์ „ ๋น„๊ต ๊ฒฐ๊ณผ:") print(f" - ๊ตฌ๋งคํ™•์ •๋œ ์ž์žฌ: {revision_comparison.get('purchased_count', 0)}๊ฐœ") print(f" - ๋ฏธ๊ตฌ๋งค ์ž์žฌ: {revision_comparison.get('unpurchased_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", []) print(f" - ๋ถ„๋ฅ˜ ํ•„์š”: {len(materials_to_classify)}๊ฐœ") + + # ๐Ÿ”ฅ ๊ตฌ๋งคํ™•์ •๋œ ์ž์žฌ ๋งคํ•‘ ์ •๋ณด ์ €์žฅ + purchased_materials_map = revision_comparison.get("purchased_materials_map", {}) + print(f" - ๊ตฌ๋งคํ™•์ • ์ž์žฌ ๋งคํ•‘: {len(purchased_materials_map)}๊ฐœ") else: print("๐Ÿ“ ์ด์ „ ๊ตฌ๋งคํ™•์ • ์ž๋ฃŒ ์—†์Œ - ์ „์ฒด ์ž์žฌ ๋ถ„๋ฅ˜") - + except Exception as e: print(f"โš ๏ธ ๋ฆฌ๋น„์ „ ๋น„๊ต ์‹คํŒจ, ์ „์ฒด ์ž์žฌ ๋ถ„๋ฅ˜๋กœ ์ง„ํ–‰: {str(e)}") import traceback @@ -752,23 +757,42 @@ async def upload_file( if not full_material_grade and material_data.get("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(""" 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 + 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 ) VALUES ( :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 + :drawing_name, :line_no, :created_at, + :purchase_confirmed, :purchase_confirmed_at, :purchase_confirmed_by ) RETURNING id """) - + # ์ฒซ ๋ฒˆ์งธ ์ž์žฌ์— ๋Œ€ํ•ด์„œ๋งŒ ๋””๋ฒ„๊ทธ ์ถœ๋ ฅ if materials_inserted == 0: print(f"์ฒซ ๋ฒˆ์งธ ์ž์žฌ ์ €์žฅ:") @@ -777,7 +801,8 @@ async def upload_file( print(f" category: {classification_result.get('category', 'UNCLASSIFIED')}") print(f" drawing_name: {material_data.get('dwg_name')}") print(f" line_no: {material_data.get('line_num')}") - + print(f" purchase_confirmed: {is_purchase_confirmed}") + material_result = db.execute(material_insert_query, { "file_id": file_id, "original_description": material_data["original_description"], @@ -795,7 +820,10 @@ async def upload_file( "is_verified": False, "drawing_name": material_data.get("dwg_name"), "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] @@ -4066,12 +4094,12 @@ def perform_simple_revision_comparison(db: Session, job_no: str, parent_file_id: } """ try: - # 1. ์ด์ „ ํŒŒ์ผ์˜ ๋ชจ๋“  ์ž์žฌ ์กฐํšŒ + # 1. ์ด์ „ ํŒŒ์ผ์˜ ๋ชจ๋“  ์ž์žฌ ์กฐํšŒ (๊ตฌ๋งคํ™•์ • ์ •๋ณด ํฌํ•จ) previous_materials_query = text(""" SELECT original_description, classified_category, size_spec, material_grade, main_nom, red_nom, drawing_name, line_no, COALESCE(total_quantity, quantity, 0) as quantity, unit, - purchase_confirmed + purchase_confirmed, purchase_confirmed_at, purchase_confirmed_by FROM materials WHERE file_id = :parent_file_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, "quantity": float(material.quantity or 0), "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: @@ -4216,6 +4246,7 @@ def perform_simple_revision_comparison(db: Session, job_no: str, parent_file_id: "excluded_purchased_count": excluded_purchased_count, "materials_to_classify": materials_to_classify, # ์‹ ๊ทœ ์ž์žฌ๋งŒ "removed_materials": removed_materials, # ์‚ญ์ œ๋œ ์ž์žฌ + "purchased_materials_map": purchased_dict, # ๐Ÿ”ฅ ๊ตฌ๋งคํ™•์ •๋œ ์ž์žฌ ๋งคํ•‘ ์ •๋ณด "total_previous": len(previous_dict), "total_new": len(new_dict) }