This commit is contained in:
huziyang@jikimo.com
2025-07-18 16:18:09 +08:00
parent fe8df494f9
commit 22f36d095c
11 changed files with 717 additions and 2 deletions

View File

@@ -8,6 +8,8 @@
<header>
<button string="打印" name="button_action_print" type="object"
class="btn-primary"/>
<button string="创建工艺设计任务" name="%(sf_manufacturing.action_create_technology_design_task_wizard)d"
type="action" class="btn-secondary" context="{'active_model': 'sf.production.demand.plan', 'active_ids': active_ids}"/>
</header>
<field name="sequence" widget="handle"/>
<field name="id" optional="hide"/>

View File

@@ -31,6 +31,7 @@
'wizard/sf_programming_reason_views.xml',
'wizard/sale_order_cancel_views.xml',
'wizard/process_outsourcing.xml',
'wizard/create_technology_design_task_wizard_views.xml',
'views/mrp_views_menus.xml',
'views/agv_scheduling_views.xml',
'views/stock_lot_views.xml',
@@ -48,6 +49,8 @@
'views/mrp_workorder_batch_replan.xml',
'views/purchase_order_view.xml',
'views/product_template_views.xml',
'views/sf_technology_design_task_views.xml',
'views/sf_technology_design_task_dashboard.xml',
# 'views/stock_warehouse_orderpoint.xml',
],
'assets': {

View File

@@ -36,6 +36,14 @@
<field name="padding">5</field>
</record>
<record id="sequence_technology_design_task" model="ir.sequence">
<field name="name">工艺设计任务编码规则</field>
<field name="code">sf.technology.design.task</field>
<field name="prefix">TD/%(year)s%(month)s%(day)s/</field>
<field name="padding">4</field>
<field name="company_id" eval="False"/>
</record>
<record id="stock_location_locations_virtual_outcontract" model="stock.location">
<field name="name">外协</field>
<field name="location_id" ref="stock.stock_location_locations_virtual"/>

View File

@@ -18,4 +18,5 @@ from . import quick_easy_order
from . import purchase_order
from . import quality_check
from . import purchase_request_line
from . import sf_technology_design_task
# from . import stock_warehouse_orderpoint

View File

@@ -0,0 +1,251 @@
# -*- 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')]),
}

View File

