Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
This commit is contained in:
@@ -5,7 +5,7 @@ from odoo.addons.sf_machine_connect.models.ftp_operate import transfer_nc_files
|
|||||||
|
|
||||||
class MainController(http.Controller):
|
class MainController(http.Controller):
|
||||||
|
|
||||||
@http.route('/api/manual_download_program', type='json', methods=['POST'], auth='wechat_token', cors='*')
|
@http.route('/api/manual_download_program', type='json', methods=['POST'], auth='public', cors='*')
|
||||||
def manual_download_program(self):
|
def manual_download_program(self):
|
||||||
"""
|
"""
|
||||||
人工线下加工传输编程文件
|
人工线下加工传输编程文件
|
||||||
@@ -18,6 +18,11 @@ class MainController(http.Controller):
|
|||||||
maintenance_equipment = request.env['maintenance.equipment'].sudo().search([('name', '=', maintenance_equipment_name)], limit=1)
|
maintenance_equipment = request.env['maintenance.equipment'].sudo().search([('name', '=', maintenance_equipment_name)], limit=1)
|
||||||
if not maintenance_equipment:
|
if not maintenance_equipment:
|
||||||
return {'code': 400, 'message': '机床不存在'}
|
return {'code': 400, 'message': '机床不存在'}
|
||||||
|
# 获取刀具组
|
||||||
|
tool_groups_id = request.env['sf.tool.groups'].sudo().search([('equipment_ids', 'in', maintenance_equipment.id)], limit=1)
|
||||||
|
if not tool_groups_id:
|
||||||
|
return {'code': 400, 'message': '刀具组不存在'}
|
||||||
|
|
||||||
ftp_resconfig = request.env['res.config.settings'].sudo().get_values()
|
ftp_resconfig = request.env['res.config.settings'].sudo().get_values()
|
||||||
source_ftp_info = {
|
source_ftp_info = {
|
||||||
'host': ftp_resconfig['ftp_host'],
|
'host': ftp_resconfig['ftp_host'],
|
||||||
@@ -36,7 +41,8 @@ class MainController(http.Controller):
|
|||||||
source_ftp_info,
|
source_ftp_info,
|
||||||
target_ftp_info,
|
target_ftp_info,
|
||||||
'/' + str(model_id),
|
'/' + str(model_id),
|
||||||
'/home/jikimo/testdir'):
|
'/home/jikimo/testdir',
|
||||||
|
end_with=tool_groups_id.name + '-all.nc'):
|
||||||
return {'code': 200, 'message': 'success'}
|
return {'code': 200, 'message': 'success'}
|
||||||
else:
|
else:
|
||||||
return {'code': 500, 'message': '传输失败'}
|
return {'code': 500, 'message': '传输失败'}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<record model="ir.ui.view" id="mrs_production_process_parameter_tree">
|
<record model="ir.ui.view" id="mrs_production_process_parameter_tree">
|
||||||
<field name="model">sf.production.process.parameter</field>
|
<field name="model">sf.production.process.parameter</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="表面工艺可选参数" create="0" delete="0">
|
<tree string="工艺可选参数" create="0" delete="0">
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="gain_way"/>
|
<field name="gain_way"/>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<record model="ir.ui.view" id="mrs_production_process_parameter_form">
|
<record model="ir.ui.view" id="mrs_production_process_parameter_form">
|
||||||
<field name="model">sf.production.process.parameter</field>
|
<field name="model">sf.production.process.parameter</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="表面工艺可选参数" create="0" delete="0" >
|
<form string="工艺可选参数" create="0" delete="0" >
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<h1>
|
<h1>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
<record model="ir.ui.view" id="sf_production_process_category_form">
|
<record model="ir.ui.view" id="sf_production_process_category_form">
|
||||||
<field name="model">sf.production.process.category</field>
|
<field name="model">sf.production.process.category</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="表面工艺类别" create="0" edit="0" delete="1">
|
<form string="工艺类别" create="0" edit="0" delete="1">
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<h1>
|
<h1>
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="表面工艺">
|
<page string="工艺">
|
||||||
<field name='production_process_ids' widget="ony2many">
|
<field name='production_process_ids' widget="ony2many">
|
||||||
<tree editable="bottom">
|
<tree editable="bottom">
|
||||||
<field name="code" string="编码号" readonly="1" force_save="1"/>
|
<field name="code" string="编码号" readonly="1" force_save="1"/>
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
<record model="ir.ui.view" id="sf_production_process_category_tree">
|
<record model="ir.ui.view" id="sf_production_process_category_tree">
|
||||||
<field name="model">sf.production.process.category</field>
|
<field name="model">sf.production.process.category</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="表面工艺类别" default_order="sequence, id" create="0" edit="0" delete="1">
|
<tree string="工艺类别" default_order="sequence, id" create="0" edit="0" delete="1">
|
||||||
<field name="sequence" widget="handle" string="序号" readonly="1"/>
|
<field name="sequence" widget="handle" string="序号" readonly="1"/>
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
<field name="name" string="名称"/>
|
<field name="name" string="名称"/>
|
||||||
@@ -163,7 +163,7 @@
|
|||||||
<record model="ir.ui.view" id="sf_production_process_tree">
|
<record model="ir.ui.view" id="sf_production_process_tree">
|
||||||
<field name="model">sf.production.process</field>
|
<field name="model">sf.production.process</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="表面工艺" create="0" edit="0" delete="0">
|
<tree string="工艺" create="0" edit="0" delete="0">
|
||||||
<field name="sequence" string="加工顺序" readonly="1"/>
|
<field name="sequence" string="加工顺序" readonly="1"/>
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
<field name="name" string="名称"/>
|
<field name="name" string="名称"/>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<record model="ir.ui.view" id="sf_production_process_form">
|
<record model="ir.ui.view" id="sf_production_process_form">
|
||||||
<field name="model">sf.production.process</field>
|
<field name="model">sf.production.process</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="表面工艺" create="0" delete="0">
|
<form string="工艺" create="0" delete="0">
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<h1>
|
<h1>
|
||||||
@@ -395,7 +395,7 @@
|
|||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="sf_production_process" model="ir.actions.act_window">
|
<record id="sf_production_process" model="ir.actions.act_window">
|
||||||
<field name="name">表面工艺</field>
|
<field name="name">工艺</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">sf.production.process</field>
|
<field name="res_model">sf.production.process</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
@@ -414,13 +414,13 @@
|
|||||||
<!-- </record>-->
|
<!-- </record>-->
|
||||||
|
|
||||||
<record id="sf_production_process_category" model="ir.actions.act_window">
|
<record id="sf_production_process_category" model="ir.actions.act_window">
|
||||||
<field name="name">表面工艺类别</field>
|
<field name="name">工艺类别</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">sf.production.process.category</field>
|
<field name="res_model">sf.production.process.category</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrs_production_process_parameter_action" model="ir.actions.act_window">
|
<record id="mrs_production_process_parameter_action" model="ir.actions.act_window">
|
||||||
<field name="name">表面工艺可选参数</field>
|
<field name="name">工艺可选参数</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">sf.production.process.parameter</field>
|
<field name="res_model">sf.production.process.parameter</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
id="menu_sf_production_process"
|
id="menu_sf_production_process"
|
||||||
name="表面工艺"
|
name="工艺"
|
||||||
parent="menu_sf_production_process_1"
|
parent="menu_sf_production_process_1"
|
||||||
sequence="2"
|
sequence="2"
|
||||||
action="sf_production_process"
|
action="sf_production_process"
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
id="menu_sf_production_process_category"
|
id="menu_sf_production_process_category"
|
||||||
name="表面工艺类别"
|
name="工艺类别"
|
||||||
parent="menu_sf_production_process_1"
|
parent="menu_sf_production_process_1"
|
||||||
sequence="1"
|
sequence="1"
|
||||||
action="sf_production_process_category"
|
action="sf_production_process_category"
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
id="mrs_production_process_parameter_view"
|
id="mrs_production_process_parameter_view"
|
||||||
name="表面工艺可选参数"
|
name="工艺可选参数"
|
||||||
parent="menu_sf_production_process_1"
|
parent="menu_sf_production_process_1"
|
||||||
sequence="2"
|
sequence="2"
|
||||||
action="mrs_production_process_parameter_action"
|
action="mrs_production_process_parameter_action"
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
<record id="sequence_production_process_parameter" model="ir.sequence">
|
<record id="sequence_production_process_parameter" model="ir.sequence">
|
||||||
<field name="name">工艺可选参数编码序列</field>
|
<field name="name">工艺可选参数编码序列</field>
|
||||||
<field name="code">sf.production.process.parameter</field>
|
<field name="code">sf.production.process.parameter</field>
|
||||||
<field name="prefix">WKSP</field>
|
<field name="padding">3</field>
|
||||||
<field name="padding">9</field>
|
<field name="number_increment">1</field>
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -11,20 +11,23 @@ class SfProductionProcessParameter(models.Model):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
|
# if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
|
||||||
vals['code'] = self.env['ir.sequence'].next_by_code('sf.production.process.parameter') or '/'
|
# vals['code'] = '101'+self.routing_id.code +self.env['ir.sequence'].next_by_code('sf.production.process.parameter')
|
||||||
if not vals.get('process_id') and vals.get('routing_id'):
|
if not vals.get('process_id') and vals.get('routing_id'):
|
||||||
vals['gain_way'] = '外协'
|
vals['gain_way'] = '外协'
|
||||||
routing_id = self.env['mrp.routing.workcenter'].browse(vals.get('routing_id'))
|
routing_id = self.env['mrp.routing.workcenter'].browse(vals.get('routing_id'))
|
||||||
if routing_id.surface_technics_id:
|
if routing_id.surface_technics_id:
|
||||||
vals['process_id'] = routing_id.surface_technics_id.id
|
vals['process_id'] = routing_id.surface_technics_id.id
|
||||||
|
if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
|
||||||
|
vals['code'] = '101' + routing_id.code + self.env['ir.sequence'].next_by_code(
|
||||||
|
'sf.production.process.parameter')
|
||||||
obj = super(SfProductionProcessParameter, self).create(vals)
|
obj = super(SfProductionProcessParameter, self).create(vals)
|
||||||
return obj
|
return obj
|
||||||
def create_service_product(self):
|
def create_service_product(self):
|
||||||
service_categ = self.env.ref(
|
service_categ = self.env.ref(
|
||||||
'sf_dlm.product_category_surface_technics_sf').sudo()
|
'sf_dlm.product_category_surface_technics_sf').sudo()
|
||||||
|
|
||||||
product_name = f"{self.process_id.name}{self.name}"
|
product_name = f"{self.process_id.name}_{self.name}"
|
||||||
product_id = self.env['product.template'].search(
|
product_id = self.env['product.template'].search(
|
||||||
[("name", '=', product_name)])
|
[("name", '=', product_name)])
|
||||||
if product_id:
|
if product_id:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/>
|
attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/>
|
||||||
<field name="server_product_process_parameters_id" string="工艺参数"
|
<field name="server_product_process_parameters_id" string="工艺参数"
|
||||||
options="{'no_create': True}"
|
options="{'no_create': True}"
|
||||||
attrs="{'invisible': ['|',('categ_type', '!=', '表面工艺'),('categ_type', '=', False)]}"/>
|
attrs="{'invisible': ['|',('detailed_type', '!=', '服务'),('detailed_type', '=', False)]}"/>
|
||||||
<field name="cutting_tool_material_id" class="custom_required"
|
<field name="cutting_tool_material_id" class="custom_required"
|
||||||
options="{'no_create': True}"
|
options="{'no_create': True}"
|
||||||
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"
|
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ class FtpController:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def transfer_nc_files(source_ftp_info, target_ftp_info, source_dir, target_dir, keep_dir=False):
|
def transfer_nc_files(source_ftp_info, target_ftp_info, source_dir, target_dir, end_with='.nc', keep_dir=False):
|
||||||
"""
|
"""
|
||||||
从源FTP服务器下载所有.nc文件并上传到目标FTP服务器,保持目录结构
|
从源FTP服务器下载所有{end_with}结尾的文件并上传到目标FTP服务器,保持目录结构
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
source_ftp_info: dict, 源FTP连接信息 {host, port, username, password}
|
source_ftp_info: dict, 源FTP连接信息 {host, port, username, password}
|
||||||
@@ -184,7 +184,7 @@ def transfer_nc_files(source_ftp_info, target_ftp_info, source_dir, target_dir,
|
|||||||
source_ftp.ftp.cwd('..')
|
source_ftp.ftp.cwd('..')
|
||||||
except:
|
except:
|
||||||
# 如果是.nc文件则传输
|
# 如果是.nc文件则传输
|
||||||
if item.lower().endswith('.nc'):
|
if item.lower().endswith(end_with):
|
||||||
# 下载到临时文件
|
# 下载到临时文件
|
||||||
temp_path = f"/tmp/{item}"
|
temp_path = f"/tmp/{item}"
|
||||||
with open(temp_path, 'wb') as f:
|
with open(temp_path, 'wb') as f:
|
||||||
|
|||||||
@@ -1814,6 +1814,8 @@ class MrpProduction(models.Model):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info('update_programming_state error:%s' % e)
|
logging.info('update_programming_state error:%s' % e)
|
||||||
raise UserError("更新编程单状态失败,请联系管理员")
|
raise UserError("更新编程单状态失败,请联系管理员")
|
||||||
|
|
||||||
|
model_id = fields.Char('模型id', related='product_id.model_id')
|
||||||
|
|
||||||
|
|
||||||
# 编程记录
|
# 编程记录
|
||||||
|
|||||||
@@ -1774,6 +1774,8 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
orderby=orderby,
|
orderby=orderby,
|
||||||
lazy=lazy
|
lazy=lazy
|
||||||
)
|
)
|
||||||
|
|
||||||
|
model_id = fields.Char('模型id', related='production_id.model_id')
|
||||||
|
|
||||||
|
|
||||||
class CNCprocessing(models.Model):
|
class CNCprocessing(models.Model):
|
||||||
|
|||||||
@@ -1067,7 +1067,8 @@ class ResProductMo(models.Model):
|
|||||||
raise UserError('产品名称【%s】已存在' % item.name)
|
raise UserError('产品名称【%s】已存在' % item.name)
|
||||||
if item.categ_type == '表面工艺':
|
if item.categ_type == '表面工艺':
|
||||||
if len(self.search([('server_product_process_parameters_id', '=',
|
if len(self.search([('server_product_process_parameters_id', '=',
|
||||||
item.server_product_process_parameters_id.id)])) > 1:
|
item.server_product_process_parameters_id.id),('server_product_process_parameters_id', '!=',
|
||||||
|
False)])) > 1:
|
||||||
raise UserError('表面工艺参数为【%s】的产品已存在' % item.server_product_process_parameters_id.name)
|
raise UserError('表面工艺参数为【%s】的产品已存在' % item.server_product_process_parameters_id.name)
|
||||||
if "create_product_product" not in self._context:
|
if "create_product_product" not in self._context:
|
||||||
templates._create_variant_ids()
|
templates._create_variant_ids()
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ class SfProductionProcessParameter(models.Model):
|
|||||||
for record in self:
|
for record in self:
|
||||||
if len(record.outsourced_service_products) > 1:
|
if len(record.outsourced_service_products) > 1:
|
||||||
raise ValidationError("工艺参数不能与多个产品关联")
|
raise ValidationError("工艺参数不能与多个产品关联")
|
||||||
|
|
||||||
|
@api.onchange('outsourced_service_products')
|
||||||
|
def _onchange_validate_partner_limit(self):
|
||||||
|
for record in self:
|
||||||
|
if len(record.outsourced_service_products) > 1:
|
||||||
|
raise ValidationError("工艺参数不能与多个产品关联")
|
||||||
@api.depends('outsourced_service_products')
|
@api.depends('outsourced_service_products')
|
||||||
def _compute_is_product_button(self):
|
def _compute_is_product_button(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import qrcode
|
|
||||||
import base64
|
|
||||||
import logging
|
import logging
|
||||||
import tempfile
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
import socket
|
|
||||||
import subprocess
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
@@ -14,95 +8,7 @@ _logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class MrpWorkorder(models.Model):
|
class MrpWorkorder(models.Model):
|
||||||
_name = 'mrp.workorder'
|
_name = 'mrp.workorder'
|
||||||
_inherit = ['mrp.workorder', 'printing.utils']
|
_inherit = ['mrp.workorder']
|
||||||
|
|
||||||
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):
|
def _compute_state(self):
|
||||||
super(MrpWorkorder, self)._compute_state()
|
super(MrpWorkorder, self)._compute_state()
|
||||||
@@ -111,21 +17,18 @@ class MrpWorkorder(models.Model):
|
|||||||
for wo in work_ids:
|
for wo in work_ids:
|
||||||
if wo.state == 'ready' and not wo.production_id.product_id.is_print_program:
|
if wo.state == 'ready' and not wo.production_id.product_id.is_print_program:
|
||||||
# 触发打印程序
|
# 触发打印程序
|
||||||
pdf_data = self.processing_drawing
|
pdf_data = workorder.processing_drawing
|
||||||
try:
|
if pdf_data:
|
||||||
if pdf_data:
|
try:
|
||||||
# 获取默认打印机配置
|
|
||||||
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):
|
printer = self.env['printing.printer'].get_default()
|
||||||
wo.production_id.product_id.is_print_program = True
|
printer.print_document(report=None, content = pdf_data, doc_format='pdf')
|
||||||
_logger.info(f"工单 {wo.name} 的PDF已成功打印")
|
|
||||||
|
wo.production_id.product_id.is_print_program = True
|
||||||
except Exception as e:
|
_logger.info(f"工单 {wo.name} 的PDF已成功打印")
|
||||||
_logger.error(f'打印配置错误: {str(e)}')
|
|
||||||
|
except Exception as e:
|
||||||
|
_logger.error(f"工单 {wo.name} 的PDF打印失败: {str(e)}")
|
||||||
|
|
||||||
class ProductTemplate(models.Model):
|
class ProductTemplate(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = 'product.template'
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<field name="is_delete_button" invisible="1"/>
|
<field name="is_delete_button" invisible="1"/>
|
||||||
<field name="code" attrs="{'readonly': True}"/>
|
<field name="code" attrs="{'readonly': True}"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="outsourced_service_products" widget="many2many_tags"/>
|
<field name="outsourced_service_products" domain="[('detailed_type', '=', 'service'),('server_product_process_parameters_id', '=', False)]"/>
|
||||||
<!-- 按钮列 -->
|
<!-- 按钮列 -->
|
||||||
<button name="action_create_service_product" string="创建服务产品" type="object"
|
<button name="action_create_service_product" string="创建服务产品" type="object"
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
|
|||||||
@@ -676,6 +676,7 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="product_id" position="after">
|
<field name="product_id" position="after">
|
||||||
<field name="part_number" string="成品零件图号"/>
|
<field name="part_number" string="成品零件图号"/>
|
||||||
|
<field name="model_id" string="模型id"/>
|
||||||
</field>
|
</field>
|
||||||
<xpath expr="//filter[@name='progress']" position="after">
|
<xpath expr="//filter[@name='progress']" position="after">
|
||||||
<filter string="待检测" name="state" domain="[('state','=','to be detected')]"/>
|
<filter string="待检测" name="state" domain="[('state','=','to be detected')]"/>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class ProductCreationWizard(models.TransientModel):
|
|||||||
service_categ = self.env.ref('sf_manufacturing.product_category_outsource_other_process').sudo()
|
service_categ = self.env.ref('sf_manufacturing.product_category_outsource_other_process').sudo()
|
||||||
default_values = {
|
default_values = {
|
||||||
'detailed_type': 'service',
|
'detailed_type': 'service',
|
||||||
'name': f"{self.process_parameter_id.process_id.name}{self.process_parameter_id.name}",
|
'name': f"{self.process_parameter_id.routing_id.name}_{self.process_parameter_id.name}",
|
||||||
'invoice_policy': 'delivery',
|
'invoice_policy': 'delivery',
|
||||||
'categ_id': service_categ.id,
|
'categ_id': service_categ.id,
|
||||||
'description': f"基于{self.process_parameter_id.name}创建的服务产品",
|
'description': f"基于{self.process_parameter_id.name}创建的服务产品",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
'author': 'jikimo',
|
'author': 'jikimo',
|
||||||
'website': 'https://sf.cs.jikimo.com',
|
'website': 'https://sf.cs.jikimo.com',
|
||||||
# 此处依赖sf_manufacturing是因为我要重写其中的一个字段operation_id的string,故需要sf_manufacturing先安装
|
# 此处依赖sf_manufacturing是因为我要重写其中的一个字段operation_id的string,故需要sf_manufacturing先安装
|
||||||
'depends': ['sf_manufacturing'],
|
'depends': ['sf_manufacturing','resource'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
# 'security/rules.xml',
|
# 'security/rules.xml',
|
||||||
|
|||||||
@@ -24,15 +24,17 @@
|
|||||||
<field name="production_line_id"/>
|
<field name="production_line_id"/>
|
||||||
<field name="date_planned_start"/>
|
<field name="date_planned_start"/>
|
||||||
<field name="date_planned_finished"/>
|
<field name="date_planned_finished"/>
|
||||||
<field name="production_type" widget="badge" decoration-warning="production_type == '人工线下加工'" decoration-success="production_type == '自动化产线加工'"/>
|
<field name="production_type" widget="badge" decoration-warning="production_type == '人工线下加工'"
|
||||||
|
decoration-success="production_type == '自动化产线加工'"/>
|
||||||
<field name="actual_start_time" optional='hide'/>
|
<field name="actual_start_time" optional='hide'/>
|
||||||
<field name="actual_end_time" optional='hide'/>
|
<field name="actual_end_time" optional='hide'/>
|
||||||
<field name="actual_process_time" optional='hide'/>
|
<field name="actual_process_time" optional='hide'/>
|
||||||
<field name="schedule_setting" optional='hide'/>
|
<field name="schedule_setting" optional='hide'/>
|
||||||
<!-- <button name="do_production_schedule" class="btn schedule_done" string="生产排程" type="object" -->
|
<!-- <button name="do_production_schedule" class="btn schedule_done" string="生产排程" type="object" -->
|
||||||
<!-- attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('actual_start_time', '!=', False)]}" -->
|
<!-- attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('actual_start_time', '!=', False)]}" -->
|
||||||
<!-- groups="sf_base.group_plan_dispatch"/> -->
|
<!-- groups="sf_base.group_plan_dispatch"/> -->
|
||||||
<button name="cancel_production_schedule" class="btn schedule_cancel" string="取消排程" type="object"
|
<button name="cancel_production_schedule" class="btn schedule_cancel" string="取消排程"
|
||||||
|
type="object"
|
||||||
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('actual_start_time', '!=', False)]}"
|
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('actual_start_time', '!=', False)]}"
|
||||||
groups="sf_base.group_plan_dispatch"/>
|
groups="sf_base.group_plan_dispatch"/>
|
||||||
</tree>
|
</tree>
|
||||||
@@ -48,9 +50,11 @@
|
|||||||
<!-- <button string="执行排程" name="do_production_schedule" type="object" class="oe_highlight" icon="fa-step-forward"/> -->
|
<!-- <button string="执行排程" name="do_production_schedule" type="object" class="oe_highlight" icon="fa-step-forward"/> -->
|
||||||
<button string="执行排程" name="do_production_schedule" type="object" class="oe_highlight"
|
<button string="执行排程" name="do_production_schedule" type="object" class="oe_highlight"
|
||||||
options='{"calendar_view": true, "date_begin": "2020-01-01", "date_end": "2020-12-31"}'
|
options='{"calendar_view": true, "date_begin": "2020-01-01", "date_end": "2020-12-31"}'
|
||||||
groups="sf_base.group_plan_dispatch" attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('actual_start_time', '!=', False)]}"/>
|
groups="sf_base.group_plan_dispatch"
|
||||||
|
attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('actual_start_time', '!=', False)]}"/>
|
||||||
<button string="取消排程" name="cancel_production_schedule" type="object" class="oe_highlight"
|
<button string="取消排程" name="cancel_production_schedule" type="object" class="oe_highlight"
|
||||||
groups="sf_base.group_plan_dispatch" attrs="{'invisible': ['|', ('state', '!=', 'done'), ('actual_start_time', '!=', False)]}"/>
|
groups="sf_base.group_plan_dispatch"
|
||||||
|
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('actual_start_time', '!=', False)]}"/>
|
||||||
<!-- <button name="archive" type="object" string="归档" icon="fa-archive" class="oe_highlight" attrs="{'invisible': [('active', '=', False)]}"/> -->
|
<!-- <button name="archive" type="object" string="归档" icon="fa-archive" class="oe_highlight" attrs="{'invisible': [('active', '=', False)]}"/> -->
|
||||||
<!-- <button name="unarchive" type="object" string="取消归档" icon="fa-archive" class="oe_highlight" attrs="{'invisible': [('active', '=', True)]}"/> -->
|
<!-- <button name="unarchive" type="object" string="取消归档" icon="fa-archive" class="oe_highlight" attrs="{'invisible': [('active', '=', True)]}"/> -->
|
||||||
|
|
||||||
@@ -66,13 +70,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<group>
|
<group>
|
||||||
<group string="基本信息">
|
<group string="基本信息">
|
||||||
<!-- <field name="active" invisible="1"/> -->
|
<!-- <field name="active" invisible="1"/> -->
|
||||||
<field name="production_id" widget="many2one_button"/>
|
<field name="production_id" widget="many2one_button"/>
|
||||||
<field name="product_id"/>
|
<field name="product_id"/>
|
||||||
<field name="origin"/>
|
<field name="origin"/>
|
||||||
<field name="product_qty"/>
|
<field name="product_qty"/>
|
||||||
<field name="order_deadline" widget="date"/>
|
<field name="order_deadline" widget="date"/>
|
||||||
<!-- <field name="process_time"/> -->
|
<!-- <field name="process_time"/> -->
|
||||||
<field name="schedule_setting"/>
|
<field name="schedule_setting"/>
|
||||||
<field name="production_line_id" domain="[('name', 'ilike', 'CNC')]"/>
|
<field name="production_line_id" domain="[('name', 'ilike', 'CNC')]"/>
|
||||||
|
|
||||||
@@ -83,15 +87,16 @@
|
|||||||
<!-- <field name="message_ids" widget="mail_thread"/> -->
|
<!-- <field name="message_ids" widget="mail_thread"/> -->
|
||||||
<!-- <field name="activity_ids"/> -->
|
<!-- <field name="activity_ids"/> -->
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
<!-- <div class="oe_chatter"> -->
|
<!-- <div class="oe_chatter"> -->
|
||||||
<!-- <field name="message_follower_ids"/> -->
|
<!-- <field name="message_follower_ids"/> -->
|
||||||
<!-- <field name="message_ids"/> -->
|
<!-- <field name="message_ids"/> -->
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group string="加工信息">
|
<group string="加工信息">
|
||||||
|
|
||||||
<field name="date_planned_start" placeholder="如果不选择计划开始时间,会取当前时间来做排程" required="1"/>
|
<field name="date_planned_start"
|
||||||
|
placeholder="如果不选择计划开始时间,会取当前时间来做排程" required="1"/>
|
||||||
<field name="date_planned_finished" required="0" invisible="1"/>
|
<field name="date_planned_finished" required="0" invisible="1"/>
|
||||||
<field name="actual_process_time"/>
|
<field name="actual_process_time"/>
|
||||||
<field name="actual_start_time"/>
|
<field name="actual_start_time"/>
|
||||||
@@ -157,8 +162,8 @@
|
|||||||
<search string="订单计划">
|
<search string="订单计划">
|
||||||
|
|
||||||
<!-- Your other filters go here -->
|
<!-- Your other filters go here -->
|
||||||
<!-- <filter name="archived" string="已归档" domain="[('active','=',False)]"/> -->
|
<!-- <filter name="archived" string="已归档" domain="[('active','=',False)]"/> -->
|
||||||
<!-- <filter name="not archived" string="未归档" domain="[('active','=',True)]"/> -->
|
<!-- <filter name="not archived" string="未归档" domain="[('active','=',True)]"/> -->
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="origin"/>
|
<field name="origin"/>
|
||||||
<field name="part_name"/>
|
<field name="part_name"/>
|
||||||
@@ -173,13 +178,16 @@
|
|||||||
<filter name="group_by_state" string="状态" domain="[]" context="{'group_by': 'state'}"/>
|
<filter name="group_by_state" string="状态" domain="[]" context="{'group_by': 'state'}"/>
|
||||||
</group>
|
</group>
|
||||||
<group expand="0" string="Group By">
|
<group expand="0" string="Group By">
|
||||||
<filter name="group_by_production_line_id" string="生产线" domain="[]" context="{'group_by': 'production_line_id'}"/>
|
<filter name="group_by_production_line_id" string="生产线" domain="[]"
|
||||||
|
context="{'group_by': 'production_line_id'}"/>
|
||||||
</group>
|
</group>
|
||||||
<searchpanel>
|
<searchpanel>
|
||||||
<!-- <field name="state" icon="fa-filter"/> -->
|
<!-- <field name="state" icon="fa-filter"/> -->
|
||||||
<field name="production_line_id" select="multi" string="生产线" icon="fa-building" enable_counters="1"/>
|
<field name="production_line_id" select="multi" string="生产线" icon="fa-building"
|
||||||
|
enable_counters="1"/>
|
||||||
<field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/>
|
<field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/>
|
||||||
<field name="production_type" select="multi" string="制造类型" icon="fa-building" enable_counters="1"/>
|
<field name="production_type" select="multi" string="制造类型" icon="fa-building"
|
||||||
|
enable_counters="1"/>
|
||||||
</searchpanel>
|
</searchpanel>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
@@ -275,7 +283,7 @@
|
|||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">sf.production.plan</field>
|
<field name="res_model">sf.production.plan</field>
|
||||||
<field name="view_mode">tree,gantt,form</field>
|
<field name="view_mode">tree,gantt,form</field>
|
||||||
<!-- <field name="context">{'search_default_group_by_state': 1, 'search_default_draft': 1, 'display_complete': True}</field> -->
|
<!-- <field name="context">{'search_default_group_by_state': 1, 'search_default_draft': 1, 'display_complete': True}</field> -->
|
||||||
<field name="context">{'search_default_draft': 1, 'display_complete': True}</field>
|
<field name="context">{'search_default_draft': 1, 'display_complete': True}</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -341,7 +349,7 @@
|
|||||||
parent="mrp.menu_mrp_manufacturing"
|
parent="mrp.menu_mrp_manufacturing"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
id="sf_workpiece_delivery__empty_racks_menu"
|
id="sf_workpiece_delivery__empty_racks_menu"
|
||||||
name="空料架配送"
|
name="空料架配送"
|
||||||
sequence="11"
|
sequence="11"
|
||||||
@@ -363,6 +371,42 @@
|
|||||||
action="sf_production_plan_action1"
|
action="sf_production_plan_action1"
|
||||||
parent="sf_production_plan_menu"
|
parent="sf_production_plan_menu"
|
||||||
/>
|
/>
|
||||||
|
<menuitem
|
||||||
|
id="menu_plan_config_root"
|
||||||
|
name="配置"
|
||||||
|
sequence="190"
|
||||||
|
parent="sf_production_plan_menu"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 二级菜单:工厂日历 -->
|
||||||
|
<menuitem
|
||||||
|
id="menu_factory_calendar"
|
||||||
|
name="工厂日历"
|
||||||
|
parent="menu_plan_config_root"
|
||||||
|
action="resource.action_resource_calendar_form"
|
||||||
|
sequence="10"
|
||||||
|
/>
|
||||||
|
<!-- <record id="action_resource_calendar_form" model="ir.actions.act_window">-->
|
||||||
|
<!-- <field name="name">Working Times</field>-->
|
||||||
|
<!-- <field name="res_model">resource.calendar</field>-->
|
||||||
|
<!-- <field name="view_mode">tree,form</field>-->
|
||||||
|
<!-- <field name="view_id" eval="False"/>-->
|
||||||
|
<!-- <field name="search_view_id" ref="view_resource_calendar_search"/>-->
|
||||||
|
<!-- <field name="help" type="html">-->
|
||||||
|
<!-- <p class="o_view_nocontent_smiling_face">-->
|
||||||
|
<!-- Define working hours and time table that could be scheduled to your project members-->
|
||||||
|
<!-- </p>-->
|
||||||
|
<!-- </field>-->
|
||||||
|
<!-- </record>-->
|
||||||
|
<!-- <record id="action_factory_calendar" model="ir.actions.act_window">-->
|
||||||
|
<!-- <field name="name">工厂日历</field>-->
|
||||||
|
<!-- <field name="res_model">resource.calendar</field>-->
|
||||||
|
<!-- <field name="view_mode">tree,form</field>-->
|
||||||
|
<!-- <field name="help" type="html">-->
|
||||||
|
<!-- <p class="o_view_nocontent_smiling_face">-->
|
||||||
|
<!-- 创建和管理工厂工作日历-->
|
||||||
|
<!-- </p>-->
|
||||||
|
<!-- </field>-->
|
||||||
|
<!-- </record>-->
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user