Accept Merge Request #2007: (feature/6694 -> develop)

Merge Request: 增加工单下发时打印编程文件pdf的功能

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2007?initial=true
This commit is contained in:
胡尧
2025-04-17 13:18:03 +08:00
committed by Coding
16 changed files with 593 additions and 11 deletions

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import models

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
{
'name': '机企猫 报工系统API',
'version': '1.0.0',
'summary': """ 机企猫 报工系统API """,
'author': '机企猫',
'website': 'https://xt.sf.jikimo.com',
'category': 'sf',
'depends': ['base', 'sf_maintenance', 'jikimo_mini_program'],
'data': [
],
'application': True,
'installable': True,
'auto_install': False,
'license': 'LGPL-3',
}

View File

@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import main

View File

@@ -0,0 +1,42 @@
import json
from odoo import http
from odoo.http import request
from odoo.addons.sf_machine_connect.models.ftp_operate import transfer_nc_files
class MainController(http.Controller):
@http.route('/api/manual_download_program', type='json', methods=['POST'], auth='wechat_token', cors='*')
def manual_download_program(self):
"""
人工线下加工传输编程文件
"""
data = json.loads(request.httprequest.data)
maintenance_equipment_name = data.get('maintenance_equipment_name')
model_id = data.get('model_id')
if not maintenance_equipment_name or not model_id:
return {'code': 400, 'message': '参数错误'}
maintenance_equipment = request.env['maintenance.equipment'].sudo().search([('name', '=', maintenance_equipment_name)], limit=1)
if not maintenance_equipment:
return {'code': 400, 'message': '机床不存在'}
ftp_resconfig = request.env['res.config.settings'].sudo().get_values()
source_ftp_info = {
'host': ftp_resconfig['ftp_host'],
'port': int(ftp_resconfig['ftp_port']),
'username': ftp_resconfig['ftp_user'],
'password': ftp_resconfig['ftp_password']
}
target_ftp_info = {
'host': maintenance_equipment.ftp_host,
'port': int(maintenance_equipment.ftp_port),
'username': maintenance_equipment.ftp_username,
'password': maintenance_equipment.ftp_password
}
# 传输nc文件
if transfer_nc_files(
source_ftp_info,
target_ftp_info,
'/' + str(model_id),
'/home/jikimo/testdir'):
return {'code': 200, 'message': 'success'}
else:
return {'code': 500, 'message': '传输失败'}

View File

@@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View File

@@ -8,6 +8,7 @@ class Printer(models.Model):
name = fields.Char(string='名称', required=True) name = fields.Char(string='名称', required=True)
ip_address = fields.Char(string='IP 地址', required=True) ip_address = fields.Char(string='IP 地址', required=True)
port = fields.Integer(string='端口', default=9100) port = fields.Integer(string='端口', default=9100)
type = fields.Selection([('zpl', 'ZPL'), ('normal', '普通')], string='类型', default='zpl')
class TableStyle(models.Model): class TableStyle(models.Model):

View File

@@ -2,7 +2,16 @@
import time, datetime import time, datetime
import hashlib import hashlib
from odoo import models from odoo import models
from typing import Optional
import socket 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): class Common(models.Model):
_name = 'sf.sync.common' _name = 'sf.sync.common'
@@ -92,3 +101,120 @@ class PrintingUtils(models.AbstractModel):
# host = "192.168.50.110" # 可以作为参数传入,或者在此配置 # host = "192.168.50.110" # 可以作为参数传入,或者在此配置
# port = 9100 # 可以作为参数传入,或者在此配置 # port = 9100 # 可以作为参数传入,或者在此配置
self.send_to_printer(host, port, zpl_code) 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', 14) # 增大字体大小到14pt
else:
# 如果没有找到中文字体,使用默认字体
c.setFont('Helvetica', 14)
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", 14) # 准确计算文字宽度
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)

View File

