diff --git a/jikimo_workorder_exception/controllers/main.py b/jikimo_workorder_exception/controllers/main.py index 6a17f958..03744ff9 100644 --- a/jikimo_workorder_exception/controllers/main.py +++ b/jikimo_workorder_exception/controllers/main.py @@ -21,8 +21,8 @@ class WorkorderExceptionConroller(http.Controller): 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'): + ret = json.loads(datas) + if not ret.get('RfidCode') or not ret.get('coding'): res = {'Succeed': False, 'ErrorCode': 400, 'Error': '参数错误'} return json.JSONEncoder().encode(res) @@ -38,7 +38,7 @@ class WorkorderExceptionConroller(http.Controller): # 创建工单异常记录,关联工单 request.env['jikimo.workorder.exception'].sudo().create({ 'workorder_id': workorder.id, - 'exception_code': ret.get('ErrorType'), + 'exception_code': ret.get('coding'), 'exception_content': ret.get('Error', '') }) diff --git a/jikimo_workorder_exception_notify/data/template_data.xml b/jikimo_workorder_exception_notify/data/template_data.xml index 554ef2c2..dec81e71 100644 --- a/jikimo_workorder_exception_notify/data/template_data.xml +++ b/jikimo_workorder_exception_notify/data/template_data.xml @@ -10,7 +10,7 @@ urgent ### 生产线无功能刀具提醒 单号:工单[{{workorder_id.production_id.name}}]({{url}}) -原因:生产线无加工程序用的{{function_tool_name}}名称功能刀具 +原因:生产线无加工程序要用的功能刀具 工单无定位数据提醒 @@ -19,7 +19,7 @@ markdown urgent - ### 生产线无功能刀具提醒 + ### 工单无定位数据提醒 单号:工单[{{workorder_id.production_id.name}}]({{url}}) 原因:无装夹定位测量数据 diff --git a/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py b/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py index bbe69ab5..9849f2cd 100644 --- a/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py +++ b/jikimo_workorder_exception_notify/models/jikimo_workorder_exception.py @@ -34,7 +34,7 @@ class JikimoWorkorderException(models.Model): rec.add_queue('无定位数据') elif rec.exception_code == 'YC0004': # 无FTP文件,调用cloud接口 - data = {'name': rec.workorder_id.programming_no, 'exception_code': 'YC0004'} + data = {'name': rec.workorder_id.production_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' 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 index 85d304be..92886ff3 100644 --- a/jikimo_workorder_exception_notify/tests/test_jikimo_workorder_exception_notify.py +++ b/jikimo_workorder_exception_notify/tests/test_jikimo_workorder_exception_notify.py @@ -14,12 +14,25 @@ class TestJikimoWorkorderExceptionNotify(TestJikimoWorkorderExceptionNotifyCommo ('model', '=', 'jikimo.workorder.exception') ])) self.assertTrue(self.env['jikimo.message.template'].search([ - ('name', '=', '加工失败'), + ('name', '=', '工单加工失败提醒'), ('model', '=', 'jikimo.workorder.exception') ])) + def test_create_message_queue_yc0001(self): + exception_record = self.env['jikimo.workorder.exception'].create({ + 'workorder_id': self.workorder.id, + 'exception_code': 'YC0001', + 'exception_content': '无CNC程序' + }) - def test_create_message_queue(self): + message_record = self.env['jikimo.message.queue'].search([ + ('res_id', '=', exception_record.id), + ('model', '=', 'jikimo.workorder.exception'), + ('message_status', '=', 'pending') + ]) + self.assertFalse(message_record) + + def test_create_message_queue_yc0002(self): exception_record = self.env['jikimo.workorder.exception'].create({ 'workorder_id': self.workorder.id, 'exception_code': 'YC0002', @@ -43,7 +56,45 @@ class TestJikimoWorkorderExceptionNotify(TestJikimoWorkorderExceptionNotifyCommo ('message_template_id', '=', message_template.id) ]) self.assertTrue(message_record) + + def test_create_message_queue_yc0003(self): + exception_record = self.env['jikimo.workorder.exception'].create({ + 'workorder_id': self.workorder.id, + 'exception_code': 'YC0003', + '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_create_message_queue_yc0004(self): + exception_record = self.env['jikimo.workorder.exception'].create({ + 'workorder_id': self.workorder.id, + 'exception_code': 'YC0004', + 'exception_content': '无CNC程序' + }) + + message_record = self.env['jikimo.message.queue'].search([ + ('res_id', '=', exception_record.id), + ('model', '=', 'jikimo.workorder.exception'), + ('message_status', '=', 'pending') + ]) + self.assertFalse(message_record) def test_get_message(self): exception_record = self.env['jikimo.workorder.exception'].create({ diff --git a/mrp_workorder/i18n/zh_CN.po b/mrp_workorder/i18n/zh_CN.po index 79a02876..18363c0a 100644 --- a/mrp_workorder/i18n/zh_CN.po +++ b/mrp_workorder/i18n/zh_CN.po @@ -1273,3 +1273,18 @@ msgstr "" #: model:product.template,description_sale:mrp_workorder.product_template_stool_top msgid "wooden stool top" msgstr "" + +#. module: mrp_workorder +#: model:quality.point.test_type,name:mrp_workorder.test_type_register_consumed_materials +msgid "Register Consumed Materials" +msgstr "登记消耗材料" + +#. module: mrp_workorder +#: model:quality.point.test_type,name:mrp_workorder.test_type_register_byproducts +msgid "Register By-products" +msgstr "按产品注册" + +#. module: mrp_workorder +#: model:quality.point.test_type,name:mrp_workorder.test_type_print_label +msgid "Print label" +msgstr "打印标签" \ No newline at end of file diff --git a/quality/i18n/zh_CN.po b/quality/i18n/zh_CN.po index 267c0196..68834fbc 100644 --- a/quality/i18n/zh_CN.po +++ b/quality/i18n/zh_CN.po @@ -1050,3 +1050,13 @@ msgstr "工作中心故障" #: model:ir.model.fields,field_description:quality.field_quality_point_test_type__active msgid "active" msgstr "有效" + +#. module: quality +#: model:quality.point.test_type,name:quality.test_type_instructions +msgid "Instructions" +msgstr "使用说明" + +#. module: quality +#: model:quality.point.test_type,name:quality.test_type_picture +msgid "Take a Picture" +msgstr "照片" \ No newline at end of file diff --git a/quality/models/quality.py b/quality/models/quality.py index 7edff2c7..83fd2258 100644 --- a/quality/models/quality.py +++ b/quality/models/quality.py @@ -15,7 +15,7 @@ class TestType(models.Model): _description = "Quality Control Test Type" # Used instead of selection field in order to hide a choice depending on the view. - name = fields.Char('Name', required=True) + name = fields.Char('Name', required=True,translate=True) technical_name = fields.Char('Technical name', required=True) active = fields.Boolean('active', default=True) diff --git a/quality_control/i18n/zh_CN.po b/quality_control/i18n/zh_CN.po index 8fd98237..d091d9b5 100644 --- a/quality_control/i18n/zh_CN.po +++ b/quality_control/i18n/zh_CN.po @@ -1185,3 +1185,14 @@ msgstr "请先进行质量检查!" #: model_terms:ir.ui.view,arch_db:quality_control.quality_alert_team_view_form msgid "e.g. The QA Masters" msgstr "例如:QA大师" + + +#. module: quality_control +#: model:quality.point.test_type,name:quality_control.test_type_passfail +msgid "Pass - Fail" +msgstr "通过-失败" + +#. module: quality_control +#: model:quality.point.test_type,name:quality_control.test_type_measure +msgid "Measure" +msgstr "测量" \ No newline at end of file diff --git a/quality_control/models/__init__.py b/quality_control/models/__init__.py index b31b19e7..c6817692 100644 --- a/quality_control/models/__init__.py +++ b/quality_control/models/__init__.py @@ -6,3 +6,4 @@ from . import stock_move from . import stock_move_line from . import stock_picking from . import stock_lot +from . import product_category \ No newline at end of file diff --git a/quality_control/models/product_category.py b/quality_control/models/product_category.py new file mode 100644 index 00000000..9b5535d4 --- /dev/null +++ b/quality_control/models/product_category.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from math import sqrt +from dateutil.relativedelta import relativedelta +from datetime import datetime + +import random + +from odoo import api, models, fields, _ +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round +from odoo.osv.expression import OR + + +class ProductCategory(models.Model): + _inherit = 'product.category' + @api.model + def name_search(self, name='', args=None, operator='ilike', limit=100): + if args is None: + args = [] + # 添加过滤条件,确保只返回名称为 'abc' 的记录 + args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])] + + # 调用父类的 name_search 方法 + return super(ProductCategory, self).name_search(name, args=args, operator=operator, limit=limit) \ No newline at end of file diff --git a/sf_base/models/base.py b/sf_base/models/base.py index c3152098..3d83cc96 100644 --- a/sf_base/models/base.py +++ b/sf_base/models/base.py @@ -394,3 +394,11 @@ class MachineToolCategory(models.Model): active = fields.Boolean('有效', default=True) category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别', default='shukong') + + +class MachiningAccuracy(models.Model): + _name = 'sf.machining.accuracy' + _description = '加工精度' + name = fields.Char('一般公差', index=True) + standard_tolerance = fields.Char(string="标准公差") + sync_id = fields.Char('同步ID') diff --git a/sf_base/security/ir.model.access.csv b/sf_base/security/ir.model.access.csv index 3d4ba3a0..34605cca 100644 --- a/sf_base/security/ir.model.access.csv +++ b/sf_base/security/ir.model.access.csv @@ -247,3 +247,7 @@ access_sf_cutting_tool_type_group_sf_stock_manager,sf_cutting_tool_type_group_sf access_sf_cutting_tool_material_group_plan_dispatch,sf_cutting_tool_material_group_plan_dispatch,model_sf_cutting_tool_material,sf_base.group_plan_dispatch,1,0,0,0 access_sf_functional_cutting_tool_model_group_plan_dispatch,sf_functional_cutting_tool_model_group_plan_dispatch,model_sf_functional_cutting_tool_model,sf_base.group_plan_dispatch,1,0,0,0 access_sf_cutting_tool_type_group_plan_dispatch,sf_cutting_tool_type_group_plan_dispatch,model_sf_cutting_tool_type,sf_base.group_plan_dispatch,1,0,0,0 + + +access_sf_machining_accuracy,sf_machining_accuracy,model_sf_machining_accuracy,base.group_user,1,0,0,0 +access_sf_machining_accuracy_admin,sf_machining_accuracy_admin,model_sf_machining_accuracy,base.group_system,1,0,0,0 diff --git a/sf_base/views/base_view.xml b/sf_base/views/base_view.xml index 8127efb7..eb2c1571 100644 --- a/sf_base/views/base_view.xml +++ b/sf_base/views/base_view.xml @@ -614,4 +614,23 @@ sf.machine.control_system tree + + #------------------加工精度------------------ + + tree.sf.machining.accuracy + sf.machining.accuracy + + + + + + + + + + 加工精度 + ir.actions.act_window + sf.machining.accuracy + tree + \ No newline at end of file diff --git a/sf_base/views/menu_view.xml b/sf_base/views/menu_view.xml index 21bb519d..4c662976 100644 --- a/sf_base/views/menu_view.xml +++ b/sf_base/views/menu_view.xml @@ -141,12 +141,18 @@ sequence="1" action="action_sf_machine_brand"/> + diff --git a/sf_dlm_management/views/product_template_management_view.xml b/sf_dlm_management/views/product_template_management_view.xml index 8f58b1ad..1862e33c 100644 --- a/sf_dlm_management/views/product_template_management_view.xml +++ b/sf_dlm_management/views/product_template_management_view.xml @@ -16,8 +16,6 @@ - - + + + + + + + + + + + diff --git a/sf_maintenance/__init__.py b/sf_maintenance/__init__.py index dc5e6b69..2ae6446f 100644 --- a/sf_maintenance/__init__.py +++ b/sf_maintenance/__init__.py @@ -2,3 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import models +from . import wizard diff --git a/sf_maintenance/__manifest__.py b/sf_maintenance/__manifest__.py index 88c53ff8..63f4604a 100644 --- a/sf_maintenance/__manifest__.py +++ b/sf_maintenance/__manifest__.py @@ -18,6 +18,7 @@ 'views/equipment_maintenance_standards_views.xml', 'views/maintenance_request_views.xml', 'views/maintenance_equipment_category_views.xml', + 'wizard/maintenance_request_wizard.xml', ], 'installable': True, 'application': False, diff --git a/sf_maintenance/models/sf_maintenance.py b/sf_maintenance/models/sf_maintenance.py index d5bfa6b4..3d68bb9a 100644 --- a/sf_maintenance/models/sf_maintenance.py +++ b/sf_maintenance/models/sf_maintenance.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- import json import base64 +import logging from datetime import timedelta import requests from odoo.addons.sf_base.commons.common import Common from odoo import api, fields, models, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError class SfMaintenanceEquipmentCategory(models.Model): @@ -122,6 +123,13 @@ class SfMaintenanceEquipment(models.Model): 'sf_maintenance_equipment_ids', string='设备维保标准') eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准', domain="[('maintenance_type','=','保养')]") + + initial_action_date = fields.Date(string='重置保养日期') + initial_action_date_old = fields.Date(string='重置保养日期(旧)') + next_action_date = fields.Date(string='下次预防保养') + + initial_overhaul_date = fields.Date(string='重置维修日期') + initial_overhaul_date_old = fields.Date(string='重置维修日期(旧)') overhaul_date = fields.Date(string='下次预防检修') overhaul_period = fields.Integer(string='预防检修频次') overhaul_duration = fields.Float(string='检修时长') @@ -129,6 +137,61 @@ class SfMaintenanceEquipment(models.Model): overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准', domain="[('maintenance_type','=','检修')]") + def confirm_maintenance(self): + """ + 确认保养/检修 + """ + context = self.env.context + if context['type'] == '保养': + if not self.initial_action_date: + raise ValidationError('重置保养日期不能为空!!') + elif self.initial_action_date < fields.Date.today(): + raise ValidationError('重置保养日期不能小于当前日期!!') + elif context['type'] == '检修': + if not self.initial_overhaul_date: + raise ValidationError('重置检修日期不能为空!!') + elif self.initial_overhaul_date < fields.Date.today(): + raise ValidationError('重置检修日期不能小于当前日期!!') + + request_ids = self.env['maintenance.request'].search([('stage_id.done', '=', False), + ('equipment_id', '=', self.id), + ('maintenance_type', '=', 'preventive'), + ('sf_maintenance_type', '=', context['type'])]) + + if not request_ids: + return self.create_maintenance_request(context['type']) + else: + return { + "type": "ir.actions.act_window", + "res_model": "maintenance.request.wizard", + "views": [[False, "form"]], + "target": "new", + 'context': { + 'equipment_id': self.id + } + } + + def create_maintenance_request(self, maintenance_request_type): + """ + 根据条件创建维保计划 + """ + if maintenance_request_type == '保养': + self._create_new_request(self.initial_action_date + timedelta(days=self.period)) + self.initial_action_date_old = self.initial_action_date + elif maintenance_request_type == '检修': + self._create_new_request1(self.initial_overhaul_date + timedelta(days=self.overhaul_period)) + self.initial_overhaul_date_old = self.initial_overhaul_date + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': f'创建{maintenance_request_type}计划', + 'message': f'新{maintenance_request_type}维保计划创建成功', + 'type': 'success', + 'next': {'type': 'ir.actions.act_window_close'}, + } + } + @api.onchange('eq_maintenance_id', 'overhaul_id') def _compute_equipment_maintenance_standards_ids(self): for record in self: @@ -591,11 +654,13 @@ class SfMaintenanceEquipment(models.Model): ('equipment_id', '=', equipment.id), ('sf_maintenance_type', '=', '保养'), ('stage_id.done', '!=', True), + ('active', '!=', False), ('close_date', '=', False)], order="request_date asc", limit=1) last_maintenance_done = self.env['maintenance.request'].search([ ('equipment_id', '=', equipment.id), ('sf_maintenance_type', '=', '保养'), ('stage_id.done', '=', True), + ('active', '!=', False), ('close_date', '!=', False)], order="close_date desc", limit=1) if next_maintenance_todo and last_maintenance_done: next_date = next_maintenance_todo.request_date @@ -624,7 +689,7 @@ class SfMaintenanceEquipment(models.Model): if next_date < date_now: next_date = date_now else: - next_date = equipment.effective_date + timedelta(days=equipment.period) + next_date = equipment.initial_action_date + timedelta(days=equipment.period) equipment.next_action_date = next_date else: self.next_action_date = False @@ -635,11 +700,13 @@ class SfMaintenanceEquipment(models.Model): ('equipment_id', '=', equipment.id), ('sf_maintenance_type', '=', '检修'), ('stage_id.done', '!=', True), + ('active', '!=', False), ('close_date', '=', False)], order="request_date asc", limit=1) last_maintenance_done = self.env['maintenance.request'].search([ ('equipment_id', '=', equipment.id), ('sf_maintenance_type', '=', '检修'), ('stage_id.done', '=', True), + ('active', '!=', False), ('close_date', '!=', False)], order="close_date desc", limit=1) if next_maintenance_todo and last_maintenance_done: next_date = next_maintenance_todo.request_date @@ -668,7 +735,7 @@ class SfMaintenanceEquipment(models.Model): if next_date < date_now: next_date = date_now else: - next_date = equipment.effective_date + timedelta(days=equipment.overhaul_period) + next_date = equipment.initial_overhaul_date + timedelta(days=equipment.overhaul_period) equipment.overhaul_date = next_date else: self.overhaul_date = False @@ -735,6 +802,7 @@ class SfMaintenanceEquipment(models.Model): next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False), ('equipment_id', '=', equipment.id), ('maintenance_type', '=', 'preventive'), + ('active', '=', True), ('request_date', '=', equipment.next_action_date), ('sf_maintenance_type', '=', '保养')]) if not next_requests: @@ -743,6 +811,7 @@ class SfMaintenanceEquipment(models.Model): next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False), ('equipment_id', '=', equipment.id), ('maintenance_type', '=', 'preventive'), + ('active', '=', True), ('request_date', '=', equipment.overhaul_date), ('sf_maintenance_type', '=', '检修')]) if not next_requests: diff --git a/sf_maintenance/models/sf_maintenance_requests.py b/sf_maintenance/models/sf_maintenance_requests.py index 8686926b..397c8c90 100644 --- a/sf_maintenance/models/sf_maintenance_requests.py +++ b/sf_maintenance/models/sf_maintenance_requests.py @@ -14,6 +14,8 @@ class SfMaintenanceEquipmentCategory(models.Model): equipment_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准', domain="[('maintenance_type','=',sf_maintenance_type)]") + active = fields.Boolean('有效', default=True) + @api.onchange('sf_maintenance_type') def _compute_equipment_maintenance_request_id(self): for record in self: diff --git a/sf_maintenance/security/ir.model.access.csv b/sf_maintenance/security/ir.model.access.csv index abbd4878..9a20f67f 100644 --- a/sf_maintenance/security/ir.model.access.csv +++ b/sf_maintenance/security/ir.model.access.csv @@ -20,7 +20,8 @@ access_maintenance_equipment_agv_log,maintenance_equipment_agv_log,model_mainten -access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,0,0,0 +access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,1,1,0 +access_maintenance_wizard_system_user,maintenance.request.wizard system user,model_maintenance_request_wizard,base.group_user,1,1,1,0 access_maintenance_equipment_group_plan_dispatch,maintenance.equipment,maintenance.model_maintenance_equipment,sf_base.group_plan_dispatch,1,0,0,0 access_maintenance_equipment_oee_group_plan_dispatch,maintenance_equipment_oee,model_maintenance_equipment_oee,sf_base.group_plan_dispatch,1,0,0,0 diff --git a/sf_maintenance/views/maintenance_views.xml b/sf_maintenance/views/maintenance_views.xml index 8c6cb40d..4fe044d3 100644 --- a/sf_maintenance/views/maintenance_views.xml +++ b/sf_maintenance/views/maintenance_views.xml @@ -60,9 +60,9 @@ - + + domain="[('brand_id', '=', brand_id)]"/> @@ -73,7 +73,7 @@ + options="{'no_create': True}"/>