GestGazziNet

Da GazziNet.
Versione del 30 mag 2025 alle 23:38 di Admin (discussione | contributi) (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...")
(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)
Vai alla navigazione Vai alla ricerca

Versione 31/5/2025

  1. === MIGLIORAMENTI APPLICATI A GESTGN ===
  2. 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)

  1. 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))
  1. 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()
  1. 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)
  1. Avvio

if __name__ == '__main__':

   inizializza_db()
   root = tk.Tk()
   app = GestGNApp(root)
   root.mainloop()