7.1 KiB
Modulo gestione_pickinglist.py
Scopo
Il modulo implementa la finestra operativa "Gestione Picking List". La finestra serve al backoffice/magazzino per:
- visualizzare le picking list ancora lavorabili;
- selezionare una sola lista alla volta;
- visualizzare le UDC residue della lista selezionata;
- prenotare una lista per darle priorita' alta sul barcode;
- s-prenotare la lista correntemente prenotata;
- mantenere UI reattiva tramite query asincrone, overlay e spinner.
La finestra lavora sulla vista residuale dbo.py_ViewPackingListRestante, quindi mostra cio' che resta da scaricare, non necessariamente il documento ERP completo. Il documento completo e' invece esposto dalla form "Storico Picking List".
Processo logico
Apertura finestra
open_pickinglist_windowcrea o riporta in primo piano una singola finestra.- La finestra viene inizialmente nascosta con
withdrawe alpha0.0. - Viene creato
GestionePickingListFrame. - Dopo la stabilizzazione layout,
_first_showavvia il primo caricamento. - La finestra viene mostrata solo quando il layout e' pronto, riducendo flicker.
Caricamento lista alta
reload_from_dbesegueSQL_PL.SQL_PLlegge dadbo.py_ViewPackingListRestante.- Il risultato viene normalizzato con
_rows_to_dicts. _refresh_mid_rowsricrea la tabella alta.- Ogni riga e' rappresentata da un
PLRow, che incapsula dizionario dati e checkbox.
Selezione lista
- Il click sul checkbox chiama
on_row_checked. - La selezione e' esclusiva: eventuali altre righe selezionate vengono deselezionate.
- Il documento selezionato viene salvato in
detail_doc. - Viene eseguita
SQL_PL_DETAILS. - Il dettaglio viene messo in cache in
_detail_cache. _refresh_details_incrementalordina e renderizza il dettaglio contksheet.
Ricarica
reload_from_db preserva il documento selezionato quando possibile. Questo e' importante per il caso operativo in cui il barcode sta scaricando UDC mentre l'operatore aggiorna la finestra.
Flusso:
_selected_documento_for_reloaddetermina il documento da mantenere.- La griglia alta viene ricaricata.
_reselect_documento_after_reloadriseleziona la stessa lista se ancora presente.- Il dettaglio viene ricaricato dalla vista residuale.
Prenotazione
on_prenotaverifica il permessopickinglist.prenota.- Richiede una riga selezionata.
- Se
IDStato == 1, l'operazione e' no-op. - Verifica sessione operatore valida.
- Chiama
sp_xExePackingListPallet_async(..., Azione="P"). - Se
rc == 0, logga audit e ricarica la griglia mantenendo il documento.
S-prenotazione
on_sprenotaverifica il permessopickinglist.sprenota.- Richiede una riga selezionata.
- Se
IDStato == 0, l'operazione e' no-op. - Chiama
sp_xExePackingListPallet_async(..., Azione="S"). - Se
rc == 0, logga audit e ricarica.
Semantica operativa
La UI non implementa toggle implicito. I pulsanti hanno semantica esplicita:
| Pulsante | Effetto |
|---|---|
Prenota |
porta la lista selezionata a priorita' alta se non gia' prenotata |
S-prenota |
libera la lista selezionata se e' la lista attiva |
Premere piu' volte Prenota sulla stessa lista gia' prenotata non la libera. Premere piu' volte S-prenota su lista non prenotata non la prenota.
Strutture dati principali
| Nome | Tipo | Ruolo |
|---|---|---|
rows_models |
list[PLRow] |
modelli riga della griglia alta |
_detail_cache |
dict[Any, list] |
cache righe dettaglio per documento |
detail_doc |
Any |
documento correntemente selezionato |
_detail_sort_key |
`str | None` |
_detail_sort_reverse |
bool |
verso ordinamento dettaglio |
pl_table |
ScrollTable |
tabella custom griglia alta |
detail_sheet |
tksheet.Sheet |
griglia dettaglio ad alto volume |
spinner |
ToolbarSpinner |
feedback leggero toolbar |
busy |
InlineBusyOverlay |
overlay query/operazioni lente |
Funzioni e classi principali
| Oggetto | Firma | Ruolo |
|---|---|---|
_rows_to_dicts |
_rows_to_dicts(res: Dict[str, Any]) -> List[Dict[str, Any]] |
normalizza payload DB |
_s |
_s(v) -> str |
converte None in stringa vuota |
_first |
_first(d: Dict[str, Any], keys: List[str], default: str = "") |
estrae il primo campo valorizzato |
ColSpec |
dataclass(title, key, width, anchor) |
descrive una colonna tabellare |
ToolbarSpinner |
classe | animazione leggera toolbar |
ScrollTable |
classe | tabella custom per griglia alta |
PLRow |
classe | modello riga PL + checkbox |
GestionePickingListFrame |
classe | frame principale |
_build_detail_sheet |
_build_detail_sheet(self) |
crea tksheet dettaglio |
_detail_rows_to_sheet_data |
_detail_rows_to_sheet_data(self, rows) |
converte righe DB in righe tksheet |
_load_detail_sheet_data |
_load_detail_sheet_data(self, data) |
applica headers, dati e zebra |
_refresh_mid_rows |
_refresh_mid_rows(self, rows) |
ricrea griglia alta |
_get_selected_model |
_get_selected_model(self) -> Optional[PLRow] |
ritorna riga selezionata |
on_row_checked |
on_row_checked(self, model: PLRow, is_checked: bool) |
carica dettaglio della lista |
reload_from_db |
reload_from_db(self, first=False, reselect_documento=None) |
aggiorna griglia alta |
_refresh_details |
_refresh_details(self) |
ridisegna dettaglio da cache |
_refresh_details_incremental |
_refresh_details_incremental(self, batch_size=25) |
render dettaglio con overlay |
on_prenota |
on_prenota(self) |
prenota lista selezionata |
on_sprenota |
on_sprenota(self) |
s-prenota lista selezionata |
create_frame |
create_frame(parent, *, db_client=None, conn_str=None, session=None) |
factory frame |
open_pickinglist_window |
open_pickinglist_window(parent, db_client, session=None) -> tk.Misc |
entry point finestra |
Query runtime
SQL_PL
Aggrega dbo.py_ViewPackingListRestante per documento. Conta UDC con:
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(CAST(Pallet AS varchar(32)))), '')) AS Pallet
Questo evita il doppio conteggio di UDC multi-lotto.
SQL_PL_DETAILS
Ritorna tutte le righe residuali della lista selezionata, ordinate per Ordinamento.
Effetti sul database
Il modulo UI non aggiorna direttamente tabelle. Tutte le modifiche passano da sp_xExePackingListPallet_async, che esegue dbo.py_sp_xExePackingListPallet.
Effetti indiretti:
- aggiorna
dbo.PyPickingListReservation; - aggiorna
dbo.Celle.IDStato; - scrive audit applicativo con
log_user_action; - la stored puo' scrivere log legacy tramite
sp_LogPackingList.
Rischi e note review
- La vista residuale cambia mentre il barcode scarica UDC: per questo
Ricaricaconserva la selezione e ricarica il dettaglio. - La tabella alta e il dettaglio possono non avere lo stesso numero di righe dello storico, perche' qui si vedono solo residui.
- La convivenza C#/Python dipende dalla presenza degli oggetti
py_*. - La selezione e' esclusiva lato UI, ma il secondo livello F2 barcode dipende dalla logica barcode/stato DB, non da una seconda prenotazione backoffice.