@@ -9,6 +9,7 @@
<field name="name"/> <field name="name"/>
<field name="ip_address"/> <field name="ip_address"/>
<field name="port"/> <field name="port"/>
<field name="type"/>
<!-- 其他字段... --> <!-- 其他字段... -->
</tree> </tree>
</field> </field>
@@ -24,6 +25,7 @@
<field name="name"/> <field name="name"/>
<field name="ip_address"/> <field name="ip_address"/>
<field name="port"/> <field name="port"/>
<field name="type"/>
</group> </group>
</sheet> </sheet>
</form> </form>

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging import logging
from ftplib import FTP import os
from ftplib import FTP, error_perm
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -52,8 +53,8 @@ class FtpController:
print(self.username, self.port, self.host, self.password) print(self.username, self.port, self.host, self.password)
ftp = FTP_P() ftp = FTP_P()
_logger.info("===================connect==================") _logger.info("===================connect==================")
# self.ftp.set_debuglevel(2) #打开调试级别2显示详细信息 # ftp.set_debuglevel(2) #打开调试级别2显示详细信息
ftp.set_pasv(0) # 0主动模式 1 #被动模式 # ftp.set_pasv(1) # 0主动模式 1 #被动模式
try: try:
ftp.connect(self.host, self.port) ftp.connect(self.host, self.port)
ftp.login(self.username, self.password) ftp.login(self.username, self.password)
@@ -128,3 +129,126 @@ class FtpController:
:return: :return:
""" """
self.ftp.delete(delpath) self.ftp.delete(delpath)
def transfer_nc_files(source_ftp_info, target_ftp_info, source_dir, target_dir, keep_dir=False):
"""
从源FTP服务器下载所有.nc文件并上传到目标FTP服务器,保持目录结构
Args:
source_ftp_info: dict, 源FTP连接信息 {host, port, username, password}
target_ftp_info: dict, 目标FTP连接信息 {host, port, username, password}
source_dir: str, 源FTP上的起始目录
target_dir: str, 目标FTP上的目标目录
keep_dir: bool, 是否保持目录结构,默认False
"""
try:
# 连接源FTP
source_ftp = FtpController(
source_ftp_info['host'],
source_ftp_info['port'],
source_ftp_info['username'],
source_ftp_info['password']
)
source_ftp.ftp.set_pasv(1)
# 连接目标FTP
target_ftp = FtpController(
target_ftp_info['host'],
target_ftp_info['port'],
target_ftp_info['username'],
target_ftp_info['password']
)
source_ftp.ftp.set_pasv(1)
# 递归遍历源目录
def traverse_dir(current_dir, relative_path=''):
source_ftp.ftp.cwd(current_dir)
file_list = source_ftp.ftp.nlst()
for item in file_list:
try:
# 尝试进入目录
source_ftp.ftp.cwd(f"{current_dir}/{item}")
# 如果成功则是目录
new_relative_path = os.path.join(relative_path, item)
# 在目标FTP创建对应目录
try:
if keep_dir:
target_ftp.ftp.mkd(f"{target_dir}/{new_relative_path}")
except:
pass # 目录可能已存在
# 递归遍历子目录
traverse_dir(f"{current_dir}/{item}", new_relative_path)
source_ftp.ftp.cwd('..')
except:
# 如果是.nc文件则传输
if item.lower().endswith('.nc'):
# 下载到临时文件
temp_path = f"/tmp/{item}"
with open(temp_path, 'wb') as f:
source_ftp.ftp.retrbinary(f'RETR {item}', f.write)
# 上传到目标FTP对应目录
if keep_dir:
target_path = f"{target_dir}/{relative_path}/{item}"
else:
target_path = f"{target_dir}/{item}"
with open(temp_path, 'rb') as f:
target_ftp.ftp.storbinary(f'STOR {target_path}', f)
# 删除临时文件
os.remove(temp_path)
logging.info(f"已传输文件: {item}")
# 清空目标目录下的所有内容
try:
target_ftp.ftp.cwd(target_dir)
files = target_ftp.ftp.nlst()
for f in files:
try:
# 尝试删除文件
target_ftp.ftp.delete(f)
except:
try:
# 如果删除失败,可能是目录,递归删除目录
def remove_dir(path):
target_ftp.ftp.cwd(path)
sub_files = target_ftp.ftp.nlst()
for sf in sub_files:
try:
target_ftp.ftp.delete(sf)
except:
remove_dir(f"{path}/{sf}")
target_ftp.ftp.cwd('..')
target_ftp.ftp.rmd(path)
remove_dir(f"{target_dir}/{f}")
except:
logging.error(f"无法删除 {f}")
pass
logging.info(f"已清空目标目录 {target_dir}")
except Exception as e:
logging.error(f"清空目标目录失败: {str(e)}")
return False
# 开始遍历
traverse_dir(source_dir)
logging.info("所有.nc文件传输完成")
return True
except Exception as e:
logging.error(f"传输过程出错: {str(e)}")
return False
finally:
# 关闭FTP连接
try:
source_ftp.ftp.quit()
target_ftp.ftp.quit()
except:
pass

View File

