diff --git a/jikimo_workorder_exception/__init__.py b/jikimo_workorder_exception/__init__.py
new file mode 100644
index 00000000..c3d410ea
--- /dev/null
+++ b/jikimo_workorder_exception/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import models
+from . import controllers
diff --git a/jikimo_workorder_exception/__manifest__.py b/jikimo_workorder_exception/__manifest__.py
new file mode 100644
index 00000000..4c63ed6d
--- /dev/null
+++ b/jikimo_workorder_exception/__manifest__.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+{
+ 'name': '机企猫 工单异常记录',
+ 'version': '1.0',
+ 'summary': '记录工单的异常日志',
+ 'sequence': 1,
+ 'category': 'sf',
+ 'website': 'https://www.sf.jikimo.com',
+ 'depends': ['sf_manufacturing', 'sf_mrs_connect'],
+ 'data': [
+ 'views/mrp_workorder_views.xml',
+ 'security/ir.model.access.csv',
+ ],
+ 'demo': [
+ ],
+ 'license': 'LGPL-3',
+ 'installable': True,
+ 'application': False,
+ 'auto_install': False,
+}
diff --git a/jikimo_workorder_exception/controllers/__init__.py b/jikimo_workorder_exception/controllers/__init__.py
new file mode 100644
index 00000000..deec4a8b
--- /dev/null
+++ b/jikimo_workorder_exception/controllers/__init__.py
@@ -0,0 +1 @@
+from . import main
\ No newline at end of file
diff --git a/jikimo_workorder_exception/controllers/main.py b/jikimo_workorder_exception/controllers/main.py
new file mode 100644
index 00000000..6a17f958
--- /dev/null
+++ b/jikimo_workorder_exception/controllers/main.py
@@ -0,0 +1,89 @@
+from odoo import http, fields
+from odoo.http import request
+import json
+import logging
+from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect
+from odoo.addons.sf_manufacturing.controllers.controllers import Manufacturing_Connect
+
+_logger = logging.getLogger(__name__)
+
+class WorkorderExceptionConroller(http.Controller):
+
+ @http.route('/AutoDeviceApi/BillError', type='json', auth='public', methods=['GET', 'POST'], csrf=False,
+ cors="*")
+ def workder_exception(self, **kw):
+ """
+ 记录工单异常
+ :param kw:
+ :return:
+ """
+ _logger.info('workder_exception:%s' % kw)
+ try:
+ res = {'Succeed': True, 'ErrorCode': 0, 'Error': ''}
+ datas = request.httprequest.data
+ ret = json.loads(datas)['Datas']
+ if not ret.get('RfidCode') or not ret.get('ErrorType'):
+ res = {'Succeed': False, 'ErrorCode': 400, 'Error': '参数错误'}
+ return json.JSONEncoder().encode(res)
+
+ # 通过RfidCode获取就绪的CNC工单
+ workorder = request.env['mrp.workorder'].sudo().search([
+ ('rfid_code', '=', ret['RfidCode']),
+ ('routing_type', '=', 'CNC加工'),
+ ])
+ if not workorder:
+ res = {'Succeed': False, 'ErrorCode': 401, 'Error': '无效的工单'}
+ return json.JSONEncoder().encode(res)
+
+ # 创建工单异常记录,关联工单
+ request.env['jikimo.workorder.exception'].sudo().create({
+ 'workorder_id': workorder.id,
+ 'exception_code': ret.get('ErrorType'),
+ 'exception_content': ret.get('Error', '')
+ })
+
+ except Exception as e:
+ res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
+ _logger.info('workder_exception error:%s' % e)
+ return json.JSONEncoder().encode(res)
+
+
+class SfMrsConnectController(Sf_Mrs_Connect):
+
+ @http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
+ cors="*")
+ def get_cnc_processing_create(self, **kw):
+ """
+ 更新工单异常记录【'YC001', 'YC004'】
+ """
+ res = super(SfMrsConnectController, self).get_cnc_processing_create(**kw)
+ # 如果有未完成的YC0001、YC0004异常记录,则标记为完成
+ res = json.loads(res)
+ _logger.info('已进入工单异常:%s' % res)
+ if res.get('production_ids'):
+ try:
+ productions = request.env['mrp.production'].sudo().search([('id', 'in', res.get('production_ids'))])
+ if productions.workorder_ids:
+ productions.workorder_ids.handle_exception(['YC0001', 'YC0004'])
+ except Exception as e:
+ _logger.info('更新工单异常记录失败:%s' % e)
+ return json.JSONEncoder().encode(res)
+
+class ManufactruingController(Manufacturing_Connect):
+
+ @http.route('/AutoDeviceApi/FeedBackStart', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
+ cors="*")
+ def button_Work_START(self, **kw):
+ """
+ 更新工单异常记录【'YC0002', 'YC0003'】
+ """
+ res = super(ManufactruingController, self).button_Work_START(**kw)
+ res = json.loads(res)
+ _logger.info('已进入工单异常:%s' % res)
+ if res.get('workorder_id'):
+ try:
+ workorder = request.env['mrp.workorder'].sudo().browse(int(res.get('workorder_id')))
+ workorder.handle_exception(['YC0002', 'YC0003'])
+ except Exception as e:
+ _logger.info('更新工单异常记录失败:%s' % e)
+ return json.JSONEncoder().encode(res)
\ No newline at end of file
diff --git a/jikimo_workorder_exception/models/__init__.py b/jikimo_workorder_exception/models/__init__.py
new file mode 100644
index 00000000..9ab4d803
--- /dev/null
+++ b/jikimo_workorder_exception/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+from . import jikimo_workorder_exception
+from . import mrp_workorder
diff --git a/jikimo_workorder_exception/models/jikimo_workorder_exception.py b/jikimo_workorder_exception/models/jikimo_workorder_exception.py
new file mode 100644
index 00000000..19dd824b
--- /dev/null
+++ b/jikimo_workorder_exception/models/jikimo_workorder_exception.py
@@ -0,0 +1,14 @@
+from odoo import models, fields
+
+
+class JikimoWorkorderException(models.Model):
+ _name = 'jikimo.workorder.exception'
+ _description = '工单异常记录'
+ _order = 'id desc'
+
+ workorder_id = fields.Many2one('mrp.workorder', string='工单')
+ exception_code = fields.Char('异常编码')
+ exception_content = fields.Char('反馈的异常/问题信息')
+ completion_time = fields.Datetime('处理完成时间')
+ state = fields.Selection([('pending', '进行中'), ('done', '已处理')], string='状态', default='pending')
+
\ No newline at end of file
diff --git a/jikimo_workorder_exception/models/mrp_workorder.py b/jikimo_workorder_exception/models/mrp_workorder.py
new file mode 100644
index 00000000..64f0dd8f
--- /dev/null
+++ b/jikimo_workorder_exception/models/mrp_workorder.py
@@ -0,0 +1,40 @@
+from odoo import models, fields
+import logging
+
+_logger = logging.getLogger(__name__)
+
+class MrpWorkorder(models.Model):
+ _inherit = 'mrp.workorder'
+
+ exception_ids = fields.One2many('jikimo.workorder.exception', 'workorder_id', string='工单异常记录')
+
+ def write(self, values):
+ if values.get('test_results') and self.exception_ids:
+ pending_exception = self.exception_ids.filtered(
+ lambda exc: exc.state == 'pending' and exc.exception_code == 'YC0005'
+ )
+ if pending_exception:
+ pending_exception.write({
+ 'completion_time': fields.Datetime.now(),
+ 'state': 'done'
+ })
+ return super(MrpWorkorder, self).write(values)
+
+ def handle_exception(self, exception_codes):
+ """
+ 处理异常
+ :param exception_codes: 需要处理的异常编码列表
+ """
+ if not isinstance(exception_codes, list):
+ exception_codes = [exception_codes]
+ if self.exception_ids:
+ _logger.info('workorder.exception_ids:%s' % self.exception_ids)
+ pending_exception = self.exception_ids.filtered(
+ lambda exc: exc.state == 'pending' and exc.exception_code in exception_codes
+ )
+ _logger.info('pending_exception:%s' % pending_exception)
+ if pending_exception:
+ pending_exception.write({
+ 'completion_time': fields.Datetime.now(),
+ 'state': 'done'
+ })
diff --git a/jikimo_workorder_exception/security/ir.model.access.csv b/jikimo_workorder_exception/security/ir.model.access.csv
new file mode 100644
index 00000000..bbc066e4
--- /dev/null
+++ b/jikimo_workorder_exception/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
+"access_jikimo_workorder_exception","access.jikimo.workorder.exception","model_jikimo_workorder_exception","mrp.group_mrp_user",1,1,1,0
diff --git a/jikimo_workorder_exception/tests/__init__.py b/jikimo_workorder_exception/tests/__init__.py
new file mode 100644
index 00000000..99feb117
--- /dev/null
+++ b/jikimo_workorder_exception/tests/__init__.py
@@ -0,0 +1,2 @@
+from . import common
+from . import test_jikimo_workorder_exception
diff --git a/jikimo_workorder_exception/tests/common.py b/jikimo_workorder_exception/tests/common.py
new file mode 100644
index 00000000..bbc729db
--- /dev/null
+++ b/jikimo_workorder_exception/tests/common.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo import fields, Command
+from odoo.tests.common import TransactionCase, HttpCase, tagged, Form
+
+import json
+import time
+import base64
+from lxml import etree
+
+@tagged('post_install', '-at_install')
+class TestJikimoWorkorderExceptionCommon(TransactionCase):
+
+ def setUp(self):
+ super(TestJikimoWorkorderExceptionCommon, self).setUp()
+ # 获取名字为“1#自动生产线”的制造中心
+ workcenter = self.env['mrp.workcenter'].search([('name', '=', '1#自动生产线')], limit=1)
+ # 创建一个产品
+ product_product = self.env['product.product'].create({
+ 'name': '测试产品',
+ 'type': 'product',
+ })
+ uom_unit = self.env.ref('uom.product_uom_unit')
+ # 创建一个bom
+ self.bom = self.env['mrp.bom'].create({
+ 'product_id': product_product.id,
+ 'product_tmpl_id': product_product.product_tmpl_id.id,
+ 'product_uom_id': uom_unit.id,
+ 'product_qty': 1.0,
+ 'type': 'normal',
+ })
+ # 创建一个制造订单
+ self.production = self.env['mrp.production'].create({
+ 'name': 'Test Production',
+ 'product_id': product_product.id,
+ 'bom_id': self.bom.id,
+ 'company_id': self.env.ref('base.main_company').id,
+ })
+ # 创建一个测试工单
+ self.workorder = self.env['mrp.workorder'].create({
+ 'name': 'Test order',
+ 'workcenter_id': workcenter.id,
+ 'product_uom_id': self.bom.product_uom_id.id,
+ 'production_id': self.production.id,
+ 'duration_expected': 1.0,
+ 'rfid_code': 'test-123456',
+ 'routing_type': 'CNC加工'
+ })
\ No newline at end of file
diff --git a/jikimo_workorder_exception/tests/test_jikimo_workorder_exception.py b/jikimo_workorder_exception/tests/test_jikimo_workorder_exception.py
new file mode 100644
index 00000000..69220947
--- /dev/null
+++ b/jikimo_workorder_exception/tests/test_jikimo_workorder_exception.py
@@ -0,0 +1,53 @@
+import json
+from datetime import datetime
+from odoo.addons.jikimo_workorder_exception.tests.common import TestJikimoWorkorderExceptionCommon
+
+class TestJikimoWorkorderException(TestJikimoWorkorderExceptionCommon):
+
+ def test_create_exception_record(self):
+ exception_record = self.env['jikimo.workorder.exception'].create({
+ 'workorder_id': self.workorder.id,
+ 'exception_code': 'YC0001',
+ 'exception_content': '无CNC编程'
+ })
+
+ self.assertTrue(exception_record)
+ self.assertEqual(exception_record.exception_content, '无CNC编程')
+ self.assertEqual(exception_record.workorder_id.id, self.workorder.id)
+ self.assertEqual(exception_record.exception_code, 'YC0001')
+
+ def test_handle_exception(self):
+ exception_record = self.env['jikimo.workorder.exception'].create({
+ 'workorder_id': self.workorder.id,
+ 'exception_code': 'YC0001',
+ 'exception_content': '无CNC编程'
+ })
+ self.workorder.handle_exception('YC0001')
+ self.assertEqual(exception_record.state, 'done')
+ # 判断完成时间是否为当前分钟
+ self.assertEqual(exception_record.completion_time.minute, datetime.now().minute)
+
+ def test_handle_exception_with_invalid_code(self):
+ exception_record = self.env['jikimo.workorder.exception'].create({
+ 'workorder_id': self.workorder.id,
+ 'exception_code': 'YC0001',
+ 'exception_content': '无CNC编程'
+ })
+ self.workorder.handle_exception(['YC0002', 'YC0004'])
+ self.assertEqual(exception_record.state, 'pending')
+ self.assertEqual(exception_record.completion_time, False)
+
+
+ def test_handle_exception_with_test_results(self):
+ exception_record = self.env['jikimo.workorder.exception'].create({
+ 'workorder_id': self.workorder.id,
+ 'exception_code': 'YC0005',
+ 'exception_content': '工单加工失败'
+ })
+ self.workorder.write({
+ 'test_results': '返工',
+ 'reason': 'cutter',
+ 'detailed_reason': '刀坏了',
+ })
+ self.assertEqual(exception_record.state, 'done')
+ self.assertEqual(exception_record.completion_time.minute, datetime.now().minute)
\ No newline at end of file
diff --git a/jikimo_workorder_exception/views/mrp_workorder_views.xml b/jikimo_workorder_exception/views/mrp_workorder_views.xml
new file mode 100644
index 00000000..e589adb4
--- /dev/null
+++ b/jikimo_workorder_exception/views/mrp_workorder_views.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ mrp.workorder.form
+ mrp.workorder
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jikimo_workorder_exception_notify/__init__.py b/jikimo_workorder_exception_notify/__init__.py
new file mode 100644
index 00000000..77bbdbd3
--- /dev/null
+++ b/jikimo_workorder_exception_notify/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import models
+
diff --git a/jikimo_workorder_exception_notify/__manifest__.py b/jikimo_workorder_exception_notify/__manifest__.py
new file mode 100644
index 00000000..0b8c1013
--- /dev/null
+++ b/jikimo_workorder_exception_notify/__manifest__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+{
+ 'name': '机企猫 工单异常消息通知',
+ 'version': '1.0',
+ 'summary': '当产生工单异常时,发送消息通知',
+ 'sequence': 1,
+ 'category': 'sf',
+ 'website': 'https://www.sf.jikimo.com',
+ 'depends': ['jikimo_workorder_exception', 'jikimo_message_notify'],
+ 'data': [
+ 'data/bussiness_node.xml',
+ 'data/template_data.xml',
+ # 'security/ir.model.access.csv',
+ ],
+ 'demo': [
+ ],
+ 'license': 'LGPL-3',
+ 'installable': True,
+ 'application': False,
+ 'auto_install': False,
+}
diff --git a/jikimo_workorder_exception_notify/data/bussiness_node.xml b/jikimo_workorder_exception_notify/data/bussiness_node.xml
new file mode 100644
index 00000000..b772158b
--- /dev/null
+++ b/jikimo_workorder_exception_notify/data/bussiness_node.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ 无功能刀具
+ jikimo.workorder.exception
+
+
+ 无定位数据
+ jikimo.workorder.exception
+
+
+ 加工失败
+ jikimo.workorder.exception
+
+
+
\ No newline at end of file
diff --git a/jikimo_workorder_exception_notify/data/template_data.xml b/jikimo_workorder_exception_notify/data/template_data.xml
new file mode 100644
index 00000000..554ef2c2
--- /dev/null
+++ b/jikimo_workorder_exception_notify/data/template_data.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ 生产线无功能刀具提醒
+
+ jikimo.workorder.exception
+
+ markdown
+ urgent
+ ### 生产线无功能刀具提醒
+单号:工单[{{workorder_id.production_id.name}}]({{url}})
+原因:生产线无加工程序用的{{function_tool_name}}名称功能刀具
+
+
+ 工单无定位数据提醒
+
+ jikimo.workorder.exception
+
+ markdown
+ urgent
+ ### 生产线无功能刀具提醒
+单号:工单[{{workorder_id.production_id.name}}]({{url}})
+原因:无装夹定位测量数据
+
+
+ 工单加工失败提醒
+
+ jikimo.workorder.exception
+
+ markdown
+ urgent
+ ### 工单加工失败提醒
+单号:工单[{{workorder_id.production_id.name}}]({{url}})
+原因:加工失败,工件下产线处理
+
+
+
\ No newline at end of file
diff --git a/jikimo_workorder_exception_notify/models/__init__.py b/jikimo_workorder_exception_notify/models/__init__.py
new file mode 100644
index 00000000..76a90c74
--- /dev/null
+++ b/jikimo_workorder_exception_notify/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+from . import jikimo_message_template
+from . import jikimo_workorder_exception
diff --git a/jikimo_workorder_exception_notify/models/jikimo_message_template.py b/jikimo_workorder_exception_notify/models/jikimo_message_template.py
new file mode 100644
index 00000000..530cbb99
--- /dev/null
+++ b/jikimo_workorder_exception_notify/models/jikimo_message_template.py
@@ -0,0 +1,10 @@
+from odoo import models
+
+
+class JikimoMessageTemplate(models.Model):
+ _inherit = "jikimo.message.template"
+
+ def _get_message_model(self):
+ res = super(JikimoMessageTemplate, self)._get_message_model()
+ res.append('jikimo.workorder.exception')
+ return res
\ No newline at end of file
diff --git a/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py b/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py
new file mode 100644
index 00000000..bbe69ab5
--- /dev/null
+++ b/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py
@@ -0,0 +1,61 @@
+from odoo import models, api
+from odoo.addons.sf_base.commons.common import Common
+import requests, logging
+
+_logger = logging.getLogger(__name__)
+
+
+class JikimoWorkorderException(models.Model):
+ _name = 'jikimo.workorder.exception'
+ _inherit = ['jikimo.workorder.exception', 'jikimo.message.dispatch']
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ res = super(JikimoWorkorderException, self).create(vals_list)
+ # 根据异常编码发送消息提醒
+ try:
+ for rec in res:
+ if rec.exception_code == 'YC0001':
+ # 无CNC程序,调用cloud接口
+ data = {'name': rec.workorder_id.production_id.programming_no, 'exception_code': 'YC0001'}
+ configsettings = self.env['res.config.settings'].sudo().get_values()
+ config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
+ url = '/api/message/workorder_exception'
+ config_url = configsettings['sf_url'] + url
+ data['token'] = configsettings['token']
+ ret = requests.post(config_url, json=data, headers=config_header)
+ ret = ret.json()
+ _logger.info('无CNC程序异常消息推送接口:%s' % ret)
+ elif rec.exception_code == 'YC0002':
+ # 无功能刀具
+ rec.add_queue('无功能刀具')
+ elif rec.exception_code == 'YC0003':
+ # 无定位数据
+ rec.add_queue('无定位数据')
+ elif rec.exception_code == 'YC0004':
+ # 无FTP文件,调用cloud接口
+ data = {'name': rec.workorder_id.programming_no, 'exception_code': 'YC0004'}
+ configsettings = self.env['res.config.settings'].sudo().get_values()
+ config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
+ url = '/api/message/workorder_exception'
+ config_url = configsettings['sf_url'] + url
+ data['token'] = configsettings['token']
+ ret = requests.post(config_url, json=data, headers=config_header)
+ ret = ret.json()
+ _logger.info('无FTP文件异常消息推送接口:%s' % ret)
+ elif rec.exception_code == 'YC0005':
+ # 加工失败
+ rec.add_queue('加工失败')
+ except Exception as e:
+ _logger.error('异常编码发送消息提醒失败:%s' % e)
+ return res
+
+ def _get_message(self, message_queue_ids):
+ contents = super(JikimoWorkorderException, self)._get_message(message_queue_ids)
+ url = self.env['ir.config_parameter'].get_param('web.base.url')
+ action_id = self.env.ref('mrp.mrp_production_action').id
+ for index, content in enumerate(contents):
+ exception_id = self.env['jikimo.workorder.exception'].browse(message_queue_ids[index].res_id)
+ url = url + '/web#id=%s&view_type=form&action=%s' % (exception_id.workorder_id.production_id.id, action_id)
+ contents[index] = content.replace('{{url}}', url)
+ return contents
diff --git a/jikimo_workorder_exception_notify/tests/__init__.py b/jikimo_workorder_exception_notify/tests/__init__.py
new file mode 100644
index 00000000..318a4c8a
--- /dev/null
+++ b/jikimo_workorder_exception_notify/tests/__init__.py
@@ -0,0 +1,2 @@
+from . import common
+from . import test_jikimo_workorder_exception_notify
diff --git a/jikimo_workorder_exception_notify/tests/common.py b/jikimo_workorder_exception_notify/tests/common.py
new file mode 100644
index 00000000..5fefe6bf
--- /dev/null
+++ b/jikimo_workorder_exception_notify/tests/common.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo import fields, Command
+from odoo.tests.common import TransactionCase, HttpCase, tagged, Form
+
+import json
+import time
+import base64
+from lxml import etree
+
+@tagged('post_install', '-at_install')
+class TestJikimoWorkorderExceptionNotifyCommonNotify(TransactionCase):
+
+ def setUp(self):
+ super(TestJikimoWorkorderExceptionNotifyCommonNotify, self).setUp()
+ # 获取最后一个工单
+ self.workorder = self.env['mrp.workorder'].search([], order='id desc', limit=1)
+
\ No newline at end of file
diff --git a/jikimo_workorder_exception_notify/tests/test_jikimo_workorder_exception_notify.py b/jikimo_workorder_exception_notify/tests/test_jikimo_workorder_exception_notify.py
new file mode 100644
index 00000000..85d304be
--- /dev/null
+++ b/jikimo_workorder_exception_notify/tests/test_jikimo_workorder_exception_notify.py
@@ -0,0 +1,62 @@
+import json
+from datetime import datetime
+from odoo.addons.jikimo_workorder_exception_notify.tests.common import TestJikimoWorkorderExceptionNotifyCommonNotify
+
+class TestJikimoWorkorderExceptionNotify(TestJikimoWorkorderExceptionNotifyCommonNotify):
+
+ def test_create_message_template(self):
+ self.assertTrue(self.env['jikimo.message.template'].search([
+ ('name', '=', '生产线无功能刀具提醒'),
+ ('model', '=', 'jikimo.workorder.exception')
+ ]))
+ self.assertTrue(self.env['jikimo.message.template'].search([
+ ('name', '=', '工单无定位数据提醒'),
+ ('model', '=', 'jikimo.workorder.exception')
+ ]))
+ self.assertTrue(self.env['jikimo.message.template'].search([
+ ('name', '=', '加工失败'),
+ ('model', '=', 'jikimo.workorder.exception')
+ ]))
+
+
+ def test_create_message_queue(self):
+ exception_record = self.env['jikimo.workorder.exception'].create({
+ 'workorder_id': self.workorder.id,
+ 'exception_code': 'YC0002',
+ 'exception_content': '无功能刀具'
+ })
+
+ bussiness_node = self.env['jikimo.message.bussiness.node'].search([
+ ('name', '=', '无功能刀具'),
+ ('model', '=', 'jikimo.workorder.exception')
+ ])
+
+ message_template = self.env['jikimo.message.template'].search([
+ ('bussiness_node_id', '=', bussiness_node.id),
+ ('model', '=', 'jikimo.workorder.exception')
+ ])
+
+ message_record = self.env['jikimo.message.queue'].search([
+ ('res_id', '=', exception_record.id),
+ ('model', '=', 'jikimo.workorder.exception'),
+ ('message_status', '=', 'pending'),
+ ('message_template_id', '=', message_template.id)
+ ])
+ self.assertTrue(message_record)
+
+
+ def test_get_message(self):
+ exception_record = self.env['jikimo.workorder.exception'].create({
+ 'workorder_id': self.workorder.id,
+ 'exception_code': 'YC0002',
+ 'exception_content': '无功能刀具'
+ })
+ message_queue_ids = self.env['jikimo.message.queue'].search([
+ ('res_id', '=', exception_record.id),
+ ('model', '=', 'jikimo.workorder.exception'),
+ ('message_status', '=', 'pending')
+ ])
+ message = self.env['jikimo.workorder.exception']._get_message(message_queue_ids)
+ self.assertTrue(message)
+
+
diff --git a/sf_base/controllers/controllers.py b/sf_base/controllers/controllers.py
index 71ed8f94..47c67322 100644
--- a/sf_base/controllers/controllers.py
+++ b/sf_base/controllers/controllers.py
@@ -38,3 +38,17 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('get_maintenance_tool_groups_Info error:%s' % e)
return json.JSONEncoder().encode(res)
+
+
+class MultiInheritController():
+ _sub_classes = []
+
+ def __init_subclass__(cls):
+ """
+ 多继承,解决多个字类时方法调用super的问题
+ """
+ super().__init_subclass__()
+ if len(cls._sub_classes) > 0 and cls not in cls._sub_classes:
+ cls.__bases__ = (cls._sub_classes[-1],)
+ if cls not in cls._sub_classes:
+ cls._sub_classes.append(cls)
diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py
index f44915f1..2a5e4d3e 100644
--- a/sf_manufacturing/controllers/controllers.py
+++ b/sf_manufacturing/controllers/controllers.py
@@ -189,6 +189,7 @@ class Manufacturing_Connect(http.Controller):
request.env['sf.production.plan'].sudo().search([('production_id', '=', production_id)]).write(
{'actual_start_time': workorder.date_start,
'state': 'processing'})
+ res.update({'workorder_id': workorder.id})
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
diff --git a/sf_manufacturing/models/mrp_routing_workcenter.py b/sf_manufacturing/models/mrp_routing_workcenter.py
index 0c380ebd..a584379f 100644
--- a/sf_manufacturing/models/mrp_routing_workcenter.py
+++ b/sf_manufacturing/models/mrp_routing_workcenter.py
@@ -40,7 +40,7 @@ class ResMrpRoutingWorkcenter(models.Model):
def get_company_id(self):
self.company_id = self.env.user.company_id.id
- company_id = fields.Many2one('res.company', compute="get_company_id", related=False)
+ company_id = fields.Many2one('res.company', compute="get_company_id", related=False, store=True)
# 排产的时候, 根据坯料的长宽高比对一下机床的最大加工尺寸.不符合就不要分配给这个加工中心(机床).
# 工单对应的工作中心,根据工序中的工作中心去匹配,
diff --git a/sf_message/controllers/main.py b/sf_message/controllers/main.py
index ab97816b..11e776dc 100644
--- a/sf_message/controllers/main.py
+++ b/sf_message/controllers/main.py
@@ -15,12 +15,13 @@ class MessageSfMrsConnect(Sf_Mrs_Connect):
def get_cnc_processing_create(self, **kw):
res = super(MessageSfMrsConnect, self).get_cnc_processing_create(**kw)
res = json.loads(res)
+ _logger.info('已进入消息推送:%s' % res)
if res.get('production_ids'):
try:
_logger.info('已编程的制造订单:%s' % res.get('production_ids'))
productions = request.env['mrp.production'].sudo().search([('id', 'in', res.get('production_ids'))])
# 过滤programming_state为已编程,tool_state为2的制造订单
- tool_state_valid_productions = productions.filtered(lambda x: x.programming_state == '已编程' and x.tool_state == '2')
+ tool_state_valid_productions = productions.filtered(lambda x: x.tool_state == '2')
if tool_state_valid_productions:
data = {
'name': tool_state_valid_productions[0].programming_no
@@ -38,3 +39,22 @@ class MessageSfMrsConnect(Sf_Mrs_Connect):
_logger.info('无效用刀异常消息推送接口:%s' % e)
return json.JSONEncoder().encode(res)
+ @http.route('/api/maintenance_logs/notify', type='json', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
+ def maintenance_logs_notify(self, **kw):
+ res = {'code': 200, 'message': '设备故障日志信息推送成功'}
+ datas = request.httprequest.data
+ ret = json.loads(datas)
+ log_id = ret.get('log_id')
+ if not log_id:
+ res = {'code': 400, 'message': '设备故障日志id不能为空'}
+ return json.JSONEncoder().encode(res)
+ try:
+ if not isinstance(log_id, list):
+ log_id = [log_id]
+ maintenance_logs = request.env['sf.maintenance.logs'].sudo().search([('id', 'in', [int(id) for id in log_id])])
+ if maintenance_logs:
+ maintenance_logs.add_queue('设备故障')
+ except Exception as e:
+ res = {'code': 400, 'message': '设备故障信息推送失败', 'error': str(e)}
+ return json.JSONEncoder().encode(res)
+
diff --git a/sf_message/data/bussiness_node.xml b/sf_message/data/bussiness_node.xml
index d9ac9ae1..a7123d44 100644
--- a/sf_message/data/bussiness_node.xml
+++ b/sf_message/data/bussiness_node.xml
@@ -111,5 +111,9 @@
quality.cnc.test
+
+ 设备故障
+ sf.maintenance.logs
+
\ No newline at end of file
diff --git a/sf_message/data/template_data.xml b/sf_message/data/template_data.xml
index f511d338..057dc009 100644
--- a/sf_message/data/template_data.xml
+++ b/sf_message/data/template_data.xml
@@ -264,5 +264,16 @@
### 待质量判定提醒
事项:共有[{{judge_num}}]({{url}})个工单需判定质量结果
+
+ 设备故障
+
+ sf.maintenance.logs
+
+ markdown
+ urgent
+ ### 设备故障及异常提醒:
+机台号:[{{maintenance_equipment_id.name}}]({{url}})
+事项:{{create_date}}故障报警
+
\ No newline at end of file
diff --git a/sf_message/models/__init__.py b/sf_message/models/__init__.py
index 25702b1e..0b9c9ad6 100644
--- a/sf_message/models/__init__.py
+++ b/sf_message/models/__init__.py
@@ -9,3 +9,4 @@ from . import sf_message_workorder
from . import sf_message_functional_tool_dismantle
from . import sf_message_mrp_production
from . import sf_message_quality_cnc_test
+from . import sf_message_maintenance_logs
diff --git a/sf_message/models/sf_message_maintenance_logs.py b/sf_message/models/sf_message_maintenance_logs.py
new file mode 100644
index 00000000..288043ff
--- /dev/null
+++ b/sf_message/models/sf_message_maintenance_logs.py
@@ -0,0 +1,22 @@
+from odoo import models, fields, api
+
+class SFMessageMaintenanceLogs(models.Model):
+ _name = 'sf.maintenance.logs'
+ _inherit = ['sf.maintenance.logs', 'jikimo.message.dispatch']
+
+ @api._model_create_multi
+ def create(self, vals_list):
+ res = super(SFMessageMaintenanceLogs, self).create(vals_list)
+ for rec in res:
+ rec.add_queue()
+ return res
+
+ def _get_message(self, message_queue_ids):
+ contents = super(SFMessageMaintenanceLogs, self)._get_message(message_queue_ids)
+ url = self.env['ir.config_parameter'].get_param('web.base.url')
+ action_id = self.env.ref('sf_maintenance.action_maintenance_logs').id
+ for index, content in enumerate(contents):
+ maintenance_logs_id = self.env['sf.maintenance.logs'].browse(message_queue_ids[index].res_id)
+ url = url + '/web#id=%s&view_type=form&action=%s' % (maintenance_logs_id.id, action_id)
+ contents[index] = content.replace('{{url}}', url)
+ return contents
\ No newline at end of file
diff --git a/sf_message/models/sf_message_template.py b/sf_message/models/sf_message_template.py
index 56346c27..5e4d66b0 100644
--- a/sf_message/models/sf_message_template.py
+++ b/sf_message/models/sf_message_template.py
@@ -14,4 +14,5 @@ class SfMessageTemplate(models.Model):
res.append('sf.functional.tool.dismantle')
res.append('purchase.order')
res.append('mrp.workorder')
+ res.append('sf.maintenance.logs')
return res
diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py
index cb56287a..c66b03bc 100644
--- a/sf_mrs_connect/controllers/controllers.py
+++ b/sf_mrs_connect/controllers/controllers.py
@@ -3,11 +3,12 @@ import logging
import os
import json
import base64
-from odoo import http
+from odoo import http, fields, models
from odoo.http import request
+from odoo.addons.sf_base.controllers.controllers import MultiInheritController
-class Sf_Mrs_Connect(http.Controller):
+class Sf_Mrs_Connect(http.Controller, MultiInheritController):
@http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*")