hariqueen's picture
Update app.py
3f47d42 verified
import gradio as gr
import main # main.py에 μž‘μ„±λœ μ „μ²˜λ¦¬ 둜직 호좜
import os
import pandas as pd
import traceback
import sys
import re
from io import StringIO
def process_file(file_path, voucher_number, employee_number):
# μƒνƒœ λ©”μ‹œμ§€μ™€ κ²°κ³Όλ₯Ό ν•¨κ»˜ λ°˜ν™˜ν•˜κΈ° μœ„ν•œ λ³€μˆ˜ μ΄ˆκΈ°ν™”
status_message = ""
output_file_path = None
# 둜그λ₯Ό μΊ‘μ²˜ν•˜κΈ° μœ„ν•œ StringIO 객체
log_capture = StringIO()
# μž…λ ₯κ°’ 검증
if file_path is None:
return None, "νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
if not voucher_number or not voucher_number.strip():
return None, "μ „ν‘œλ²ˆν˜Έλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”."
if not employee_number or not employee_number.strip():
return None, "μ‚¬μ›λ²ˆν˜Έλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”. μ‚¬μ›λ²ˆν˜ΈλŠ” ν•„μˆ˜ μž…λ ₯κ°’μž…λ‹ˆλ‹€."
try:
# ν‘œμ€€ 좜λ ₯을 캑처
original_stdout = sys.stdout
sys.stdout = log_capture
# 파일 ν™•μž₯자 확인
ext = os.path.splitext(file_path)[1].lower()
if ext == ".xlsx":
# μ—‘μ…€ νŒŒμΌμ„ CSV둜 λ³€ν™˜
df = pd.read_excel(file_path)
csv_path = file_path.replace(".xlsx", ".csv")
df.to_csv(csv_path, index=False)
input_path = csv_path
else:
# 이미 CSV 파일이면 κ·ΈλŒ€λ‘œ μ‚¬μš©
input_path = file_path
# 메인 μ „μ²˜λ¦¬ ν•¨μˆ˜ 호좜 (μ „ν‘œλ²ˆν˜Έμ™€ μ‚¬μ›λ²ˆν˜Έ λ„˜κ²¨μ£ΌκΈ°)
output_path = main.process_rental_company_with_voucher(input_path, voucher_number, employee_number)
output_file_path = output_path
# 성곡 λ©”μ‹œμ§€ μž‘μ„±
status_message = "βœ… 파일 λ³€ν™˜ 성곡! μœ„ λ²„νŠΌμ„ ν΄λ¦­ν•˜μ—¬ λ‹€μš΄λ‘œλ“œν•˜μ„Έμš”."
except Exception as e:
# 였λ₯˜ λ°œμƒ μ‹œ κ°„λ‹¨ν•œ 였λ₯˜ λ©”μ‹œμ§€
status_message = f"❌ 였λ₯˜ λ°œμƒ: {str(e)}"
finally:
# 캑처된 둜그 κ°€μ Έμ˜€κΈ°
log_output = log_capture.getvalue()
sys.stdout = original_stdout # μ›λž˜ ν‘œμ€€ 좜λ ₯으둜 볡ꡬ
# μ£Όμš” 정보 μΆ”μΆœ (였λ₯˜ λ°œμƒ 여뢀와 상관없이)
important_info = []
# κΈˆμ•‘ ν•„λ“œ 정보 μΆ”μΆœ
amount_field_match = re.search(r"μ‚¬μš©ν•  κΈˆμ•‘ ν•„λ“œ: '([^']*)'", log_output)
if amount_field_match:
important_info.append(f"μ‚¬μš©ν•  κΈˆμ•‘ ν•„λ“œ: '{amount_field_match.group(1)}'")
# νŒ€ ν•„λ“œ 정보 μΆ”μΆœ
team_field_match = re.search(r"νŒ€ ν•„λ“œλ‘œ '([^']*)'λ₯Ό μžλ™ μΈμ‹ν–ˆμŠ΅λ‹ˆλ‹€", log_output)
if team_field_match:
important_info.append(f"νŒ€ ν•„λ“œλ‘œ '{team_field_match.group(1)}'λ₯Ό μžλ™ μΈμ‹ν–ˆμŠ΅λ‹ˆλ‹€.")
# μ œμ™Έλœ ν•­λͺ© 정보 μΆ”μΆœ
excluded_rows_match = re.search(r"κΈˆμ•‘μ΄ μ—†λŠ” ν–‰\(λ°˜λ‚© ν•­λͺ©\) (\d+)개λ₯Ό μ œμ™Έν•©λ‹ˆλ‹€", log_output)
if excluded_rows_match:
important_info.append(f"κΈˆμ•‘μ΄ μ—†λŠ” ν–‰(λ°˜λ‚© ν•­λͺ©) {excluded_rows_match.group(1)}개λ₯Ό μ œμ™Έν•©λ‹ˆλ‹€.")
# κΈˆμ•‘ 정보 μΆ”μΆœ
amt_info = []
debit_sum_match = re.search(r"μ°¨λ³€ κΈˆμ•‘ 합계: (\d+)", log_output)
credit_sum_match = re.search(r"λŒ€λ³€ κΈˆμ•‘: (\d+)", log_output)
debit_count_match = re.search(r"μ°¨λ³€ 건수: (\d+)", log_output)
credit_count_match = re.search(r"λŒ€λ³€ 건수: (\d+)", log_output)
if debit_sum_match:
amt_info.append(f"μ°¨λ³€ κΈˆμ•‘ 합계: {int(debit_sum_match.group(1)):,}")
if credit_sum_match:
amt_info.append(f"λŒ€λ³€ κΈˆμ•‘: {int(credit_sum_match.group(1)):,}")
if debit_count_match:
amt_info.append(f"μ°¨λ³€ 건수: {debit_count_match.group(1)}")
if credit_count_match:
amt_info.append(f"λŒ€λ³€ 건수: {credit_count_match.group(1)}")
if amt_info:
important_info.append("AMT ν•„λ“œ 확인:")
important_info.extend(amt_info)
# λ§€ν•‘ 였λ₯˜ 정보 μΆ”μΆœ (였λ₯˜κ°€ μžˆμ„ κ²½μš°μ—λ§Œ)
if not output_file_path and "λ§€ν•‘λ˜μ§€ μ•Šμ€ νŒ€λͺ…" in log_output: # 였λ₯˜ λ°œμƒ μ‹œμ—λ§Œ λ§€ν•‘ 정보 ν‘œμ‹œ
unmapped_section = re.search(r"λ§€ν•‘λ˜μ§€ μ•Šμ€ νŒ€λͺ… (\d+)개:(.*?)(?=\n\n|\Z)", log_output, re.DOTALL)
if unmapped_section:
unmapped_count = unmapped_section.group(1)
unmapped_teams = re.findall(r"- '([^']*)'", unmapped_section.group(2))
important_info.append(f"λ§€ν•‘λ˜μ§€ μ•Šμ€ νŒ€λͺ… {unmapped_count}개:")
for team in unmapped_teams:
important_info.append(f"- '{team}'")
# μ£Όμš” 정보λ₯Ό μƒνƒœ λ©”μ‹œμ§€μ— μΆ”κ°€ (항상)
if important_info:
status_message += "\n\n" + "\n".join(important_info)
return output_file_path, status_message
# Gradio μΈν„°νŽ˜μ΄μŠ€ ꡬ성
with gr.Blocks() as demo:
gr.Markdown("# ERP μžλ™ μ „ν‘œ λ³€ν™˜κΈ°\n\nμ—…λ‘œλ“œν•  파일과 μ „ν‘œλ²ˆν˜Έ, μ‚¬μ›λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜μ„Έμš”.")
with gr.Row():
file_input = gr.File(
label="λ Œνƒˆλ£Œ 파일 μ—…λ‘œλ“œ (CSV λ˜λŠ” Excel)",
file_types=[".csv", ".xlsx"],
type="filepath"
)
with gr.Row():
voucher_input = gr.Textbox(
label="μ „ν‘œλ²ˆν˜Έ μž…λ ₯ (ν•„μˆ˜)",
placeholder="예: 20250427001"
)
employee_input = gr.Textbox(
label="μ‚¬μ›λ²ˆν˜Έ μž…λ ₯ (ν•„μˆ˜)",
placeholder="예: 00616"
)
with gr.Row():
submit_btn = gr.Button("제좜", variant="primary")
clear_btn = gr.Button("μ§€μš°κΈ°")
output_file = gr.File(label="μ „μ²˜λ¦¬ μ™„λ£Œ 파일 λ‹€μš΄λ‘œλ“œ")
# μƒνƒœ λ©”μ‹œμ§€λ₯Ό 파일 λ‹€μš΄λ‘œλ“œ μ˜μ—­ μ•„λž˜λ‘œ 이동
status_output = gr.Textbox(
label="처리 μƒνƒœ",
placeholder="νŒŒμΌμ„ μ œμΆœν•˜λ©΄ 처리 μƒνƒœκ°€ 여기에 ν‘œμ‹œλ©λ‹ˆλ‹€.",
lines=10
)
# λ²„νŠΌ 클릭 이벀트 μ—°κ²°
submit_btn.click(
fn=process_file,
inputs=[file_input, voucher_input, employee_input],
outputs=[output_file, status_output]
)
clear_btn.click(
fn=lambda: (None, "", "", ""),
inputs=[],
outputs=[file_input, voucher_input, employee_input, status_output]
)
# μ‹œμž‘ λ©”μ‹œμ§€ ν‘œμ‹œ
print("ERP μžλ™ μ „ν‘œ λ³€ν™˜κΈ°κ°€ μ‹œμž‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
demo.launch()