打印相关抽象为公用类

This commit is contained in:
mgw
2024-03-20 11:28:58 +08:00
parent 0363f8c8a3
commit f38c062804
3 changed files with 239 additions and 79 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -65,7 +65,7 @@
<field name="arch" type="xml">
<xpath expr="//field[@name='product_uom_id']" position="after">
<field name="lot_qr_code" widget="image"/>
<button name="print_qr_code" string="打印编码" type="object" class="oe_highlight"/>
<button name="print_single_method" string="打印编码" type="object" class="oe_highlight"/>
</xpath>
</field>
</record>
@@ -103,6 +103,11 @@
groups="sf_warehouse.group_sf_stock_user" data-hotkey="k"/>
</xpath>
<!-- <xpath expr="//form//sheet//notebook//page//field[@name='move_ids_without_package']" position="before"> -->
<!-- <field name="check_in" invisible="True"/> -->
<!-- <button name="print_all_barcode" string="打印所有编码" type="object" attrs="{'invisible': [('check_in', '!=', 'IN')]}"/> -->
<!-- </xpath> -->
</field>
</record>
@@ -135,5 +140,19 @@
</field>
</record>
<record id="sf_view_stock_move_operations" model="ir.ui.view">
<field name="name">sf.stock.move.operations.form</field>
<field name="model">stock.move</field>
<field name="inherit_id" ref="stock.view_stock_move_operations"/>
<field name="arch" type="xml">
<!-- <xpath expr="//form//field[@name='move_line_ids']" position="before"> -->
<!-- <button name="print_all_barcode" type="object" string="打印所有编码"/> -->
<!-- </xpath> -->
<xpath expr="//form//field[@name='product_id']" position="before">
<button name="print_all_barcode" type="object" string="打印所有编码" class="oe_highlight"/> -->
</xpath>
</field>
</record>
</data>
</odoo>