Grazie a tutti per le risposte,
20/02/2024 - sihsandrea ha scritto:
in che senso? cosa fanno questi trigger?
faccio prima ad incollarti quel poco che ho scritto cosi magari spiego meglio anche l'intento:
--crea la tabella Produzione
CREATE TABLE Produzione (
id INTEGER PRIMARY KEY,
data_produzione DATE,
numero_giornaliero INTEGER,
miscelaVARCHAR(200),
prodotto VARCHAR(200),
cella INTEGER,
quantità DECIMAL(7,2),
c_lav VARCHAR(2),
cliente VARCHAR(200),
numero_produzione INTEGER,
numero_prodotto INTEGER,
lotto VARCHAR (12)
);
-- crea la tabella operazioni_silos
CREATE TABLE operazioni_silos (
id_operazione INTEGER PRIMARY KEY AUTOINCREMENT,
cella INTEGER,
data DATE,
prodotto VARCHAR(200),
quantità DECIMAL,
id_produzione INTEGER,
id_travaso INTEGER,
id_carico INTEGER,
id_insacco INTEGER,
id_rimanenze INTEGER,
FOREIGN KEY (id_produzione) REFERENCES Produzione (id),
FOREIGN KEY (id_carico) REFERENCES carico (id_carico)
);
-- crea la tabella carico
CREATE TABLE carico (
id_carico INTEGER PRIMARY KEY AUTOINCREMENT,
data DATE,
cliente VARCHAR (50),
prodotto VARCHAR (200),
cella_1 INTEGER,
percentuale_1 INTEGER,
quantità_1 DECIMAL,
cella_2 INTEGER,
percentuale_2 INTEGER,
quantità_2 DECIMAL,
cella_3 INTEGER,
percentuale_3 INTEGER,
quantità_3 DECIMAL,
quantità_tot DECIMAL,
trasporto VARCHAR (50),
operatore VARCHAR (20),
FOREIGN KEY (cella_1) REFERENCES operazioni_silos (cella),
FOREIGN KEY (cella_2) REFERENCES operazioni_silos (cella),
FOREIGN KEY (cella_3) REFERENCES operazioni_silos (cella)
);
--crea la tabella totali_celle
CREATE TABLE totali_celle (
id_cella INTEGER PRIMARY KEY,
quantità DECIMAL DEFAULT 0,
prodotto VARCHAR (200),
FOREIGN KEY (id_cella) REFERENCES operazioni_silos (cella)
ON UPDATE CASCADE
ON DELETE CASCADE
);
-- inserisce righe vuote con il numero della cella in totali_celle
INSERT INTO totali_celle (id_cella) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10),
(11), (12), (13), (14), (15), (16), (17), (18), (19),
(20), (21), (22), (23), (24), (25), (26), (27), (28),
(29), (30), (46), (47), (48), (49), (50), (51), (52), (53), (54);
-- inserisce il trigger aggiungi da produzione alla tabella Produzione
CREATE TRIGGER aggiungi_da_Produzione
AFTER INSERT ON Produzione
FOR EACH ROW
WHEN NEW.id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM operazioni_silos WHERE id_produzione = NEW.id)
BEGIN
INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_produzione)
VALUES (NEW.cella, NEW.data_produzione, NEW.prodotto, NEW.quantità, NEW.id);
END;
-- inserisce il trigger aggiorna operazioni_silos
CREATE TRIGGER aggiorna_da_Produzione
AFTER UPDATE ON Produzione
FOR EACH ROW
BEGIN
UPDATE operazioni_silos
SET cella=NEW.cella, data=NEW.data_produzione, prodotto=NEW.prodotto, quantità=NEW.quantità
WHERE id_produzione=NEW.id;
END;
-- inserisce il trigger rimuove operazione se rimosso da Produzione alla tabella Produzione
CREATE TRIGGER rimuovi_da_Produzione
AFTER DELETE ON Produzione
FOR EACH ROW
BEGIN
DELETE FROM operazioni_silos
WHERE id_produzione = OLD.id;
END;
-- inserisce il trigger aggiunge totali celle alla tabella operazioni_silos
CREATE TRIGGER aggiungi_a_totali_celle
AFTER INSERT ON operazioni_silos
FOR EACH ROW
WHEN NEW.id_produzione IS NOT NULL
BEGIN
UPDATE totali_celle
SET quantità = quantità + NEW.quantità,
prodotto = NEW.prodotto
WHERE id_cella = NEW.cella;
END;
-- Aggiorna totali_celle se viene modificata una quantità in produzione
CREATE TRIGGER aggiorna_totali_celle
AFTER UPDATE ON operazioni_silos
FOR EACH ROW
WHEN NEW.id_produzione IS NOT NULL
BEGIN
-- Calcola la differenza di quantità e variala nella vecchia cella
UPDATE totali_celle
SET quantità = quantità - OLD.quantità
WHERE id_cella = OLD.cella;
-- Calcola la differenza di quantità e variala nella nuova cella
UPDATE totali_celle
SET quantità = quantità + NEW.quantità,
prodotto = NEW.prodotto
WHERE id_cella = NEW.cella;
END;
-- inserisce il trigger rimuovi da totali_celle se viene cancellata una operazione in operazioni_silos
CREATE TRIGGER Rimuovi_totali_celle_da_Produzione
AFTER DELETE ON operazioni_silos
FOR EACH ROW
WHEN OLD.id_produzione IS NOT NULL
BEGIN
UPDATE totali_celle
SET quantità = quantità - OLD.quantità
WHERE id_cella = OLD.cella;
END;
-- inserisce il trigger prodotto NULL se il totale cella è 0 in totali_celle
CREATE TRIGGER prodotto_NULL
AFTER UPDATE ON totali_celle
FOR EACH ROW
BEGIN
UPDATE totali_celle
SET prodotto = NULL
WHERE quantità = 0;
END;
-- inserisce il trigger togli da carico alla tabella carico, inserisce una riga in operazioni silos per ogni cella compilata in carico
CREATE TRIGGER togli_da_carico
AFTER INSERT ON carico
FOR EACH ROW
BEGIN
-- Prima inserzione
INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_carico)
VALUES (NEW.cella_1, NEW.data, NEW.prodotto, -NEW.quantità_1, NEW.id_carico);
-- Seconda inserzione se cella_2 non è NULL
INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_carico)
SELECT NEW.cella_2, NEW.data, NEW.prodotto, -NEW.quantità_2, NEW.id_carico
WHERE NEW.cella_2 IS NOT '';
-- Terza inserzione se cella_3 non è NULL
INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_carico)
SELECT NEW.cella_3, NEW.data, NEW.prodotto, -NEW.quantità_3, NEW.id_carico
WHERE NEW.cella_3 IS NOT '';
END;
-- inserisce il trigger toglie da totali celle se inserito un record in operazioni silos da carico
CREATE TRIGGER togli_a_totali_celle_da_carico
AFTER INSERT ON operazioni_silos
FOR EACH ROW
WHEN NEW.id_carico IS NOT NULL
BEGIN
UPDATE totali_celle
SET quantità = quantità + NEW.quantità
WHERE id_cella = NEW.cella;
END;
-- inserisce trigger che rimouve un record da operazioni silos se rimosso da carico
CREATE TRIGGER rimuovi_da_operazioni_silos_se_rimosso_in_carico
AFTER DELETE ON carico
FOR EACH ROW
BEGIN
DELETE FROM operazioni_silos
WHERE id_carico = OLD.id_carico;
END;
-- inserisce il trigger che aggiunge in totali celle se cancella un record in carico
CREATE TRIGGER aggiunge_totali_celle_se_rimosso_carico
AFTER DELETE ON operazioni_silos
FOR EACH ROW
WHEN OLD.id_carico IS NOT NULL
BEGIN
UPDATE totali_celle
SET quantità = quantità - OLD.quantità
WHERE id_cella = OLD.cella;
END;
-- inserisce il trigger che aggiorna operazioni silos se modifico carico
CREATE TRIGGER aggiorna_operazioni_silos_se_modifica_carico
AFTER UPDATE ON carico
FOR EACH ROW
BEGIN
UPDATE operazioni_silos
SET cella=NEW.cella_1, data=NEW.data, prodotto=NEW.prodotto, quantità=-NEW.quantità_1
WHERE id_carico=NEW.id_carico AND cella=NEW.cella_1;
UPDATE operazioni_silos
SET cella=NEW.cella_2, data=NEW.data, prodotto=NEW.prodotto, quantità=-NEW.quantità_2
WHERE id_carico=NEW.id_carico AND cella=NEW.cella_2;
UPDATE operazioni_silos
SET cella=NEW.cella_3, data=NEW.data, prodotto=NEW.prodotto, quantità=-NEW.quantità_3
WHERE id_carico=NEW.id_carico AND cella=NEW.cella_3;
END;
20/02/2024 - migliorabile ha scritto:
i metodi di lavoro si studiano e si applicano con la pratica. E ci vogliono anni. Spiegarlo in un post vuol dire concentrare anni di esperienza in una manciata di parole. Complicato.
Sqlite: no. Non e' lo strumento giusto per questo tipo di applicazioni. Si usa MySQL, mariadb, postgresql, oppure per cose grosse (non e' il tuo caso) SQL server, oracle, db2.
trigger: no. Al 99% dei casi i tuoi dati non sono ‘normalizzati'.
Anche per questo si deve studiare: teoria relazione dei dati, forme normali, proprieta' ACID,…
quindi, fondamentalmente: tutto sbagliato, tutto da rifare.
D'altra parte tutto dipende da quale e' il tuo obbiettivo: pestare tasti per vedere che effetto che fa, in questo caso il tuo approccio non e' il massimo ma ci puo' stare
oppure
realizzare qualcosa di utile, nel qual caso ti mancano le basi, da quanto ho capito.
Ti ringrazio per queste parole, ti dico la verità, mi sarebbe sempre piaciuto poter studiare e imparare a programmare, da ragazzetto ho fatto altre scelte, ora ci sto provando con i mezzi ed il tempo a mia disposizione, purtroppo non conosco di persona nessuno che mi può aiutare e cerco di arrangiarmi, l'obbiettivo sarebbe quello di arrivare a qualcosa di utile, se non ci riesco, almeno avrò imparato qualcosa di nuovo… Sono pronto anche a studiare, il problema è anche capire dove indirizzare lo sforzo. Se mi dite che sono in un vicolo cieco, bene riparto da zero. Se mi dite che SQlite non va bene, proverò con quello che mi suggerite voi. Ma capite che nella mia situazione non è nemmeno facile capire se la strada imboccata sia quella giusta.
20/02/2024 - migliorabile ha scritto:
Dal punto di vista di Python non cambia un gran che. Se usa sqlalchemy molte cose vengono nascoste ed usare uno o l'altro non cambia molto.
Per scrivere il codice SQL sto utilizzando DBeaver, mentre l'inserimento dei dati avviene tramite python, vi metto qui un esempio di una pagina del programmino, se ne avete tempo e voglia create un database, modificate database_path, lanciate l'SQL e verificate il funzionamento del programmino.
import customtkinter as ctk
import tkinter as tk
from tkinter import *
from tkinter import ttk
from CTkMessagebox import CTkMessagebox
from PIL import Image, ImageTk
import sqlite3
from Gestione_DB.inserisci_nuovi_produzione import inserisci_nuovi
from Gestione_DB.aggiorna_dati_produzione2 import aggiorna2
import subprocess
# Percorso del database SQLite
database_path = 'PERCORSO DB'
#abilita dark mode
ctk.set_appearance_mode("Dark")
def apri_main():
#dimentica tutti i widget nel frame
for widget in main_frame.winfo_children():
widget.pack_forget()
widget.grid_forget()
#ripristina i pulsanti del main
button3 = ctk.CTkButton(master=main_frame, text='CARICO', width=200, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= apri_carico)
button3.pack(expand='true',side= 'left', padx=20, pady=50)
button3.configure(font= ('Lato', 16))
def apri_carico():
#dimentica tutti i widget nel frame
for widget in main_frame.winfo_children():
widget.pack_forget()
main_frame.columnconfigure(0, weight=1)
main_frame.rowconfigure(0, weight=1)
main_frame.rowconfigure(1, weight=4)
main_frame.rowconfigure(2, weight=2)
main_frame.rowconfigure(3, weight=1)
#crea frame top
frame_top = ctk.CTkFrame(main_frame)
frame_top.grid(column='0',row='0', padx=10, sticky=NSEW)
#crea frame tabella
frame_tabella = ctk.CTkFrame(main_frame)
#frame_tabella.configure(fg_color='red')
frame_tabella.grid(column='0', row='1', padx=10, sticky=NSEW)
#crea frame pulsanti
frame_pulsanti = ctk.CTkFrame(main_frame)
#frame_pulsanti.configure(fg_color='green')
frame_pulsanti.grid(column='0', row='2', padx=10, sticky=NSEW)
frame_pulsanti.columnconfigure(0, weight=1)
frame_pulsanti.columnconfigure(1, weight=1)
#crea frame sinsitra all'interno di frame pulsanti
frame_sinistra = ctk.CTkFrame(frame_pulsanti)
#frame_sinistra.configure(fg_color='red')
frame_sinistra.grid(column='0', row='1', sticky=NSEW)
#crea frame destra all'interno di frame pulsanti
frame_destra = ctk.CTkFrame(frame_pulsanti)
#frame_destra.configure(fg_color='green')
frame_destra.grid(column='1', row='1', sticky=NSEW)
#crea frame bottom
frame_bottom = ctk.CTkFrame(main_frame)
#frame_bottom.configure(fg_color='white')
frame_bottom.grid(column='0', row='3', padx=10, sticky=NSEW)
# crea e inserisci l'etichetta CARICO nel frame_top
label_carico = ctk.CTkLabel(frame_top, text="CARICO", text_color='#FFFFB3')
label_carico.pack(side='top', pady=30)
label_carico.configure(font=('Lato', 20, 'bold'))
#Svuota la treeview
def clear_treeview():
tabella.delete(*tabella.get_children())
#Aggiorna la treeviw dal database
def aggiorna_treeview():
clear_treeview()
apri_database_carico()
# MODIFICA CARICO
# messaggio che chiede conferma
def conferma_modifica(entry_id):
msg = CTkMessagebox(title="Conferma modifica", width=450,fg_color='light grey', bg_color='black', font=('Lato', 15), text_color='black', border_width=2, border_color='black', button_color='#FFEE80', button_text_color='#8B0000', button_hover_color='#FFFFB3', message=f"Stai per modificare il carico ID {entry_id.get()} \n Vuoi continuare?",
icon="question", option_1="SI", option_2="NO")
risposta = msg.get()
if risposta == 'SI':
modifica_carico()
def modifica_carico():
''' Questa parte di codice commentato serviva per aggiornare la treeview senza l'ausilio del database, ora aggiorna il database e refresha la treeview
in base a cosa trova nel database aggiornato
#prendi il numero del record
selected = tabella.focus()
#aggiorna record
tabella.item(selected, text="",values= (entry_id.get(),
entry_data.get(),
entry_cliente.get(),
entry_prodotto.get(),
entry_cella_1.get(),
entry_percentuale_1.get(),
entry_quantità_1.get(),
entry_cella_2.get(),
entry_percentuale_2.get(),
entry_quantità_2.get(),
entry_cella_3.get(),
entry_percentuale_3.get(),
entry_quantità_3.get(),
entry_quantità_tot.get(),
entry_trasporto.get(),
entry_operatore.get(),
))
'''
# aggiorna il database
# Collegamento al DB TRACCIADB (tabella Produzione)
conn = sqlite3.connect(database_path)
# Crea un cursore
c = conn.cursor()
c.execute("""UPDATE carico SET
data = :data,
cliente = :cliente,
prodotto = :prodotto,
cella_1 = :cella_1,
percentuale_1 = :percentuale_1,
quantità_1 = :quantità_1,
cella_2 = :cella_2,
percentuale_2 = :percentuale_2,
quantità_2 = :quantità_2,
cella_3 = :cella_3,
percentuale_3 = :percentuale_3,
quantità_3 = :quantità_3,
quantità_tot = :quantità_tot,
trasporto = :trasporto,
operatore = :operatore
WHERE oid = :oid""",
{
'data': entry_data.get(),
'cliente': entry_cliente.get(),
'prodotto': entry_prodotto.get(),
'cella_1': entry_cella_1.get(),
'percentuale_1': entry_percentuale_1.get(),
'quantità_1': entry_quantità_1.get(),
'cella_2': entry_cella_2.get(),
'percentuale_2': entry_percentuale_2.get(),
'quantità_2': entry_quantità_2.get(),
'cella_3': entry_cella_3.get(),
'percentuale_3': entry_percentuale_3.get(),
'quantità_3': entry_quantità_3.get(),
'quantità_tot': entry_quantità_tot.get(),
'trasporto': entry_trasporto.get(),
'operatore': entry_operatore.get(),
'oid': entry_id.get(),
})
# Commit cambiamenti
conn.commit()
#Chiudi
conn.close()
#clear entry
clear_entry()
#Questo comando sotto è necessario altrimenti da un errore quando chiama aggiorna tabella (non ho capito il perché ma è così)
#c'ho bestemmiato tanto!!!!
tabella.update()
#aggiorna treeview
aggiorna_treeview()
# aggiungi un carico
def aggiungi_carico():
# Collegamento al DB TRACCIADB (tabella Produzione)
conn = sqlite3.connect(database_path)
# Crea un cursore
c = conn.cursor()
# Per inserire un nuovo record ha bisogno di inserire qualcosa in tutte le colonne, quindi vuole anche l'id, con questo escamotage leggo
# l'ultimo id dal database e ci aggiungo 1, dopodiche assegno questa variabile all'inserimento di id
c.execute('SELECT MAX(id_carico) FROM carico')
ultimo_id_carico = c.fetchone()[0]
nuovo_id = ultimo_id_carico+1
#aggiunge un nuovo record
c.execute("""INSERT INTO carico VALUES (
:id,
:data,
:cliente,
:prodotto,
:cella_1,
:percentuale_1,
:quantità_1,
:cella_2,
:percentuale_2,
:quantità_2,
:cella_3,
:percentuale_3,
:quantità_3,
:quantità_tot,
:trasporto,
:operatore)""",
{
'id': nuovo_id,
'data': entry_data.get(),
'cliente': entry_cliente.get(),
'prodotto': entry_prodotto.get(),
'cella_1': entry_cella_1.get(),
'percentuale_1': entry_percentuale_1.get(),
'quantità_1': entry_quantità_1.get(),
'cella_2': entry_cella_2.get(),
'percentuale_2': entry_percentuale_2.get(),
'quantità_2': entry_quantità_2.get(),
'cella_3': entry_cella_3.get(),
'percentuale_3': entry_percentuale_3.get(),
'quantità_3': entry_quantità_3.get(),
'quantità_tot': entry_quantità_tot.get(),
'trasporto': entry_trasporto.get(),
'operatore': entry_operatore.get(),
})
# Commit cambiamenti
conn.commit()
#Chiudi
conn.close()
#clear entry boxes
clear_entry()
#aggiorna la treeview
aggiorna_treeview()
#Elimina un record
# messaggio che chiede conferma
def conferma_elimina(entry_id):
msg = CTkMessagebox(title="Conferma eliminazione", message=f"Stai per eliminare il carico ID {entry_id.get()} \n Vuoi continuare?",
icon="question", option_1="SI", option_2="NO")
risposta = msg.get()
if risposta == 'SI':
elimina_carico()
def elimina_carico():
# Queste 2 righe commentate servivano per aggiornare la treeview senza l'ausilio del databse, ora elimina il record dal database ed aggiorna la
# treeview in base a quello che trova nel database aggiornato
#x = tabella.selection()[0]
#tabella.delete(x)
# Collegamento al DB TRACCIADB (tabella Produzione)
conn = sqlite3.connect(database_path)
# Crea un cursore
c = conn.cursor()
# cancella dal database
c.execute("DELETE from carico WHERE oid =" + entry_id.get())
# Commit cambiamenti
conn.commit()
#Chiudi
conn.close()
#Clear entry boxes
clear_entry()
#aggiorna treeview
aggiorna_treeview()
#Clear entry boxes
def clear_entry():
entry_id.delete(0, END)
entry_data.delete(0, END)
entry_cliente.delete(0, END)
entry_prodotto.delete(0, END)
entry_quantità_tot.delete(0, END)
entry_trasporto.delete(0, END)
entry_operatore.delete(0, END)
entry_cella_1.delete(0, END)
entry_percentuale_1.delete(0, END)
entry_quantità_1.delete(0, END)
entry_cella_2.delete(0, END)
entry_percentuale_2.delete(0, END)
entry_quantità_2.delete(0, END)
entry_cella_3.delete(0, END)
entry_percentuale_3.delete(0, END)
entry_quantità_3.delete(0, END)
# Collega al DATABASE
def apri_database_carico():
# Collegamento al DB TRACCIADB (tabella Produzione)
conn = sqlite3.connect(database_path)
# Crea un cursore
c = conn.cursor()
c.execute("SELECT rowid, * FROM carico ORDER BY id_carico DESC")
records = c.fetchall()
# Aggiunge i dati alla treeview
global count
count = 0
for record in records:
if count % 2 == 0:
tabella.insert(parent='', index='end', iid=count, text='', values=(record[0],
record[2],
record[3],
record[4],
record[5],
record[6],
record[7],
record[8],
record[9],
record[10],
record[11],
record[12],
record[13],
record[14],
record[15],
record[16]), tags=('evenrow',))
else:
tabella.insert(parent='', index='end', iid=count, text='', values=(record[0],
record[2],
record[3],
record[4],
record[5],
record[6],
record[7],
record[8],
record[9],
record[10],
record[11],
record[12],
record[13],
record[14],
record[15],
record[16]), tags=('oddrow',))
count +=1
# Commit cambiamenti
conn.commit()
#Chiudi
conn.close()
# clear tabella
#def clear_tabella():
# tabella.delete(*tabella.get_children())
style = ttk.Style()
# configura i colori della treeview
style.configure("Treeview",
background="#FFEE80",
foreground= "black",
rowheight=25,
fieldbackground= "#FFEE80")
# Stile intestazione
style.configure('Treeview.Heading', background="#FFD700", fieldbackground='#FFEE80', foreground='#8B0000')
style.map('Treeview.Heading',
background=[('active', '#FFEE80')])
# cambia il colore della selezione
style.map('Treeview',
background=[('selected', "#8B0000")],
text_color=[('selected', "#FFEE80")])
# crea la scrollbar
tabella_scroll = Scrollbar(frame_tabella)
tabella_scroll.pack(side=RIGHT, fill=Y, padx=10, pady=20)
#crea tabella
tabella = ttk.Treeview(frame_tabella, yscrollcommand=tabella_scroll.set, selectmode="extended")
# configura la scrollbar
tabella_scroll.configure(background='#FFD700', activebackground='#FFEE80', troughcolor='#FFFFB3')
tabella_scroll.config(command=tabella.yview)
style.configure('Vertical.TScrollbar',background='blue', troughcolor="blue")
# definisce le colonne
tabella['columns'] = (
"id_carico",
"data",
"cliente",
"prodotto",
"cella_1",
"percentuale_1",
"quantità_1",
"cella_2",
"percentuale_2",
"quantità_2",
"cella_3",
"percentuale_3",
"quantità_3",
"quantità_tot",
"trasporto",
"operatore"
)
# formatta le colonne
tabella.column("#0", width=0, stretch=NO) #colonna fantasma che treeview aggiunge da solo a sinistra, con stretch=NO la rendiamo invisibile
tabella.column("id_carico", anchor=CENTER , width=10)
tabella.column("data", anchor=CENTER , width=70)
tabella.column("cliente", anchor=W , width=250)
tabella.column("prodotto", anchor=W , width=300)
tabella.column("cella_1", anchor=CENTER , width=40)
tabella.column("percentuale_1", anchor=CENTER , width=40)
tabella.column("quantità_1", anchor=CENTER , width=40)
tabella.column("cella_2", anchor=CENTER , width=40)
tabella.column("percentuale_2", anchor=CENTER , width=40)
tabella.column("quantità_2", anchor=CENTER , width=40)
tabella.column("cella_3", anchor=CENTER , width=40)
tabella.column("percentuale_3", anchor=CENTER , width=40)
tabella.column("quantità_3", anchor=CENTER , width=40)
tabella.column("quantità_tot", anchor=CENTER , width=40)
tabella.column("trasporto", anchor=W , width=100)
tabella.column("operatore", anchor=W , width=60)
# crea l'intestazione
tabella.heading("#0")
tabella.heading("id_carico", text="id", anchor=CENTER)
tabella.heading("data", text="data", anchor=CENTER)
tabella.heading("cliente", text="cliente", anchor=CENTER)
tabella.heading("prodotto", text="prodotto", anchor=CENTER)
tabella.heading("cella_1", text="cella_1", anchor=CENTER)
tabella.heading("percentuale_1", text="%_1", anchor=CENTER)
tabella.heading("quantità_1", text="Q.li_1", anchor=CENTER)
tabella.heading("cella_2", text="cella_2", anchor=CENTER)
tabella.heading("percentuale_2", text="%_2", anchor=CENTER)
tabella.heading("quantità_2", text="Q.li_2", anchor=CENTER)
tabella.heading("cella_3", text="cella_3", anchor=CENTER)
tabella.heading("percentuale_3", text="%_3", anchor=CENTER)
tabella.heading("quantità_3", text="Q.li_3", anchor=CENTER)
tabella.heading("quantità_tot", text="Q.li_tot", anchor=CENTER)
tabella.heading("trasporto", text="trasporto", anchor=CENTER)
tabella.heading("operatore", text="operatore", anchor=CENTER)
# crea i colori alternati delle righe
tabella.tag_configure('oddrow', background="#FFFFB3")
tabella.tag_configure('evenrow', background="#FFEE80")
# packa la tabella
tabella.pack(fill= 'both', expand='true', ipady=100, ipadx=200, padx=15, pady=20)
#esegui apri database_carico
apri_database_carico()
#inserisce l'id nel frame sinistra
label_id = ctk.CTkLabel(frame_sinistra, text="ID", text_color='#FFFFB3')
label_id.grid(column=3, row=0, padx=10)
label_id.configure(font=('Lato', 16))
entry_id = ctk.CTkEntry(frame_sinistra, fg_color='#FFFFB3',text_color='black', width=70, border_color='#8B0000')
entry_id.grid(column=4, row=0,pady=10, padx=10)
entry_id.configure(font=('Lato', 16))
#inserisce i campi di inserimento nel frame destra
#inserisce tutte le etichette
label_data = ctk.CTkLabel(frame_destra, text="Data", text_color='#FFFFB3')
label_data.grid(column=0, row=0, padx=10)
label_data.configure(font=('Lato', 16))
label_cliente = ctk.CTkLabel(frame_destra, text="Cliente", text_color='#FFFFB3')
label_cliente.grid(column=0, row=1, padx=10)
label_cliente.configure(font=('Lato', 16))
label_prodotto = ctk.CTkLabel(frame_destra, text="Prodotto", text_color='#FFFFB3')
label_prodotto.grid(column=0, row=2, padx=10)
label_prodotto.configure(font=('Lato', 16))
label_quantità_tot = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
label_quantità_tot.grid(column=2, row=0, padx=10)
label_quantità_tot.configure(font=('Lato', 16))
label_trasporto = ctk.CTkLabel(frame_destra, text="Trasporto", text_color='#FFFFB3')
label_trasporto.grid(column=2, row=1, padx=10)
label_trasporto.configure(font=('Lato', 16))
label_operatore = ctk.CTkLabel(frame_destra, text="Operatore", text_color='#FFFFB3')
label_operatore.grid(column=2, row=2, padx=10)
label_operatore.configure(font=('Lato', 16))
label_cella_1 = ctk.CTkLabel(frame_destra, text="Cella 1", text_color='#FFFFB3')
label_cella_1.grid(column=4, row=0, padx=10)
label_cella_1.configure(font=('Lato', 16))
label_percentuale_1 = ctk.CTkLabel(frame_destra, text="%", text_color='#FFFFB3')
label_percentuale_1.grid(column=4, row=1, padx=10)
label_percentuale_1.configure(font=('Lato', 16))
label_quantità_1 = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
label_quantità_1.grid(column=4, row=2, padx=10)
label_quantità_1.configure(font=('Lato', 16))
label_cella_2 = ctk.CTkLabel(frame_destra, text="Cella 2", text_color='#FFFFB3')
label_cella_2.grid(column=6, row=0, padx=10)
label_cella_2.configure(font=('Lato', 16))
label_percentuale_2 = ctk.CTkLabel(frame_destra, text="%", text_color='#FFFFB3')
label_percentuale_2.grid(column=6, row=1, padx=10)
label_percentuale_2.configure(font=('Lato', 16))
label_quantità_2 = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
label_quantità_2.grid(column=6, row=2, padx=10)
label_quantità_2.configure(font=('Lato', 16))
label_cella_3 = ctk.CTkLabel(frame_destra, text="Cella 3", text_color='#FFFFB3')
label_cella_3.grid(column=8, row=0, padx=10)
label_cella_3.configure(font=('Lato', 16))
label_percentuale_3 = ctk.CTkLabel(frame_destra, text="%", text_color='#FFFFB3')
label_percentuale_3.grid(column=8, row=1, padx=10)
label_percentuale_3.configure(font=('Lato', 16))
label_quantità_3 = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
label_quantità_3.grid(column=8, row=2, padx=10)
label_quantità_3.configure(font=('Lato', 16))
#inserisce le entry boxes
entry_data = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
entry_data.grid(column=1, row=0,pady=10, padx=10)
entry_data.configure(font=('Lato', 16))
entry_cliente = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
entry_cliente.grid(column=1, row=1, pady=10, padx=10)
entry_cliente.configure(font=('Lato', 16))
entry_prodotto = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
entry_prodotto.grid(column=1, row=2, pady=10, padx=10)
entry_prodotto.configure(font=('Lato', 16))
entry_quantità_tot = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
entry_quantità_tot.grid(column=3, row=0, pady=10, padx=10)
entry_quantità_tot.configure(font=('Lato', 16))
entry_trasporto = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
entry_trasporto.grid(column=3, row=1, pady=10, padx=10)
entry_trasporto.configure(font=('Lato', 16))
entry_operatore = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
entry_operatore.grid(column=3, row=2, pady=10, padx=10)
entry_operatore.configure(font=('Lato', 16))
entry_cella_1 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_cella_1.grid(column=5, row=0, pady=10, padx=10)
entry_cella_1.configure(font=('Lato', 16))
entry_percentuale_1 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_percentuale_1.grid(column=5, row=1, pady=10, padx=10)
entry_percentuale_1.configure(font=('Lato', 16))
entry_quantità_1 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_quantità_1.grid(column=5, row=2, pady=10, padx=10)
entry_quantità_1.configure(font=('Lato', 16))
entry_cella_2 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_cella_2.grid(column=7, row=0, pady=10, padx=10)
entry_cella_2.configure(font=('Lato', 16))
entry_percentuale_2 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_percentuale_2.grid(column=7, row=1, pady=10, padx=10)
entry_percentuale_2.configure(font=('Lato', 16))
entry_quantità_2 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_quantità_2.grid(column=7, row=2, pady=10, padx=10)
entry_quantità_2.configure(font=('Lato', 16))
entry_cella_3 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_cella_3.grid(column=9, row=0, pady=10, padx=10)
entry_cella_3.configure(font=('Lato', 16))
entry_percentuale_3 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_percentuale_3.grid(column=9, row=1, pady=10, padx=10)
entry_percentuale_3.configure(font=('Lato', 16))
entry_quantità_3 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
entry_quantità_3.grid(column=9, row=2, pady=10, padx=10)
entry_quantità_3.configure(font=('Lato', 16))
# Aggiunge pulsanti nel frame_sinistra
button23 = ctk.CTkButton(frame_sinistra, text='INSERISCI CARICO',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= aggiungi_carico)
button23.grid(column=0, row=0, padx=20, pady=20)
button23.configure(font= ('Lato', 16))
# il command deve essere una lambda function perché garantisce che la funzione conferma_modifica(entry_id) venga eseguita con l'attuale valore presente in entry_id al momento del clic,
# evitando che venga valutato solo al momento della creazione del button.
button24 = ctk.CTkButton(frame_sinistra, text='MODIFICA CARICO',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command=lambda: conferma_modifica(entry_id))
button24.grid(column=0, row=1, padx=20, pady=20)
button24.configure(font= ('Lato', 16))
button25 = ctk.CTkButton(frame_sinistra, text='ELIMINA CARICO',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command=lambda: conferma_elimina(entry_id))
button25.grid(column=0, row=2, padx=20, pady=20)
button25.configure(font= ('Lato', 16))
button26 = ctk.CTkButton(frame_sinistra, text='SVUOTA CAMPI',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= clear_entry)
button26.grid(column=2, row=0, padx=20, pady=20)
button26.configure(font= ('Lato', 16))
# Aggiunge i dati della riga selezionata alle entry boxes
def select_record(e):
# Clear entry_boxes
entry_id.delete(0, END)
entry_data.delete(0, END)
entry_cliente.delete(0, END)
entry_prodotto.delete(0, END)
entry_quantità_tot.delete(0, END)
entry_trasporto.delete(0, END)
entry_operatore.delete(0, END)
entry_cella_1.delete(0, END)
entry_percentuale_1.delete(0, END)
entry_quantità_1.delete(0, END)
entry_cella_2.delete(0, END)
entry_percentuale_2.delete(0, END)
entry_quantità_2.delete(0, END)
entry_cella_3.delete(0, END)
entry_percentuale_3.delete(0, END)
entry_quantità_3.delete(0, END)
#prende il record Number
selected = tabella.focus()
# Ho dovuto mettere queste condizioni per verificare che ci fosse veramente una riga selezionata, altrimenti succedeva
# (ad esempio quando si apriva una messagebox), che cercava di inseirre dei valori nelle entry senza avere una selezione attiva e dava errore
if selected:
# Prende il record values
values = tabella.item(selected, 'values')
# Controlla se ci sono valori e inserisci nelle entry boxes
if values:
#inserisce nelle entry boxes
entry_id.insert(0, values[0])
entry_data.insert(0, values[1])
entry_cliente.insert(0, values[2])
entry_prodotto.insert(0, values[3])
entry_quantità_tot.insert(0, values[13])
entry_trasporto.insert(0, values[14])
entry_operatore.insert(0, values[15])
entry_cella_1.insert(0, values[4])
entry_percentuale_1.insert(0, values[5])
entry_quantità_1.insert(0, values[6])
entry_cella_2.insert(0, values[7])
entry_percentuale_2.insert(0, values[8])
entry_quantità_2.insert(0, values[9])
entry_cella_3.insert(0, values[10])
entry_percentuale_3.insert(0, values[11])
entry_quantità_3.insert(0, values[12])
#inserisce nelle entry quando selezioni una riga
tabella.bind("<ButtonRelease-1>", select_record)
#inserisce il tasto indietro
button13 = ctk.CTkButton(frame_bottom, text='Indietro', border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= apri_main)
button13.pack(side='right', padx=20, pady=20)
button13.configure(font= ('Lato', 16))
#crea la prima finestra con tre pulsanti
root = ctk.CTk()
root.title('Programmino')
# apre la finestra al centro dello schermo
window_height = 1000
window_width = 1800
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))
root.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
# Campo per pulsanti
main_frame = ctk.CTkFrame(master=root)
#Colora il frame di rosso, per rimettere normale cancella queste 3 righe sotto e togli il commento a quella sopra
'''
style = ctk.Style()
style.configure("Custom.TFrame", background="red")
main_frame = ctk.CTkFrame(master=root, style="Custom.TFrame")
'''
# Aggiungi i pulsanti al frame
button3 = ctk.CTkButton(master=main_frame, text='CARICO', border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', width=200, command= apri_carico)
button3.pack(expand='true', side='left', padx=20, pady=50)
button3.configure(font= ('Lato', 16))
# Imposta la posizione del frame al centro della finestra
#main_frame.pack(expand=True, fill='both')
#main_frame.configure(fg_color='yellow')
main_frame.pack(fill= 'both', expand='true')
root.mainloop()