File size: 6,572 Bytes
2129e5e
98c9fa6
fd99d5c
 
675f467
 
3f55dc7
675f467
fd99d5c
3f47d42
675f467
 
 
 
 
 
 
3f47d42
98c9fa6
675f467
3f47d42
 
 
 
 
 
fd99d5c
675f467
 
 
 
 
 
 
fd99d5c
675f467
 
 
 
 
 
 
 
 
fd99d5c
3f47d42
 
675f467
 
 
3f55dc7
675f467
 
d6463ae
3f55dc7
675f467
 
 
 
 
 
d6463ae
3f55dc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d6463ae
3f55dc7
 
 
 
 
 
 
 
d6463ae
 
 
675f467
 
fd99d5c
 
 
3f47d42
fd99d5c
 
98c9fa6
 
 
675f467
98c9fa6
3f47d42
 
98c9fa6
3f47d42
98c9fa6
 
3f47d42
 
 
 
 
fd99d5c
 
675f467
fd99d5c
3f55dc7
 
 
 
675f467
 
 
 
 
fd99d5c
98c9fa6
fd99d5c
98c9fa6
3f47d42
675f467
fd99d5c
 
 
3f47d42
fd99d5c
3f47d42
fd99d5c
 
675f467
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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()