Stabilizza picking barcode e patch cumulativa online

This commit is contained in:
2026-07-04 17:03:55 +02:00
parent 5dd7139b19
commit 77da8d9bad
13 changed files with 1153 additions and 97 deletions

View File

@@ -68,6 +68,9 @@ class BarcodeClientApp:
self._auto_advance_id: str | None = None
self._pallet_auto_focus_id: str | None = None
self._paused_queue_id: int | None = None
self._pallet_user_input_serial = 0
self._priority_loaded_input_serial = 0
self._priority_expected_pallet = ""
self._status_colors = {
"red": "#f4cccc",
"green": "#d9ead3",
@@ -237,16 +240,20 @@ class BarcodeClientApp:
parent.columnconfigure(1, weight=1)
if scanned:
self.pallet_entry = entry
self.pallet_entry.bind("<KeyPress>", self._on_pallet_keypress, add="+")
self.scanned_var.trace_add("write", lambda *_: self._on_scanned_var_changed())
else:
self.destination_entry = entry
self.destination_var.trace_add("write", lambda *_: self._limit_var(self.destination_var, 8))
self.destination_var.trace_add("write", lambda *_: self._on_destination_var_changed())
def _limit_var(self, variable: tk.StringVar, max_len: int) -> None:
value = str(variable.get() or "")
if len(value) > max_len:
variable.set(value[:max_len])
def _on_pallet_keypress(self, _event=None) -> None:
self._pallet_user_input_serial += 1
def _on_scanned_var_changed(self) -> None:
self._limit_var(self.scanned_var, 8)
if self._pallet_auto_focus_id is not None:
@@ -260,6 +267,10 @@ class BarcodeClientApp:
return
self._pallet_auto_focus_id = self.root.after(80, self._auto_focus_destination_after_scan)
def _on_destination_var_changed(self) -> None:
self._limit_var(self.destination_var, 8)
self._refresh_action_labels()
def _auto_focus_destination_after_scan(self) -> None:
self._pallet_auto_focus_id = None
pallet = str(self.scanned_var.get() or "").strip()
@@ -269,6 +280,11 @@ class BarcodeClientApp:
return
if getattr(self.service.state, "mode", "") == "confirm":
return
if getattr(self.service.state, "mode", "") in ("priority_high", "priority_low"):
expected = str(getattr(self.service.state, "expected_pallet", "") or "").strip()
if expected and pallet == expected and self._is_fresh_priority_scan(expected):
self._submit()
return
if bool(getattr(self.service.state, "destination_readonly", False)):
return
self._focus_destination_input()
@@ -371,7 +387,9 @@ class BarcodeClientApp:
except Exception:
pass
self._pallet_auto_focus_id = None
self.queue_var.set(state.queue_label)
pause_context = self._paused_queue_id is not None and state.mode not in ("priority_high", "priority_low")
effective_queue_label = "Pausa PL" if pause_context else state.queue_label
self.queue_var.set(effective_queue_label)
self.destination_var.set(state.destination_barcode)
self.scanned_var.set(state.scanned_pallet)
self.info1_var.set(self._status_text_with_wait_hint(state))
@@ -380,25 +398,28 @@ class BarcodeClientApp:
self.info4_var.set(state.expected_pallet)
self.status_band.configure(bg=state.status_color or self._status_colors["red"])
if state.mode in ("priority_high", "priority_low"):
self._priority_loaded_input_serial = self._pallet_user_input_serial
self._priority_expected_pallet = str(state.expected_pallet or "").strip()
else:
self._priority_expected_pallet = ""
try:
if str(state.queue_label or "") != "Pausa PL":
if str(effective_queue_label or "") != "Pausa PL":
self._paused_queue_id = None
resumable_queue = self._resumable_queue_from_state(state)
if state.mode in ("priority_high", "priority_low") or resumable_queue is not None:
self.btn_submit.configure(text="[F3] Pausa PL")
else:
self.btn_submit.configure(text="[F3] Carica")
if state.mode in ("priority_high", "priority_low"):
self.btn_unload.configure(text="[F4] Salta UDC")
else:
self.btn_unload.configure(text="[F4] Scarica")
queue_buttons_state = "disabled" if str(state.queue_label or "") == "Pausa PL" else "normal"
self._refresh_action_labels(state)
queue_buttons_state = "disabled" if str(effective_queue_label or "") == "Pausa PL" else "normal"
self.btn_f1.configure(state=queue_buttons_state)
self.btn_f2.configure(state=queue_buttons_state)
except Exception:
pass
destination_readonly = bool(getattr(state, "destination_readonly", False))
destination_readonly = False if pause_context else bool(getattr(state, "destination_readonly", False))
try:
self.destination_entry.configure(state="normal")
if destination_readonly:
@@ -419,6 +440,22 @@ class BarcodeClientApp:
else:
self.root.after(20, self._focus_primary_input)
def _refresh_action_labels(self, state: BarcodeViewState | None = None) -> None:
current_state = state or self.service.state
try:
if current_state.mode in ("priority_high", "priority_low"):
self.btn_unload.configure(text="[F4] Salta UDC")
return
destination = str(self.destination_var.get() or "").strip()
if destination == self.NON_SCAFFALATA_BARCODE:
self.btn_unload.configure(text="[F4] Non scaff.")
elif destination:
self.btn_unload.configure(text="[F4] Dissocia")
else:
self.btn_unload.configure(text="[F4] Scarica")
except Exception:
pass
def _focus_primary_input(self) -> None:
try:
self.pallet_entry.focus_force()
@@ -448,6 +485,14 @@ class BarcodeClientApp:
except Exception:
pass
def _is_fresh_priority_scan(self, expected: str) -> bool:
mode = str(getattr(self.service.state, "mode", "") or "")
if mode not in ("priority_high", "priority_low"):
return False
if str(expected or "").strip() != self._priority_expected_pallet:
return False
return self._pallet_user_input_serial > self._priority_loaded_input_serial
def _on_pallet_enter(self, _event=None) -> str:
pallet = str(self.scanned_var.get() or "").strip()
destination = str(self.destination_var.get() or "").strip()
@@ -455,7 +500,15 @@ class BarcodeClientApp:
return "break"
if destination in (self.NON_SCAFFALATA_BARCODE, self.SHIPPED_BARCODE):
if bool(getattr(self.service.state, "destination_readonly", False)):
self._submit()
mode = str(getattr(self.service.state, "mode", "") or "")
if mode in ("priority_high", "priority_low"):
expected = str(getattr(self.service.state, "expected_pallet", "") or "").strip()
if expected and pallet == expected and self._is_fresh_priority_scan(expected):
self._submit()
else:
self._focus_primary_input()
else:
self._submit()
else:
self._focus_destination_input()
return "break"
@@ -510,7 +563,10 @@ class BarcodeClientApp:
self._skip_current_picking_pallet()
return
if pallet:
self._submit_unload_with_source_check()
if destination == self.NON_SCAFFALATA_BARCODE:
self._submit()
else:
self._submit_unload_with_source_check()
return
if self._is_priority_pause():
return