import tkinter as tk from tkinter import filedialog, messagebox from PIL import Image import pytesseract import hashlib import sqlite3 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives.serialization import load_pem_private_key import os import re import base64 import datetime import xml.etree.ElementTree as ET # Configuracion de OCR pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' # Cambia si es necesario # Crear clave RSA para firmar clave_privada = rsa.generate_private_key(public_exponent=65537, key_size=2048) clave_publica = clave_privada.public_key() # Crear base de datos conn = sqlite3.connect("facturas.db") c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS facturas ( id INTEGER PRIMARY KEY AUTOINCREMENT, nombre_archivo TEXT, datos_extraidos TEXT, hash TEXT, firma BLOB, csv TEXT, fecha TEXT, nif_emisor TEXT, nif_receptor TEXT, total REAL )''') conn.commit() # Funciones del programa def seleccionar_archivo(): ruta = filedialog.askopenfilename(filetypes=[("PDF o Imagen", "*.png;*.jpg;*.jpeg;*.tiff;*.bmp")]) if ruta: texto = extraer_texto(ruta) nif_emisor = extraer_nif(texto, emisor=True) nif_receptor = extraer_nif(texto, emisor=False) total = extraer_total(texto) fecha = extraer_fecha(texto) hash_valor = generar_hash(texto) firma = firmar_texto(texto) csv = generar_csv(hash_valor) guardar_en_db(ruta, texto, hash_valor, firma, csv, fecha, nif_emisor, nif_receptor, total) generar_facturae(ruta, nif_emisor, nif_receptor, fecha, total, csv) messagebox.showinfo("Éxito", "Factura procesada y guardada.") mostrar_resultado(texto, hash_valor, csv, fecha, nif_emisor, nif_receptor, total) def extraer_texto(ruta): imagen = Image.open(ruta) texto = pytesseract.image_to_string(imagen, lang='spa') return texto def extraer_nif(texto, emisor=True): nif_pattern = r'\b[A-Z]?[0-9]{7,8}[A-Z]?\b' nifs = re.findall(nif_pattern, texto) return nifs[0] if emisor and nifs else (nifs[1] if len(nifs) > 1 else "") def extraer_total(texto): total_pattern = r'Total[:\s]*([0-9]+[.,][0-9]{2})' match = re.search(total_pattern, texto, re.IGNORECASE) return float(match.group(1).replace(',', '.')) if match else 0.0 def extraer_fecha(texto): fecha_pattern = r'(\d{2}[\/\-]\d{2}[\/\-]\d{4})' match = re.search(fecha_pattern, texto) return match.group(1) if match else datetime.date.today().strftime("%d/%m/%Y") def generar_hash(texto): return hashlib.sha256(texto.encode('utf-8')).hexdigest() def firmar_texto(texto): firma = clave_privada.sign( texto.encode('utf-8'), padding.PKCS1v15(), hashes.SHA256() ) return firma def generar_csv(hash_valor): return "CSV-" + hash_valor[:10] def guardar_en_db(nombre_archivo, texto, hash_valor, firma, csv, fecha, nif_emisor, nif_receptor, total): c.execute("""INSERT INTO facturas (nombre_archivo, datos_extraidos, hash, firma, csv, fecha, nif_emisor, nif_receptor, total) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", (nombre_archivo, texto, hash_valor, firma, csv, fecha, nif_emisor, nif_receptor, total)) conn.commit() def generar_facturae(nombre_archivo, emisor, receptor, fecha, total, csv): root = ET.Element("Facturae") ET.SubElement(root, "Emisor").text = emisor ET.SubElement(root, "Receptor").text = receptor ET.SubElement(root, "Fecha").text = fecha ET.SubElement(root, "Total").text = str(total) ET.SubElement(root, "CSV").text = csv tree = ET.ElementTree(root) nombre_xml = os.path.splitext(os.path.basename(nombre_archivo))[0] + "_facturae.xml" tree.write(nombre_xml) def mostrar_resultado(texto, hash_valor, csv, fecha, nif_emisor, nif_receptor, total): resultado.delete("1.0", tk.END) resultado.insert(tk.END, f"📄 Texto extraído:\n{texto}\n") resultado.insert(tk.END, f"\n🔐 Hash: {hash_valor}\n") resultado.insert(tk.END, f"🧾 CSV generado: {csv}\n") resultado.insert(tk.END, f"📅 Fecha: {fecha}\n") resultado.insert(tk.END, f"🏢 NIF Emisor: {nif_emisor}\n") resultado.insert(tk.END, f"👤 NIF Receptor: {nif_receptor}\n") resultado.insert(tk.END, f"💰 Total: {total} €\n") # GUI ventana = tk.Tk() ventana.title("Digitalizador de Facturas AEAT - v2.0") ventana.geometry("800x600") titulo = tk.Label(ventana, text="Digitalizador de Facturas (Cumplimiento AEAT)", font=("Arial", 16)) titulo.pack(pady=10) boton = tk.Button(ventana, text="📤 Seleccionar factura", command=seleccionar_archivo, bg="#4CAF50", fg="white", font=("Arial", 12)) boton.pack(pady=20) resultado = tk.Text(ventana, wrap="word", height=20) resultado.pack(padx=10, pady=10, fill="both", expand=True) ventana.mainloop()