import qrcode import base64 import logging import tempfile import os import platform import socket import subprocess from io import BytesIO from odoo import models, fields, api from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class MrpWorkorder(models.Model): _name = 'mrp.workorder' _inherit = ['mrp.workorder', 'printing.utils'] def print_pdf(self, printer_config, pdf_data): """跨平台打印函数,支持网络打印机(IP:端口)""" # 将PDF数据保存到临时文件 with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file: pdf_binary = base64.b64decode(pdf_data) temp_file.write(pdf_binary) temp_file_path = temp_file.name _logger.info(f"开始打印PDF文件: {temp_file_path}") try: # 获取打印机名称或IP地址 printer_name = printer_config.printer_id.name if not printer_name: raise UserError('打印机名称未配置') # 使用打印机配置中的IP地址和端口 printer_ip = printer_config.printer_id.ip_address printer_port = printer_config.printer_id.port _logger.info(f"使用网络打印机: IP={printer_ip}, 端口={printer_port}") if platform.system() == 'Windows': _logger.info(f"Windows环境不支持网络打印机") else: # Linux环境 # try: # import cups # # 处理网络打印机情况 # _logger.info(f"Linux环境下连接网络打印机: {printer_ip}:{printer_port}") # # 创建连接 # conn = cups.Connection() # # 检查打印机是否已经添加到系统 # printers = conn.getPrinters() # _logger.info(f"可用打印机列表: {list(printers.keys())}") # network_printer_name = f"IP_{printer_ip}_{printer_port}" # # 如果打印机不存在,尝试添加 # if network_printer_name not in printers: # _logger.info(f"添加网络打印机: {network_printer_name}") # conn.addPrinter( # network_printer_name, # device=f"socket://{printer_ip}:{printer_port}", # info=f"Network Printer {printer_ip}:{printer_port}", # location="Network" # ) # # 设置打印机为启用状态 # conn.enablePrinter(network_printer_name) # _logger.info(f"网络打印机添加成功: {network_printer_name}") # # 打印文件 # _logger.info(f"开始打印到网络打印机: {network_printer_name}") # job_id = conn.printFile(network_printer_name, temp_file_path, "工单打印", {}) # _logger.info(f"打印作业ID: {job_id}") # except ImportError as ie: # _logger.error(f"导入CUPS库失败: {str(ie)}") # 尝试使用lp命令打印 try: _logger.info("尝试使用lp命令打印...") # 使用socket设置打印 cmd = f"lp -h {printer_ip}:{printer_port} -d {printer_name} {temp_file_path}" _logger.info(f"执行lp打印命令: {cmd}") result = subprocess.run(cmd, shell=True, check=True, capture_output=True) _logger.info(f"lp打印结果: {result.stdout.decode()}") except Exception as e: _logger.error(f"lp命令打印失败: {str(e)}") raise UserError(f'打印失败,请安装cups打印库: pip install pycups 或确保lp命令可用') return True except Exception as e: _logger.error(f"打印失败详细信息: {str(e)}") raise UserError(f'打印失败: {str(e)}') finally: # 清理临时文件 if os.path.exists(temp_file_path): try: os.unlink(temp_file_path) _logger.info(f"临时文件已清理: {temp_file_path}") except Exception as e: _logger.error(f"清理临时文件失败: {str(e)}") def _compute_state(self): super(MrpWorkorder, self)._compute_state() for workorder in self: work_ids = workorder.production_id.workorder_ids.filtered(lambda w: w.routing_type == '装夹预调' or w.routing_type == '人工线下加工') for wo in work_ids: if wo.state == 'ready' and not wo.production_id.product_id.is_print_program: # 触发打印程序 pdf_data = self.processing_drawing try: if pdf_data: # 获取默认打印机配置 printer_config = self.env['printer.configuration'].sudo().search([('model', '=', self._name), ('printer_id.type', '=', 'normal')], limit=1) if not printer_config: raise UserError('请先配置打印机') # 执行打印 if self.print_pdf(printer_config, pdf_data): wo.production_id.product_id.is_print_program = True _logger.info(f"工单 {wo.name} 的PDF已成功打印") except Exception as e: _logger.error(f'打印配置错误: {str(e)}') class ProductTemplate(models.Model): _inherit = 'product.template' is_print_program = fields.Boolean(string='是否打印程序', default=False)