From 47c37018abaf7d94bc3deec083b0adf03cfbffee Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 19 May 2025 17:11:33 +0200 Subject: [PATCH] vsersion 2 --- fac1.1.py | 145 ++++++++++++++++++ factura_20250327_082633.json | 7 + factura_20250327_082838.json | 7 + factura_20250327_082904.json | 7 + factura_20250327_083023.json | 7 + factura_20250329_091909.json | 7 + facturas.db | Bin 12288 -> 12288 bytes ...factura-es-moderno-rojo-750px_facturae.xml | 1 + qr_1dbac13a.png | Bin 0 -> 1094 bytes qr_9e851b53.png | Bin 0 -> 1064 bytes 10 files changed, 181 insertions(+) create mode 100644 fac1.1.py create mode 100644 factura_20250327_082633.json create mode 100644 factura_20250327_082838.json create mode 100644 factura_20250327_082904.json create mode 100644 factura_20250327_083023.json create mode 100644 factura_20250329_091909.json create mode 100644 modelo-factura-es-moderno-rojo-750px_facturae.xml create mode 100644 qr_1dbac13a.png create mode 100644 qr_9e851b53.png 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 606f54fa642fdec63e1f91417557c596ad24a36d..63d71d37c605f7dd3cf8f0eb0429a9931091f31c 100644 GIT binary patch literal 12288 zcmeI1(Qo549LLk%iE$^U@^(*?eoR6K-01A4X_HClXuC|R*s8HsV<#d_ZtQfKGCOmU z>KNi-Cn1F3pSX8;K=1^Qec=D#uiz0oYc<#notP%H2V08meKI*YkykRTFt7}YQMj(fw3C` zhJYbp2p9r}fFWQA7y^cXAz%m?0{;VnbEmTOXl14H;-j356Bdy$FC@tpWwp2GcSb&p zI^As_7Ej^5hj29=k?aUY{=o=#_xd}Xy=U-=|7`75KT2|um5$dKPvv1s@{4}1F-I&s zB4yk6*Q;+l>aA3)m{ayVJ5AJ?{*V;8DDMv!13koxnm*gVsd+A|tNP#<>#eEEOfm!v z0YktLFa!(%L%o;*ki7P$BvDfV@8o}Q{sA|-9mO0MQDs$W6y2s zs}&N@4Q+?Z<>#WB;qNfEM4@d2rahY_kHG%o_)P$P4~ucG(E)Bb?U9g)9WWYg1`U#$vc>iNr-LIh{h3eyp~N}?Bb@| zuqkRQjkXb{&NyVmrA>^R?a*~8bCh-|MiF)!x2WKTw~lbBf;%DKd00pwdOiNB-hl7N za-x>6o2Ydn(6R%L+_vLEw~!N&tG?D!suw6j6)tCawNn^;aD7Phm<&kDDg?mcwP#zrxaC(O_qf+PQ!TiGlyNtlyH?2 z7S%R=IpjZ@xMmm&El}B>GbYmFfJlZ2jis(9;#osYOSzpzp2b5L%RWA<~r}~?|Kl=+N)ODQz delta 1223 zcmZ8geM}o=7;lSg@h#Ay+1TvBmu%Cqe%)Pr{n-3S+a0c~FrXb7I)svVC;?x5ggS>w{PoA&e zllS*LPghe{(~D-kp>J)l(4e!Y59aH1Izz#Lu3)BMV7QGa*j;T{R%Eg0>s8b&V5Lpq zRotlHwiFiGrDjgBmhnd!81)Cj3|x}CQA7!B)hf$+jQZt8#l`w(`2IB}D#LRyR25|& zV`^b_ZK%>;TMxH0_0YdFx+7GjAyzU~Q7eGj6QxA6j2n^6#`&}aqs*>sfJ3UJG~#wu zMm#4eiz0EP#21+{UQQqw2=53iAhJrjVR0Cq^|aa?B{A8xy7%p8Dvlde1Gx!msj-n_EX{Cq=jvty@%WyKM8Y{kkRRZ2P% z5{CuJ7DKF>l93H7wmFY1N;X+)m24iGNVeOPVoUi#0%RgKf*=8?)uOOk5;TFZARrhL zSvvqhB+FREGJ=(vl;+3K=><*??Ihu7cbXTFHLC&0BFYc}5XKyWb-acnVN4^BS=({s7(We0{*Ja8uuinA=7T?@%l*6|LEGH44^S~IcZG# zTok5AlB6)}@p+Lq=A*fomu4x#hh5Dy74x{gUPK|HnU1l@=_Q;V97AsMY5)BdSHFMR z|BvBNQRbH)-aB_HnK+pj?2X*CpwqVwulUe-{z&fN+4!#=dpEql?BLD36RoSF*LN-N zWZ&$0<*kgVW2Elv>n>B_cZQKazdU|{SO*6#Imci9yuRYfw_~@rP7go+#1OjYNa>a< zn-w}?MJ^B27*PcyX{_W`GC#8WCGeefZ7nAp% s`uc+v4+SH2wnZ%dw?(=)<`2p=t251x6hh9_*R?O-sLv_BJ9{n4zwJ7ntpET3 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 0000000000000000000000000000000000000000..f1ead5366fee57784463caed020529eb68580f2d GIT binary patch literal 1094 zcmV-M1iAZ(P)|1-#Tty617$7NV9XpSYq17n=0I7CH5fAo%37?!n6JphfE_@;mtse* z6um5Al;s$$4iA3XEuc*-fiVl2js=5WUl5=@qk0Y=hYKR^<$utq5kK>LZUAi|RmmJf ze8J;MW6qm*75=#gVCD(@T@6)_f7<&&8#o@u+{DBqpHb5o9*30BN|;3;W4;t~cl(e2 zW7FdkYdfZDUqbeh$^!PDLk z+Q9KJW+AiJhAZ}9c+hfMDkHZjkEFUr#B1gTkTGA1349HWNLL08gOjjygYLQBlZ^Sr zJ_O<=zI*T5$tN`5?|1D4+_iJ(9~yk~p**M(CIpX&#g2Cs=dT)$aY$V%d6W525vUR- zM4!;;6Wj;D2P23c7GqPeGao7fRn^<0{9%A;=W8L?UHlROnhB+_mL(vx()2&Y$kwKd}Y+=b4GByoIvt3z9$*;f6RwK z#z4#>vK~(=pEdm3XlQ(6)9njEb>%Y9IdvKh`M%8mnJez7+gmOx1J%WJCk-+(m=*{5 zsq(zU91-f{#v+?j-v_FM3Cl?1r;XPwe0x2ew)s#ws6HQJ-YLddCJ3eOB!+fX&RGVJb1j*iO9ez1U z2Afk`@FuH=3PF`HVWEgEpv&0rdqviJllAuHpt|%jcY2e}uY)LOGN*=%&Z#E^*iGp8 zB6fP?p-)T3{N8bh=gl69)Z0Un@s~HA>pjVsU*4BNEP(#(QcW5SSv^z?s)Px#5ewVT z7JC-crZY%)W7%y!R067uIf}0F5mJ^v!y!d99`x9&UZtZSkAK?xK^r(8#=I{MH9>v7 z?c>{6P1}6v4p6Pj zEuc*-fiVluN;@rd#&|1-1ys)b1%hc**|xS-p#T5? M07*qoM6N<$f|%0>IsgCw literal 0 HcmV?d00001 diff --git a/qr_9e851b53.png b/qr_9e851b53.png new file mode 100644 index 0000000000000000000000000000000000000000..3925f7260bdb483c219d89e199c20dfdcd92efc6 GIT binary patch literal 1064 zcmeAS@N?(olHy`uVBq!ia0y~yU_1oEj6eZ~kmN5f7#Nt}d%8G=RLprh=Wgy}1D@lW zryS&EAF#d9_{3&@>7m;zwr?7D57g-_XkhQ0^oGSiL;CF2l|QNj?z+@luyJ(BPvSjj zsb-_e60nq|%lI2k@~MBwEEo2)2&)Fon3<=q&QPqeZGGRSdR}VYH_P)4%R_WE8<`$F zntxNMw{{N`gE{ks8@~%uHThwqkzu#-MpZ4PY(Y7VJe4Q^=*}a{2 z{GhOu+tmKxvhx4Z4BQ61Vm-qb*S%`pbC*y%3;pO$InD*&-xO;+Nxgk#?Sjgg9A=AJt~ywVXgy=@Yfp-qn2t%`y< zIl8l(cPH9U5w7{>J7Lqtm;-)Cv$iTq=IF|Ox_L4s-9>r&3h#F1S^irLwl37#uyxOw z=LNsch5UNcV~kr(4cA&l+*n8+y1St*Io7L_pgP9Y}Pyd_O8p{@X^Cu z)%~lp(T!X8_`Nskx@{sk^A+&dA}_Kr~Y3WZ&qY6_wYQ^gXJ-{U5VR| zIbThvF3oy$DL_vsm-}+@I+2yUvJBFJhhl^6O5-iBZr9X^`n}<$7sz$%k9oXF+0iwl z{E>T5-h3_BEa#~S%3dB~fl*R-?nL-5jn~y#SF&qbXtS^8SphT6w&aw|-AVH1`{R0l z8n@?9pMI8;-!?vsbKAA;?U&A;D19Z8emh9htNGVLuMKzioY~~L^cwrxhb5WwSMr87 z_G(u1r*(W?c%X#yx!~i3xJwiJ3}qIzS=9VoZ_79Dg25`0g+iXsFJJh#OySD%KArQ= z#Mb-*hVk8E*}CdkkIU5eeLLOP(7W$D^N&4$h3@}mG;bFw)wSl>wzNcb17CiY$IahD zL4TjB=4R{MUTwO4J&Sbh`*umQSfhkb)}2XTUqt`8_4olN@8VO7-~U~Z`J$%cXS?}@ z-{*FGJS=daePQMXxn<$D`SHAFSA_2qX;cPGd51Cv}X*Zl9n%ZmdKI;Vst09gD29smFU literal 0 HcmV?d00001