251 lines
11 KiB
Python
251 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
||
from odoo import fields, models, api, _
|
||
from odoo.exceptions import ValidationError
|
||
|
||
|
||
class SfTechnologyDesignTask(models.Model):
|
||
_name = 'sf.technology.design.task'
|
||
_description = '工艺设计任务'
|
||
_order = 'create_date desc'
|
||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||
|
||
# 基本信息
|
||
name = fields.Char('任务编号', required=True, copy=False, readonly=True,
|
||
default=lambda self: _('New'))
|
||
state = fields.Selection([
|
||
('pending', '待工艺设计'),
|
||
('in_progress', '进行中'),
|
||
('completed', '已完成'),
|
||
('cancelled', '已取消'),
|
||
], string='状态', default='pending', tracking=True)
|
||
|
||
# 关联需求计划
|
||
demand_plan_id = fields.Many2one('sf.production.demand.plan', string='需求计划', required=True, ondelete='cascade')
|
||
|
||
# 销售订单信息
|
||
sale_order_id = fields.Many2one('sale.order', string='销售订单', compute='_compute_sale_order_info', store=True)
|
||
sale_order_line_id = fields.Many2one('sale.order.line', string='销售订单明细', compute='_compute_sale_order_info', store=True)
|
||
customer_name = fields.Char('客户名称', compute='_compute_sale_order_info', store=True)
|
||
|
||
# 产品信息
|
||
product_id = fields.Many2one('product.product', string='产品名称', compute='_compute_product_info', store=True)
|
||
part_name = fields.Char('零件名称', compute='_compute_product_info', store=True)
|
||
part_number = fields.Char('零件图号', compute='_compute_product_info', store=True)
|
||
model_id = fields.Char('模型ID', compute='_compute_product_info', store=True)
|
||
|
||
# 产品类型和文件
|
||
product_type = fields.Selection([
|
||
('standard', '标准件'),
|
||
('custom', '定制件'),
|
||
('prototype', '样件'),
|
||
], string='零件类型', default='custom', store=True)
|
||
model_file = fields.Binary('模型文件', compute='_compute_model_info', store=True)
|
||
model_filename = fields.Char('模型文件名', compute='_compute_model_info', store=True)
|
||
|
||
# 材料信息
|
||
materials_id = fields.Many2one('sf.production.materials', string='材料及型号', compute='_compute_material_info', store=True)
|
||
blank_type = fields.Selection([('圆料', '圆料'), ('方料', '方料')], string='坯料分类', compute='_compute_material_info', store=True)
|
||
blank_precision = fields.Selection([('精坯', '精坯'), ('粗坯', '粗坯')], string='坯料类型', compute='_compute_material_info', store=True)
|
||
embryo_long = fields.Char('坯料尺寸', compute='_compute_embryo_long', store=True)
|
||
|
||
# 加工信息
|
||
machining_precision = fields.Selection([
|
||
('0.10', '±0.10mm'),
|
||
('0.05', '±0.05mm'),
|
||
('0.03', '±0.03mm'),
|
||
('0.02', '±0.02mm'),
|
||
('0.01', '±0.01mm')
|
||
], string='加工精度', compute='_compute_machining_info', store=True)
|
||
machining_panel = fields.Char('加工面', compute='_compute_machining_info', store=True)
|
||
|
||
# 订单信息
|
||
product_uom_qty = fields.Float('订单数量', compute='_compute_order_info', store=True)
|
||
is_incoming_material = fields.Boolean('客供料', compute='_compute_order_info', store=True)
|
||
|
||
# 工艺参数
|
||
clamping_times = fields.Integer('装夹次数', default=1)
|
||
single_clamping_duration = fields.Float('单次装夹时长(分钟)', default=30.0)
|
||
cnc_processing_duration = fields.Float('CNC加工时长(分钟)', default=0.0)
|
||
|
||
# 质量要求
|
||
customer_quality_requirements = fields.Text('客户质量要求')
|
||
processing_drawing_2d = fields.Binary('2D加工图纸')
|
||
processing_drawing_filename = fields.Char('2D图纸文件名')
|
||
|
||
# 时间信息
|
||
create_date = fields.Datetime('创建时间', default=fields.Datetime.now)
|
||
start_date = fields.Datetime('开始时间')
|
||
complete_date = fields.Datetime('完成时间')
|
||
deadline = fields.Datetime('截止时间')
|
||
|
||
# 负责人
|
||
assigned_to = fields.Many2one('res.users', string='负责人', tracking=True)
|
||
created_by = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user, readonly=True)
|
||
|
||
# 备注
|
||
notes = fields.Text('备注')
|
||
|
||
@api.depends('demand_plan_id')
|
||
def _compute_sale_order_info(self):
|
||
for record in self:
|
||
if record.demand_plan_id:
|
||
record.sale_order_id = record.demand_plan_id.sale_order_id
|
||
record.sale_order_line_id = record.demand_plan_id.sale_order_line_id
|
||
record.customer_name = record.demand_plan_id.customer_name
|
||
else:
|
||
record.sale_order_id = False
|
||
record.sale_order_line_id = False
|
||
record.customer_name = ""
|
||
|
||
@api.depends('demand_plan_id')
|
||
def _compute_product_info(self):
|
||
for record in self:
|
||
if record.demand_plan_id and record.demand_plan_id.product_id:
|
||
record.product_id = record.demand_plan_id.product_id
|
||
if record.product_id.product_tmpl_id:
|
||
record.part_name = record.product_id.product_tmpl_id.part_name
|
||
record.part_number = record.product_id.product_tmpl_id.part_number
|
||
record.model_id = record.product_id.product_tmpl_id.model_id
|
||
else:
|
||
record.part_name = ""
|
||
record.part_number = ""
|
||
record.model_id = ""
|
||
else:
|
||
record.product_id = False
|
||
record.part_name = ""
|
||
record.part_number = ""
|
||
record.model_id = ""
|
||
|
||
@api.depends('product_id')
|
||
def _compute_model_info(self):
|
||
for record in self:
|
||
if record.product_id and record.product_id.product_tmpl_id:
|
||
template = record.product_id.product_tmpl_id
|
||
record.model_file = template.model_file
|
||
record.model_filename = template.model_name
|
||
else:
|
||
record.model_file = False
|
||
record.model_filename = ""
|
||
|
||
@api.depends('product_id')
|
||
def _compute_material_info(self):
|
||
for record in self:
|
||
if record.product_id and record.product_id.product_tmpl_id:
|
||
template = record.product_id.product_tmpl_id
|
||
record.materials_id = template.materials_id
|
||
record.blank_type = template.blank_type
|
||
record.blank_precision = template.blank_precision
|
||
else:
|
||
record.materials_id = False
|
||
record.blank_type = False
|
||
record.blank_precision = False
|
||
|
||
@api.depends('product_id')
|
||
def _compute_machining_info(self):
|
||
for record in self:
|
||
if record.product_id and record.product_id.product_tmpl_id:
|
||
template = record.product_id.product_tmpl_id
|
||
record.machining_precision = template.model_machining_precision
|
||
record.machining_panel = template.model_processing_panel
|
||
else:
|
||
record.machining_precision = False
|
||
record.machining_panel = ""
|
||
|
||
@api.depends('demand_plan_id')
|
||
def _compute_order_info(self):
|
||
for record in self:
|
||
if record.demand_plan_id:
|
||
record.product_uom_qty = record.demand_plan_id.product_uom_qty
|
||
record.is_incoming_material = record.demand_plan_id.is_incoming_material
|
||
else:
|
||
record.product_uom_qty = 0.0
|
||
record.is_incoming_material = False
|
||
|
||
@api.depends('product_id')
|
||
def _compute_embryo_long(self):
|
||
for record in self:
|
||
if record.product_id and record.product_id.product_tmpl_id:
|
||
template = record.product_id.product_tmpl_id
|
||
record.embryo_long = f"{template.model_long}×{template.model_width}×{template.model_height}"
|
||
else:
|
||
record.embryo_long = ""
|
||
|
||
@api.model
|
||
def create(self, vals):
|
||
if vals.get('name', _('New')) == _('New'):
|
||
vals['name'] = self.env['ir.sequence'].next_by_code('sf.technology.design.task') or _('New')
|
||
return super(SfTechnologyDesignTask, self).create(vals)
|
||
|
||
def action_start_design(self):
|
||
"""开始工艺设计"""
|
||
self.ensure_one()
|
||
if self.state != 'pending':
|
||
raise ValidationError(_('只有待工艺设计的任务才能开始设计'))
|
||
self.write({
|
||
'state': 'in_progress',
|
||
'start_date': fields.Datetime.now(),
|
||
})
|
||
self.message_post(body=_('工艺设计任务已开始'))
|
||
|
||
def action_complete_design(self):
|
||
"""完成工艺设计"""
|
||
self.ensure_one()
|
||
if self.state != 'in_progress':
|
||
raise ValidationError(_('只有进行中的任务才能完成'))
|
||
self.write({
|
||
'state': 'completed',
|
||
'complete_date': fields.Datetime.now(),
|
||
})
|
||
self.message_post(body=_('工艺设计任务已完成'))
|
||
|
||
def action_cancel_task(self):
|
||
"""取消任务"""
|
||
self.ensure_one()
|
||
if self.state in ['completed']:
|
||
raise ValidationError(_('已完成的任务不能取消'))
|
||
self.write({
|
||
'state': 'cancelled',
|
||
})
|
||
self.message_post(body=_('工艺设计任务已取消'))
|
||
|
||
def action_reset_to_pending(self):
|
||
"""重置为待工艺设计"""
|
||
self.ensure_one()
|
||
if self.state not in ['in_progress', 'cancelled']:
|
||
raise ValidationError(_('只有进行中或已取消的任务才能重置'))
|
||
self.write({
|
||
'state': 'pending',
|
||
'start_date': False,
|
||
'complete_date': False,
|
||
})
|
||
self.message_post(body=_('工艺设计任务已重置为待设计状态'))
|
||
|
||
@api.model
|
||
def create_from_demand_plan(self, demand_plan_ids):
|
||
"""从需求计划创建工艺设计任务"""
|
||
tasks = self.env['sf.technology.design.task']
|
||
for demand_plan in demand_plan_ids:
|
||
# 检查是否已存在工艺设计任务
|
||
existing_task = self.search([
|
||
('demand_plan_id', '=', demand_plan.id),
|
||
('state', 'not in', ['cancelled'])
|
||
], limit=1)
|
||
|
||
if not existing_task:
|
||
task_vals = {
|
||
'demand_plan_id': demand_plan.id,
|
||
'deadline': fields.Datetime.now() + fields.timedelta(days=3), # 默认3天期限
|
||
}
|
||
task = self.create(task_vals)
|
||
tasks |= task
|
||
|
||
return tasks
|
||
|
||
def get_task_count_by_state(self):
|
||
"""获取各状态的任务数量"""
|
||
return {
|
||
'pending': self.search_count([('state', '=', 'pending')]),
|
||
'in_progress': self.search_count([('state', '=', 'in_progress')]),
|
||
'completed': self.search_count([('state', '=', 'completed')]),
|
||
'cancelled': self.search_count([('state', '=', 'cancelled')]),
|
||
} |