GestGazziNet: differenze tra le versioni
(Creata pagina con "Versione 31/5/2025 <code> # === MIGLIORAMENTI APPLICATI A GESTGN === # Ristrutturazione completa con GUI completa e migliorata. import os import sqlite3 import tkinter as tk from tkinter import ttk, filedialog, messagebox from datetime import datetime import shutil import platform import subprocess DB_FILE = 'gestgn.db' PDF_DIR = 'allegati_pdf' FORNITORI = ['Amazon', 'Unieuro', 'Comet', 'MediaWorld'] os.makedirs(PDF_DIR, exist_ok=True) # Utility def centra_finestr...") |
Nessun oggetto della modifica |
||
Riga 1: | Riga 1: | ||
Versione 31/5/2025 | Versione 31/5/2025 | ||
< | <p> | ||
# === MIGLIORAMENTI APPLICATI A GESTGN === | # === MIGLIORAMENTI APPLICATI A GESTGN === | ||
# Ristrutturazione completa con GUI completa e migliorata. | # Ristrutturazione completa con GUI completa e migliorata. | ||
Riga 375: | Riga 375: | ||
app = GestGNApp(root) | app = GestGNApp(root) | ||
root.mainloop() | root.mainloop() | ||
</ | </p> |
Versione delle 23:38, 30 mag 2025
Versione 31/5/2025
- === MIGLIORAMENTI APPLICATI A GESTGN ===
- Ristrutturazione completa con GUI completa e migliorata.
import os import sqlite3 import tkinter as tk from tkinter import ttk, filedialog, messagebox from datetime import datetime import shutil import platform import subprocess DB_FILE = 'gestgn.db' PDF_DIR = 'allegati_pdf' FORNITORI = ['Amazon', 'Unieuro', 'Comet', 'MediaWorld'] os.makedirs(PDF_DIR, exist_ok=True)
- Utility
def centra_finestra(finestra, padre): finestra.update_idletasks() w, h = finestra.winfo_width(), finestra.winfo_height() x = padre.winfo_x() + (padre.winfo_width() // 2) - (w // 2) y = padre.winfo_y() + (padre.winfo_height() // 2) - (h // 2) finestra.geometry(f"{w}x{h}+{x}+{y}") def apri_pdf(nome_file): path = os.path.join(PDF_DIR, nome_file) if not os.path.exists(path): messagebox.showerror("Errore", "File PDF non trovato") return try: if platform.system() == 'Windows': os.startfile(path) elif platform.system() == 'Darwin': subprocess.run(['open', path]) else: subprocess.run(['xdg-open', path]) except Exception as e: messagebox.showerror("Errore apertura PDF", str(e))
- Database
def inizializza_db(): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute(CREATE TABLE IF NOT EXISTS inventory ( id INTEGER PRIMARY KEY AUTOINCREMENT, id_code TEXT UNIQUE, riferimento TEXT, fornitore TEXT, descrizione TEXT, pdf_file TEXT, created_at TEXT, active INTEGER DEFAULT 1 )) conn.commit() conn.close() def genera_codice(): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("SELECT MAX(id) FROM inventory") max_id = c.fetchone()[0] conn.close() return f"INV-{(max_id or 0) + 1:04d}" def aggiungi_articolo(rif, fornitore, descrizione, pdf_path): codice = genera_codice() now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") nome_pdf = "" if pdf_path: estensione = os.path.splitext(pdf_path)[1] nome_pdf = f"{codice}_{datetime.now().strftime('%Y%m%d_%H%M%S')}{estensione}" try: shutil.copy(pdf_path, os.path.join(PDF_DIR, nome_pdf)) except Exception as e: messagebox.showerror("Errore copia PDF", str(e)) return conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute(INSERT INTO inventory (id_code, riferimento, fornitore, descrizione, pdf_file, created_at) VALUES (?, ?, ?, ?, ?, ?), (codice, rif.strip(), fornitore.strip(), descrizione.strip(), nome_pdf, now)) conn.commit() conn.close() def carica_articoli(attivi=True): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("SELECT * FROM inventory WHERE active=? ORDER BY created_at DESC", (1 if attivi else 0,)) risultati = c.fetchall() conn.close() return risultati def modifica_articolo(id, riferimento, fornitore, descrizione): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("UPDATE inventory SET riferimento=?, fornitore=?, descrizione=? WHERE id=?", (riferimento.strip(), fornitore.strip(), descrizione.strip(), id)) conn.commit() conn.close() def elimina_logicamente(id): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("UPDATE inventory SET active=0 WHERE id=?", (id,)) conn.commit() conn.close() def recupera_articolo(id): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("UPDATE inventory SET active=1 WHERE id=?", (id,)) conn.commit() conn.close()
- GUI (completa con tutte le funzioni)
class GestGNApp: def __init__(self, root): self.root = root root.title("GestGN - Gestione Inventario IA Docet") self.refresh_attivo = tk.BooleanVar(value=False) self.tempo_refresh = tk.IntVar(value=30) frame = ttk.Frame(root, padding=10) frame.pack(fill=tk.BOTH, expand=True) style = ttk.Style() style.theme_use('clam') ttk.Button(frame, text="Aggiungi", command=self.finestra_aggiungi).grid(row=0, column=0, padx=5, pady=5) ttk.Button(frame, text="Modifica", command=self.finestra_modifica).grid(row=0, column=1, padx=5, pady=5) ttk.Button(frame, text="Elimina", command=self.elimina_articolo).grid(row=0, column=2, padx=5, pady=5) ttk.Button(frame, text="Apri PDF", command=self.visualizza_pdf).grid(row=0, column=3, padx=5, pady=5) ttk.Button(frame, text="Visualizza Disattivati", command=self.visualizza_disattivati).grid(row=0, column=4, padx=5, pady=5) ttk.Button(frame, text="Visualizza", command=self.visualizza_dettagli).grid(row=0, column=5, padx=5, pady=5) ttk.Button(frame, text="Esci", command=root.destroy).grid(row=0, column=6, padx=5, pady=5) ttk.Label(frame, text="Refresh (s):").grid(row=2, column=0, sticky="w", padx=5) spin_refresh = ttk.Spinbox(frame, from_=5, to=3600, textvariable=self.tempo_refresh, width=6) spin_refresh.grid(row=2, column=1, sticky="w", padx=5) chk_refresh = ttk.Checkbutton(frame, text="Auto-refresh", variable=self.refresh_attivo) chk_refresh.grid(row=2, column=2, columnspan=2, sticky="w", padx=5) self.tabella = ttk.Treeview(frame, columns=("id", "id_code", "riferimento", "fornitore", "descrizione", "pdf_file", "created_at"), show="headings") self.intestazioni = { "id": "ID", "id_code": "Codice", "riferimento": "Riferimento", "fornitore": "Fornitore", "descrizione": "Descrizione", "pdf_file": "PDF", "created_at": "Data Creazione" } for col in self.tabella["columns"]: self.tabella.heading(col, text=self.intestazioni[col]) self.tabella.grid(row=1, column=0, columnspan=7, sticky="nsew") frame.rowconfigure(1, weight=1) frame.columnconfigure(6, weight=1) self.aggiorna_tabella() self.schedule_refresh() def aggiorna_tabella(self): for r in self.tabella.get_children(): self.tabella.delete(r) for riga in carica_articoli(): self.tabella.insert(, tk.END, values=riga) def schedule_refresh(self): if self.refresh_attivo.get(): self.aggiorna_tabella() self.root.after(self.tempo_refresh.get() * 1000, self.schedule_refresh) def finestra_aggiungi(self): win = tk.Toplevel(self.root) win.title("Aggiungi Articolo") win.grab_set() win.transient(self.root) ttk.Label(win, text="Riferimento").grid(row=0, column=0) rif = ttk.Entry(win) rif.grid(row=0, column=1) ttk.Label(win, text="Fornitore").grid(row=1, column=0) fornitore = ttk.Combobox(win, values=FORNITORI, state="readonly") fornitore.grid(row=1, column=1) ttk.Label(win, text="Descrizione").grid(row=2, column=0) descrizione = ttk.Entry(win) descrizione.grid(row=2, column=1) pdf_path = tk.StringVar() ttk.Label(win, text="PDF Allegato").grid(row=3, column=0) ttk.Entry(win, textvariable=pdf_path).grid(row=3, column=1) ttk.Button(win, text="Sfoglia", command=lambda: pdf_path.set(filedialog.askopenfilename(filetypes=[("PDF", "*.pdf")], parent=win))).grid(row=3, column=2) def salva(): if not rif.get() or not fornitore.get() or not descrizione.get(): messagebox.showwarning("Attenzione", "Compila tutti i campi obbligatori", parent=win) return if not pdf_path.get(): if not messagebox.askyesno("Nessun PDF", "Vuoi salvare il record anche senza allegato?", parent=win): return aggiungi_articolo(rif.get(), fornitore.get(), descrizione.get(), pdf_path.get()) messagebox.showinfo("Salvato", "Articolo aggiunto con successo", parent=win) win.destroy() self.aggiorna_tabella() ttk.Button(win, text="Salva", command=salva).grid(row=4, column=0, columnspan=3, pady=10) centra_finestra(win, self.root) def finestra_modifica(self): item = self.tabella.selection() if not item: messagebox.showinfo("Info", "Seleziona un record da modificare", parent=self.root) return valori = self.tabella.item(item[0])["values"] id, _, riferimento, fornitore, descrizione = valori[:5] win = tk.Toplevel(self.root) win.title("Modifica Articolo") win.grab_set() win.transient(self.root) ttk.Label(win, text="Riferimento").grid(row=0, column=0) rif = ttk.Entry(win) rif.insert(0, riferimento) rif.grid(row=0, column=1) ttk.Label(win, text="Fornitore").grid(row=1, column=0) forn = ttk.Combobox(win, values=FORNITORI, state="readonly") forn.set(fornitore) forn.grid(row=1, column=1) ttk.Label(win, text="Descrizione").grid(row=2, column=0) desc = ttk.Entry(win) desc.insert(0, descrizione) desc.grid(row=2, column=1) def salva(): modifica_articolo(id, rif.get(), forn.get(), desc.get()) messagebox.showinfo("Modificato", "Articolo modificato correttamente", parent=win) win.destroy() self.aggiorna_tabella() ttk.Button(win, text="Salva", command=salva).grid(row=3, column=0, columnspan=2, pady=10) centra_finestra(win, self.root) def elimina_articolo(self): item = self.tabella.selection() if not item: messagebox.showinfo("Info", "Seleziona un record da eliminare", parent=self.root) return valori = self.tabella.item(item[0])["values"] id = valori[0] if messagebox.askyesno("Conferma", "Vuoi davvero disattivare questo articolo?", parent=self.root): elimina_logicamente(id) messagebox.showinfo("Eliminato", "Articolo disattivato correttamente", parent=self.root) self.aggiorna_tabella() def visualizza_pdf(self): item = self.tabella.selection() if not item: messagebox.showinfo("Info", "Seleziona un record con PDF da aprire", parent=self.root) return valori = self.tabella.item(item[0])["values"] nome_file = valori[5] if nome_file: apri_pdf(nome_file) else: messagebox.showwarning("PDF mancante", "Questo articolo non ha un PDF associato", parent=self.root) def visualizza_disattivati(self): finestra = tk.Toplevel(self.root) finestra.title("Articoli Disattivati") finestra.transient(self.root) finestra.grab_set() tabella_disattivi = ttk.Treeview(finestra, columns=("id", "id_code", "riferimento", "fornitore", "descrizione", "pdf_file", "created_at"), show="headings") for col in tabella_disattivi["columns"]: tabella_disattivi.heading(col, text=self.intestazioni[col]) tabella_disattivi.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) for riga in carica_articoli(attivi=False): tabella_disattivi.insert(, tk.END, values=riga) def elimina_definitivamente(): item = tabella_disattivi.selection() if not item: messagebox.showinfo("Info", "Seleziona un record da eliminare definitivamente", parent=finestra) return id = tabella_disattivi.item(item[0])["values"][0] if messagebox.askyesno("Conferma", "Sei sicuro di voler eliminare definitivamente questo articolo?", parent=finestra): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("DELETE FROM inventory WHERE id=?", (id,)) conn.commit() conn.close() messagebox.showinfo("Eliminato", "Articolo eliminato definitivamente", parent=finestra) tabella_disattivi.delete(item[0]) frame_bottoni = ttk.Frame(finestra) frame_bottoni.pack(pady=5) ttk.Button(frame_bottoni, text="Recupera", command=lambda: self.recupera_selezionato(tabella_disattivi, finestra)).pack(side=tk.LEFT, padx=5) ttk.Button(frame_bottoni, text="Elimina Definitivamente", command=elimina_definitivamente).pack(side=tk.LEFT, padx=5) ttk.Button(frame_bottoni, text="Chiudi", command=finestra.destroy).pack(side=tk.LEFT, padx=5) centra_finestra(finestra, self.root) def recupera_selezionato(self, tabella_disattivi, finestra): item = tabella_disattivi.selection() if not item: messagebox.showinfo("Info", "Seleziona un record da recuperare", parent=finestra) return id = tabella_disattivi.item(item[0])["values"][0] if messagebox.askyesno("Conferma", "Vuoi davvero recuperare questo articolo?", parent=finestra): recupera_articolo(id) messagebox.showinfo("Recuperato", "Articolo riattivato correttamente", parent=finestra) tabella_disattivi.delete(item[0]) def stampa_etichetta(self, codice, riferimento, fornitore): try: etichetta = f"{codice} {fornitore}" file_path = "/tmp/etichetta.txt" with open(file_path, "w") as f: f.write(etichetta) # Stampa tramite lp per sistemi Linux subprocess.run(["lp", "-d", "Brother_QL_700", file_path], check=True) except Exception as e: messagebox.showerror("Errore Stampa", f"Errore durante la stampa dell'etichetta: {e}", parent=self.root) def visualizza_dettagli(self): item = self.tabella.selection() if not item: messagebox.showinfo("Info", "Seleziona un record da visualizzare", parent=self.root) return valori = self.tabella.item(item[0])["values"] if len(valori) < 7: messagebox.showerror("Errore", "Il record selezionato non contiene tutti i dati richiesti", parent=self.root) return id, codice, riferimento, fornitore, descrizione, pdf_file, created_at = valori[:7] win = tk.Toplevel(self.root) win.title(f"Dettagli Articolo {codice}") win.transient(self.root) win.grab_set() campi = [ ("ID", id), ("Codice", codice), ("Riferimento", riferimento), ("Fornitore", fornitore), ("Descrizione", descrizione), ("PDF", pdf_file if pdf_file else "Nessun PDF"), ("Creato il", created_at) ] for i, (label, valore) in enumerate(campi): ttk.Label(win, text=label + ":").grid(row=i, column=0, sticky="w", padx=5, pady=2) ttk.Label(win, text=valore).grid(row=i, column=1, sticky="w", padx=5, pady=2) ttk.Button(win, text="Stampa Etichetta", command=lambda: self.stampa_etichetta(codice, riferimento, fornitore)).grid(row=len(campi), column=0, columnspan=2, pady=5) ttk.Button(win, text="Chiudi", command=win.destroy).grid(row=len(campi)+1, column=0, columnspan=2, pady=10) centra_finestra(win, self.root)
- Avvio
if __name__ == '__main__': inizializza_db() root = tk.Tk() app = GestGNApp(root) root.mainloop()