Files
factu/fac1.1.py
2025-05-19 17:11:33 +02:00

146 lines
4.4 KiB
Python

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()