diff --git a/fac1.1.py b/fac1.1.py new file mode 100644 index 0000000..7482284 --- /dev/null +++ b/fac1.1.py @@ -0,0 +1,145 @@ +from tkinter import * +from tkinter import filedialog, messagebox +from PIL import Image, ImageTk +import pytesseract +import re +import os +import json +import datetime +import hashlib +import qrcode +import sqlite3 + +# Configuración del path de Tesseract +pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' + +# Base de datos de solo lectura (una vez creada) +DB_PATH = "facturas.db" + +def init_db(): + conn = sqlite3.connect(DB_PATH) + c = conn.cursor() + c.execute('''CREATE TABLE IF NOT EXISTS facturas ( + hash TEXT PRIMARY KEY, + datos TEXT, + qr_path TEXT, + fecha TEXT)''') + conn.commit() + conn.close() + +def seleccionar_archivo(): + ruta = filedialog.askopenfilename(filetypes=[("Imágenes", "*.png;*.jpg;*.jpeg")]) + if ruta: + mostrar_factura(ruta) + texto = extraer_texto(ruta) + datos = extraer_datos(texto) + mostrar_datos(datos) + hash_val, qr_path = guardar_en_db(datos) + mostrar_hash_qr(hash_val, qr_path) + guardar_datos_json(datos) + +def mostrar_factura(ruta): + imagen = Image.open(ruta) + imagen = imagen.resize((500, 700)) + img_tk = ImageTk.PhotoImage(imagen) + + img_label.config(image=img_tk) + img_label.image = img_tk + +def extraer_texto(ruta): + imagen = Image.open(ruta) + return pytesseract.image_to_string(imagen, lang='spa') + +def extraer_datos(texto): + return { + "NIF Emisor": extraer_nif_emisor(texto), + "NIF Receptor": extraer_nif_receptor(texto), + "Fecha": extraer_fecha(texto), + "Total": extraer_total(texto), + "Texto Completo": texto + } + +def mostrar_datos(datos): + for widget in datos_frame.winfo_children(): + widget.destroy() + + for campo, valor in datos.items(): + Label(datos_frame, text=f"{campo}:", font=("Arial", 10, "bold")).pack(anchor="w") + Label(datos_frame, text=valor, font=("Arial", 10), wraplength=350, justify=LEFT).pack(anchor="w") + Label(datos_frame, text="").pack() + +def mostrar_hash_qr(hash_val, qr_path): + Label(datos_frame, text="Hash SHA-256:", font=("Arial", 10, "bold")).pack(anchor="w") + Label(datos_frame, text=hash_val, font=("Arial", 8), wraplength=350, justify=LEFT, fg="blue").pack(anchor="w") + + qr_img = Image.open(qr_path) + qr_img = qr_img.resize((150, 150)) + qr_tk = ImageTk.PhotoImage(qr_img) + + qr_label = Label(datos_frame, image=qr_tk) + qr_label.image = qr_tk + qr_label.pack(anchor="w", pady=10) + +def guardar_datos_json(datos): + fecha_actual = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + nombre_archivo = f"factura_{fecha_actual}.json" + with open(nombre_archivo, "w", encoding="utf-8") as f: + json.dump(datos, f, ensure_ascii=False, indent=4) + +def guardar_en_db(datos): + datos_str = json.dumps(datos, ensure_ascii=False) + hash_val = hashlib.sha256(datos_str.encode("utf-8")).hexdigest() + + qr = qrcode.make(hash_val) + qr_path = f"qr_{hash_val[:8]}.png" + qr.save(qr_path) + + conn = sqlite3.connect(DB_PATH) + c = conn.cursor() + try: + c.execute("INSERT INTO facturas (hash, datos, qr_path, fecha) VALUES (?, ?, ?, ?)", + (hash_val, datos_str, qr_path, datos.get("Fecha", ""))) + conn.commit() + except sqlite3.IntegrityError: + messagebox.showinfo("Info", "La factura ya ha sido registrada (hash duplicado).") + finally: + conn.close() + return hash_val, qr_path + +def extraer_nif_emisor(texto): + match = re.search(r'\b[A-Z0-9]{8,9}\b', texto) + return match.group() if match else "No encontrado" + +def extraer_nif_receptor(texto): + match = re.findall(r'\b[A-Z0-9]{8,9}\b', texto) + if len(match) > 1: + return match[1] + return "No encontrado" + +def extraer_fecha(texto): + match = re.search(r'\d{2}/\d{2}/\d{4}', texto) + return match.group() if match else "No encontrada" + +def extraer_total(texto): + match = re.search(r'(\d+[.,]\d{2})\s*[€€]', texto) + return match.group(1) + " €" if match else "No encontrado" + +# GUI principal +init_db() +root = Tk() +root.title("Visor de Factura + OCR") +root.geometry("900x720") + +main_frame = Frame(root) +main_frame.pack(fill=BOTH, expand=True) + +img_label = Label(main_frame) +img_label.pack(side=LEFT, padx=10, pady=10) + +datos_frame = Frame(main_frame) +datos_frame.pack(side=RIGHT, fill=Y, padx=10, pady=10) + +btn = Button(root, text="Seleccionar Factura", command=seleccionar_archivo) +btn.pack(pady=10) + +root.mainloop() diff --git a/factura_20250327_082633.json b/factura_20250327_082633.json new file mode 100644 index 0000000..4ba99b2 --- /dev/null +++ b/factura_20250327_082633.json @@ -0,0 +1,7 @@ +{ + "NIF Emisor": "No encontrado", + "NIF Receptor": "No encontrado", + "Fecha": "29/01/2019", + "Total": "199.65 €", + "Texto Completo": "Factura ES-001\n\nRojo Polo Paella Inc.\n\nCarretera Muelle 38\n37531 Ávila, Ávila\n\nFacturar a\n\nLeda Villareal\nVirgen Blanca 63\n08759 Burgos, Burgos\n\nEnviar a Fecha 29/01/2019\nLeda Villareal N* de pedido 1730/2019\nCercas Bajas 68\n\nFecha 29/01/2019\n\n47300 Cádiz, Cádiz\nvencimiento\n\nCant. Descripción Precio unitario Importe\n1 Talla pequeña traje de luces en rojo 100.00 100.00\n2 Mui grande churrolito 25.00 50.00\n3 Equipaje de Fútbol 5.00 15.00\nSubtotal 165.00\nIVA 21.0% 34.65\nTotal 199.65 €\n\n4\n\nCondiciones y forma de pago\n\nEl pago se realizará en un plazo de 15 días\n\nBanco Santander\nIBAN: ES12 3456 7891\n'SWIFT/BIC: ABCDESM1XXX\n" +} \ No newline at end of file diff --git a/factura_20250327_082838.json b/factura_20250327_082838.json new file mode 100644 index 0000000..4ba99b2 --- /dev/null +++ b/factura_20250327_082838.json @@ -0,0 +1,7 @@ +{ + "NIF Emisor": "No encontrado", + "NIF Receptor": "No encontrado", + "Fecha": "29/01/2019", + "Total": "199.65 €", + "Texto Completo": "Factura ES-001\n\nRojo Polo Paella Inc.\n\nCarretera Muelle 38\n37531 Ávila, Ávila\n\nFacturar a\n\nLeda Villareal\nVirgen Blanca 63\n08759 Burgos, Burgos\n\nEnviar a Fecha 29/01/2019\nLeda Villareal N* de pedido 1730/2019\nCercas Bajas 68\n\nFecha 29/01/2019\n\n47300 Cádiz, Cádiz\nvencimiento\n\nCant. Descripción Precio unitario Importe\n1 Talla pequeña traje de luces en rojo 100.00 100.00\n2 Mui grande churrolito 25.00 50.00\n3 Equipaje de Fútbol 5.00 15.00\nSubtotal 165.00\nIVA 21.0% 34.65\nTotal 199.65 €\n\n4\n\nCondiciones y forma de pago\n\nEl pago se realizará en un plazo de 15 días\n\nBanco Santander\nIBAN: ES12 3456 7891\n'SWIFT/BIC: ABCDESM1XXX\n" +} \ No newline at end of file diff --git a/factura_20250327_082904.json b/factura_20250327_082904.json new file mode 100644 index 0000000..4ba99b2 --- /dev/null +++ b/factura_20250327_082904.json @@ -0,0 +1,7 @@ +{ + "NIF Emisor": "No encontrado", + "NIF Receptor": "No encontrado", + "Fecha": "29/01/2019", + "Total": "199.65 €", + "Texto Completo": "Factura ES-001\n\nRojo Polo Paella Inc.\n\nCarretera Muelle 38\n37531 Ávila, Ávila\n\nFacturar a\n\nLeda Villareal\nVirgen Blanca 63\n08759 Burgos, Burgos\n\nEnviar a Fecha 29/01/2019\nLeda Villareal N* de pedido 1730/2019\nCercas Bajas 68\n\nFecha 29/01/2019\n\n47300 Cádiz, Cádiz\nvencimiento\n\nCant. Descripción Precio unitario Importe\n1 Talla pequeña traje de luces en rojo 100.00 100.00\n2 Mui grande churrolito 25.00 50.00\n3 Equipaje de Fútbol 5.00 15.00\nSubtotal 165.00\nIVA 21.0% 34.65\nTotal 199.65 €\n\n4\n\nCondiciones y forma de pago\n\nEl pago se realizará en un plazo de 15 días\n\nBanco Santander\nIBAN: ES12 3456 7891\n'SWIFT/BIC: ABCDESM1XXX\n" +} \ No newline at end of file diff --git a/factura_20250327_083023.json b/factura_20250327_083023.json new file mode 100644 index 0000000..4c0e257 --- /dev/null +++ b/factura_20250327_083023.json @@ -0,0 +1,7 @@ +{ + "NIF Emisor": "No encontrado", + "NIF Receptor": "No encontrado", + "Fecha": "No encontrada", + "Total": "199.65 €", + "Texto Completo": "Factura ES-001\n\nRojo Polo Paella Inc.\n\nCarretera Muelle 38\n37531 Ávila, Ávila\n\nLeda Villareal Leda Villareal N? de pedido 1730/2019\n1 Talla pequeña traje de luces en rojo 100.00 100.00\n2 Mui grande churrolito. 25.00 50.00\n3 Equipaje de Fútbol 5.00 15.00\n\nSubtotal 165.00\nIVA 21.0% 34.65\nTotal 199.65 €\n\nCondiciones y forma de pago\n\nEl pago se realizará en un plazo de 15 días\n\nBanco Santander\nIBAN: ES12 3456 7891\n'SWIFT/BIC: ABCDESM1XXX\n" +} \ No newline at end of file diff --git a/factura_20250329_091909.json b/factura_20250329_091909.json new file mode 100644 index 0000000..4ba99b2 --- /dev/null +++ b/factura_20250329_091909.json @@ -0,0 +1,7 @@ +{ + "NIF Emisor": "No encontrado", + "NIF Receptor": "No encontrado", + "Fecha": "29/01/2019", + "Total": "199.65 €", + "Texto Completo": "Factura ES-001\n\nRojo Polo Paella Inc.\n\nCarretera Muelle 38\n37531 Ávila, Ávila\n\nFacturar a\n\nLeda Villareal\nVirgen Blanca 63\n08759 Burgos, Burgos\n\nEnviar a Fecha 29/01/2019\nLeda Villareal N* de pedido 1730/2019\nCercas Bajas 68\n\nFecha 29/01/2019\n\n47300 Cádiz, Cádiz\nvencimiento\n\nCant. Descripción Precio unitario Importe\n1 Talla pequeña traje de luces en rojo 100.00 100.00\n2 Mui grande churrolito 25.00 50.00\n3 Equipaje de Fútbol 5.00 15.00\nSubtotal 165.00\nIVA 21.0% 34.65\nTotal 199.65 €\n\n4\n\nCondiciones y forma de pago\n\nEl pago se realizará en un plazo de 15 días\n\nBanco Santander\nIBAN: ES12 3456 7891\n'SWIFT/BIC: ABCDESM1XXX\n" +} \ No newline at end of file diff --git a/facturas.db b/facturas.db index 606f54f..63d71d3 100644 Binary files a/facturas.db and b/facturas.db differ diff --git a/modelo-factura-es-moderno-rojo-750px_facturae.xml b/modelo-factura-es-moderno-rojo-750px_facturae.xml new file mode 100644 index 0000000..f89e118 --- /dev/null +++ b/modelo-factura-es-moderno-rojo-750px_facturae.xml @@ -0,0 +1 @@ +29/01/2019165.0CSV-5ee435e194 \ No newline at end of file diff --git a/qr_1dbac13a.png b/qr_1dbac13a.png new file mode 100644 index 0000000..f1ead53 Binary files /dev/null and b/qr_1dbac13a.png differ diff --git a/qr_9e851b53.png b/qr_9e851b53.png new file mode 100644 index 0000000..3925f72 Binary files /dev/null and b/qr_9e851b53.png differ