# -*- coding: utf-8 -*- import base64 from odoo import api, fields, models, SUPERUSER_ID, _ from odoo.exceptions import UserError import logging from datetime import date, datetime, timedelta import requests import json from odoo.addons.sf_base.commons.common import Common class SfMaintenanceEquipmentCategory(models.Model): _inherit = 'maintenance.equipment.category' _description = '设备类别' equipment_type = fields.Selection([('机床', '机床')], string='类型', default='机床') class SfMaintenanceEquipment(models.Model): _inherit = 'maintenance.equipment' _description = '设备' crea_url = "/api/machine_tool/create" def get_no(self): partner = self.env['maintenance.equipment'].sudo().search( [('MTcode', '!=', '')], limit=1, order="id desc") if not partner: num = "%04d" % 1 else: m = int(partner.MTcode) + 1 num = "%04d" % m return num equipment_maintenance_standards_ids = fields.Many2many('equipment.maintenance.standards', 'sf_maintenance_equipment_ids', string='设备维保标准') eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准', domain="[('maintenance_type','=','保养')]") overhaul_date = fields.Date(string='下次预防检修') overhaul_period = fields.Integer(string='预防检修频次') overhaul_duration = fields.Float(string='检修时长') overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准', domain="[('maintenance_type','=','检修')]") @api.onchange('eq_maintenance_id', 'overhaul_id') def _compute_equipment_maintenance_standards_ids(self): for record in self: if record.eq_maintenance_id and record.overhaul_id: record.equipment_maintenance_standards_ids = [ (6, 0, [record.eq_maintenance_id.id, record.overhaul_id.id])] break if record.eq_maintenance_id: record.equipment_maintenance_standards_ids = [(6, 0, [record.eq_maintenance_id.id])] break if record.overhaul_id: record.equipment_maintenance_standards_ids = [(6, 0, [record.overhaul_id.id])] break else: record.equipment_maintenance_standards_ids = False MTcode = fields.Char("编码", default=get_no) created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user) equipment_type = fields.Selection([('机床', '机床')], compute='_compute_category_id') @api.depends('category_id') def _compute_category_id(self): for record in self: if record: record.equipment_type = record.category_id.equipment_type code = fields.Char('机台号') name = fields.Char('名称') knife_type = fields.Selection( [("BT40", "BT40"), ("BT30", "BT30")], default="", string="刀把类型") number_of_knife_library = fields.Integer('刀库数量(把)') rotate_speed = fields.Integer('转速') number_of_axles = fields.Selection( [("三轴", "三轴"), ("四轴", "四轴"), ("五轴", "五轴")], default="", string="轴数") # 加工进程 x_axis = fields.Integer('X轴') y_axis = fields.Integer('Y轴') z_axis = fields.Integer('Z轴') b_axis = fields.Integer('B轴') c_axis = fields.Integer('C轴') remark = fields.Char('备注') is_binding = fields.Boolean('是否绑定机床', default=False) precision_min = fields.Float('X轴定位精度min(mm)', digits=(12, 3)) precision_max = fields.Float('X轴定位精度max(mm)', digits=(12, 3)) control_system_id = fields.Many2one('sf.machine.control_system', string="控制系统") # 多个机床型号对应一个机床 brand_id = fields.Many2one('sf.machine.brand', string='品牌') type_id = fields.Many2one('sf.machine_tool.type', '型号') state = fields.Selection( [("正常", "正常"), ("故障", "故障"), ("不可用", "不可用")], default='正常', string="机床状态") # 0606新增字段 machine_tool_picture = fields.Binary('图片') heightened_way = fields.Selection([ ('sifudianji', '伺服电机驱动'), ('youyagang', '油压缸驱动'), ('chilunjia', '齿轮架驱动') ], string="主轴加高方式", default='sifudianji') workpiece_load = fields.Char('工件最大负载(kg)') lead_screw = fields.Char('丝杆') workbench_L = fields.Char('工作台长度(mm)') workbench_W = fields.Char('工作台宽度(mm)') guide_rail = fields.Char('导轨') machine_tool_L = fields.Char('机床长度(mm)') machine_tool_W = fields.Char('机床宽度(mm)') machine_tool_H = fields.Char('机床高度(mm)') feed_speed = fields.Char('进给速度(mm/min)') tool_speed = fields.Char('刀具速度(m/min)') distance_min = fields.Char('主轴端面至工作台面距离MIN(mm)') distance_max = fields.Char('主轴端面至工作台面距离MAX(mm)') taper = fields.Char('主轴锥度(°)') torque = fields.Char('主轴电机扭矩(n/m)') motor_power = fields.Char('主轴电机功率(kw)') tool_quality_max = fields.Char('刀具最大质量(kg)') tool_long_max = fields.Char('刀具最大长度(mm)') tool_diameter_max = fields.Char('刀具刀径max(mm)') tool_diameter_min = fields.Char('刀具刀径min(mm)') machine_tool_category = fields.Many2one('sf.machine_tool.category', string='机床类型') # 一个机床对应一個加工工厂,一个加工工厂对应多个机床 factory_id = fields.Many2one('res.partner', string='所属工厂', domain="[('is_factory', '=', True)]") # 一个机床对应一个供应商,一个供应商对应多个机床 supplier_id = fields.Many2one('res.partner', string='制造商', domain="[('is_vendor', '=', True)]") registration_date = fields.Date('注册日期') state_zc = fields.Selection([("已注册", "已注册"), ("未注册", "未注册")], string="注册状态", default='未注册', tracking=True) active = fields.Boolean('有效', default=True) # 多个型号对应一个机床 machine_tool_id = fields.Many2one('sf.machine_tool', '机床') sf_maintenance_logs_ids = fields.One2many('sf.maintenance.logs','maintenance_equipment_id', '设备故障日志') def name_get(self): result = [] for parameter in self: if parameter.code: name = parameter.name + '-' + parameter.code else: name = parameter.name result.append((parameter.id, name)) return result @api.constrains('rotate_speed') def _check_rotate_speed(self): if self.rotate_speed <= 0: raise UserError("转速不能为0") @api.constrains('precision') def _check_precision(self): if self.precision <= 0.00: raise UserError("加工精度不能为0") @api.constrains('number_of_knife_library') def _check_number_of_knife_library(self): if self.number_of_knife_library <= 0: raise UserError("刀库数量不能为0") @api.constrains('x_axis') def _check_x_axis(self): if self.x_axis <= 0: raise UserError("加工行程里x轴不能为0") @api.constrains('y_axis') def _check_y_axis(self): if self.y_axis <= 0: raise UserError("加工行程里y轴不能为0") @api.constrains('z_axis') def _check_z_axis(self): if self.z_axis <= 0: raise UserError("加工行程里z轴不能为0") @api.constrains('b_axis') def _check_b_axis(self): if self.number_of_axles == '四轴': print(self.number_of_axles) if self.b_axis <= 0: raise UserError("加工行程里b轴不能为0") @api.constrains('c_axis') def _check_c_axis(self): if self.number_of_axles == '五轴': if self.c_axis <= 0: raise UserError("加工行程里c轴不能为0") @api.onchange('type_id') def get_type_info(self): for item in self: item.knife_type = item.type_id.knife_type item.number_of_knife_library = item.type_id.number_of_knife_library item.number_of_axles = item.type_id.number_of_axles item.rotate_speed = item.type_id.rotate_speed item.precision_min = item.type_id.precision_min item.precision_max = item.type_id.precision_max item.control_system_id = item.type_id.control_system_id item.x_axis = item.type_id.x_axis item.y_axis = item.type_id.y_axis item.z_axis = item.type_id.z_axis item.b_axis = item.type_id.b_axis item.c_axis = item.type_id.c_axis item.machine_tool_picture = item.type_id.machine_tool_picture item.heightened_way = item.type_id.heightened_way item.workpiece_load = item.type_id.workpiece_load item.lead_screw = item.type_id.lead_screw item.workbench_L = item.type_id.workbench_L item.workbench_W = item.type_id.workbench_W item.guide_rail = item.type_id.guide_rail item.machine_tool_L = item.type_id.machine_tool_L item.machine_tool_W = item.type_id.machine_tool_W item.machine_tool_H = item.type_id.machine_tool_H item.feed_speed = item.type_id.feed_speed item.tool_speed = item.type_id.tool_speed item.distance_min = item.type_id.distance_min item.distance_max = item.type_id.distance_max item.taper = item.type_id.taper item.torque = item.type_id.torque item.motor_power = item.type_id.motor_power item.tool_quality_max = item.type_id.tool_quality_max item.tool_long_max = item.type_id.tool_long_max item.tool_diameter_max = item.type_id.tool_diameter_max item.tool_diameter_min = item.type_id.tool_diameter_min item.machine_tool_category = item.type_id.machine_tool_category.id item.brand_id = item.type_id.brand_id.id # 注册同步机床 def enroll_machine_tool(self): sf_sync_config = self.env['res.config.settings'].get_values() token = sf_sync_config['token'] sf_secret_key = sf_sync_config['sf_secret_key'] headers = Common.get_headers(self, token, sf_secret_key) strurl = sf_sync_config['sf_url'] + self.crea_url objs_all = self.env['maintenance.equipment'].search([('MTcode', '=', self.MTcode)]) machine_tool_list = [] if objs_all: for item in objs_all: if item.machine_tool_picture != False: image = base64.b64encode(item.machine_tool_picture).decode('utf-8') else: image = False val = { 'MTcode': item.MTcode, 'factory_token': token, 'id': item.id, 'name': item.name, 'code': item.code, 'precision': item.precision, 'knife_type': item.knife_type, 'number_of_knife_library': item.number_of_knife_library, 'rotate_speed': item.rotate_speed, 'number_of_axles': item.number_of_axles, 'control_system_id': self.env['sf.machine.control_system'].search( [('id', '=', item.control_system_id.id)]).code, 'type_id': self.env['sf.machine_tool.type'].search([('id', '=', item.type_id.id)]).code, 'brand_id': self.env['sf.machine.brand'].search([('id', '=', item.brand_id.id)]).code, 'supplier_id': item.supplier_id.id, 'x_axis': item.x_axis, 'y_axis': item.y_axis, 'z_axis': item.z_axis, 'b_axis': item.b_axis, 'c_axis': item.c_axis, 'state': item.state, 'active': item.active, 'machine_tool_picture': image, 'heightened_way': item.heightened_way, 'workpiece_load': item.workpiece_load, 'lead_screw': item.lead_screw, 'workbench_L': item.workbench_L, 'workbench_W': item.workbench_W, 'guide_rail': item.guide_rail, 'machine_tool_L': item.machine_tool_L, 'machine_tool_W': item.machine_tool_W, 'machine_tool_H': item.machine_tool_H, 'feed_speed': item.feed_speed, 'tool_speed': item.tool_speed, 'distance': item.distance, 'taper': item.taper, 'torque': item.torque, 'motor_power': item.motor_power, 'tool_quality_max': item.tool_quality_max, 'tool_long_max': item.tool_long_max, 'tool_diameter_max': item.tool_diameter_max, 'machine_tool_category': item.machine_tool_category.code, } machine_tool_list.append(val) # kw = machine_tool_list kw = json.dumps(machine_tool_list, ensure_ascii=False) r = requests.post(strurl, json={}, data={'kw': kw, 'token': token}, headers=headers) ret = r.json() self.code = ret['message'] self.state_zc = "已注册" if r == 200: return "机床注册成功" else: raise UserError("没有注册机床信息") # 修改原生方法,生成维保日期 @api.depends('effective_date', 'period', 'maintenance_ids.request_date', 'maintenance_ids.close_date', 'overhaul_period') def _compute_next_maintenance(self): date_now = fields.Date.context_today(self) equipments = self.filtered(lambda x: x.period > 0) if equipments: for equipment in equipments: next_maintenance_todo = self.env['maintenance.request'].search([ ('equipment_id', '=', equipment.id), ('sf_maintenance_type', '=', '保养'), ('stage_id.done', '!=', True), ('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), ('close_date', '!=', False)], order="close_date desc", limit=1) if next_maintenance_todo and last_maintenance_done: next_date = next_maintenance_todo.request_date date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date # If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2 times the period and next request is in the future # We use 2 times the period to avoid creation too closed request from a manually one created if date_gap > timedelta(0) and date_gap > timedelta( days=equipment.period) * 2 and next_maintenance_todo.request_date > date_now: # If the new date still in the past, we set it for today if last_maintenance_done.close_date + timedelta(days=equipment.period) < date_now: next_date = date_now else: next_date = last_maintenance_done.close_date + timedelta(days=equipment.period) elif next_maintenance_todo: next_date = next_maintenance_todo.request_date date_gap = next_maintenance_todo.request_date - date_now # If next maintenance to do is in the future, and in more than 2 times the period, we insert an new request # We use 2 times the period to avoid creation too closed request from a manually one created if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.period) * 2: next_date = date_now + timedelta(days=equipment.period) elif last_maintenance_done: next_date = last_maintenance_done.close_date + timedelta(days=equipment.period) # If when we add the period to the last maintenance done and we still in past, we plan it for today if next_date < date_now: next_date = date_now else: next_date = equipment.effective_date + timedelta(days=equipment.period) equipment.next_action_date = next_date else: self.next_action_date = False overhaul_equipments = self.filtered(lambda x: x.overhaul_period > 0) if overhaul_equipments: for equipment in overhaul_equipments: next_maintenance_todo = self.env['maintenance.request'].search([ ('equipment_id', '=', equipment.id), ('sf_maintenance_type', '=', '检修'), ('stage_id.done', '!=', True), ('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), ('close_date', '!=', False)], order="close_date desc", limit=1) if next_maintenance_todo and last_maintenance_done: next_date = next_maintenance_todo.request_date date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date # If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2 times the period and next request is in the future # We use 2 times the period to avoid creation too closed request from a manually one created if date_gap > timedelta(0) and date_gap > timedelta( days=equipment.overhaul_period) * 2 and next_maintenance_todo.request_date > date_now: # If the new date still in the past, we set it for today if last_maintenance_done.close_date + timedelta(days=equipment.overhaul_period) < date_now: next_date = date_now else: next_date = last_maintenance_done.close_date + timedelta(days=equipment.overhaul_period) elif next_maintenance_todo: next_date = next_maintenance_todo.request_date date_gap = next_maintenance_todo.request_date - date_now # If next maintenance to do is in the future, and in more than 2 times the period, we insert an new request # We use 2 times the period to avoid creation too closed request from a manually one created if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.overhaul_period) * 2: next_date = date_now + timedelta(days=equipment.overhaul_period) elif last_maintenance_done: next_date = last_maintenance_done.close_date + timedelta(days=equipment.overhaul_period) # If when we add the period to the last maintenance done and we still in past, we plan it for today if next_date < date_now: next_date = date_now else: next_date = equipment.effective_date + timedelta(days=equipment.overhaul_period) equipment.overhaul_date = next_date else: self.overhaul_date = False # 拼接维保请求字符串 def _prepare_maintenance_request_vals(self, date): self.ensure_one() return { 'name': _('Preventive Maintenance - %s', self.name), 'request_date': date, 'schedule_date': date, 'category_id': self.category_id.id, 'equipment_id': self.id, 'maintenance_type': 'preventive', 'owner_user_id': self.owner_user_id.id, 'user_id': self.technician_user_id.id, 'maintenance_team_id': self.maintenance_team_id.id, 'duration': self.maintenance_duration, 'company_id': self.company_id.id or self.env.company.id, 'equipment_maintenance_id': self.eq_maintenance_id.id, 'sf_maintenance_type': '保养' } # 拼接维保请求字符串 def _prepare_maintenance_request_vals1(self, date): self.ensure_one() return { 'name': _('Preventive Maintenance - %s', self.name), 'request_date': date, 'schedule_date': date, 'category_id': self.category_id.id, 'equipment_id': self.id, 'maintenance_type': 'preventive', 'owner_user_id': self.owner_user_id.id, 'user_id': self.technician_user_id.id, 'maintenance_team_id': self.maintenance_team_id.id, 'duration': self.overhaul_duration, 'company_id': self.company_id.id or self.env.company.id, 'equipment_maintenance_id': self.overhaul_id.id, 'sf_maintenance_type': '检修' } # 创建维保请求 def _create_new_request(self, date): self.ensure_one() vals = self._prepare_maintenance_request_vals(date) maintenance_requests = self.env['maintenance.request'].create(vals) return maintenance_requests def _create_new_request1(self, date): self.ensure_one() vals = self._prepare_maintenance_request_vals1(date) maintenance_requests = self.env['maintenance.request'].create(vals) return maintenance_requests # 生成维保请求定时器 @api.model def _cron_generate_requests(self): """ Generates maintenance request on the next_action_date or today if none exists """ for equipment in self.search([('period', '>', 0)]): next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False), ('equipment_id', '=', equipment.id), ('maintenance_type', '=', 'preventive'), ('request_date', '=', equipment.next_action_date), ('sf_maintenance_type', '=', '保养')]) if not next_requests: equipment._create_new_request(equipment.next_action_date) for equipment in self.search([('overhaul_period', '>', 0)]): next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False), ('equipment_id', '=', equipment.id), ('maintenance_type', '=', 'preventive'), ('request_date', '=', equipment.overhaul_date), ('sf_maintenance_type', '=', '检修')]) if not next_requests: equipment._create_new_request1(equipment.overhaul_date) image_id = fields.Many2many('maintenance.equipment.image', 'equipment_id', string='设备图文') class MaintenanceStandardImage(models.Model): _name = 'maintenance.equipment.image' _description = '设备图文展示' image = fields.Binary(string='设备图文') equipment_id = fields.Many2many('maintenance.equipment', 'image_id', string='设备')