| @@ -517,8 +517,8 @@ def generate_zpl_dataflex( | |||||
| ) -> str: | ) -> str: | ||||
| """ | """ | ||||
| Row 1 (from zero): QR code, then item name (rotated 90°). | Row 1 (from zero): QR code, then item name (rotated 90°). | ||||
| Row 2: smaller Lot, then expiry at the next X, then item code. | |||||
| Text is ^A@R (90° CW); the next line under Lot is +X, not +Y. | |||||
| Row 2: expiry, then Lot at the next X, then item code. | |||||
| Text is ^A@R (90° CW); the next line under expiry is +X, not +Y. | |||||
| Label and QR use lotNo from API when present, else batch_no (Bxxxxx). | Label and QR use lotNo from API when present, else batch_no (Bxxxxx). | ||||
| Light preprint (~JA/~RO) is sent before labels; full ~JR recovery is only for「打袋重設」. | Light preprint (~JA/~RO) is sent before labels; full ~JR recovery is only for「打袋重設」. | ||||
| """ | """ | ||||
| @@ -539,9 +539,9 @@ def generate_zpl_dataflex( | |||||
| host_id = _dataflex_host_identification_sgd_prefix(job_order_id) | host_id = _dataflex_host_identification_sgd_prefix(job_order_id) | ||||
| if exp_esc: | if exp_esc: | ||||
| row2 = f"""^FO0,200 | row2 = f"""^FO0,200 | ||||
| ^A@R,40,40,{font_regular}^FD{label_esc}^FS | |||||
| ^FO42,200 | |||||
| ^A@R,40,40,{font_regular}^FD{exp_esc}^FS | ^A@R,40,40,{font_regular}^FD{exp_esc}^FS | ||||
| ^FO42,200 | |||||
| ^A@R,40,40,{font_regular}^FD{label_esc}^FS | |||||
| ^FO88,200 | ^FO88,200 | ||||
| ^A@R,88,88,{font_bold}^FD{code}^FS""" | ^A@R,88,88,{font_bold}^FD{code}^FS""" | ||||
| else: | else: | ||||
| @@ -700,8 +700,8 @@ def generate_zpl_label_small( | |||||
| else: | else: | ||||
| qr_data = f"QA,{batch_no}" | qr_data = f"QA,{batch_no}" | ||||
| exp_zpl = f""" | exp_zpl = f""" | ||||
| ^FO150,230 | |||||
| ^A@N,36,36,{font}^FD{exp_esc}^FS""" if exp_esc else "" | |||||
| ^FO150,194 | |||||
| ^A@N,25,25,{font}^FD{exp_esc}^FS""" if exp_esc else "" | |||||
| return f"""^XA | return f"""^XA | ||||
| ^CI28 | ^CI28 | ||||
| ^PW500 | ^PW500 | ||||
| @@ -712,9 +712,9 @@ def generate_zpl_label_small( | |||||
| ^FO10,110 | ^FO10,110 | ||||
| ^BQN,2,6^FD{qr_data}^FS | ^BQN,2,6^FD{qr_data}^FS | ||||
| ^FO150,110 | ^FO150,110 | ||||
| ^A@N,48,48,{font}^FD{code}^FS | |||||
| ^FO150,175 | |||||
| ^A@N,40,40,{font}^FD{label_line2_esc}^FS{exp_zpl} | |||||
| ^A@N,34,34,{font}^FD{code}^FS | |||||
| ^FO150,156 | |||||
| ^A@N,28,28,{font}^FD{label_line2_esc}^FS{exp_zpl} | |||||
| ^XZ""" | ^XZ""" | ||||
| @@ -724,9 +724,10 @@ LABEL_IMAGE_W = 720 | |||||
| LABEL_IMAGE_H = 530 | LABEL_IMAGE_H = 530 | ||||
| LABEL_PADDING = 23 | LABEL_PADDING = 23 | ||||
| LABEL_FONT_NAME_SIZE = 42 | LABEL_FONT_NAME_SIZE = 42 | ||||
| LABEL_FONT_CODE_SIZE = 49 | |||||
| LABEL_FONT_BATCH_SIZE = 34 | |||||
| LABEL_FONT_EXPIRY_SIZE = 34 | |||||
| # Item code / lot / expiry ~70% of original size so all three fit under the name. | |||||
| LABEL_FONT_CODE_SIZE = 34 | |||||
| LABEL_FONT_BATCH_SIZE = 24 | |||||
| LABEL_FONT_EXPIRY_SIZE = 24 | |||||
| LABEL_QR_SIZE = 210 | LABEL_QR_SIZE = 210 | ||||
| @@ -1229,8 +1230,8 @@ def save_laser_last_count(date_str: str, count: int) -> None: | |||||
| LASER_PUSH_INTERVAL = 2 # seconds between pushes (like sample script) | LASER_PUSH_INTERVAL = 2 # seconds between pushes (like sample script) | ||||
| # Click row with 激光機 selected: send this many times, delay between sends (not after last). | |||||
| LASER_ROW_SEND_COUNT = 3 | |||||
| # Click row with 激光機 selected: one payload. Sending 3 queued 2–3 old bags after a job change. | |||||
| LASER_ROW_SEND_COUNT = 1 | |||||
| LASER_ROW_SEND_DELAY_SEC = 3 | LASER_ROW_SEND_DELAY_SEC = 3 | ||||
| @@ -2272,6 +2273,17 @@ def open_dataflex_stop_window( | |||||
| def stop() -> None: | def stop() -> None: | ||||
| stop_event.set() | stop_event.set() | ||||
| # Cancel labels already sitting in the DataFlex buffer so the next job | |||||
| # does not print 2–3 leftover bags of the previous job. | |||||
| ip, port = session.printer_ip, session.printer_port | |||||
| def _cancel_buffer() -> None: | |||||
| try: | |||||
| send_dataflex_preprint_reset(ip, port, force=True) | |||||
| except Exception: | |||||
| pass | |||||
| threading.Thread(target=_cancel_buffer, daemon=True).start() | |||||
| stop_win_ref[0] = None | stop_win_ref[0] = None | ||||
| clear_topmost() | clear_topmost() | ||||
| try: | try: | ||||