from datetime import datetime, timedelta from odoo import models, fields, api, _ import logging, json import requests from odoo.addons.sf_base.commons.common import Common from urllib.parse import urlencode _logger = logging.getLogger(__name__) class SFMessageWork(models.Model): _name = 'mrp.workorder' _inherit = ['mrp.workorder', 'jikimo.message.dispatch'] @api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state', 'production_id.tool_state', 'production_id.schedule_state', 'sequence', 'production_id.programming_state') def _compute_state(self): super(SFMessageWork, self)._compute_state() for workorder in self: min_sequence_wk = None work_ids = workorder.production_id.workorder_ids.filtered(lambda w: w.routing_type == '装夹预调') if work_ids: min_sequence_wk = work_ids.sorted(key=lambda w: w.sequence)[0] if ( workorder.state == 'ready' and workorder.routing_type == '装夹预调' and workorder.id == min_sequence_wk.id) or ( workorder.state == 'ready' and workorder.routing_type == '人工线下加工'): message_template = self.env["jikimo.message.template"].sudo().search( [("name", "=", '工单已下发通知')], limit=1) jikimo_message_queue = self.env['jikimo.message.queue'].sudo().search( [('res_id', '=', workorder.production_id.product_id.id), ("message_status", "in", ("pending", "sent")), ('message_template_id', '=', message_template.id)]) if not jikimo_message_queue: workorder.production_id.product_id.add_queue('工单已下发通知') def _get_message(self, message_queue_ids): contents = [] bussiness_node = None url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S") current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf) current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S') time_range = timedelta(minutes=2) template_names = { '预警': ['装夹预调工单逾期预警', 'CNC加工工单逾期预警', '解除装夹工单逾期预警', '表面工艺工单逾期预警'], '已逾期': ['装夹预调工单已逾期', 'CNC加工工单已逾期', '解除装夹工单已逾期', '表面工艺工单已逾期'] } i = 0 for message_queue_id in message_queue_ids: if message_queue_id.message_template_id.name in template_names['预警'] + template_names['已逾期']: item = message_queue_id.message_template_id bussiness_node = item.bussiness_node_id.name for reminder_time in item.reminder_time_ids: content = item.content target_time = datetime.combine(current_time_datetime.date(), datetime.min.time()).replace( hour=reminder_time.time_point, minute=0, second=0, microsecond=0 ) # logging.info(current_time) # logging.info(target_time) # logging.info(target_time - time_range) # logging.info(target_time + time_range) if target_time - time_range <= current_time_datetime <= target_time + time_range: search_condition = [ ('delivery_warning', '=', 'warning')] if bussiness_node in template_names['预警'] else [ ('delivery_warning', '=', 'overdue')] record = self.sudo().search(search_condition + [('id', '=', int(message_queue_id.res_id))]) if record: bussiness_node = item.bussiness_node_id.name # 分割业务节点名称,提取出业务节点关键字 business_node_key = bussiness_node.split('工单')[0].strip() workcenter_mapping = { '装夹预调': '工件装夹', 'CNC加工': '自动生产', '解除装夹': '工件拆卸', '表面工艺': '表面工艺外协', } workcenter_name = workcenter_mapping.get(business_node_key) active_id = self.env['mrp.workcenter'].search([('name', 'ilike', workcenter_name)], limit=1).id i += 1 if i >= 1: action_id = self.env.ref('sf_message.mrp_workorder_action_notify').id url_with_id = f"{url}/web#view_type=list&action={action_id}&active_id={active_id}" content_template = content.replace('{{url}}', url_with_id) if bussiness_node in template_names['预警']: content = content_template.replace('{{warning_num}}', str(i)) elif bussiness_node in template_names['已逾期']: content = content_template.replace('{{overdue_num}}', str(i)) contents.append(content) return contents, message_queue_ids def _overdue_or_warning_func(self): workorders = self.env['mrp.workorder'].search( [("state", "in", ["ready", "progress", "to be detected"]), ('schedule_state', '=', '已排')]) grouped_workorders = {} for workorder in workorders: routing_type = workorder.routing_type if routing_type not in grouped_workorders: grouped_workorders[routing_type] = [] grouped_workorders[routing_type].append(workorder) for routing_type, orders in grouped_workorders.items(): print(f"Routing Type: {routing_type}, Orders: {len(orders)}") for item in orders: if item.date_planned_finished: current_time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S") current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_str) current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S') date_planned_finished_str = self.env['sf.sync.common'].sudo().get_add_time( item.date_planned_finished.strftime("%Y-%m-%d %H:%M:%S")) date_planned_finished = datetime.strptime(date_planned_finished_str, '%Y-%m-%d %H:%M:%S') twelve_hours_ago = current_time_datetime - timedelta(hours=12) if current_time_datetime >= date_planned_finished and item.delivery_warning not in ['overdue']: # logging.info("------overdue-------") # logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, " # f"Planned Finish: {date_planned_finished}") item.delivery_warning = 'overdue' elif twelve_hours_ago <= current_time_datetime <= date_planned_finished and item.delivery_warning not in [ 'warning']: # logging.info("------warning-------") # logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, " # f"Planned Finish: {date_planned_finished}") item.delivery_warning = 'warning' business_node_ids = { '装夹预调_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue').id, '装夹预调_warning': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue_warning').id, 'CNC加工_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue').id, 'CNC加工_warning': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue_warning').id, '解除装夹_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue').id, '解除装夹_warning': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue_warning').id, '表面工艺_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue').id, '表面工艺_warning': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue_warning').id, } message_templates = {key: self.env["jikimo.message.template"].sudo().search([ ("model", "=", self._name), ("bussiness_node_id", "=", business_node_ids[key]) ]) for key in business_node_ids} for item in orders: if item.delivery_warning in ['overdue', 'warning']: warning_type = 'warning' if item.delivery_warning == 'warning' else 'overdue' key = f"{item.routing_type}_{warning_type}" bussiness_node_id = business_node_ids.get(key, None) if bussiness_node_id: message_template = message_templates.get(key) if message_template and message_template.id: message_queue_ids = self.env["jikimo.message.queue"].sudo().search([ ("message_template_id", "=", message_template.id), ("message_status", "=", "pending"), ("res_id", "=", item.id) ], limit=1) if not message_queue_ids: overdue_message = '工单已逾期' if item.delivery_warning == 'overdue' else '工单逾期预警' queue_method_name = f'add_queue' # 构建参数列表,其中包含item.routing_type和overdue_message args = [f'{item.routing_type}{overdue_message}'] # 获取add_queue方法并调用它,传入参数列表 getattr(item, queue_method_name)(*args) if item.delivery_warning == 'overdue': # 把消息队列中销售订单预警的状态改为取消发送 key = f"{item.routing_type}_{'warning'}" business_node_id_warning = business_node_ids.get(key, None) if business_node_id_warning: message_template_warning = self.env["jikimo.message.template"].search([ ("model", "=", self._name), ("bussiness_node_id", "=", business_node_id_warning) ], limit=1) if message_template_warning: work_order_warning = self.env['jikimo.message.queue'].search([ ('res_id', '=', item.id), ('message_status', '=', 'pending'), ('message_template_id', '=', message_template_warning.id) ]) if work_order_warning: logging.info('取消发送:%s' % work_order_warning) work_order_warning.write({'message_status': 'cancel'}) def _recover_time_warning_func(self): workorder_done = self.env['mrp.workorder'].search([("state", "in", ["done", "rework", "cancel"])]) workorder_overdue = workorder_done.filtered(lambda x: x.delivery_warning in ['overdue', 'warning']) if workorder_overdue: workorder_overdue.write({'delivery_warning': 'normal'}) message_queue_ids = self.env["jikimo.message.queue"].sudo().search([ ("message_status", "=", "pending"), ("res_id", "in", [item.id for item in workorder_overdue]) ]) if message_queue_ids: message_queue_ids.write({'message_status': 'cancel'})