优化质量检测(加工检测)及消息推送
This commit is contained in:
@@ -1033,7 +1033,7 @@
|
||||
name="Overview"
|
||||
action="quality_alert_team_action"
|
||||
parent="menu_quality_root"
|
||||
sequence="5"/>
|
||||
sequence="5" active="False"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_quality_control"
|
||||
|
||||
@@ -615,14 +615,13 @@ class Manufacturing_Connect(http.Controller):
|
||||
if ret['IsComplete'] is True:
|
||||
# 向AGV任务调度下发下产线任务
|
||||
workorders = request.env['mrp.workorder'].browse(workorder_ids)
|
||||
res['workorder_ids'] = workorder_ids
|
||||
request.env['sf.agv.scheduling'].add_scheduling(ret['DeviceId'], '下产线', workorders)
|
||||
else:
|
||||
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
|
||||
except RepeatTaskException as e:
|
||||
logging.info('AGVToProduct error:%s' % e)
|
||||
except Exception as e:
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e), 'workorder_ids': workorder_ids}
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
|
||||
logging.info('AGVDownProduct error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
<field name='process_state' attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
<field name='tag_type' readonly="1" attrs='{"invisible": [("tag_type","=",False)]}'
|
||||
decoration-danger="tag_type == '重新加工'"/>
|
||||
<field name="rfid_code" force_save="1" readonly="1" cache="True"
|
||||
<field name="rfid_code" force_save="1" readonly="0" cache="True"
|
||||
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
|
||||
<field name="rfid_code_old" readonly="0" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock'],
|
||||
'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock', 'sf_quality'],
|
||||
'data': [
|
||||
'data/bussiness_node.xml',
|
||||
'data/cron_data.xml',
|
||||
|
||||
@@ -89,5 +89,10 @@
|
||||
<field name="model">mrp.workorder</field>
|
||||
</record>
|
||||
|
||||
<record id="bussiness_quality_cnc_test" model="jikimo.message.bussiness.node">
|
||||
<field name="name">待质量判定</field>
|
||||
<field name="model">quality.cnc.test</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -25,5 +25,18 @@
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">
|
||||
<field name="name">检查工单是否完成并恢复正常时效</field>
|
||||
<field name="model_id" ref="model_mrp_workorder"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model._recover_time_warning_func()</field>
|
||||
<field name="interval_number">10</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="doall" eval="False"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -227,5 +227,16 @@
|
||||
<!--单号:组装任务单[{{name}}]({{request_url}})-->
|
||||
<!--事项:{{use_tool_time}}前完成组装</field>-->
|
||||
<!-- </record>-->
|
||||
|
||||
<record id="template_quality_cnc_test" model="jikimo.message.template">
|
||||
<field name="name">待质量判定</field>
|
||||
<field name="model_id" ref="sf_quality.model_quality_cnc_test"/>
|
||||
<field name="model">quality.cnc.test</field>
|
||||
<field name="bussiness_node_id" ref="bussiness_quality_cnc_test"/>
|
||||
<field name="msgtype">markdown</field>
|
||||
<field name="urgency">normal</field>
|
||||
<field name="content">### 待质量判定提醒
|
||||
事项:共有[{{judge_num}}]({{url}})个工单需判定质量结果</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -7,3 +7,4 @@ from . import sf_message_functional_tool_assembly
|
||||
from . import sf_message_purchase
|
||||
from . import sf_message_workorder
|
||||
from . import sf_message_functional_tool_dismantle
|
||||
from . import sf_message_quality_cnc_test
|
||||
|
||||
36
sf_message/models/sf_message_quality_cnc_test.py
Normal file
36
sf_message/models/sf_message_quality_cnc_test.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from odoo import models, fields, api, _
|
||||
|
||||
|
||||
class SFMessageQualityCncTest(models.Model):
|
||||
_name = 'quality.cnc.test'
|
||||
_inherit = ['quality.cnc.test', 'jikimo.message.dispatch']
|
||||
|
||||
def create(self, vals_list):
|
||||
res = super(SFMessageQualityCncTest, self).create(vals_list)
|
||||
if res:
|
||||
try:
|
||||
logging.info('add_queue res:%s' % res)
|
||||
res.add_queue('待质量判定')
|
||||
except Exception as e:
|
||||
logging.info('add_queue error:%s' % e)
|
||||
return res
|
||||
|
||||
# 继承并重写jikimo.message.dispatch的_get_message()
|
||||
def _get_message(self, message_queue_ids):
|
||||
contents = []
|
||||
url = self.env['ir.config_parameter'].get_param('web.base.url')
|
||||
i = 0
|
||||
for item in message_queue_ids:
|
||||
if item.message_template_id.bussiness_node_id.name == '待质量判定':
|
||||
content = item.message_template_id.content
|
||||
i += 1
|
||||
if i >= 1:
|
||||
action_id = self.env.ref('sf_quality.action_quality_cnc_test').id
|
||||
url_with_id = f"{url}/web#view_type=list&action={action_id}"
|
||||
content_template = content.replace('{{judge_num}}', str(i))
|
||||
content_template = content_template.replace('{{url}}', url_with_id)
|
||||
contents.append(content_template)
|
||||
return contents
|
||||
@@ -148,3 +148,8 @@ class SFMessageWork(models.Model):
|
||||
args = [f'{item.routing_type}{overdue_message}']
|
||||
# 获取add_queue方法并调用它,传入参数列表
|
||||
getattr(item, queue_method_name)(*args)
|
||||
|
||||
def _recover_time_warning_func(self):
|
||||
workorder_done = self.env['mrp.workorder'].search([("state", "=", "done")])
|
||||
workorder_overdue = workorder_done.filtered(lambda x: x.delivery_warning == 'overdue')
|
||||
workorder_overdue.write({'delivery_warning': 'normal'})
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
from . import controller
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from . import workorder
|
||||
@@ -1,28 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
import requests
|
||||
import logging
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from odoo.addons.sf_manufacturing.controllers.controllers import Manufacturing_Connect
|
||||
from odoo.addons.sf_base.commons.common import Common
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SfQualityConnect(Manufacturing_Connect):
|
||||
|
||||
@http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def AGVDownProduct(self, **kw):
|
||||
res = super(SfQualityConnect, self).AGVDownProduct(**kw)
|
||||
res = json.loads(res)
|
||||
if res.get('workorder_ids'):
|
||||
try:
|
||||
_logger.info('已下产线的工单:%s' % res.get('workorder_ids'))
|
||||
for order_id in res['workorder_ids']:
|
||||
request.env['quality.cnc.test'].sudo().create(
|
||||
{'workorder_id': order_id, 'write_uid': False, 'write_date': False})
|
||||
except Exception as e:
|
||||
_logger.info('AGV运送下产线接口:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
@@ -25,23 +25,44 @@ class SfQualityCncTest(models.Model):
|
||||
('pass', '合格'),
|
||||
('fail', '不合格')], string='判定结果')
|
||||
number = fields.Integer('数量', default=1)
|
||||
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], default='合格',
|
||||
string="检测结果")
|
||||
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果")
|
||||
reason = fields.Selection(
|
||||
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"),
|
||||
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")
|
||||
detailed_reason = fields.Text('详细原因')
|
||||
|
||||
def submit_pass(self):
|
||||
self.write({'result': 'pass', 'test_results': '合格', 'state': 'done'})
|
||||
self.write({'result': 'pass', 'test_results': self.test_results, 'state': 'done'})
|
||||
self.workorder_id.write({'test_results': self.test_results})
|
||||
self.workorder_id.button_finish()
|
||||
|
||||
def submit_fail(self):
|
||||
if not self.reason and not self.detailed_reason:
|
||||
raise UserError(_('请填写【检测情况】里的信息'))
|
||||
if not self.reason and not self.detailed_reason and not self.test_results:
|
||||
raise UserError(_('请填写【判定结果】里的信息'))
|
||||
else:
|
||||
self.write({'result': 'fail', 'test_results': '合格', 'state': 'done'})
|
||||
self.write({'result': 'fail', 'test_results': self.test_results, 'state': 'done'})
|
||||
self.workorder_id.write(
|
||||
{'test_results': self.test_results, 'reason': self.reason, 'detailed_reason': self.detailed_reason})
|
||||
self.workorder_id.button_finish()
|
||||
|
||||
|
||||
class SfQualityWorkOrder(models.Model):
|
||||
_inherit = 'mrp.workorder'
|
||||
|
||||
def button_finish(self):
|
||||
super(SfQualityWorkOrder, self).button_finish()
|
||||
if self.routing_type == 'CNC加工':
|
||||
quality_cnc_test = self.env['quality.cnc.test'].search([('workorder_id', '=', self.id)])
|
||||
if quality_cnc_test:
|
||||
quality_cnc_test.write({'result': 'fail' if self.test_results in ['返工', '报废'] else 'pass',
|
||||
'test_results': self.test_results, 'state': 'done',
|
||||
'reason': self.reason,
|
||||
'detailed_reason': self.detailed_reason,
|
||||
'detection_report': self.detection_report})
|
||||
|
||||
def write(self, vals):
|
||||
res = super(SfQualityWorkOrder, self).write(vals)
|
||||
if self.state == 'to be detected':
|
||||
quality_cnc_test = self.env['quality.cnc.test'].search([('workorder_id', '=', self.id)])
|
||||
if not quality_cnc_test:
|
||||
self.env['quality.cnc.test'].sudo().create({'workorder_id': self.id})
|
||||
|
||||
@@ -70,5 +70,8 @@ access_stock_move_group_quality_director,stock_move_group_quality_director,stock
|
||||
access_quality_cnc_test_group_quality,quality_cnc_test_group_quality,model_quality_cnc_test,sf_base.group_quality,1,1,0,0
|
||||
access_quality_cnc_test_group_quality_director,quality_cnc_test_group_quality_director,model_quality_cnc_test,sf_base.group_quality_director,1,1,0,0
|
||||
|
||||
access_quality_cnc_test_group_sf_equipment_user,quality_cnc_test_group_sf_equipment_user,model_quality_cnc_test,sf_base.group_sf_equipment_user,1,1,0,0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -39,7 +39,7 @@
|
||||
filter_domain="[('production_id', 'ilike', self)]"/>
|
||||
<field name="product_id" string="产品"
|
||||
filter_domain="[('product_id', 'ilike', self)]"/>
|
||||
<searchpanel class="account_root">
|
||||
<searchpanel>
|
||||
<field name="state" icon="fa-filter" enable_counters="1"/>
|
||||
<field name="result" icon="fa-filter" enable_counters="1"/>
|
||||
</searchpanel>
|
||||
@@ -96,14 +96,20 @@
|
||||
<page string="检测报告">
|
||||
<field name="detection_report" string="" widget="pdf_viewer"/>
|
||||
</page>
|
||||
<page string="检测情况">
|
||||
<page string="判定结果">
|
||||
<group>
|
||||
<field name="test_results"/>
|
||||
<field name="reason"/>
|
||||
<field name="detailed_reason"/>
|
||||
<field name="test_results" attrs="{'readonly': [('state','=', 'done')]}"/>
|
||||
<field name="reason" attrs="{'readonly': [('state','=', 'done')]}"/>
|
||||
<field name="detailed_reason" attrs="{'readonly': [('state','=', 'done')]}"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="其他">
|
||||
<page string="2D图纸">
|
||||
<!-- <field name="detection_report" string="" widget="pdf_viewer"/>-->
|
||||
</page>
|
||||
<page string="客户质量标准">
|
||||
<!-- <field name="detection_report" string="" widget="pdf_viewer"/>-->
|
||||
</page>
|
||||
<page string="其他" attrs="{'readonly': [('state','=', 'done')]}">
|
||||
<group>
|
||||
<field name="write_uid" widget='many2one_avatar_user' string="判定人" readonly="1"/>
|
||||
<field name="write_date" string="判定时间" readonly="1"/>
|
||||
@@ -115,6 +121,54 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="quality_cnc_test_view_kanban" model="ir.ui.view">
|
||||
<field name="name">quality.cnc.test.view.kanban</field>
|
||||
<field name="model">quality.cnc.test</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="oe_background_grey o_kanban_dashboard o_quality_kanban" create="0">
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record oe_kanban_card oe_kanban_global_click">
|
||||
<div class="add_flex">
|
||||
<div class="o_kanban_card_header">
|
||||
<div class="o_kanban_card_header_title">
|
||||
<field name="name"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="container o_kanban_card_content">
|
||||
<div>
|
||||
<field name="production_id"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="processing_panel"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="state"
|
||||
widget="label_selection"
|
||||
options="{'classes': {'waiting': 'warning', 'done': 'success'}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="show_state" t-attf-class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record oe_kanban_card oe_kanban_global_click-->
|
||||
<!-- ">-->
|
||||
<!-- <div t-attf-class="#{record.result.raw_value == 'pass' ? 'color_1' : ''}"></div>-->
|
||||
<!-- <div t-attf-class="#{record.result.raw_value == 'fail' ? 'color_2' : ''}"></div>-->
|
||||
<!-- <p class="o_kanban_record_bottom"-->
|
||||
<!-- t-attf-class="#{record.result.raw_value == 'pass' ? 'font_color_1' : ''}-->
|
||||
<!-- #{record.state.result == 'fail' ? 'font_color_2' : ''}}">-->
|
||||
<!-- <field name="result"/>-->
|
||||
<!-- </p>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_quality_cnc_test"
|
||||
name="加工质检"
|
||||
@@ -123,4 +177,26 @@
|
||||
parent="quality_control.menu_quality_control"
|
||||
/>
|
||||
|
||||
|
||||
<record id="action_quality_cnc_test_kanban" model="ir.actions.act_window">
|
||||
<field name="name">驾驶舱</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">quality.cnc.test</field>
|
||||
<field name="view_mode">kanban,form</field>
|
||||
<field name="view_id" ref="quality_cnc_test_view_kanban"/>
|
||||
<field name="search_view_id" ref="quality_cnc_test_search"/>
|
||||
<field name="domain">[]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
暂无加工质检单
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_quality_cnc_test_dashboard"
|
||||
name="驾驶舱"
|
||||
action="action_quality_cnc_test_kanban"
|
||||
parent="quality_control.menu_quality_root"
|
||||
sequence="5"/>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -34,36 +34,36 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- <record model="ir.ui.view" id="quality_point_view_form_inherit_sf">-->
|
||||
<!-- <field name="name">quality.point.form.inherit.sf</field>-->
|
||||
<!-- <field name="model">quality.point</field>-->
|
||||
<!-- <field name="inherit_id" ref="quality.quality_point_view_form"/>-->
|
||||
<!-- <field name="arch" type="xml">-->
|
||||
<!--<!– <xpath expr="//sheet//group//group//field[@name='title']" position="replace"> –>-->
|
||||
<!--<!– <field name="title" class="custom_required" required="1"/> –>-->
|
||||
<!--<!– </xpath> –>-->
|
||||
<!-- <xpath expr="//sheet//group//group//field[@name='title']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- <attribute name="required">1</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- <xpath expr="//sheet//group//group//field[@name='picking_type_ids']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- <attribute name="required">1</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- </field>-->
|
||||
<!-- </record>-->
|
||||
<!-- <record model="ir.ui.view" id="quality_point_view_form_inherit_sf">-->
|
||||
<!-- <field name="name">quality.point.form.inherit.sf</field>-->
|
||||
<!-- <field name="model">quality.point</field>-->
|
||||
<!-- <field name="inherit_id" ref="quality.quality_point_view_form"/>-->
|
||||
<!-- <field name="arch" type="xml">-->
|
||||
<!--<!– <xpath expr="//sheet//group//group//field[@name='title']" position="replace"> –>-->
|
||||
<!--<!– <field name="title" class="custom_required" required="1"/> –>-->
|
||||
<!--<!– </xpath> –>-->
|
||||
<!-- <xpath expr="//sheet//group//group//field[@name='title']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- <attribute name="required">1</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- <xpath expr="//sheet//group//group//field[@name='picking_type_ids']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- <attribute name="required">1</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- </field>-->
|
||||
<!-- </record>-->
|
||||
|
||||
<!-- <record model="ir.ui.view" id="sf_quality_point_view_form_inherit_quality_control">-->
|
||||
<!-- <field name="name">sf.quality.point.form.inherit.sf</field>-->
|
||||
<!-- <field name="model">quality.point</field>-->
|
||||
<!-- <field name="inherit_id" ref="quality_control.quality_point_view_form_inherit_quality_control"/>-->
|
||||
<!-- <field name="arch" type="xml">-->
|
||||
<!-- <xpath expr="//field[@name='measure_on']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- <xpath expr="//field[@name='measure_frequency_type']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- </field>-->
|
||||
<!-- </record>-->
|
||||
<!-- <record model="ir.ui.view" id="sf_quality_point_view_form_inherit_quality_control">-->
|
||||
<!-- <field name="name">sf.quality.point.form.inherit.sf</field>-->
|
||||
<!-- <field name="model">quality.point</field>-->
|
||||
<!-- <field name="inherit_id" ref="quality_control.quality_point_view_form_inherit_quality_control"/>-->
|
||||
<!-- <field name="arch" type="xml">-->
|
||||
<!-- <xpath expr="//field[@name='measure_on']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- <xpath expr="//field[@name='measure_frequency_type']" position="attributes">-->
|
||||
<!-- <attribute name="class">custom_required</attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- </field>-->
|
||||
<!-- </record>-->
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user