Vladt-Tempest commited on
Commit
10fa36b
·
1 Parent(s): 388c630

Corrección de sonido de error en carga y avisos de proceso

Browse files
__pycache__/commercial_invoice.cpython-310.pyc CHANGED
Binary files a/__pycache__/commercial_invoice.cpython-310.pyc and b/__pycache__/commercial_invoice.cpython-310.pyc differ
 
app.py CHANGED
@@ -5,25 +5,42 @@ from pdf2image import convert_from_path
5
  import logging
6
  from commercial_invoice import process_invoice_batch, logger
7
 
8
- def play_error_sound():
9
- """Reproduce un sonido de error usando winsound"""
10
- import winsound
11
- winsound.MessageBeep(winsound.MB_ICONHAND)
 
 
 
 
 
12
 
13
- def procesar_pdf(pdf_path):
14
  """Procesa un archivo PDF y extrae información de las facturas"""
 
 
 
 
 
 
15
  try:
16
  # Validar que el nombre del archivo comience con "ci145"
17
  filename = os.path.basename(pdf_path).lower()
18
  if not filename.startswith("ci145"):
19
- error_msg = '<span style="color: red; font-weight: bold">⚠️ El tipo de archivo cargado no es compatible con el formato de extracción que maneja este programa, el cual está customizado para manejar únicamente los archivos que empiezan por "ci145".</span>'
20
- play_error_sound()
 
 
 
21
  logger.error("Archivo incompatible: " + filename)
22
- return error_msg, None
23
 
 
 
24
  # Crear directorio temporal para las imágenes
25
  with tempfile.TemporaryDirectory() as temp_dir:
26
  logger.info(f"Convirtiendo PDF a imágenes: {pdf_path}")
 
27
 
28
  # Convertir PDF a imágenes
29
  images = convert_from_path(pdf_path)
@@ -31,16 +48,19 @@ def procesar_pdf(pdf_path):
31
 
32
  # Guardar imágenes temporalmente
33
  for i, image in enumerate(images):
 
34
  image_path = os.path.join(temp_dir, f'pagina_{i+1}.jpg')
35
  image.save(image_path, 'JPEG')
36
  image_paths.append(image_path)
37
 
38
  logger.info(f"Se generaron {len(image_paths)} imágenes")
 
39
 
40
  # Procesar las imágenes
41
  coordinates_json = "./coordinates_CI.json"
42
  results_df = process_invoice_batch(image_paths, coordinates_json)
43
 
 
44
  # Guardar resultados
45
  output_dir = "./data"
46
  os.makedirs(output_dir, exist_ok=True)
@@ -49,28 +69,54 @@ def procesar_pdf(pdf_path):
49
  facturas_path = os.path.join(output_dir, 'facturas_procesadas.csv')
50
  results_df.to_csv(facturas_path, index=False)
51
 
52
- # Preparar mensaje de resultados
53
- mensaje = f"Procesamiento completado:\n"
54
- mensaje += f"- Páginas procesadas: {len(image_paths)}\n"
55
- mensaje += f"- Campos extraídos: {len(results_df.columns)-1}\n\n"
56
- mensaje += f"Archivos generados:\n"
57
- mensaje += f"1. Facturas procesadas: {facturas_path}\n"
 
 
 
 
 
 
 
58
 
59
  # Verificar archivo de productos
60
  productos_path = os.path.join(output_dir, 'productos_por_factura.csv')
61
  if os.path.exists(productos_path):
62
- mensaje += f"2. Productos por factura: {productos_path}"
 
 
63
 
64
- return mensaje, [facturas_path, productos_path]
 
65
 
66
  except Exception as e:
67
- error_msg = f'<span style="color: red; font-weight: bold">⚠️ Error durante el procesamiento: {str(e)}</span>'
68
- play_error_sound()
 
 
 
69
  logger.error(error_msg)
70
- return error_msg, None
 
 
71
 
72
  def crear_interfaz():