@@ -4,3 +4,4 @@ from . import sf_maintenance_oee
from . import sf_maintenance_logs from . import sf_maintenance_logs
from . import sf_equipment_maintenance_standards from . import sf_equipment_maintenance_standards
from . import sf_maintenance_requests from . import sf_maintenance_requests
from . import maintenance_printer

View File

@@ -0,0 +1,92 @@
import qrcode
import base64
from io import BytesIO
from odoo import models, fields, api
class MaintenanceEquipment(models.Model):
_name = 'maintenance.equipment'
_inherit = ['maintenance.equipment', 'printing.utils']
qr_code_image = fields.Binary(string='二维码', compute='_generate_qr_code')
@api.depends('name')
def _generate_qr_code(self):
for record in self:
# Generate QR code
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(record.name)
qr.make(fit=True)
qr_image = qr.make_image(fill_color="black", back_color="white")
# Encode the image data in base64
image_stream = BytesIO()
qr_image.save(image_stream, format="PNG")
encoded_image = base64.b64encode(image_stream.getvalue())
record.qr_code_image = encoded_image
def print_single_method(self):
print('self.name========== %s' % self.name)
self.ensure_one()
qr_code_data = self.qr_code_image
if not qr_code_data:
raise UserError("没有找到二维码数据。")
maintenance_equipment_name = self.name
# host = "192.168.50.110" # 可以根据实际情况修改
# port = 9100 # 可以根据实际情况修改
# 获取默认打印机配置
printer_config = self.env['printer.configuration'].sudo().search([('model', '=', self._name)], limit=1)
if not printer_config:
raise UserError('请先配置打印机')
host = printer_config.printer_id.ip_address
port = printer_config.printer_id.port
self.print_qr_code(maintenance_equipment_name, host, port)
def generate_zpl_code(self, code):
"""生成ZPL代码用于打印二维码标签
Args:
code: 需要编码的内容
Returns:
str: ZPL指令字符串
"""
zpl_code = "^XA\n" # 开始ZPL格式
# 设置打印参数
zpl_code += "^LH0,0\n" # 设置标签起始位置
zpl_code += "^CI28\n" # 设置中文编码
zpl_code += "^PW400\n" # 设置打印宽度为400点
zpl_code += "^LL300\n" # 设置标签长度为300点
# 打印标题
zpl_code += "^FO10,20\n" # 设置标题位置
zpl_code += "^A0N,30,30\n" # 设置字体大小
zpl_code += "^FD机床二维码^FS\n" # 打印标题文本
# 打印二维码
zpl_code += "^FO50,60\n" # 设置二维码位置
zpl_code += f"^BQN,2,8\n" # 设置二维码参数:模式2,放大倍数8
zpl_code += f"^FDLA,{code}^FS\n" # 二维码内容
# 打印编码文本
zpl_code += "^FO50,220\n" # 设置编码文本位置
zpl_code += "^A0N,25,25\n" # 设置字体大小
zpl_code += f"^FD编码: {code}^FS\n" # 打印编码文本
# 打印日期
zpl_code += "^FO50,260\n"
zpl_code += "^A0N,20,20\n"
zpl_code += f"^FD打印日期: {fields.Date.today()}^FS\n"
zpl_code += "^PQ1\n" # 打印1份
zpl_code += "^XZ\n" # 结束ZPL格式
return zpl_code

View File

@@ -826,6 +826,11 @@ class SfMaintenanceEquipment(models.Model):
image_lq_id = fields.Many2many('maintenance.equipment.image', 'equipment_lq_id', string='冷却方式', image_lq_id = fields.Many2many('maintenance.equipment.image', 'equipment_lq_id', string='冷却方式',
domain="[('type', '=', '冷却方式')]") domain="[('type', '=', '冷却方式')]")
ftp_host = fields.Char('FTP 主机')
ftp_port = fields.Char('FTP 端口')
ftp_username = fields.Char('FTP 用户名')
ftp_password = fields.Char('FTP 密码')
class SfRobotAxisNum(models.Model): class SfRobotAxisNum(models.Model):
_name = 'sf.robot.axis.num' _name = 'sf.robot.axis.num'

View File

