Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

This commit is contained in:
mgw
2025-04-21 12:20:56 +08:00
17 changed files with 128 additions and 160 deletions

View File

@@ -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': '传输失败'}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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)]}"

View File

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

View File

@@ -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')
# 编程记录 # 编程记录

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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')]"/>

View File

@@ -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}创建的服务产品",

View File

@@ -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',

View File

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