@@ -195,4 +195,10 @@ access_sf_work_individuation_page_group_plan_dispatch,sf_work_individuation_page
access_sf_sale_order_cancel_wizard,sf_sale_order_cancel_wizard,model_sf_sale_order_cancel_wizard,sf_base.group_sf_order_user,1,1,1,0
access_sf_sale_order_cancel_line,sf_sale_order_cancel_line,model_sf_sale_order_cancel_line,sf_base.group_sf_order_user,1,0,1,1
access_product_creation_wizard,product_creation_wizard,model_product_creation_wizard,base.group_user,1,1,1,0
access_product_creation_wizard,product_creation_wizard,model_product_creation_wizard,base.group_user,1,1,1,0
access_sf_technology_design_task_group_sf_mrp_user,sf_technology_design_task_group_sf_mrp_user,model_sf_technology_design_task,sf_base.group_sf_mrp_user,1,1,1,0
access_sf_technology_design_task_group_sf_mrp_manager,sf_technology_design_task_group_sf_mrp_manager,model_sf_technology_design_task,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_technology_design_task_group_plan_dispatch,sf_technology_design_task_group_plan_dispatch,model_sf_technology_design_task,sf_base.group_plan_dispatch,1,1,1,0
access_sf_technology_design_task_group_production_engineer,sf_technology_design_task_group_production_engineer,model_sf_technology_design_task,sf_base.group_production_engineer,1,1,1,0
access_sf_create_technology_design_task_wizard_group_sf_mrp_user,sf_create_technology_design_task_wizard_group_sf_mrp_user,model_sf_create_technology_design_task_wizard,sf_base.group_sf_mrp_user,1,1,1,0
access_sf_create_technology_design_task_wizard_group_sf_mrp_manager,sf_create_technology_design_task_wizard_group_sf_mrp_manager,model_sf_create_technology_design_task_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
195
196
197
198
199
200
201
202
203
204

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- 工艺设计任务仪表板视图 -->
<record id="view_sf_technology_design_task_dashboard" model="ir.ui.view">
<field name="name">sf.technology.design.task.dashboard</field>
<field name="model">sf.technology.design.task</field>
<field name="arch" type="xml">
<kanban class="o_kanban_small_column" default_group_by="state">
<field name="name"/>
<field name="state"/>
<field name="product_id"/>
<field name="part_name"/>
<field name="assigned_to"/>
<field name="deadline"/>
<field name="create_date"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<div class="oe_kanban_content">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
</div>
</div>
<div class="o_kanban_record_body">
<div class="o_kanban_primary_left">
<field name="product_id"/>
</div>
<div class="o_kanban_primary_right">
<field name="part_name"/>
</div>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<field name="assigned_to"/>
</div>
<div class="oe_kanban_bottom_right">
<field name="deadline"/>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- 工艺设计任务仪表板动作 -->
<record id="action_sf_technology_design_task_dashboard" model="ir.actions.act_window">
<field name="name">工艺设计任务仪表板</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.technology.design.task</field>
<field name="view_mode">kanban</field>
<field name="view_id" ref="view_sf_technology_design_task_dashboard"/>
<field name="context">{'search_default_filter_pending': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
创建第一个工艺设计任务
</p>
<p>
工艺设计任务用于管理产品工艺设计流程,包括从需求计划到工艺完成的整个过程。
</p>
</field>
</record>
<!-- 工艺设计任务仪表板菜单 -->
<menuitem id="menu_sf_technology_design_task_dashboard"
name="工艺设计仪表板"
sequence="15"
action="action_sf_technology_design_task_dashboard"
parent="mrp.menu_mrp_manufacturing"/>
</odoo>

View File

@@ -0,0 +1,280 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- 工艺设计任务列表视图 -->
<record id="view_sf_technology_design_task_tree" model="ir.ui.view">
<field name="name">sf.technology.design.task.tree</field>
<field name="model">sf.technology.design.task</field>
<field name="arch" type="xml">
<tree string="工艺设计任务" default_order="create_date desc"
class="technology_design_task_tree freeze-columns-before-part_number">
<header>
<button string="开始设计" name="action_start_design" type="object"
class="btn-primary" attrs="{'invisible': [('state', '!=', 'pending')]}"/>
<button string="完成设计" name="action_complete_design" type="object"
class="btn-success" attrs="{'invisible': [('state', '!=', 'in_progress')]}"/>
<button string="取消任务" name="action_cancel_task" type="object"
class="btn-secondary" attrs="{'invisible': [('state', 'in', ['completed'])]}"/>
<button string="重置任务" name="action_reset_to_pending" type="object"
class="btn-warning" attrs="{'invisible': [('state', 'not in', ['in_progress', 'cancelled'])]}"/>
</header>
<!-- 主要字段 -->
<field name="name" string="任务编号"/>
<field name="state" widget="badge"
decoration-success="state == 'completed'"
decoration-warning="state == 'in_progress'"
decoration-danger="state == 'cancelled'"/>
<field name="sale_order_id" string="销售单号"/>
<field name="product_id" string="产品名称"/>
<field name="part_name" string="零件名称"/>
<field name="part_number" string="零件图号"/>
<field name="product_type" string="零件类型"/>
<field name="model_id" string="模型ID" optional="hide"/>
<field name="model_filename" string="模型文件" optional="hide"/>
<field name="materials_id" string="材料及型号"/>
<field name="blank_type" string="坯料分类" optional="hide"/>
<field name="blank_precision" string="坯料类型" optional="hide"/>
<field name="embryo_long" string="坯料尺寸" optional="hide"/>
<field name="machining_precision" string="加工精度" optional="hide"/>
<field name="machining_panel" string="加工面" optional="hide"/>
<field name="product_uom_qty" string="订单数量"/>
<field name="is_incoming_material" string="客供料"/>
<field name="clamping_times" string="装夹次数" optional="hide"/>
<field name="single_clamping_duration" string="单次装夹时长" optional="hide"/>
<field name="cnc_processing_duration" string="CNC加工时长" optional="hide"/>
<field name="customer_quality_requirements" string="客户质量要求" optional="hide"/>
<field name="processing_drawing_filename" string="2D加工图纸" optional="hide"/>
<field name="customer_name" string="客户名称" optional="hide"/>
<!-- 时间字段 -->
<field name="create_date" string="创建时间" optional="hide"/>
<field name="start_date" string="开始时间" optional="hide"/>
<field name="complete_date" string="完成时间" optional="hide"/>
<field name="deadline" string="截止时间" optional="hide"/>
<!-- 负责人字段 -->
<field name="assigned_to" string="负责人" optional="hide"/>
<field name="created_by" string="创建人" optional="hide"/>
<!-- 备注 -->
<field name="notes" string="备注" optional="hide"/>
</tree>
</field>
</record>
<!-- 工艺设计任务搜索视图 -->
<record id="view_sf_technology_design_task_search" model="ir.ui.view">
<field name="name">sf.technology.design.task.search</field>
<field name="model">sf.technology.design.task</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="sale_order_id"/>
<field name="product_id"/>
<field name="part_name"/>
<field name="part_number"/>
<field name="customer_name"/>
<field name="materials_id"/>
<field name="assigned_to"/>
<field name="created_by"/>
<filter name="filter_pending" string="待工艺设计" domain="[('state', '=', 'pending')]"/>
<filter name="filter_in_progress" string="进行中" domain="[('state', '=', 'in_progress')]"/>
<filter name="filter_completed" string="已完成" domain="[('state', '=', 'completed')]"/>
<filter name="filter_cancelled" string="已取消" domain="[('state', '=', 'cancelled')]"/>
<separator/>
<filter name="filter_my_tasks" string="我的任务" domain="[('assigned_to', '=', uid)]"/>
<filter name="filter_overdue" string="已逾期" domain="[('deadline', '&lt;', context_today()), ('state', 'not in', ['completed', 'cancelled'])]"/>
<group expand="0" string="Group By">
<filter name="group_by_state" string="状态" domain="[]" context="{'group_by': 'state'}"/>
<filter name="group_by_sale_order" string="销售单号" domain="[]" context="{'group_by': 'sale_order_id'}"/>
<filter name="group_by_product" string="产品" domain="[]" context="{'group_by': 'product_id'}"/>
<filter name="group_by_customer" string="客户" domain="[]" context="{'group_by': 'customer_name'}"/>
<filter name="group_by_assigned_to" string="负责人" domain="[]" context="{'group_by': 'assigned_to'}"/>
<filter name="group_by_created_by" string="创建人" domain="[]" context="{'group_by': 'created_by'}"/>
<filter name="group_by_create_date" string="创建日期" domain="[]" context="{'group_by': 'create_date:day'}"/>
<filter name="group_by_deadline" string="截止日期" domain="[]" context="{'group_by': 'deadline:day'}"/>
</group>
</search>
</field>
</record>
<!-- 工艺设计任务表单视图 -->
<record id="view_sf_technology_design_task_form" model="ir.ui.view">
<field name="name">sf.technology.design.task.form</field>
<field name="model">sf.technology.design.task</field>
<field name="arch" type="xml">
<form string="工艺设计任务">
<header>
<button name="action_start_design" string="开始设计" type="object"
class="btn-primary" attrs="{'invisible': [('state', '!=', 'pending')]}"/>
<button name="action_complete_design" string="完成设计" type="object"
class="btn-success" attrs="{'invisible': [('state', '!=', 'in_progress')]}"/>
<button name="action_cancel_task" string="取消任务" type="object"
class="btn-secondary" attrs="{'invisible': [('state', 'in', ['completed'])]}"/>
<button name="action_reset_to_pending" string="重置任务" type="object"
class="btn-warning" attrs="{'invisible': [('state', 'not in', ['in_progress', 'cancelled'])]}"/>
<field name="state" widget="statusbar"
statusbar_visible="pending,in_progress,completed"/>
</header>
<sheet>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<group>
<group string="基本信息">
<field name="demand_plan_id"/>
<field name="sale_order_id"/>
<field name="customer_name"/>
<field name="assigned_to"/>
<field name="created_by"/>
</group>
<group string="时间信息">
<field name="create_date"/>
<field name="start_date"/>
<field name="complete_date"/>
<field name="deadline"/>
</group>
</group>
<notebook>
<page string="产品信息">
<group>
<group string="产品详情">
<field name="product_id"/>
<field name="part_name"/>
<field name="part_number"/>
<field name="product_type"/>
<field name="model_id"/>
<field name="model_file" filename="model_filename"/>
<field name="model_filename" invisible="1"/>
</group>
<group string="材料信息">
<field name="materials_id"/>
<field name="blank_type"/>
<field name="blank_precision"/>
<field name="embryo_long"/>
</group>
</group>
</page>
<page string="加工信息">
<group>
<group string="加工参数">
<field name="machining_precision"/>
<field name="machining_panel"/>
<field name="product_uom_qty"/>
<field name="is_incoming_material"/>
</group>
<group string="工艺参数">
<field name="clamping_times"/>
<field name="single_clamping_duration"/>
<field name="cnc_processing_duration"/>
</group>
</group>
</page>
<page string="质量要求">
<group>
<field name="customer_quality_requirements" nolabel="1"/>
</group>
<group string="图纸文件">
<field name="processing_drawing_2d" filename="processing_drawing_filename"/>
<field name="processing_drawing_filename" invisible="1"/>
</group>
</page>
<page string="备注">
<field name="notes" nolabel="1"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
<!-- 工艺设计任务动作 -->
<record id="action_sf_technology_design_task" model="ir.actions.act_window">
<field name="name">工艺设计任务</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.technology.design.task</field>
<field name="view_mode">tree,form</field>
<field name="context">{'search_default_filter_pending': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
创建第一个工艺设计任务
</p>
<p>
工艺设计任务用于管理产品工艺设计流程,包括从需求计划到工艺完成的整个过程。
</p>
</field>
</record>
<!-- 工艺设计任务菜单 -->
<menuitem id="menu_sf_technology_design_task"
name="工艺设计任务"
sequence="20"
action="action_sf_technology_design_task"
parent="mrp.menu_mrp_manufacturing"/>
<!-- 工艺设计任务看板视图 -->
<record id="view_sf_technology_design_task_kanban" model="ir.ui.view">
<field name="name">sf.technology.design.task.kanban</field>
<field name="model">sf.technology.design.task</field>
<field name="arch" type="xml">
<kanban class="o_kanban_small_column" default_group_by="state">
<field name="name"/>
<field name="state"/>
<field name="product_id"/>
<field name="part_name"/>
<field name="assigned_to"/>
<field name="deadline"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<div class="oe_kanban_content">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
</div>
</div>
<div class="o_kanban_record_body">
<div class="o_kanban_primary_left">
<field name="product_id"/>
</div>
<div class="o_kanban_primary_right">
<field name="part_name"/>
</div>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<field name="assigned_to"/>
</div>
<div class="oe_kanban_bottom_right">
<field name="deadline"/>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>

View File

@@ -6,4 +6,5 @@ from . import production_technology_re_adjust_wizard
from . import mrp_workorder_batch_replan_wizard
from . import sf_programming_reason
from . import sale_order_cancel
from . import process_outsourcing
from . import process_outsourcing
from . import create_technology_design_task_wizard

View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
from odoo import fields, models, api, _
from odoo.exceptions import UserError
class CreateTechnologyDesignTaskWizard(models.TransientModel):
_name = 'sf.create.technology.design.task.wizard'
_description = '创建工艺设计任务向导'
demand_plan_ids = fields.Many2many('sf.production.demand.plan', string='需求计划', required=True)
assigned_to = fields.Many2one('res.users', string='负责人', default=lambda self: self.env.user)
deadline = fields.Datetime('截止时间', required=True)
notes = fields.Text('备注')
@api.model
def default_get(self, fields_list):
res = super(CreateTechnologyDesignTaskWizard, self).default_get(fields_list)
if self.env.context.get('active_model') == 'sf.production.demand.plan':
demand_plan_ids = self.env.context.get('active_ids', [])
res['demand_plan_ids'] = [(6, 0, demand_plan_ids)]
return res
def action_create_tasks(self):
"""创建工艺设计任务"""
if not self.demand_plan_ids:
raise UserError(_('请选择需求计划'))
# 检查是否已存在工艺设计任务
existing_tasks = self.env['sf.technology.design.task'].search([
('demand_plan_id', 'in', self.demand_plan_ids.ids),
('state', 'not in', ['cancelled'])
])
if existing_tasks:
raise UserError(_('以下需求计划已存在工艺设计任务:\n%s') %
'\n'.join([task.demand_plan_id.name for task in existing_tasks]))
# 创建工艺设计任务
tasks = self.env['sf.technology.design.task']
for demand_plan in self.demand_plan_ids:
task_vals = {
'demand_plan_id': demand_plan.id,
'assigned_to': self.assigned_to.id,
'deadline': self.deadline,
'notes': self.notes,
}
task = self.env['sf.technology.design.task'].create(task_vals)
tasks |= task
# 返回工艺设计任务列表视图
return {
'type': 'ir.actions.act_window',
'name': _('工艺设计任务'),
'res_model': 'sf.technology.design.task',
'view_mode': 'tree,form',
'domain': [('id', 'in', tasks.ids)],
'context': {'search_default_filter_pending': 1},
}

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_create_technology_design_task_wizard_form" model="ir.ui.view">
<field name="name">sf.create.technology.design.task.wizard.form</field>
<field name="model">sf.create.technology.design.task.wizard</field>
<field name="arch" type="xml">
<form string="创建工艺设计任务">
<group>
<field name="demand_plan_ids" widget="many2many_tags"/>
<field name="assigned_to"/>
<field name="deadline"/>
<field name="notes"/>
</group>
<footer>
<button name="action_create_tasks" string="创建任务" type="object" class="btn-primary"/>
<button string="取消" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_create_technology_design_task_wizard" model="ir.actions.act_window">
<field name="name">创建工艺设计任务</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.create.technology.design.task.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>