131 lines
6.7 KiB
Python
131 lines
6.7 KiB
Python
import datetime
|
|
from collections import defaultdict
|
|
from odoo import fields, models
|
|
from odoo.addons.resource.models.resource import Intervals
|
|
|
|
|
|
class ResWorkcenter(models.Model):
|
|
_name = "mrp.workcenter"
|
|
_inherit = ['mrp.workcenter', 'mail.thread']
|
|
|
|
# 生产线显示
|
|
production_line_show = fields.Char(string='生产线名称')
|
|
equipment_id = fields.Many2one('maintenance.equipment', string="设备", tracking=True)
|
|
production_line_id = fields.Many2one('sf.production.line', string='生产线',
|
|
related='equipment_id.production_line_id', store=True)
|
|
is_process_outsourcing = fields.Boolean('工艺外协')
|
|
users_ids = fields.Many2many("res.users", 'users_workcenter', tracking=True)
|
|
|
|
def write(self, vals):
|
|
if 'users_ids' in vals:
|
|
old_users = self.users_ids
|
|
res = super(ResWorkcenter, self).write(vals)
|
|
new_users = self.users_ids
|
|
added_users = new_users - old_users
|
|
removed_users = old_users - new_users
|
|
if added_users or removed_users:
|
|
message = "增加 → %s ; 移除 → %s (可操作用户)" % (
|
|
# ','.join(added_users.mapped('name')), ','.join(removed_users.mapped('name')))
|
|
added_users.mapped('name'), removed_users.mapped('name'))
|
|
self.message_post(body=message)
|
|
return res
|
|
return super(ResWorkcenter, self).write(vals)
|
|
|
|
name = fields.Char('Work Center', related='resource_id.name', store=True, readonly=False, tracking=True)
|
|
time_efficiency = fields.Float('Time Efficiency', related='resource_id.time_efficiency', default=100, store=True,
|
|
readonly=False, tracking=True)
|
|
default_capacity = fields.Float(
|
|
'Capacity', default=1.0,
|
|
help="Default number of pieces (in product UoM) that can be produced in parallel (at the same time) at this work center. For example: the capacity is 5 and you need to produce 10 units, then the operation time listed on the BOM will be multiplied by two. However, note that both time before and after production will only be counted once.",
|
|
tracking=True)
|
|
|
|
oee_target = fields.Float(
|
|
string='OEE Target', help="Overall Effective Efficiency Target in percentage", default=90, tracking=True)
|
|
|
|
time_start = fields.Float('Setup Time', tracking=True)
|
|
time_stop = fields.Float('Cleanup Time', tracking=True)
|
|
costs_hour = fields.Float(string='Cost per hour', help='Hourly processing cost.', default=0.0, tracking=True)
|
|
|
|
equipment_status = fields.Selection(
|
|
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), ("封存(报废)", "封存(报废)")],
|
|
string="设备状态", related='equipment_id.state')
|
|
|
|
# @api.depends('equipment_id')
|
|
# def _compute_equipment_id(self):
|
|
# for record in self:
|
|
# if record:
|
|
# record.equipment_status = record.equipment_id.state
|
|
|
|
equipment_image = fields.Binary('设备图片', related='equipment_id.machine_tool_picture')
|
|
|
|
# 查询工艺外协加工中心
|
|
def get_process_outsourcing_workcenter(self):
|
|
outsourcing_workcenter = self.env['mrp.workcenter'].search([('is_process_outsourcing', '=', True)])
|
|
return outsourcing_workcenter.id
|
|
|
|
# @api.onchange('machine_tool_id')
|
|
# def update_machine_tool_is_binding(self):
|
|
# machine_tool = self.env["sf.machine_tool"].search([('is_binding', '=', True)])
|
|
# if machine_tool:
|
|
# for item in machine_tool:
|
|
# workcenter_machine_tool = self.env["mrp.workcenter"].search([('machine_tool_id', '=', item.id)])
|
|
# if workcenter_machine_tool:
|
|
# if self.machine_tool_id.id:
|
|
# if workcenter_machine_tool.id != self.machine_tool_id.id:
|
|
# self.machine_tool_id.is_binding = True
|
|
# else:
|
|
# self.machine_tool_id.is_binding = True
|
|
# else:
|
|
# self.machine_tool_id.is_binding = True
|
|
# item.is_binding = False
|
|
# else:
|
|
# self.machine_tool_id.is_binding = True
|
|
|
|
def action_work_order(self):
|
|
if not self.env.context.get('desktop_list_view', False):
|
|
action = self.env["ir.actions.actions"]._for_xml_id("sf_manufacturing.mrp_workorder_action_tablet")
|
|
return action
|
|
else:
|
|
return super(ResWorkcenter, self).action_work_order()
|
|
|
|
def _get_unavailability_intervals(self, start_datetime, end_datetime):
|
|
res = super(ResWorkcenter, self)._get_unavailability_intervals(start_datetime, end_datetime)
|
|
if not self:
|
|
return res
|
|
sql = """
|
|
SELECT workcenter_id, ARRAY_AGG((schedule_date || '|' || schedule_date + INTERVAL '1h' * duration)) as date_intervals
|
|
FROM maintenance_request
|
|
LEFT JOIN maintenance_equipment
|
|
ON maintenance_request.equipment_id = maintenance_equipment.id
|
|
WHERE
|
|
schedule_date IS NOT NULL
|
|
AND duration IS NOT NULL
|
|
AND equipment_id IS NOT NULL
|
|
AND maintenance_equipment.workcenter_id IS NOT NULL
|
|
AND maintenance_equipment.workcenter_id IN %s
|
|
AND (schedule_date, schedule_date + INTERVAL '1 hour') OVERLAPS (%s, %s)
|
|
GROUP BY maintenance_equipment.workcenter_id;
|
|
"""
|
|
self.env.cr.execute(sql, [tuple(self.ids), fields.Datetime.to_string(start_datetime.astimezone()),
|
|
fields.Datetime.to_string(end_datetime.astimezone())])
|
|
res_maintenance = defaultdict(list)
|
|
for wc_row in self.env.cr.dictfetchall():
|
|
res_maintenance[wc_row.get('workcenter_id')] = [
|
|
[fields.Datetime.to_datetime(i) for i in intervals.split('|')]
|
|
for intervals in wc_row.get('date_intervals')
|
|
]
|
|
|
|
for wc_id in self.ids:
|
|
intervals_previous_list = [(s.timestamp(), e.timestamp(), self.env['maintenance.request']) for s, e in
|
|
res[wc_id]]
|
|
intervals_maintenances_list = [(m[0].timestamp(), m[1].timestamp(), self.env['maintenance.request']) for m
|
|
in res_maintenance[wc_id]]
|
|
final_intervals_wc = Intervals(intervals_previous_list + intervals_maintenances_list)
|
|
res[wc_id] = [(datetime.fromtimestamp(s), datetime.fromtimestamp(e)) for s, e, _ in final_intervals_wc]
|
|
return res
|
|
|
|
|
|
class ResWorkcenterProductivity(models.Model):
|
|
_inherit = 'mrp.workcenter.productivity'
|
|
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
|