vsersion 2
This commit is contained in:
145
fac1.1.py
Normal file
145
fac1.1.py
Normal file
@@ -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()
|
||||
7
factura_20250327_082633.json
Normal file
7
factura_20250327_082633.json
Normal file
@@ -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"
|
||||
}
|
||||
7
factura_20250327_082838.json
Normal file
7
factura_20250327_082838.json
Normal file
@@ -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"
|
||||
}
|
||||
7
factura_20250327_082904.json
Normal file
7
factura_20250327_082904.json
Normal file
@@ -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"
|
||||
}
|
||||
7
factura_20250327_083023.json
Normal file
7
factura_20250327_083023.json
Normal file
@@ -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"
|
||||
}
|
||||
7
factura_20250329_091909.json
Normal file
7
factura_20250329_091909.json
Normal file
@@ -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"
|
||||
}
|
||||
BIN
facturas.db
BIN
facturas.db
Binary file not shown.
1
modelo-factura-es-moderno-rojo-750px_facturae.xml
Normal file
1
modelo-factura-es-moderno-rojo-750px_facturae.xml
Normal file
@@ -0,0 +1 @@
|
||||
<Facturae><Emisor /><Receptor /><Fecha>29/01/2019</Fecha><Total>165.0</Total><CSV>CSV-5ee435e194</CSV></Facturae>
|
||||
BIN
qr_1dbac13a.png
Normal file
BIN
qr_1dbac13a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
qr_9e851b53.png
Normal file
BIN
qr_9e851b53.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Reference in New Issue
Block a user