diff --git a/sf_base/commons/common.py b/sf_base/commons/common.py index b423e160..683e8ece 100644 --- a/sf_base/commons/common.py +++ b/sf_base/commons/common.py @@ -2,7 +2,7 @@ import time, datetime import hashlib from odoo import models - +import socket class Common(models.Model): _name = 'sf.sync.common' @@ -29,3 +29,66 @@ class Common(models.Model): d = dt + datetime.timedelta(hours=8) nTime = d.strftime("%Y-%m-%d %H:%M:%S") return nTime + + +class PrintingUtils(models.AbstractModel): + _name = 'printing.utils' + _description = 'Utility class for printing functionalities' + + def generate_zpl_code(self, code): + # 实现生成ZPL代码的逻辑 + # 初始化ZPL代码字符串 + zpl_code = "^XA\n" + zpl_code += "^CW1,E:SIMSUN.TTF^FS\n" + zpl_code += "^CI28\n" + + # 设置二维码位置 + zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行 + zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n" + + # 设置资产编号文本位置 + zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行 + zpl_code += "^A1N,45,45^FD编码名称: ^FS\n" + + # 设置{code}文本位置 + # 假设{code}文本需要位于资产编号和二维码下方,中间位置 + # 设置{code}文本位置并启用自动换行 + zpl_code += "^FO300,120\n" # {code}文本的起始位置 + zpl_code += "^FB500,4,0,L,0\n" # 定义一个宽度为500点的文本框,最多4行,左对齐 + zpl_code += f"^A1N,40,40^FD{code}^FS\n" + + # 在{code}文本框周围绘制线框 + # 假设线框的外部尺寸为宽度500点,高度200点 + # zpl_code += "^FO300,110^GB500,200,2^FS\n" # 绘制线框,边框粗细为2点 + + zpl_code += "^PQ1,0,1,Y\n" + zpl_code += "^XZ\n" + return zpl_code + + def send_to_printer(self, host, port, zpl_code): + + # 实现发送ZPL代码到打印机的逻辑 + # 将ZPL代码转换为字节串 + print('zpl_code', zpl_code) + zpl_bytes = zpl_code.encode('utf-8') + print(zpl_bytes) + + # 创建socket对象 + mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + mysocket.connect((host, port)) # 连接到打印机 + mysocket.send(zpl_bytes) # 发送ZPL代码 + print("ZPL code sent to printer successfully.") + except Exception as e: + print(f"Error with the connection: {e}") + finally: + mysocket.close() # 关闭连接 + + def print_qr_code(self, lot_name, host, port): + # 实现打印二维码的逻辑 + # 这里需要传入 lot_name 参数,因为我们不能直接访问 self.lot_id.name + zpl_code = self.generate_zpl_code(lot_name) + # 发送ZPL代码到打印机 + # host = "192.168.50.110" # 可以作为参数传入,或者在此配置 + # port = 9100 # 可以作为参数传入,或者在此配置 + self.send_to_printer(host, port, zpl_code) diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index bfce3b07..bdf4ce32 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -4,13 +4,12 @@ import logging import base64 import qrcode import io -import socket import requests from odoo import api, fields, models, _ from odoo.osv import expression -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError class SfLocation(models.Model): @@ -414,7 +413,8 @@ class ShelfLocation(models.Model): class Sf_stock_move_line(models.Model): - _inherit = 'stock.move.line' + _name = 'stock.move.line' + _inherit = ['stock.move.line', 'printing.utils'] current_location_id = fields.Many2one( 'sf.shelf.location', string='当前货位', compute='_compute_current_location_id', store=True) @@ -465,89 +465,120 @@ class Sf_stock_move_line(models.Model): else: record.lot_qr_code = False - def generate_zpl_code(self, code): - # 初始化ZPL代码字符串 - zpl_code = "^XA\n" - zpl_code += "^CW1,E:SIMSUN.TTF^FS\n" - zpl_code += "^CI28\n" - - # 设置二维码位置 - zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行 - zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n" - - # 设置资产编号文本位置 - zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行 - zpl_code += "^A1N,45,45^FD编码名称: ^FS\n" - - # 设置{code}文本位置 - # 假设{code}文本需要位于资产编号和二维码下方,中间位置 - # 设置{code}文本位置并启用自动换行 - zpl_code += "^FO300,120\n" # {code}文本的起始位置 - zpl_code += "^FB500,4,0,L,0\n" # 定义一个宽度为500点的文本框,最多4行,左对齐 - zpl_code += f"^A1N,40,40^FD{code}^FS\n" - - # 在{code}文本框周围绘制线框 - # 假设线框的外部尺寸为宽度500点,高度200点 - # zpl_code += "^FO300,110^GB500,200,2^FS\n" # 绘制线框,边框粗细为2点 - - zpl_code += "^PQ1,0,1,Y\n" - zpl_code += "^XZ\n" - return zpl_code - - def send_to_printer(self, host, port, zpl_code): - # 将ZPL代码转换为字节串 - print('zpl_code', zpl_code) - zpl_bytes = zpl_code.encode('utf-8') - print(zpl_bytes) - - # 创建socket对象 - mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - mysocket.connect((host, port)) # 连接到打印机 - mysocket.send(zpl_bytes) # 发送ZPL代码 - print("ZPL code sent to printer successfully.") - except Exception as e: - print(f"Error with the connection: {e}") - finally: - mysocket.close() # 关闭连接 - - def print_qr_code(self): - self.ensure_one() # 确保这个方法只为一个记录调用 - # if not self.lot_id: - # raise UserError("没有找到序列号。") - # 假设_lot_qr_code方法已经生成了二维码并保存在字段中 + def print_single_method(self): + self.ensure_one() qr_code_data = self.lot_qr_code if not qr_code_data: raise UserError("没有找到二维码数据。") - # 生成ZPL代码 - zpl_code = self.generate_zpl_code(self.lot_id.name) - # 设置打印机的IP地址和端口号 - host = "192.168.50.110" - port = 9100 - # 发送ZPL代码到打印机 - self.send_to_printer(host, port, zpl_code) + lot_name = self.lot_name + host = "192.168.50.110" # 可以根据实际情况修改 + port = 9100 # 可以根据实际情况修改 + self.print_qr_code(lot_name, host, port) - # # 生成下载链接或直接触发下载 - # # 此处的实现依赖于你的具体需求,以下是触发下载的一种示例 - # attachment = self.env['ir.attachment'].sudo().create({ - # 'datas': self.lot_qr_code, - # 'type': 'binary', - # 'description': '二维码图片', - # 'name': self.lot_name + '.png', - # # 'res_id': invoice.id, - # # 'res_model': 'stock.picking', - # 'public': True, - # 'mimetype': 'application/x-png', - # # 'model_name': 'stock.picking', - # }) - # # 返回附件的下载链接 - # download_url = '/web/content/%s?download=true' % attachment.id + # 返回当前wizard页面 # base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') # return { # 'type': 'ir.actions.act_url', # 'url': str(base_url) + download_url, # 'target': 'self', # } + # 获取当前wizard的视图ID或其他标识信息 + view_id = self.env.context.get('view_id') + # 构造返回wizard页面的action字典 + action = { + 'type': 'ir.actions.act_window', + 'name': '返回 Wizard', + 'res_model': 'stock.move', # 替换为你的wizard模型名称 + 'view_mode': 'form', + 'view_id': view_id, # 如果需要基于特定的视图返回 + 'target': 'new', # 如果需要在新的窗口或标签页打开 + 'res_id': self.id, # 如果你想要返回当前记录的视图 + } + return action + + # def generate_zpl_code(self, code): + # # 初始化ZPL代码字符串 + # zpl_code = "^XA\n" + # zpl_code += "^CW1,E:SIMSUN.TTF^FS\n" + # zpl_code += "^CI28\n" + # + # # 设置二维码位置 + # zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行 + # zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n" + # + # # 设置资产编号文本位置 + # zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行 + # zpl_code += "^A1N,45,45^FD编码名称: ^FS\n" + # + # # 设置{code}文本位置 + # # 假设{code}文本需要位于资产编号和二维码下方,中间位置 + # # 设置{code}文本位置并启用自动换行 + # zpl_code += "^FO300,120\n" # {code}文本的起始位置 + # zpl_code += "^FB500,4,0,L,0\n" # 定义一个宽度为500点的文本框,最多4行,左对齐 + # zpl_code += f"^A1N,40,40^FD{code}^FS\n" + # + # # 在{code}文本框周围绘制线框 + # # 假设线框的外部尺寸为宽度500点,高度200点 + # # zpl_code += "^FO300,110^GB500,200,2^FS\n" # 绘制线框,边框粗细为2点 + # + # zpl_code += "^PQ1,0,1,Y\n" + # zpl_code += "^XZ\n" + # return zpl_code + # + # def send_to_printer(self, host, port, zpl_code): + # # 将ZPL代码转换为字节串 + # print('zpl_code', zpl_code) + # zpl_bytes = zpl_code.encode('utf-8') + # print(zpl_bytes) + # + # # 创建socket对象 + # mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # try: + # mysocket.connect((host, port)) # 连接到打印机 + # mysocket.send(zpl_bytes) # 发送ZPL代码 + # print("ZPL code sent to printer successfully.") + # except Exception as e: + # print(f"Error with the connection: {e}") + # finally: + # mysocket.close() # 关闭连接 + # + # def print_qr_code(self): + # self.ensure_one() # 确保这个方法只为一个记录调用 + # # if not self.lot_id: + # # raise UserError("没有找到序列号。") + # # 假设_lot_qr_code方法已经生成了二维码并保存在字段中 + # qr_code_data = self.lot_qr_code + # if not qr_code_data: + # raise UserError("没有找到二维码数据。") + # # 生成ZPL代码 + # zpl_code = self.generate_zpl_code(self.lot_id.name) + # # 设置打印机的IP地址和端口号 + # host = "192.168.50.110" + # port = 9100 + # # 发送ZPL代码到打印机 + # self.send_to_printer(host, port, zpl_code) + # + # # # 生成下载链接或直接触发下载 + # # # 此处的实现依赖于你的具体需求,以下是触发下载的一种示例 + # # attachment = self.env['ir.attachment'].sudo().create({ + # # 'datas': self.lot_qr_code, + # # 'type': 'binary', + # # 'description': '二维码图片', + # # 'name': self.lot_name + '.png', + # # # 'res_id': invoice.id, + # # # 'res_model': 'stock.picking', + # # 'public': True, + # # 'mimetype': 'application/x-png', + # # # 'model_name': 'stock.picking', + # # }) + # # # 返回附件的下载链接 + # # download_url = '/web/content/%s?download=true' % attachment.id + # # base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + # # return { + # # 'type': 'ir.actions.act_url', + # # 'url': str(base_url) + download_url, + # # 'target': 'self', + # # } # # # 定义一个方法,用于根据序列号生成二维码 # # @api.depends('lot_id') @@ -683,6 +714,17 @@ class Sf_stock_move_line(models.Model): class SfStockPicking(models.Model): _inherit = 'stock.picking' + check_in = fields.Char(string='查询是否为入库单', compute='_check_is_in') + + @api.depends('name') + def _check_is_in(self): + """ + 判断是否为出库单 + """ + if self.name: + is_check_in = self.name.split('/') + self.check_in = is_check_in[1] + def button_validate(self): """ 重写验证方法,当验证时意味着调拨单已经完成,已经移动到了目标货位,所以需要将当前货位的状态改为空闲 @@ -695,6 +737,20 @@ class SfStockPicking(models.Model): line.current_location_id.location_status = '空闲' return res + # def print_all_barcode(self): + # """ + # 打印所有编码 + # """ + # print('================') + # for record in self.move_ids_without_package: + # print('record', record) + # print('record.move_line_ids', record.move_line_ids) + # + # # record.move_line_ids.print_qr_code() + # + # print('record.move_line_ids.lot_id', record.move_line_ids.lot_id) + # print('record.move_line_ids.lot_id.name', record.move_line_ids.lot_id.name) + class SfProcurementGroup(models.Model): _inherit = 'procurement.group' @@ -868,7 +924,8 @@ class SfStockScrap(models.Model): class CustomStockMove(models.Model): - _inherit = 'stock.move' + _name = 'stock.move' + _inherit = ['stock.move', 'printing.utils'] def action_assign_serial_show_details(self): # 首先执行原有逻辑 @@ -897,3 +954,24 @@ class CustomStockMove(models.Model): binary_data = buffer.getvalue() data = base64.b64encode(binary_data).decode() # 确保返回的是字符串形式的数据 return data + + def print_all_barcode(self): + """ + 打印所有编码 + """ + print('================') + for record in self.move_line_ids: + print('record', record) + if not record.lot_name: + continue + record.ensure_one() + # qr_code_data = record.lot_qr_code + # if not qr_code_data: + # raise UserError("没有找到二维码数据。") + lot_name = record.lot_name + # todo 待控制 + if not lot_name: + raise ValidationError("请先分配序列号") + host = "192.168.50.110" # 可以根据实际情况修改 + port = 9100 # 可以根据实际情况修改 + record.print_qr_code(lot_name, host, port) diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml index e7d63d67..77021663 100644 --- a/sf_warehouse/views/change_stock_move_views.xml +++ b/sf_warehouse/views/change_stock_move_views.xml @@ -65,7 +65,7 @@ -