73
- with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
74
  gr.Markdown("# Extractor de Información de Facturas")
75
 
76
  with gr.Row():
@@ -80,12 +126,24 @@ def crear_interfaz():
80
  )
81
 
82
  with gr.Row():
83
- procesar_btn = gr.Button("Procesar PDF")
 
 
 
 
84
 
85
  with gr.Row():
86
  output_text = gr.HTML(
87
- label="Resultados",
88
- value="Los resultados del procesamiento aparecerán aquí..."
 
 
 
 
 
 
 
 
89
  )
90
 
91
  with gr.Row():
@@ -97,13 +155,13 @@ def crear_interfaz():
97
  )
98
 
99
  def process_and_return(pdf_path):
100
- message, csv_files = procesar_pdf(pdf_path)
101
- return message, csv_files if csv_files else None
102
 
103
  procesar_btn.click(
104
  fn=process_and_return,
105
  inputs=[pdf_input],
106
- outputs=[output_text, files_output],
107
  show_progress=True
108
  ).then(
109
  lambda: gr.update(visible=True),
@@ -115,4 +173,4 @@ def crear_interfaz():
115
 
116
  if __name__ == "__main__":
117
  demo = crear_interfaz()
118
- demo.launch(share=True)
 
5
  import logging
6
  from commercial_invoice import process_invoice_batch, logger
7
 
8
+ # Configurar handler para capturar logs
9
+ class GradioHandler(logging.Handler):
10
+ def __init__(self, log_history):
11
+ super().__init__()
12
+ self.log_history = log_history
13
+
14
+ def emit(self, record):
15
+ log_entry = self.format(record)
16
+ self.log_history.append(log_entry)
17
 
18
+ def procesar_pdf(pdf_path, progress=gr.Progress()):
19
  """Procesa un archivo PDF y extrae información de las facturas"""
20
+ log_history = []
21
+ handler = GradioHandler(log_history)
22
+ formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
23
+ handler.setFormatter(formatter)
24
+ logger.addHandler(handler)
25
+
26
  try:
27
  # Validar que el nombre del archivo comience con "ci145"
28
  filename = os.path.basename(pdf_path).lower()
29
  if not filename.startswith("ci145"):
30
+ error_msg = """
31
+ <div style='color: red; font-weight: bold; padding: 10px; border: 1px solid red; border-radius: 5px; background-color: #ffe6e6;'>
32
+ ⚠️ El tipo de archivo cargado no es compatible con el formato de extracción que maneja este programa, el cual está customizado para manejar únicamente los archivos que empiezan por "ci145".
33
+ </div>
34
+ """
35
  logger.error("Archivo incompatible: " + filename)
36
+ return error_msg, None, "\n".join(log_history)
37
 
38
+ progress(0.1, desc="Iniciando procesamiento...")
39
+
40
  # Crear directorio temporal para las imágenes
41
  with tempfile.TemporaryDirectory() as temp_dir:
42
  logger.info(f"Convirtiendo PDF a imágenes: {pdf_path}")
43
+ progress(0.2, desc="Convirtiendo PDF a imágenes...")
44
 
45
  # Convertir PDF a imágenes
46
  images = convert_from_path(pdf_path)
 
48
 
49
  # Guardar imágenes temporalmente
50
  for i, image in enumerate(images):
51
+ progress((0.3 + (i/len(images) * 0.2)), desc=f"Procesando página {i+1} de {len(images)}...")
52
  image_path = os.path.join(temp_dir, f'pagina_{i+1}.jpg')
53
  image.save(image_path, 'JPEG')
54
  image_paths.append(image_path)
55
 
56
  logger.info(f"Se generaron {len(image_paths)} imágenes")
57
+ progress(0.5, desc="Procesando imágenes...")
58
 
59
  # Procesar las imágenes
60
  coordinates_json = "./coordinates_CI.json"
61
  results_df = process_invoice_batch(image_paths, coordinates_json)
62
 
63
+ progress(0.8, desc="Guardando resultados...")
64
  # Guardar resultados
65
  output_dir = "./data"
66
  os.makedirs(output_dir, exist_ok=True)
 
69
  facturas_path = os.path.join(output_dir, 'facturas_procesadas.csv')
70
  results_df.to_csv(facturas_path, index=False)
71
 
72
+ progress(0.9, desc="Finalizando...")
73
+ # Preparar mensaje de resultados con estilo
74
+ mensaje = """
75
+ <div style='padding: 10px; border: 1px solid #4CAF50; border-radius: 5px; background-color: #f1f8e9;'>
76
+ <h3 style='color: #2E7D32; margin-top: 0;'>✅ Procesamiento completado</h3>
77
+ <ul style='list-style-type: none; padding-left: 0;'>
78
+ <li>📄 Páginas procesadas: {}</li>
79
+ <li>📊 Campos extraídos: {}</li>
80
+ </ul>
81
+ <h4 style='color: #2E7D32;'>Archivos generados:</h4>
82
+ <ol>
83
+ <li>facturas_procesadas.csv</li>
84
+ """.format(len(image_paths), len(results_df.columns)-1)
85
 
86
  # Verificar archivo de productos
87
  productos_path = os.path.join(output_dir, 'productos_por_factura.csv')
88
  if os.path.exists(productos_path):
89
+ mensaje += "<li>productos_por_factura.csv</li>"
90
+
91
+ mensaje += "</ol></div>"
92
 
93
+ progress(1.0, desc="¡Proceso completado!")
94
+ return mensaje, [facturas_path, productos_path], "\n".join(log_history)
95
 
96
  except Exception as e:
97
+ error_msg = f"""
98
+ <div style='color: red; font-weight: bold; padding: 10px; border: 1px solid red; border-radius: 5px; background-color: #ffe6e6;'>
99
+ ⚠️ Error durante el procesamiento: {str(e)}
100
+ </div>
101
+ """
102
  logger.error(error_msg)
103
+ return error_msg, None, "\n".join(log_history)
104
+ finally:
105
+ logger.removeHandler(handler)
106
 
107
  def crear_interfaz():
108
+ with gr.Blocks(css="""
109
+ .message { margin-bottom: 20px; }
110
+ .error { color: red; font-weight: bold; }
111
+ .logs {
112
+ font-family: monospace;
113
+ background-color: #f5f5f5;
114
+ padding: 10px;
115
+ border-radius: 5px;
116
+ max-height: 200px;
117
+ overflow-y: auto;
118
+ }
119
+ """) as demo:
120
  gr.Markdown("# Extractor de Información de Facturas")
121
 
122
  with gr.Row():
 
126
  )
127
 
128
  with gr.Row():
129
+ procesar_btn = gr.Button(
130
+ "Procesar PDF",
131
+ variant="primary",
132
+ elem_classes=["custom-button"]
133
+ )
134
 
135
  with gr.Row():
136
  output_text = gr.HTML(
137
+ label="Resultados"
138
+ )
139
+
140
+ with gr.Row():
141
+ log_output = gr.Textbox(
142
+ label="Logs del proceso",
143
+ elem_classes=["logs"],
144
+ lines=10,
145
+ max_lines=10,
146
+ show_label=True
147
  )
148
 
149
  with gr.Row():
 
155
  )
156
 
157
  def process_and_return(pdf_path):
158
+ message, csv_files, logs = procesar_pdf(pdf_path)
159
+ return message, csv_files if csv_files else None, logs
160
 
161
  procesar_btn.click(
162
  fn=process_and_return,
163
  inputs=[pdf_input],
164
+ outputs=[output_text, files_output, log_output],
165
  show_progress=True
166
  ).then(
167
  lambda: gr.update(visible=True),
 
173
 
174
  if __name__ == "__main__":
175
  demo = crear_interfaz()
176
+ demo.launch(share=False)