221 lines
8.7 KiB
Python
221 lines
8.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
import time, datetime
|
||
import hashlib
|
||
from odoo import models
|
||
from typing import Optional
|
||
import socket
|
||
import os
|
||
import logging
|
||
import qrcode
|
||
from reportlab.pdfgen import canvas
|
||
from reportlab.lib.units import inch
|
||
from PyPDF2 import PdfFileReader, PdfFileWriter
|
||
from reportlab.pdfbase import pdfmetrics
|
||
from reportlab.pdfbase.ttfonts import TTFont
|
||
|
||
class Common(models.Model):
|
||
_name = 'sf.sync.common'
|
||
_description = u'公用类'
|
||
|
||
def get_headers(self, token, secret_key):
|
||
'''
|
||
获取requests中的heardes参数
|
||
'''
|
||
timestamp = int(time.time())
|
||
check_str = '%s%s%s' % (token, timestamp, secret_key)
|
||
check_sf_str = hashlib.sha1(check_str.encode('utf-8')).hexdigest()
|
||
headers = {'TOKEN': token,
|
||
'TIMESTAMP': str(timestamp),
|
||
'checkstr': check_sf_str}
|
||
return headers
|
||
|
||
def get_add_time(self, parse_time):
|
||
"""
|
||
把时间增加8小时
|
||
:return:
|
||
"""
|
||
dt = datetime.datetime.strptime(parse_time, "%Y-%m-%d %H:%M:%S")
|
||
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 += "^FB400,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)
|
||
|
||
|
||
def add_qr_code_to_pdf(self, pdf_path:str, content:str, buttom_text:Optional[str]=False):
|
||
"""
|
||
在PDF文件中添加二维码
|
||
:param pdf_path: PDF文件路径
|
||
:param content: 二维码内容
|
||
:param buttom_text: 二维码下方文字
|
||
:return: 是否成功
|
||
"""
|
||
if not os.path.exists(pdf_path):
|
||
logging.warning(f'PDF文件不存在: {pdf_path}')
|
||
return False
|
||
|
||
# 生成二维码
|
||
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
||
qr.add_data(str(content))
|
||
qr.make(fit=True)
|
||
qr_img = qr.make_image(fill_color="black", back_color="white")
|
||
|
||
# 保存二维码为临时文件
|
||
qr_temp_path = '/tmp/qr_temp.png'
|
||
qr_img.save(qr_temp_path)
|
||
|
||
# 创建一个临时PDF文件路径
|
||
output_temp_path = '/tmp/output_temp.pdf'
|
||
|
||
try:
|
||
# 使用reportlab创建一个新的PDF
|
||
|
||
|
||
# 注册中文字体
|
||
font_paths = [
|
||
"/usr/share/fonts/windows/simsun.ttc", # Windows系统宋体
|
||
"c:/windows/fonts/simsun.ttc", # Windows系统宋体另一个位置
|
||
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", # Linux Droid字体
|
||
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", # 文泉驿正黑
|
||
"/usr/share/fonts/chinese/TrueType/simsun.ttc", # 某些Linux发行版位置
|
||
]
|
||
|
||
font_found = False
|
||
for font_path in font_paths:
|
||
if os.path.exists(font_path):
|
||
try:
|
||
pdfmetrics.registerFont(TTFont('SimSun', font_path))
|
||
font_found = True
|
||
break
|
||
except:
|
||
continue
|
||
|
||
# 读取原始PDF
|
||
with open(pdf_path, "rb") as original_file:
|
||
existing_pdf = PdfFileReader(original_file)
|
||
output = PdfFileWriter()
|
||
|
||
# 处理第一页
|
||
page = existing_pdf.getPage(0)
|
||
# 获取页面尺寸
|
||
page_width = float(page.mediaBox.getWidth())
|
||
page_height = float(page.mediaBox.getHeight())
|
||
|
||
# 创建一个新的PDF页面用于放置二维码
|
||
c = canvas.Canvas(output_temp_path, pagesize=(page_width, page_height))
|
||
|
||
# 设置字体
|
||
if font_found:
|
||
c.setFont('SimSun', 10) # 增大字体大小到14pt
|
||
else:
|
||
# 如果没有找到中文字体,使用默认字体
|
||
c.setFont('Helvetica', 10)
|
||
logging.warning("未找到中文字体,将使用默认字体")
|
||
|
||
# 在右下角绘制二维码,预留边距
|
||
qr_size = 1.5 * inch # 二维码大小为2英寸
|
||
margin = 0.1 * inch # 边距为0.4英寸
|
||
qr_y = margin + 20 # 将二维码向上移动一点,为文字留出空间
|
||
c.drawImage(qr_temp_path, page_width - qr_size - margin, qr_y, width=qr_size, height=qr_size)
|
||
|
||
if buttom_text:
|
||
# 在二维码下方绘制文字
|
||
text = buttom_text
|
||
text_width = c.stringWidth(text, "SimSun" if font_found else "Helvetica", 10) # 准确计算文字宽度
|
||
text_x = page_width - qr_size - margin + (qr_size - text_width) / 2 # 文字居中对齐
|
||
text_y = margin + 20 # 文字位置靠近底部
|
||
c.drawString(text_x, text_y, text)
|
||
|
||
c.save()
|
||
|
||
# 读取带有二维码的临时PDF
|
||
with open(output_temp_path, "rb") as qr_file:
|
||
qr_pdf = PdfFileReader(qr_file)
|
||
qr_page = qr_pdf.getPage(0)
|
||
|
||
# 合并原始页面和二维码页面
|
||
page.mergePage(qr_page)
|
||
output.addPage(page)
|
||
|
||
# 添加剩余的页面
|
||
for i in range(1, existing_pdf.getNumPages()):
|
||
output.addPage(existing_pdf.getPage(i))
|
||
|
||
# 保存最终的PDF到一个临时文件
|
||
final_temp_path = pdf_path + '.tmp'
|
||
with open(final_temp_path, "wb") as output_file:
|
||
output.write(output_file)
|
||
|
||
# 替换原始文件
|
||
os.replace(final_temp_path, pdf_path)
|
||
|
||
return True
|
||
|
||
finally:
|
||
# 清理临时文件
|
||
if os.path.exists(qr_temp_path):
|
||
os.remove(qr_temp_path)
|
||
if os.path.exists(output_temp_path):
|
||
os.remove(output_temp_path)
|
||
os.remove(output_temp_path) |