@@ -1053,6 +1053,26 @@
</page> </page>
</xpath> </xpath>
<xpath expr="//group/field[@name='location']" position="after">
<field name="qr_code_image" widget="image" readonly="1" attrs="{'invisible': [('equipment_type', '!=', '机床')]}" />
<label for="print_single_method"/>
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
<button type="object" class="oe_highlight" name='print_single_method' string="打印机床二维码"
attrs="{'invisible': [('equipment_type', '!=', '机床')]}"/>
</div>
</xpath>
<xpath expr="//page[@name='maintenance']" position="after">
<page name="network_config" string="网络配置" attrs="{'invisible': [('equipment_type', '!=', '机床')]}" >
<group>
<group string="ftp配置">
<field name="ftp_host" string="主机"/>
<field name="ftp_port" string="端口"/>
<field name="ftp_username" string="用户名"/>
<field name="ftp_password" string="密码" password="True"/>
</group>
</group>
</page>
</xpath>
</data> </data>
</field> </field>
</record> </record>

View File

@@ -16,4 +16,5 @@ from . import sf_production_common
from . import sale_order from . import sale_order
from . import quick_easy_order from . import quick_easy_order
from . import purchase_order from . import purchase_order
from . import quality_check from . import quality_check
from . import workorder_printer

View File

@@ -0,0 +1,134 @@
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)

View File

@@ -8,6 +8,7 @@ from odoo.http import request
from odoo.addons.sf_base.controllers.controllers import MultiInheritController from odoo.addons.sf_base.controllers.controllers import MultiInheritController
class Sf_Mrs_Connect(http.Controller, MultiInheritController): class Sf_Mrs_Connect(http.Controller, MultiInheritController):
@http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, @http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@@ -22,6 +23,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
try: try:
res = {'status': 1, 'message': '成功'} res = {'status': 1, 'message': '成功'}
datas = request.httprequest.data datas = request.httprequest.data
model_id = None
ret = json.loads(datas) ret = json.loads(datas)
ret = json.loads(ret['result']) ret = json.loads(ret['result'])
logging.info('下发编程单:%s' % ret) logging.info('下发编程单:%s' % ret)
@@ -57,6 +59,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no']) res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no'])
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
for production in productions: for production in productions:
model_id = production.product_id.model_id # 一个编程单的制造订单对应同一个模型
production.write({'programming_state': '已编程', 'work_state': '已编程', 'is_rework': False}) production.write({'programming_state': '已编程', 'work_state': '已编程', 'is_rework': False})
for panel in ret['processing_panel'].split(','): for panel in ret['processing_panel'].split(','):
# 查询状态为进行中且工序类型为CNC加工的工单 # 查询状态为进行中且工序类型为CNC加工的工单
@@ -83,19 +86,23 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
# panel) # panel)
program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel) program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel)
files_panel = os.listdir(program_path_tmp_panel) files_panel = os.listdir(program_path_tmp_panel)
panel_file_path = ''
if files_panel: if files_panel:
for file in files_panel: for file in files_panel:
file_extension = os.path.splitext(file)[1] file_extension = os.path.splitext(file)[1]
if file_extension.lower() == '.pdf': if file_extension.lower() == '.pdf':
panel_file_path = os.path.join(program_path_tmp_panel, file) panel_file_path = os.path.join(program_path_tmp_panel, file)
logging.info('panel_file_path:%s' % panel_file_path) logging.info('panel_file_path:%s' % panel_file_path)
cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
pre_workorder = productions.workorder_ids.filtered( # 向编程单中添加二维码
lambda ap: ap.routing_type in ['装夹预调', '人工线下加工'] and ap.state not in ['done', 'rework' request.env['printing.utils'].add_qr_code_to_pdf(panel_file_path, model_id, "扫码获取工单")
'cancel'] and ap.processing_panel == panel) cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
if pre_workorder: pre_workorder = productions.workorder_ids.filtered(
pre_workorder.write( lambda ap: ap.routing_type in ['装夹预调', '人工线下加工'] and ap.state not in ['done', 'rework'
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) 'cancel'] and ap.processing_panel == panel)
if pre_workorder:
pre_workorder.write(
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
productions.write({'programming_state': '已编程', 'work_state': '已编程'}) productions.write({'programming_state': '已编程', 'work_state': '已编程'})
productions.filtered(lambda p: p.production_type == '人工线下加工').write({'manual_quotation': True}) productions.filtered(lambda p: p.production_type == '人工线下加工').write({'manual_quotation': True})
logging.info('已更新制造订单编程状态:%s' % productions.ids) logging.info('已更新制造订单编程状态:%s' % productions.ids)
@@ -268,3 +275,6 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
request.cr.rollback() request.cr.rollback()
logging.info('get_cnc_processing_create error:%s' % e) logging.info('get_cnc_processing_create error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)