Milestone ultima alpha
This commit is contained in:
@@ -66,7 +66,10 @@ except Exception:
|
||||
natural_sort_key = None # type: ignore[assignment]
|
||||
|
||||
# Usa overlay e runner "collaudati"
|
||||
from gestione_aree import BusyOverlay, AsyncRunner
|
||||
from busy_overlay import InlineBusyOverlay
|
||||
from gestione_aree import AsyncRunner
|
||||
from locale_text import load_locale_catalog, text as loc_text
|
||||
from ui_theme import theme_color, theme_font, theme_section, theme_value
|
||||
from user_session import UserSession
|
||||
from window_placement import place_window_fullsize_below_parent_later
|
||||
|
||||
@@ -583,12 +586,18 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
def __init__(self, master, *, db_client=None, conn_str=None, session: UserSession | None = None):
|
||||
"""Create the master/detail picking list frame."""
|
||||
super().__init__(master)
|
||||
self._theme = theme_section("pickinglist_window", {})
|
||||
self._locale_catalog = load_locale_catalog()
|
||||
if db_client is None:
|
||||
raise ValueError("GestionePickingListFrame richiede un db_client condiviso.")
|
||||
self.db_client = db_client
|
||||
self.session = session
|
||||
self.runner = AsyncRunner(self) # runner condiviso (usa loop globale)
|
||||
self.busy = BusyOverlay(self) # overlay collaudato
|
||||
self.busy = InlineBusyOverlay(self, self._theme)
|
||||
try:
|
||||
self.configure(fg_color=theme_color(self._theme, "window_fg_color", ("#efefef", "#2f2f2f")))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.rows_models: list[PLRow] = []
|
||||
self._detail_cache: Dict[Any, list] = {}
|
||||
@@ -601,8 +610,7 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
self._render_job = None # Tracking del job di rendering in corso
|
||||
|
||||
self._build_layout()
|
||||
# 🔇 Niente reload immediato: carichiamo quando la finestra è idle (= già resa)
|
||||
self.after_idle(self._first_show)
|
||||
self._initial_load_started = False
|
||||
|
||||
def _can(self, action: str) -> bool:
|
||||
"""Return whether the current user can execute one picking-list action."""
|
||||
@@ -616,6 +624,9 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
|
||||
def _first_show(self):
|
||||
"""Chiamato a finestra già resa → evitiamo sfarfallio del primo paint e mostriamo wait-cursor."""
|
||||
if self._initial_load_started:
|
||||
return
|
||||
self._initial_load_started = True
|
||||
self._first_loading = True
|
||||
try:
|
||||
self.winfo_toplevel().configure(cursor="watch")
|
||||
@@ -633,13 +644,22 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
|
||||
top = ctk.CTkFrame(self)
|
||||
top.grid(row=0, column=0, sticky="ew", padx=10, pady=(8,4))
|
||||
try:
|
||||
top.configure(fg_color=theme_color(self._theme, "toolbar_frame_fg_color", ("#d7d7d7", "#3b3b3b")))
|
||||
except Exception:
|
||||
pass
|
||||
for i, (text, cmd) in enumerate([
|
||||
("Ricarica", self.reload_from_db),
|
||||
("Prenota", self.on_prenota),
|
||||
("S-prenota", self.on_sprenota),
|
||||
("Esporta XLSX", self.on_export)
|
||||
(loc_text("picking.button.reload", catalog=self._locale_catalog, default="Ricarica"), self.reload_from_db),
|
||||
(loc_text("picking.button.prenota", catalog=self._locale_catalog, default="Prenota"), self.on_prenota),
|
||||
(loc_text("picking.button.sprenota", catalog=self._locale_catalog, default="S-prenota"), self.on_sprenota),
|
||||
(loc_text("picking.button.export", catalog=self._locale_catalog, default="Esporta XLSX"), self.on_export)
|
||||
]):
|
||||
ctk.CTkButton(top, text=text, command=cmd).grid(row=0, column=i, padx=6)
|
||||
ctk.CTkButton(
|
||||
top,
|
||||
text=text,
|
||||
command=cmd,
|
||||
font=theme_font(self._theme, "toolbar_button_font", ("Segoe UI", 10, "bold")),
|
||||
).grid(row=0, column=i, padx=6)
|
||||
|
||||
# --- micro spinner a destra della toolbar ---
|
||||
self.spinner = ToolbarSpinner(top)
|
||||
@@ -942,7 +962,7 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
|
||||
# ----- load PL -----
|
||||
@_log_call()
|
||||
def reload_from_db(self, first: bool = False):
|
||||
def reload_from_db(self, first: bool = False, reselect_documento: str | None = None):
|
||||
"""Load or reload the picking list summary table from the database."""
|
||||
self.spinner.start(" Carico…") # spinner ON
|
||||
async def _job():
|
||||
@@ -952,6 +972,8 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
rows = _rows_to_dicts(res)
|
||||
_log_dataset("SQL_PL", rows)
|
||||
self._refresh_mid_rows(rows)
|
||||
if reselect_documento:
|
||||
self.after_idle(lambda doc=reselect_documento: self._reselect_documento_after_reload(doc))
|
||||
self.spinner.stop() # spinner OFF
|
||||
# se era il primo load, ripristina il cursore standard
|
||||
if self._first_loading:
|
||||
@@ -1057,7 +1079,7 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
self.spinner.start(" Prenoto…")
|
||||
|
||||
async def _job():
|
||||
return await sp_xExePackingListPallet_async(self.db_client, id_operatore, documento)
|
||||
return await sp_xExePackingListPallet_async(self.db_client, id_operatore, documento, "P")
|
||||
|
||||
def _ok(res: SPResult):
|
||||
_MODULE_LOGGER.log(_MODULE_LOG_LEVEL, f"Esito prenotazione documento={documento} rc={getattr(res, 'rc', None)} message={getattr(res, 'message', None)}")
|
||||
@@ -1070,7 +1092,8 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
outcome="ok",
|
||||
target=documento,
|
||||
)
|
||||
self._recolor_row_by_documento(documento, desired)
|
||||
self._detail_cache.pop(documento, None)
|
||||
self.reload_from_db(reselect_documento=documento)
|
||||
else:
|
||||
msg = (res.message if res else "Errore sconosciuto")
|
||||
log_user_action(
|
||||
@@ -1130,7 +1153,7 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
self.spinner.start(" S-prenoto…")
|
||||
|
||||
async def _job():
|
||||
return await sp_xExePackingListPallet_async(self.db_client, id_operatore, documento)
|
||||
return await sp_xExePackingListPallet_async(self.db_client, id_operatore, documento, "S")
|
||||
|
||||
def _ok(res: SPResult):
|
||||
_MODULE_LOGGER.log(_MODULE_LOG_LEVEL, f"Esito s-prenotazione documento={documento} rc={getattr(res, 'rc', None)} message={getattr(res, 'message', None)}")
|
||||
@@ -1143,7 +1166,8 @@ class GestionePickingListFrame(ctk.CTkFrame):
|
||||
outcome="ok",
|
||||
target=documento,
|
||||
)
|
||||
self._recolor_row_by_documento(documento, desired)
|
||||
self._detail_cache.pop(documento, None)
|
||||
self.reload_from_db(reselect_documento=documento)
|
||||
else:
|
||||
msg = (res.message if res else "Errore sconosciuto")
|
||||
log_user_action(
|
||||
@@ -1215,9 +1239,12 @@ def open_pickinglist_window(parent: tk.Misc, db_client, session: UserSession | N
|
||||
pass
|
||||
|
||||
win = ctk.CTkToplevel(parent)
|
||||
win.title("Gestione Picking List")
|
||||
win.geometry("1200x700")
|
||||
win.minsize(1000, 560)
|
||||
locale_catalog = load_locale_catalog()
|
||||
win.title(loc_text("picking.title", catalog=locale_catalog, default="Gestione Picking List"))
|
||||
theme = theme_section("pickinglist_window", {})
|
||||
win.geometry(str(theme_value(theme, "window_geometry", "1200x700")))
|
||||
minsize = theme_value(theme, "window_minsize", [1000, 560])
|
||||
win.minsize(int(minsize[0]), int(minsize[1]))
|
||||
setattr(parent, key, win)
|
||||
|
||||
# Keep the toplevel hidden until the child frame has built its initial layout.
|
||||
@@ -1238,19 +1265,9 @@ def open_pickinglist_window(parent: tk.Misc, db_client, session: UserSession | N
|
||||
try:
|
||||
win.update_idletasks()
|
||||
place_window_fullsize_below_parent_later(parent, win)
|
||||
try:
|
||||
win.deiconify()
|
||||
except Exception:
|
||||
pass
|
||||
win.lift()
|
||||
try:
|
||||
win.focus_force()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
win.attributes("-alpha", 1.0)
|
||||
except Exception:
|
||||
pass
|
||||
win.after(340, lambda: frame._first_show())
|
||||
win.after(360, lambda: win.lift() if getattr(win, "winfo_exists", lambda: False)() else None)
|
||||
win.after(380, lambda: win.focus_force() if getattr(win, "winfo_exists", lambda: False)() else None)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user