198 lines
13 KiB
Python
198 lines
13 KiB
Python
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'})
|
||
|
||
def write(self, vals):
|
||
res = super(SFMessageWork, self).write(vals)
|
||
if ('leave_id' in vals and vals['leave_id'] is False or 'date_planned_start' in vals and vals['date_planned_start'] is False) \
|
||
and self.schedule_state != '未排':
|
||
self.add_queue('计划数据异常跟踪')
|
||
return res
|